duckdb 0.3.3-dev149.0 → 0.3.3-dev1506.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/Makefile +2 -0
- package/binding.gyp +8 -8
- package/lib/duckdb-binding.js +4 -2
- package/lib/duckdb.js +108 -20
- package/package.json +1 -1
- package/src/connection.cpp +274 -1
- package/src/database.cpp +1 -0
- package/src/duckdb.cpp +116114 -105380
- package/src/duckdb.hpp +7097 -5632
- package/src/duckdb_node.hpp +9 -0
- package/src/parquet-amalgamation.cpp +36901 -36749
- package/src/parquet-amalgamation.hpp +27 -9
- package/test/extension.test.js +86 -0
- package/test/udf.test.js +149 -0
|
@@ -7133,7 +7133,7 @@ public:
|
|
|
7133
7133
|
throw std::runtime_error("Decode bit width too large");
|
|
7134
7134
|
}
|
|
7135
7135
|
byte_encoded_len = ((bit_width_ + 7) / 8);
|
|
7136
|
-
max_val = (1 << bit_width_) - 1;
|
|
7136
|
+
max_val = (uint64_t(1) << bit_width_) - 1;
|
|
7137
7137
|
}
|
|
7138
7138
|
|
|
7139
7139
|
template <typename T>
|
|
@@ -7185,12 +7185,12 @@ private:
|
|
|
7185
7185
|
ByteBuffer buffer_;
|
|
7186
7186
|
|
|
7187
7187
|
/// Number of bits needed to encode the value. Must be between 0 and 64.
|
|
7188
|
-
|
|
7188
|
+
uint32_t bit_width_;
|
|
7189
7189
|
uint64_t current_value_;
|
|
7190
7190
|
uint32_t repeat_count_;
|
|
7191
7191
|
uint32_t literal_count_;
|
|
7192
7192
|
uint8_t byte_encoded_len;
|
|
7193
|
-
|
|
7193
|
+
uint64_t max_val;
|
|
7194
7194
|
|
|
7195
7195
|
uint8_t bitpack_pos = 0;
|
|
7196
7196
|
|
|
@@ -7410,12 +7410,16 @@ public:
|
|
|
7410
7410
|
|
|
7411
7411
|
virtual void Skip(idx_t num_values);
|
|
7412
7412
|
|
|
7413
|
-
|
|
7414
|
-
const
|
|
7413
|
+
ParquetReader &Reader();
|
|
7414
|
+
const LogicalType &Type() const;
|
|
7415
|
+
const SchemaElement &Schema() const;
|
|
7416
|
+
idx_t FileIdx() const;
|
|
7417
|
+
idx_t MaxDefine() const;
|
|
7418
|
+
idx_t MaxRepeat() const;
|
|
7415
7419
|
|
|
7416
7420
|
virtual idx_t GroupRowsAvailable();
|
|
7417
7421
|
|
|
7418
|
-
unique_ptr<BaseStatistics> Stats(const std::vector<ColumnChunk> &columns);
|
|
7422
|
+
virtual unique_ptr<BaseStatistics> Stats(const std::vector<ColumnChunk> &columns);
|
|
7419
7423
|
|
|
7420
7424
|
protected:
|
|
7421
7425
|
// readers that use the default Read() need to implement those
|
|
@@ -7574,10 +7578,17 @@ public:
|
|
|
7574
7578
|
: ParquetReader(allocator, move(file_handle_p), vector<LogicalType>(), string()) {
|
|
7575
7579
|
}
|
|
7576
7580
|
|
|
7577
|
-
ParquetReader(ClientContext &context, string file_name, const vector<
|
|
7581
|
+
ParquetReader(ClientContext &context, string file_name, const vector<string> &names,
|
|
7582
|
+
const vector<LogicalType> &expected_types_p, const vector<column_t> &column_ids,
|
|
7578
7583
|
ParquetOptions parquet_options, const string &initial_filename = string());
|
|
7579
7584
|
ParquetReader(ClientContext &context, string file_name, ParquetOptions parquet_options)
|
|
7580
|
-
: ParquetReader(context, move(file_name), vector<
|
|
7585
|
+
: ParquetReader(context, move(file_name), vector<string>(), vector<LogicalType>(), vector<column_t>(),
|
|
7586
|
+
parquet_options, string()) {
|
|
7587
|
+
}
|
|
7588
|
+
ParquetReader(ClientContext &context, string file_name, const vector<LogicalType> &expected_types_p,
|
|
7589
|
+
ParquetOptions parquet_options)
|
|
7590
|
+
: ParquetReader(context, move(file_name), vector<string>(), expected_types_p, vector<column_t>(),
|
|
7591
|
+
parquet_options, string()) {
|
|
7581
7592
|
}
|
|
7582
7593
|
~ParquetReader();
|
|
7583
7594
|
|
|
@@ -7604,7 +7615,8 @@ public:
|
|
|
7604
7615
|
static LogicalType DeriveLogicalType(const SchemaElement &s_ele, bool binary_as_string);
|
|
7605
7616
|
|
|
7606
7617
|
private:
|
|
7607
|
-
void InitializeSchema(const vector<
|
|
7618
|
+
void InitializeSchema(const vector<string> &names, const vector<LogicalType> &expected_types_p,
|
|
7619
|
+
const vector<column_t> &column_ids, const string &initial_filename_p);
|
|
7608
7620
|
bool ScanInternal(ParquetReaderScanState &state, DataChunk &output);
|
|
7609
7621
|
unique_ptr<ColumnReader> CreateReader(const duckdb_parquet::format::FileMetaData *file_meta_data);
|
|
7610
7622
|
|
|
@@ -7623,6 +7635,12 @@ private:
|
|
|
7623
7635
|
|
|
7624
7636
|
private:
|
|
7625
7637
|
unique_ptr<FileHandle> file_handle;
|
|
7638
|
+
//! column-id map, used when reading multiple parquet files since separate parquet files might have columns at
|
|
7639
|
+
//! different positions e.g. the first file might have column "a" at position 0, the second at position 1, etc
|
|
7640
|
+
vector<column_t> column_id_map;
|
|
7641
|
+
//! Map of column_id -> cast, used when reading multiple parquet files when parquet files have diverging types
|
|
7642
|
+
//! for the same column
|
|
7643
|
+
unordered_map<column_t, LogicalType> cast_map;
|
|
7626
7644
|
};
|
|
7627
7645
|
|
|
7628
7646
|
} // namespace duckdb
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
var duckdb = require('..');
|
|
2
|
+
var fs = require('fs');
|
|
3
|
+
var assert = require('assert');
|
|
4
|
+
var path = require('path');
|
|
5
|
+
|
|
6
|
+
const extension_base_path = "../../../build/release/extension";
|
|
7
|
+
|
|
8
|
+
// Look for extensions that we can load and test
|
|
9
|
+
let extension_paths = [];
|
|
10
|
+
const extension_full_path = path.resolve(__dirname, extension_base_path);
|
|
11
|
+
if (fs.existsSync(extension_full_path)) {
|
|
12
|
+
extension_paths = extension_paths.concat(fs.readdirSync(extension_full_path).map(function (file) {
|
|
13
|
+
if (!fs.statSync(extension_full_path+'/'+file).isDirectory())
|
|
14
|
+
return undefined;
|
|
15
|
+
const potential_extension_path = extension_full_path+`/${file}/${file}.duckdb_extension`;
|
|
16
|
+
if (fs.existsSync(potential_extension_path)) {
|
|
17
|
+
return potential_extension_path;
|
|
18
|
+
}
|
|
19
|
+
}).filter(a=>a));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Note: test will pass on http request failing due to connection issues.
|
|
23
|
+
const test_httpfs = async function (db, done) {
|
|
24
|
+
db.all("SELECT id, first_name, last_name FROM PARQUET_SCAN('https://raw.githubusercontent.com/cwida/duckdb/master/data/parquet-testing/userdata1.parquet') LIMIT 3;", function(err, rows) {
|
|
25
|
+
if (err) {
|
|
26
|
+
if (err.message.startsWith("Unable to connect to URL")) {
|
|
27
|
+
console.warn("Warning: HTTP request failed in extension.test.js");
|
|
28
|
+
done();
|
|
29
|
+
} else {
|
|
30
|
+
throw err;
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
assert.deepEqual(rows, [
|
|
34
|
+
{ id: 1, first_name: 'Amanda', last_name: 'Jordan'},
|
|
35
|
+
{ id: 2, first_name: 'Albert', last_name: 'Freeman'},
|
|
36
|
+
{ id: 3, first_name: 'Evelyn', last_name: 'Morgan'},
|
|
37
|
+
]);
|
|
38
|
+
done();
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const test_tpch = async function (db, done) {
|
|
44
|
+
db.all("CALL DBGEN(sf=0.01);", function(err) {
|
|
45
|
+
if (err) {
|
|
46
|
+
throw err;
|
|
47
|
+
}
|
|
48
|
+
done();
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const test_extension = function(extension_name, db, done) {
|
|
53
|
+
switch(extension_name) {
|
|
54
|
+
case 'httpfs.duckdb_extension':
|
|
55
|
+
test_httpfs(db, done);
|
|
56
|
+
break;
|
|
57
|
+
case 'tpch.duckdb_extension':
|
|
58
|
+
test_tpch(db, done);
|
|
59
|
+
break;
|
|
60
|
+
default:
|
|
61
|
+
done();
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
describe('Extension loading', function() {
|
|
67
|
+
var db;
|
|
68
|
+
|
|
69
|
+
before(function(done) {
|
|
70
|
+
db = new duckdb.Database(':memory:', done);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
for (ext of extension_paths) {
|
|
74
|
+
const extension_path = ext;
|
|
75
|
+
const extension_name = ext.replace(/^.*[\\\/]/, '');
|
|
76
|
+
|
|
77
|
+
it(extension_name, function(done) {
|
|
78
|
+
db.run(`LOAD '${extension_path}';`, function(err) {
|
|
79
|
+
if (err) {
|
|
80
|
+
throw err;
|
|
81
|
+
}
|
|
82
|
+
test_extension(extension_name, db, done);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
});
|
package/test/udf.test.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
var duckdb = require('..');
|
|
2
|
+
var assert = require('assert');
|
|
3
|
+
|
|
4
|
+
describe('UDFs', function() {
|
|
5
|
+
var db;
|
|
6
|
+
|
|
7
|
+
before(function(done) {
|
|
8
|
+
db = new duckdb.Database(':memory:', done);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('0ary int', function(done) {
|
|
12
|
+
db.register("udf", "integer", () => 42);
|
|
13
|
+
db.all("select udf() v", function(err, rows) {
|
|
14
|
+
if (err) throw err;
|
|
15
|
+
assert.equal(rows[0].v, 42);
|
|
16
|
+
});
|
|
17
|
+
db.unregister("udf", done);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('0ary double', function(done) {
|
|
21
|
+
db.register("udf", "double", () => 4.2);
|
|
22
|
+
db.all("select udf() v", function(err, rows) {
|
|
23
|
+
if (err) throw err;
|
|
24
|
+
assert.equal(rows[0].v, 4.2);
|
|
25
|
+
});
|
|
26
|
+
db.unregister("udf", done);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('0ary string', function(done) {
|
|
30
|
+
db.register("udf", "varchar", () => 'hello');
|
|
31
|
+
db.all("select udf() v", function(err, rows) {
|
|
32
|
+
if (err) throw err;
|
|
33
|
+
assert.equal(rows[0].v, 'hello');
|
|
34
|
+
});
|
|
35
|
+
db.unregister("udf", done);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('0ary int null', function(done) {
|
|
39
|
+
db.register("udf", "integer", () => undefined);
|
|
40
|
+
db.all("select udf() v", function(err, rows) {
|
|
41
|
+
if (err) throw err;
|
|
42
|
+
assert.equal(rows[0].v, undefined);
|
|
43
|
+
});
|
|
44
|
+
db.unregister("udf", done);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
it('0ary string null', function(done) {
|
|
49
|
+
db.register("udf", "varchar", () => undefined);
|
|
50
|
+
db.all("select udf() v", function(err, rows) {
|
|
51
|
+
if (err) throw err;
|
|
52
|
+
assert.equal(rows[0].v, undefined);
|
|
53
|
+
});
|
|
54
|
+
db.unregister("udf", done);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
it('unary int', function(done) {
|
|
59
|
+
db.register("udf", "integer", (x) => x+1);
|
|
60
|
+
db.all("select udf(42) v", function(err, rows) {
|
|
61
|
+
if (err) throw err;
|
|
62
|
+
assert.equal(rows[0].v, 43);
|
|
63
|
+
});
|
|
64
|
+
db.unregister("udf", done);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('unary double', function(done) {
|
|
68
|
+
db.register("udf", "double", (x) => x);
|
|
69
|
+
db.all("select udf(4.2::double) v", function(err, rows) {
|
|
70
|
+
if (err) throw err;
|
|
71
|
+
assert.equal(rows[0].v, 4.2);
|
|
72
|
+
});
|
|
73
|
+
db.unregister("udf", done);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('unary int null', function(done) {
|
|
77
|
+
db.register("udf", "integer", (x) => undefined);
|
|
78
|
+
db.all("select udf(42) v", function(err, rows) {
|
|
79
|
+
if (err) throw err;
|
|
80
|
+
assert.equal(rows[0].v, undefined);
|
|
81
|
+
});
|
|
82
|
+
db.unregister("udf", done);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
it('unary double null', function(done) {
|
|
87
|
+
db.register("udf", "double", (x) => undefined);
|
|
88
|
+
db.all("select udf(4.2::double) v", function(err, rows) {
|
|
89
|
+
if (err) throw err;
|
|
90
|
+
assert.equal(rows[0].v, undefined);
|
|
91
|
+
});
|
|
92
|
+
db.unregister("udf", done);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
it('unary string', function(done) {
|
|
97
|
+
db.register("udf", "varchar", (x) => 'hello ' + x);
|
|
98
|
+
db.all("select udf('world') v", function(err, rows) {
|
|
99
|
+
if (err) throw err;
|
|
100
|
+
assert.equal(rows[0].v, 'hello world');
|
|
101
|
+
});
|
|
102
|
+
db.unregister("udf", done);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('unary string null', function(done) {
|
|
106
|
+
db.register("udf", "varchar", (x) => undefined);
|
|
107
|
+
db.all("select udf('world') v", function(err, rows) {
|
|
108
|
+
if (err) throw err;
|
|
109
|
+
assert.equal(rows[0].v, undefined);
|
|
110
|
+
});
|
|
111
|
+
db.unregister("udf", done);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('binary int', function(done) {
|
|
115
|
+
db.register("udf", "integer", (x, y) => x + y);
|
|
116
|
+
db.all("select udf(40, 2) v", function(err, rows) {
|
|
117
|
+
if (err) throw err;
|
|
118
|
+
assert.equal(rows[0].v, 42);
|
|
119
|
+
});
|
|
120
|
+
db.unregister("udf", done);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('binary string', function(done) {
|
|
124
|
+
db.register("udf", "varchar", (x, y) => x + ' ' + y);
|
|
125
|
+
db.all("select udf('hello', 'world') v", function(err, rows) {
|
|
126
|
+
if (err) throw err;
|
|
127
|
+
assert.equal(rows[0].v, 'hello world');
|
|
128
|
+
});
|
|
129
|
+
db.unregister("udf", done);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('ternary int', function(done) {
|
|
133
|
+
db.register("udf", "integer", (x, y, z) => x + y + z);
|
|
134
|
+
db.all("select udf(21, 20, 1) v", function(err, rows) {
|
|
135
|
+
if (err) throw err;
|
|
136
|
+
assert.equal(rows[0].v, 42);
|
|
137
|
+
});
|
|
138
|
+
db.unregister("udf", done);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('unary larger series', function(done) {
|
|
142
|
+
db.register("udf", "integer", (x) => 1);
|
|
143
|
+
db.all("select sum(udf(range::double)) v from range(10000)", function(err, rows) {
|
|
144
|
+
if (err) throw err;
|
|
145
|
+
assert.equal(rows[0].v, 10000);
|
|
146
|
+
});
|
|
147
|
+
db.unregister("udf", done);
|
|
148
|
+
});
|
|
149
|
+
});
|