duckdb 0.3.5-dev75.0 → 0.3.5-dev758.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/statement.cpp CHANGED
@@ -121,6 +121,89 @@ static duckdb::Value bind_parameter(const Napi::Value source) {
121
121
  return duckdb::Value();
122
122
  }
123
123
 
124
+ static Napi::Value convert_col_val(Napi::Env &env, duckdb::Value dval, duckdb::LogicalTypeId id) {
125
+ Napi::Value value;
126
+
127
+ // TODO templateroo here
128
+ switch (id) {
129
+ case duckdb::LogicalTypeId::BOOLEAN: {
130
+ value = Napi::Boolean::New(env, duckdb::BooleanValue::Get(dval));
131
+ } break;
132
+ case duckdb::LogicalTypeId::INTEGER: {
133
+ value = Napi::Number::New(env, duckdb::IntegerValue::Get(dval));
134
+ } break;
135
+ case duckdb::LogicalTypeId::FLOAT: {
136
+ value = Napi::Number::New(env, duckdb::FloatValue::Get(dval));
137
+ } break;
138
+ case duckdb::LogicalTypeId::DOUBLE: {
139
+ value = Napi::Number::New(env, duckdb::DoubleValue::Get(dval));
140
+ } break;
141
+ case duckdb::LogicalTypeId::BIGINT: {
142
+ value = Napi::Number::New(env, duckdb::BigIntValue::Get(dval));
143
+ } break;
144
+ case duckdb::LogicalTypeId::HUGEINT: {
145
+ value = Napi::Number::New(env, dval.GetValue<double>());
146
+ } break;
147
+ case duckdb::LogicalTypeId::DECIMAL: {
148
+ value = Napi::Number::New(env, dval.GetValue<double>());
149
+ } break;
150
+ case duckdb::LogicalTypeId::INTERVAL: {
151
+ auto interval = duckdb::IntervalValue::Get(dval);
152
+ auto object_value = Napi::Object::New(env);
153
+ object_value.Set("months", interval.months);
154
+ object_value.Set("days", interval.days);
155
+ object_value.Set("micros", interval.micros);
156
+ value = object_value;
157
+ } break;
158
+ #if (NAPI_VERSION > 4)
159
+ case duckdb::LogicalTypeId::DATE: {
160
+ const auto scale = duckdb::Interval::SECS_PER_DAY * duckdb::Interval::MSECS_PER_SEC;
161
+ value = Napi::Date::New(env, double(dval.GetValue<int32_t>() * scale));
162
+ } break;
163
+ case duckdb::LogicalTypeId::TIMESTAMP:
164
+ case duckdb::LogicalTypeId::TIMESTAMP_TZ: {
165
+ value = Napi::Date::New(env, double(dval.GetValue<int64_t>() / duckdb::Interval::MICROS_PER_MSEC));
166
+ } break;
167
+ #endif
168
+ case duckdb::LogicalTypeId::VARCHAR: {
169
+ value = Napi::String::New(env, duckdb::StringValue::Get(dval));
170
+ } break;
171
+ case duckdb::LogicalTypeId::BLOB: {
172
+ auto &blob = duckdb::StringValue::Get(dval);
173
+ value = Napi::Buffer<char>::Copy(env, blob.c_str(), blob.length());
174
+ } break;
175
+ case duckdb::LogicalTypeId::SQLNULL: {
176
+ value = env.Null();
177
+ } break;
178
+ case duckdb::LogicalTypeId::LIST: {
179
+ auto child_type = duckdb::ListType::GetChildType(dval.type());
180
+ auto &child_values = duckdb::ListValue::GetChildren(dval);
181
+ auto object_value = Napi::Array::New(env);
182
+ for (duckdb::idx_t child_idx = 0; child_idx < child_values.size(); child_idx++) {
183
+ auto child_value = child_values.at(child_idx);
184
+ object_value.Set(child_idx, convert_col_val(env, child_value, child_type.id()));
185
+ }
186
+ value = object_value;
187
+ } break;
188
+ case duckdb::LogicalTypeId::STRUCT: {
189
+ auto &child_types = duckdb::StructType::GetChildTypes(dval.type());
190
+ auto &child_values = duckdb::StructValue::GetChildren(dval);
191
+ auto object_value = Napi::Object::New(env);
192
+ for (duckdb::idx_t child_idx = 0; child_idx < child_values.size(); child_idx++) {
193
+ auto child_value = child_values.at(child_idx);
194
+ auto child_type = child_types.at(child_idx);
195
+ object_value.Set(child_type.first, convert_col_val(env, child_value, child_type.second.id()));
196
+ }
197
+ value = object_value;
198
+ } break;
199
+ default:
200
+ Napi::Error::New(env, "Data type is not supported " + dval.type().ToString()).ThrowAsJavaScriptException();
201
+ return env.Null();
202
+ }
203
+
204
+ return value;
205
+ }
206
+
124
207
  static Napi::Value convert_chunk(Napi::Env &env, std::vector<std::string> names, duckdb::DataChunk &chunk) {
125
208
  Napi::EscapableHandleScope scope(env);
126
209
  std::vector<Napi::String> node_names;
@@ -134,75 +217,13 @@ static Napi::Value convert_chunk(Napi::Env &env, std::vector<std::string> names,
134
217
  Napi::Object row_result = Napi::Object::New(env);
135
218
 
136
219
  for (duckdb::idx_t col_idx = 0; col_idx < chunk.ColumnCount(); col_idx++) {
137
- Napi::Value value;
138
- // set up a new Napi::Object for some data types, e.g. INTERVAL
139
- Napi::Object object_value;
140
-
141
- bool is_object_value {false};
142
-
143
- auto dval = chunk.GetValue(col_idx, row_idx);
220
+ duckdb::Value dval = chunk.GetValue(col_idx, row_idx);
144
221
  if (dval.IsNull()) {
145
222
  row_result.Set(node_names[col_idx], env.Null());
146
223
  continue;
147
224
  }
148
225
 
149
- // TODO templateroo here
150
- switch (chunk.data[col_idx].GetType().id()) {
151
- case duckdb::LogicalTypeId::BOOLEAN: {
152
- value = Napi::Boolean::New(env, duckdb::BooleanValue::Get(dval));
153
- } break;
154
- case duckdb::LogicalTypeId::INTEGER: {
155
- value = Napi::Number::New(env, duckdb::IntegerValue::Get(dval));
156
- } break;
157
- case duckdb::LogicalTypeId::FLOAT: {
158
- value = Napi::Number::New(env, duckdb::FloatValue::Get(dval));
159
- } break;
160
- case duckdb::LogicalTypeId::DOUBLE: {
161
- value = Napi::Number::New(env, duckdb::DoubleValue::Get(dval));
162
- } break;
163
- case duckdb::LogicalTypeId::BIGINT: {
164
- value = Napi::Number::New(env, duckdb::BigIntValue::Get(dval));
165
- } break;
166
- case duckdb::LogicalTypeId::HUGEINT: {
167
- value = Napi::Number::New(env, dval.GetValue<double>());
168
- } break;
169
- case duckdb::LogicalTypeId::INTERVAL: {
170
- auto interval = duckdb::IntervalValue::Get(dval);
171
- is_object_value = true;
172
- object_value = Napi::Object::New(env);
173
- object_value.Set("months", interval.months);
174
- object_value.Set("days", interval.days);
175
- object_value.Set("micros", interval.micros);
176
- } break;
177
- #if (NAPI_VERSION > 4)
178
- case duckdb::LogicalTypeId::DATE: {
179
- const auto scale = duckdb::Interval::SECS_PER_DAY * duckdb::Interval::MSECS_PER_SEC;
180
- value = Napi::Date::New(env, double(dval.GetValue<int32_t>() * scale));
181
- } break;
182
- case duckdb::LogicalTypeId::TIMESTAMP: {
183
- value = Napi::Date::New(env, double(dval.GetValue<int64_t>() / duckdb::Interval::MICROS_PER_MSEC));
184
- } break;
185
- #endif
186
- case duckdb::LogicalTypeId::VARCHAR: {
187
- value = Napi::String::New(env, duckdb::StringValue::Get(dval));
188
- } break;
189
- case duckdb::LogicalTypeId::BLOB: {
190
- auto &blob = duckdb::StringValue::Get(dval);
191
- value = Napi::Buffer<char>::Copy(env, blob.c_str(), blob.length());
192
- } break;
193
- case duckdb::LogicalTypeId::SQLNULL: {
194
- value = env.Null();
195
- } break;
196
- default:
197
- Napi::Error::New(env, "Data type is not supported " + dval.type().ToString())
198
- .ThrowAsJavaScriptException();
199
- return env.Null();
200
- }
201
- if (is_object_value == true) {
202
- row_result.Set(node_names[col_idx], object_value);
203
- } else {
204
- row_result.Set(node_names[col_idx], value);
205
- }
226
+ row_result.Set(node_names[col_idx], convert_col_val(env, dval, chunk.data[col_idx].GetType().id()));
206
227
  }
207
228
  result.Set(row_idx, row_result);
208
229
  }
@@ -21,16 +21,73 @@ describe("data type support", function () {
21
21
  });
22
22
  });
23
23
  it("supports INTERVAL values", function (done) {
24
- db.prepare(`SELECT
24
+ db.prepare(`SELECT
25
25
  INTERVAL 1 MINUTE as minutes,
26
26
  INTERVAL 5 DAY as days,
27
27
  INTERVAL 4 MONTH as months,
28
- INTERVAL 4 MONTH + INTERVAL 5 DAY + INTERVAL 1 MINUTE as combined;`).each((err, row) => {
28
+ INTERVAL 4 MONTH + INTERVAL 5 DAY + INTERVAL 1 MINUTE as combined;`
29
+ ).each((err, row) => {
29
30
  assert(err === null);
30
- assert.deepEqual(row.minutes, { months: 0, days: 0, micros: 60 * 1000 * 1000});
31
- assert.deepEqual(row.days, { months: 0, days: 5, micros: 0});
32
- assert.deepEqual(row.months, {months: 4, days: 0, micros: 0});
33
- assert.deepEqual(row.combined, {months: 4, days: 5, micros: 60 * 1000 * 1000});
31
+ assert.deepEqual(row.minutes, {
32
+ months: 0,
33
+ days: 0,
34
+ micros: 60 * 1000 * 1000,
35
+ });
36
+ assert.deepEqual(row.days, { months: 0, days: 5, micros: 0 });
37
+ assert.deepEqual(row.months, { months: 4, days: 0, micros: 0 });
38
+ assert.deepEqual(row.combined, {
39
+ months: 4,
40
+ days: 5,
41
+ micros: 60 * 1000 * 1000,
42
+ });
43
+ done();
44
+ });
45
+ });
46
+ it("supports STRUCT values", function (done) {
47
+ db.prepare(`SELECT {'x': 1, 'y': 2, 'z': {'a': 'b'}} as struct`).each(
48
+ (err, row) => {
49
+ assert.deepEqual(row.struct, { x: 1, y: 2, z: { a: "b" } });
50
+ done();
51
+ }
52
+ );
53
+ });
54
+ it("supports LIST values", function (done) {
55
+ db.prepare(`SELECT ['duck', 'duck', 'goose'] as list`).each((err, row) => {
56
+ assert.deepEqual(row.list, ["duck", "duck", "goose"]);
57
+ done();
58
+ });
59
+ });
60
+ it("supports DATE values", function (done) {
61
+ db.prepare(`SELECT '2021-01-01'::DATE as dt;`).each((err, row) => {
62
+ assert(err === null);
63
+ assert.deepEqual(row.dt, new Date(Date.UTC(2021, 0, 1)));
64
+ done();
65
+ });
66
+ });
67
+ it("supports TIMESTAMP values", function (done) {
68
+ db.prepare(`SELECT '2021-01-01T00:00:00'::TIMESTAMP as ts;`).each((err, row) => {
69
+ assert(err === null);
70
+ assert.deepEqual(row.ts, new Date(Date.UTC(2021, 0, 1)));
71
+ done();
72
+ });
73
+ });
74
+ it("supports TIMESTAMP WITH TIME ZONE values", function (done) {
75
+ db.prepare(`SELECT '2021-01-01T00:00:00Z'::TIMESTAMPTZ as tstz;`).each((err, row) => {
76
+ assert(err === null);
77
+ assert.deepEqual(row.tstz, new Date(Date.UTC(2021, 0, 1)));
78
+ done();
79
+ });
80
+ });
81
+ it("supports DECIMAL values", function (done) {
82
+ db.run("CREATE TABLE decimal_table (d DECIMAL(24, 6))");
83
+ const stmt = db.prepare("INSERT INTO decimal_table VALUES (?)");
84
+ const values = [0, -1, 23534642362547.543463];
85
+ values.forEach((d) => {
86
+ stmt.run(d);
87
+ });
88
+ db.prepare("SELECT d from decimal_table;").all((err, res) => {
89
+ assert(err === null);
90
+ assert(res.every((v, i) => v.d === values[i]));
34
91
  done();
35
92
  });
36
93
  });
@@ -543,7 +543,7 @@ describe('prepare', function() {
543
543
  });
544
544
  it("should aggregate approx_count_distinct(flt)", function (done) {
545
545
  db.all("SELECT approx_count_distinct(flt) as approx_count_distinct FROM foo", function (err, res) {
546
- assert.ok(res[0].approx_count_distinct >= 1000);
546
+ assert.ok(res[0].approx_count_distinct >= 950);
547
547
  done(err);
548
548
  });
549
549
  });
@@ -587,7 +587,7 @@ describe('prepare', function() {
587
587
  });
588
588
  it("should aggregate approx_count_distinct(num)", function (done) {
589
589
  db.all("SELECT approx_count_distinct(num) as approx_count_distinct FROM foo", function (err, res) {
590
- assert.ok(res[0].approx_count_distinct >= 1000);
590
+ assert.ok(res[0].approx_count_distinct >= 950);
591
591
  done(err);
592
592
  });
593
593
  });