@ohos-ports/duckdb 0.0.0-stage → 1.4.2-beta.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/LICENSE +7 -0
- package/README.md +127 -2
- package/duckdb.js +1 -0
- package/lib/binding/duckdb.node +4 -0
- package/lib/duckdb-binding.js +16 -0
- package/lib/duckdb.d.ts +281 -0
- package/lib/duckdb.js +763 -0
- package/lib/index.js +1 -0
- package/package.json +44 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2018-2025 Stichting DuckDB Foundation
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,128 @@
|
|
|
1
|
-
|
|
1
|
+
> [!WARNING]
|
|
2
|
+
> The original DuckDB <> Node.js bindings in this package are deprecated in favor of the new and shiny `@duckdb/node-api` package. Currently, the plan is to release this package `duckdb-node` for the last time for the DuckDB 1.4.x (~Fall 2025) series but *not* for the DuckDB 1.5.x series (~Early 2026) any more. Please [contact](https://duckdblabs.com/contact/) DuckDB Labs if you absolutely require updates after that.
|
|
3
|
+
|
|
4
|
+
# DuckDB Node Bindings
|
|
5
|
+
|
|
6
|
+
This package provides a Node.js API for [DuckDB](https://github.com/duckdb/duckdb), the "SQLite for Analytics". The API for this client is somewhat compliant to the SQLite Node.js client for easier transition (and transition you must eventually).
|
|
7
|
+
|
|
8
|
+
Load the package and create a database object:
|
|
9
|
+
|
|
10
|
+
```js
|
|
11
|
+
var duckdb = require('duckdb');
|
|
12
|
+
|
|
13
|
+
var db = new duckdb.Database(':memory:'); // or a file name for a persistent DB
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Then you can run a query:
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
db.all('SELECT 42 AS fortytwo', function(err, res) {
|
|
20
|
+
if (err) {
|
|
21
|
+
console.warn(err);
|
|
22
|
+
}
|
|
23
|
+
console.log(res[0].fortytwo)
|
|
24
|
+
});
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Other available methods are `each`, where the callback is invoked for each row, `run` to execute a single statement without results and `exec`, which can execute several SQL commands at once but also does not return results. All those commands can work with prepared statements, taking the values for the parameters as additional arguments. For example like so:
|
|
28
|
+
|
|
29
|
+
```js
|
|
30
|
+
db.all('SELECT ?::INTEGER AS fortytwo, ?::STRING as hello', 42, 'Hello, World', function(err, res) {
|
|
31
|
+
if (err) {
|
|
32
|
+
console.warn(err);
|
|
33
|
+
}
|
|
34
|
+
console.log(res[0].fortytwo)
|
|
35
|
+
console.log(res[0].hello)
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
However, these are all shorthands for something much more elegant. A database can have multiple `Connection`s, those are created using `db.connect()`.
|
|
40
|
+
|
|
41
|
+
```js
|
|
42
|
+
var con = db.connect();
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
You can create multiple connections, each with their own transaction context.
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
`Connection` objects also contain shorthands to directly call `run()`, `all()` and `each()` with parameters and callbacks, respectively, for example:
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
con.all('SELECT 42 AS fortytwo', function(err, res) {
|
|
52
|
+
if (err) {
|
|
53
|
+
console.warn(err);
|
|
54
|
+
}
|
|
55
|
+
console.log(res[0].fortytwo)
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
From connections, you can create prepared statements (and only that) using `con.prepare()`:
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
var stmt = con.prepare('select ?::INTEGER as fortytwo');
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
To execute this statement, you can call for example `all()` on the `stmt` object:
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
stmt.all(42, function(err, res) {
|
|
69
|
+
if (err) {
|
|
70
|
+
console.warn(err);
|
|
71
|
+
}
|
|
72
|
+
console.log(res[0].fortytwo)
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
You can also execute the prepared statement multiple times. This is for example useful to fill a table with data:
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
con.run('CREATE TABLE a (i INTEGER)');
|
|
80
|
+
var stmt = con.prepare('INSERT INTO a VALUES (?)');
|
|
81
|
+
for (var i = 0; i < 10; i++) {
|
|
82
|
+
stmt.run(i);
|
|
83
|
+
}
|
|
84
|
+
stmt.finalize();
|
|
85
|
+
con.all('SELECT * FROM a', function(err, res) {
|
|
86
|
+
if (err) {
|
|
87
|
+
console.warn(err);
|
|
88
|
+
}
|
|
89
|
+
console.log(res)
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
`prepare()` can also take a callback which gets the prepared statement as an argument:
|
|
94
|
+
|
|
95
|
+
```js
|
|
96
|
+
var stmt = con.prepare('select ?::INTEGER as fortytwo', function(err, stmt) {
|
|
97
|
+
stmt.all(42, function(err, res) {
|
|
98
|
+
if (err) {
|
|
99
|
+
console.warn(err);
|
|
100
|
+
}
|
|
101
|
+
console.log(res[0].fortytwo)
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Supported Node versions
|
|
107
|
+
We actively support only LTS and In-Support Node versions, as per July 2023, they are: Node 18, Node 20 and Node 21. For OSX and Linux targets, also Node 22 is available.
|
|
108
|
+
Release schedule for Node.js can be checked here: https://github.com/nodejs/release#release-schedule.
|
|
109
|
+
|
|
110
|
+
We currently bundle and test DuckDB also for Node 12, 14, 16, 17 and 19. We plan of going so going forward as long as the tooling supports it.
|
|
111
|
+
As per July 2023, Node 15 has been removed from the supported versions.
|
|
112
|
+
|
|
113
|
+
## Development
|
|
114
|
+
|
|
115
|
+
### First install:
|
|
116
|
+
|
|
117
|
+
To install all the dev dependencies of the project, run `npm install` (this uses package.json)
|
|
118
|
+
You might want to add the `--ignore-scripts` option if you don't care about building the package for now and just want to install the dependencies.
|
|
119
|
+
|
|
120
|
+
### Tests:
|
|
121
|
+
Tests are located in `test` and can be run with `npm test`
|
|
122
|
+
To run a single test, you can use `npm test -- --grep "name of test as given in describe"`
|
|
123
|
+
|
|
124
|
+
### Additional notes:
|
|
125
|
+
To build the NodeJS package from source, when on Windows, requires the following extra steps:
|
|
126
|
+
- Set `OPENSSL_ROOT_DIR` to the root directory of an OpenSSL installation
|
|
127
|
+
- Supply the `STATIC_OPENSSL=1` option when executing `make`, or set `-DOPENSSL_USE_STATIC_LIBS=1` manually when calling `cmake`
|
|
2
128
|
|
|
3
|
-
This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
|
package/duckdb.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./lib/duckdb');
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// @ohos-ports/duckdb: vendored native binding loader (openharmony/arm64)
|
|
2
|
+
// The prebuilt, signed duckdb.node addon is shipped inside this package at
|
|
3
|
+
// lib/binding/duckdb.node, so no @mapbox/node-pre-gyp download/build step is
|
|
4
|
+
// needed at install time (upstream npm duckdb 404s its openharmony prebuilds).
|
|
5
|
+
var path = require('path');
|
|
6
|
+
var binding_path = path.join(__dirname, 'binding', 'duckdb.node');
|
|
7
|
+
var fs = require('fs');
|
|
8
|
+
if (!fs.existsSync(binding_path)) {
|
|
9
|
+
throw new Error(
|
|
10
|
+
'@ohos-ports/duckdb: native binding not found at ' + binding_path +
|
|
11
|
+
' — this package ships a prebuilt openharmony/arm64 addon and does not support building from source at install time.'
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
var binding = require(binding_path);
|
|
15
|
+
|
|
16
|
+
module.exports = exports = binding;
|
package/lib/duckdb.d.ts
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript declarations for Node.JS bindings for DuckDb.
|
|
3
|
+
* See https://duckdb.org/docs/api/nodejs/overview for details
|
|
4
|
+
* on Node.JS API
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export type ExceptionType =
|
|
8
|
+
| "Invalid" // invalid type
|
|
9
|
+
| "Out of Range" // value out of range error
|
|
10
|
+
| "Conversion" // conversion/casting error
|
|
11
|
+
| "Unknown Type" // unknown type
|
|
12
|
+
| "Decimal" // decimal related
|
|
13
|
+
| "Mismatch Type" // type mismatch
|
|
14
|
+
| "Divide by Zero" // divide by 0
|
|
15
|
+
| "Object Size" // object size exceeded
|
|
16
|
+
| "Invalid type" // incompatible for operation
|
|
17
|
+
| "Serialization" // serialization
|
|
18
|
+
| "TransactionContext" // transaction management
|
|
19
|
+
| "Not implemented" // method not implemented
|
|
20
|
+
| "Expression" // expression parsing
|
|
21
|
+
| "Catalog" // catalog related
|
|
22
|
+
| "Parser" // parser related
|
|
23
|
+
| "Binder" // binder related
|
|
24
|
+
| "Planner" // planner related
|
|
25
|
+
| "Scheduler" // scheduler related
|
|
26
|
+
| "Executor" // executor related
|
|
27
|
+
| "Constraint" // constraint related
|
|
28
|
+
| "Index" // index related
|
|
29
|
+
| "Stat" // stat related
|
|
30
|
+
| "Connection" // connection related
|
|
31
|
+
| "Syntax" // syntax related
|
|
32
|
+
| "Settings" // settings related
|
|
33
|
+
| "Optimizer" // optimizer related
|
|
34
|
+
| "NullPointer" // nullptr exception
|
|
35
|
+
| "IO" // IO exception
|
|
36
|
+
| "INTERRUPT" // interrupt
|
|
37
|
+
| "FATAL" // Fatal exceptions are non-recoverable and render the entire DB in an unusable state
|
|
38
|
+
| "INTERNAL" // Internal exceptions indicate something went wrong internally (i.e. bug in the code base)
|
|
39
|
+
| "Invalid Input" // Input or arguments error
|
|
40
|
+
| "Out of Memory" // out of memory
|
|
41
|
+
| "Permission" // insufficient permissions
|
|
42
|
+
| "Parameter Not Resolved" // parameter types could not be resolved
|
|
43
|
+
| "Parameter Not Allowed" // parameter types not allowed
|
|
44
|
+
| "Dependency" // dependency
|
|
45
|
+
| "Unknown"
|
|
46
|
+
| "HTTP"
|
|
47
|
+
;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Standard error shape for DuckDB errors
|
|
51
|
+
*/
|
|
52
|
+
export interface _DuckDbError extends Error {
|
|
53
|
+
errno: -1; // value of ERROR
|
|
54
|
+
code: 'DUCKDB_NODEJS_ERROR';
|
|
55
|
+
errorType: ExceptionType;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface HttpError extends _DuckDbError {
|
|
59
|
+
errorType: 'HTTP';
|
|
60
|
+
statusCode: number;
|
|
61
|
+
response: string;
|
|
62
|
+
reason: string;
|
|
63
|
+
headers: Record<string, string>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export type DuckDbError = HttpError | _DuckDbError;
|
|
67
|
+
|
|
68
|
+
type Callback<T> = (err: DuckDbError | null, res: T) => void;
|
|
69
|
+
|
|
70
|
+
export type RowData = {
|
|
71
|
+
[columnName: string]: any;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export type TableData = RowData[];
|
|
75
|
+
export type ArrowIterable = Iterable<Uint8Array> | AsyncIterable<Uint8Array>;
|
|
76
|
+
export type ArrowArray = Uint8Array[];
|
|
77
|
+
|
|
78
|
+
export class Connection {
|
|
79
|
+
constructor(db: Database, callback?: Callback<any>);
|
|
80
|
+
|
|
81
|
+
close(callback?: Callback<void>): void;
|
|
82
|
+
|
|
83
|
+
all(sql: string, ...args: [...any, Callback<TableData>] | []): void;
|
|
84
|
+
arrowIPCAll(sql: string, ...args: [...any, Callback<ArrowArray>] | []): void;
|
|
85
|
+
each(sql: string, ...args: [...any, Callback<RowData>] | []): void;
|
|
86
|
+
exec(sql: string, ...args: [...any, Callback<void>] | []): void;
|
|
87
|
+
|
|
88
|
+
prepare(sql: string, ...args: [...any, Callback<Statement>] | []): Statement;
|
|
89
|
+
run(sql: string, ...args: [...any, Callback<void>] | []): Statement;
|
|
90
|
+
|
|
91
|
+
register_udf(
|
|
92
|
+
name: string,
|
|
93
|
+
return_type: string,
|
|
94
|
+
fun: (...args: any[]) => any
|
|
95
|
+
): void;
|
|
96
|
+
|
|
97
|
+
register_bulk(
|
|
98
|
+
name: string,
|
|
99
|
+
return_type: string,
|
|
100
|
+
fun: (...args: any[]) => any
|
|
101
|
+
): void;
|
|
102
|
+
unregister_udf(name: string, callback: Callback<any>): void;
|
|
103
|
+
|
|
104
|
+
stream(sql: any, ...args: any[]): QueryResult;
|
|
105
|
+
arrowIPCStream(sql: any, ...args: any[]): Promise<IpcResultStreamIterator>;
|
|
106
|
+
|
|
107
|
+
register_buffer(name: string, array: ArrowIterable, force: boolean, callback?: Callback<void>): void;
|
|
108
|
+
unregister_buffer(name: string, callback?: Callback<void>): void;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export class QueryResult implements AsyncIterable<RowData> {
|
|
112
|
+
[Symbol.asyncIterator](): AsyncIterator<RowData>;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export class IpcResultStreamIterator implements AsyncIterator<Uint8Array>, AsyncIterable<Uint8Array> {
|
|
116
|
+
[Symbol.asyncIterator](): this;
|
|
117
|
+
|
|
118
|
+
next(...args: [] | [undefined]): Promise<IteratorResult<Uint8Array, any>>;
|
|
119
|
+
|
|
120
|
+
toArray(): Promise<ArrowArray>;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface ReplacementScanResult {
|
|
124
|
+
function: string;
|
|
125
|
+
parameters: Array<unknown>;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export type ReplacementScanCallback = (
|
|
129
|
+
table: string
|
|
130
|
+
) => ReplacementScanResult | null;
|
|
131
|
+
|
|
132
|
+
export enum TokenType {
|
|
133
|
+
IDENTIFIER = 0,
|
|
134
|
+
NUMERIC_CONSTANT = 1,
|
|
135
|
+
STRING_CONSTANT = 2,
|
|
136
|
+
OPERATOR = 3,
|
|
137
|
+
KEYWORD = 4,
|
|
138
|
+
COMMENT = 5,
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface ScriptTokens {
|
|
142
|
+
offsets: number[];
|
|
143
|
+
types: TokenType[];
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export class Database {
|
|
147
|
+
constructor(path: string, accessMode?: number | Record<string,string>, callback?: Callback<any>);
|
|
148
|
+
constructor(path: string, callback?: Callback<any>);
|
|
149
|
+
|
|
150
|
+
close(callback?: Callback<void>): void;
|
|
151
|
+
|
|
152
|
+
connect(): Connection;
|
|
153
|
+
|
|
154
|
+
all(sql: string, ...args: [...any, Callback<TableData>] | []): this;
|
|
155
|
+
arrowIPCAll(sql: string, ...args: [...any, Callback<ArrowArray>] | []): void;
|
|
156
|
+
each(sql: string, ...args: [...any, Callback<RowData>] | []): this;
|
|
157
|
+
exec(sql: string, ...args: [...any, Callback<void>] | []): void;
|
|
158
|
+
|
|
159
|
+
prepare(sql: string, ...args: [...any, Callback<Statement>] | []): Statement;
|
|
160
|
+
run(sql: string, ...args: [...any, Callback<void>] | []): Statement;
|
|
161
|
+
|
|
162
|
+
register_udf(
|
|
163
|
+
name: string,
|
|
164
|
+
return_type: string,
|
|
165
|
+
fun: (...args: any[]) => any
|
|
166
|
+
): void;
|
|
167
|
+
unregister_udf(name: string, callback: Callback<any>): void;
|
|
168
|
+
|
|
169
|
+
stream(sql: any, ...args: any[]): QueryResult;
|
|
170
|
+
arrowIPCStream(sql: any, ...args: any[]): Promise<IpcResultStreamIterator>;
|
|
171
|
+
|
|
172
|
+
serialize(done?: Callback<void>): void;
|
|
173
|
+
parallelize(done?: Callback<void>): void;
|
|
174
|
+
wait(done: Callback<void>): void;
|
|
175
|
+
|
|
176
|
+
get(columnName: string, cb: Callback<RowData>): void;
|
|
177
|
+
get(columnName: string, num: number, cb: Callback<RowData>): void;
|
|
178
|
+
|
|
179
|
+
interrupt(): void;
|
|
180
|
+
|
|
181
|
+
register_buffer(name: string, array: ArrowIterable, force: boolean, callback?: Callback<void>): void;
|
|
182
|
+
|
|
183
|
+
unregister_buffer(name: string, callback?: Callback<void>): void;
|
|
184
|
+
|
|
185
|
+
registerReplacementScan(
|
|
186
|
+
replacementScan: ReplacementScanCallback
|
|
187
|
+
): Promise<void>;
|
|
188
|
+
|
|
189
|
+
tokenize(text: string): ScriptTokens;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export type GenericTypeInfo = {
|
|
193
|
+
id: string,
|
|
194
|
+
sql_type: string,
|
|
195
|
+
alias?: string,
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export type StructTypeInfo = {
|
|
199
|
+
id: "STRUCT",
|
|
200
|
+
alias?: string,
|
|
201
|
+
sql_type: string,
|
|
202
|
+
children: TypeInfoChildren,
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export type ListTypeInfo = {
|
|
206
|
+
id: "LIST",
|
|
207
|
+
alias?: string,
|
|
208
|
+
sql_type: string,
|
|
209
|
+
child: TypeInfo,
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export type MapTypeInfo = {
|
|
213
|
+
id: "MAP",
|
|
214
|
+
alias?: string,
|
|
215
|
+
sql_type: string,
|
|
216
|
+
key: TypeInfo,
|
|
217
|
+
value: TypeInfo,
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export type UnionTypeInfo = {
|
|
221
|
+
id: "UNION",
|
|
222
|
+
alias?: string,
|
|
223
|
+
sql_type: string,
|
|
224
|
+
children: TypeInfoChildren,
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export type DecimalTypeInfo = {
|
|
228
|
+
id: "DECIMAL",
|
|
229
|
+
alias?: string,
|
|
230
|
+
sql_type: string,
|
|
231
|
+
width: number,
|
|
232
|
+
scale: number,
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export type EnumTypeInfo = {
|
|
236
|
+
id: "ENUM",
|
|
237
|
+
alias?: string,
|
|
238
|
+
sql_type: string,
|
|
239
|
+
name: string,
|
|
240
|
+
values: string[],
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export type TypeInfoChildren = { name: string, type: TypeInfo }[];
|
|
244
|
+
|
|
245
|
+
export type TypeInfo = GenericTypeInfo | StructTypeInfo | ListTypeInfo | MapTypeInfo | UnionTypeInfo | DecimalTypeInfo | EnumTypeInfo;
|
|
246
|
+
|
|
247
|
+
export type ColumnInfo = { name: string, type: TypeInfo };
|
|
248
|
+
|
|
249
|
+
export class Statement {
|
|
250
|
+
sql: string;
|
|
251
|
+
|
|
252
|
+
constructor(connection: Connection, sql: string);
|
|
253
|
+
|
|
254
|
+
all(...args: [...any, Callback<TableData>] | any[]): this;
|
|
255
|
+
|
|
256
|
+
arrowIPCAll(...args: [...any, Callback<ArrowArray>] | any[]): void;
|
|
257
|
+
|
|
258
|
+
each(...args: [...any, Callback<RowData>] | any[]): this;
|
|
259
|
+
|
|
260
|
+
finalize(callback?: Callback<void>): void;
|
|
261
|
+
|
|
262
|
+
run(...args: [...any, Callback<void>] | any[]): Statement;
|
|
263
|
+
|
|
264
|
+
columns(): ColumnInfo[];
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export const ERROR: number;
|
|
268
|
+
|
|
269
|
+
export const OPEN_CREATE: number;
|
|
270
|
+
|
|
271
|
+
export const OPEN_FULLMUTEX: number;
|
|
272
|
+
|
|
273
|
+
export const OPEN_PRIVATECACHE: number;
|
|
274
|
+
|
|
275
|
+
export const OPEN_READONLY: number;
|
|
276
|
+
|
|
277
|
+
export const OPEN_READWRITE: number;
|
|
278
|
+
|
|
279
|
+
export const OPEN_SHAREDCACHE: number;
|
|
280
|
+
|
|
281
|
+
export const INTERRUPT: number;
|
package/lib/duckdb.js
ADDED
|
@@ -0,0 +1,763 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module duckdb
|
|
3
|
+
* @summary DuckDB is an embeddable SQL OLAP Database Management System
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
var duckdb = require('./duckdb-binding.js');
|
|
7
|
+
module.exports = exports = duckdb;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Check that errno attribute equals this to check for a duckdb error
|
|
11
|
+
* @constant {number}
|
|
12
|
+
*/
|
|
13
|
+
var ERROR = duckdb.ERROR;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Open database in readonly mode
|
|
17
|
+
* @constant {number}
|
|
18
|
+
*/
|
|
19
|
+
var OPEN_READONLY = duckdb.OPEN_READONLY;
|
|
20
|
+
/**
|
|
21
|
+
* Currently ignored
|
|
22
|
+
* @constant {number}
|
|
23
|
+
*/
|
|
24
|
+
var OPEN_READWRITE = duckdb.OPEN_READWRITE;
|
|
25
|
+
/**
|
|
26
|
+
* Currently ignored
|
|
27
|
+
* @constant {number}
|
|
28
|
+
*/
|
|
29
|
+
var OPEN_CREATE = duckdb.OPEN_CREATE;
|
|
30
|
+
/**
|
|
31
|
+
* Currently ignored
|
|
32
|
+
* @constant {number}
|
|
33
|
+
*/
|
|
34
|
+
var OPEN_FULLMUTEX = duckdb.OPEN_FULLMUTEX;
|
|
35
|
+
/**
|
|
36
|
+
* Currently ignored
|
|
37
|
+
* @constant {number}
|
|
38
|
+
*/
|
|
39
|
+
var OPEN_SHAREDCACHE = duckdb.OPEN_SHAREDCACHE;
|
|
40
|
+
/**
|
|
41
|
+
* Currently ignored
|
|
42
|
+
* @constant {number}
|
|
43
|
+
*/
|
|
44
|
+
var OPEN_PRIVATECACHE = duckdb.OPEN_PRIVATECACHE;
|
|
45
|
+
|
|
46
|
+
// some wrappers for compatibilities sake
|
|
47
|
+
/**
|
|
48
|
+
* Main database interface
|
|
49
|
+
* @arg path - path to database file or :memory: for in-memory database
|
|
50
|
+
* @arg access_mode - access mode
|
|
51
|
+
* @arg config - the configuration object
|
|
52
|
+
* @arg callback - callback function
|
|
53
|
+
*/
|
|
54
|
+
var Database = duckdb.Database;
|
|
55
|
+
/**
|
|
56
|
+
* @class
|
|
57
|
+
*/
|
|
58
|
+
var Connection = duckdb.Connection;
|
|
59
|
+
/**
|
|
60
|
+
* @class
|
|
61
|
+
*/
|
|
62
|
+
var Statement = duckdb.Statement;
|
|
63
|
+
/**
|
|
64
|
+
* @class
|
|
65
|
+
*/
|
|
66
|
+
var QueryResult = duckdb.QueryResult;
|
|
67
|
+
/**
|
|
68
|
+
* Types of tokens return by `tokenize`.
|
|
69
|
+
*/
|
|
70
|
+
var TokenType = duckdb.TokenType;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @method
|
|
74
|
+
* @return data chunk
|
|
75
|
+
*/
|
|
76
|
+
QueryResult.prototype.nextChunk;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Function to fetch the next result blob of an Arrow IPC Stream in a zero-copy way.
|
|
80
|
+
* (requires arrow extension to be loaded)
|
|
81
|
+
*
|
|
82
|
+
* @method
|
|
83
|
+
* @return data chunk
|
|
84
|
+
*/
|
|
85
|
+
QueryResult.prototype.nextIpcBuffer;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @name asyncIterator
|
|
89
|
+
* @memberof module:duckdb~QueryResult
|
|
90
|
+
* @method
|
|
91
|
+
* @instance
|
|
92
|
+
* @yields data chunks
|
|
93
|
+
*/
|
|
94
|
+
QueryResult.prototype[Symbol.asyncIterator] = async function*() {
|
|
95
|
+
let prefetch = this.nextChunk();
|
|
96
|
+
while (true) {
|
|
97
|
+
const chunk = await prefetch;
|
|
98
|
+
// Null chunk indicates end of stream
|
|
99
|
+
if (!chunk) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// Prefetch the next chunk while we're iterating
|
|
103
|
+
prefetch = this.nextChunk();
|
|
104
|
+
for (const row of chunk) {
|
|
105
|
+
yield row;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Run a SQL statement and trigger a callback when done
|
|
113
|
+
* @arg sql
|
|
114
|
+
* @param {...*} params
|
|
115
|
+
* @param callback
|
|
116
|
+
* @return {void}
|
|
117
|
+
*/
|
|
118
|
+
Connection.prototype.run = function (sql) {
|
|
119
|
+
var statement = new Statement(this, sql);
|
|
120
|
+
return statement.run.apply(statement, arguments);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Run a SQL query and triggers the callback once for all result rows
|
|
125
|
+
* @arg sql
|
|
126
|
+
* @param {...*} params
|
|
127
|
+
* @param callback
|
|
128
|
+
* @return {void}
|
|
129
|
+
*/
|
|
130
|
+
Connection.prototype.all = function (sql) {
|
|
131
|
+
var statement = new Statement(this, sql);
|
|
132
|
+
return statement.all.apply(statement, arguments);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Utility class for streaming Apache Arrow IPC
|
|
136
|
+
class IpcResultStreamIterator {
|
|
137
|
+
constructor(stream_result_p) {
|
|
138
|
+
this._depleted = false;
|
|
139
|
+
this.stream_result = stream_result_p;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async next() {
|
|
143
|
+
if (this._depleted) {
|
|
144
|
+
return { done: true, value: null };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const ipc_raw = await this.stream_result.nextIpcBuffer();
|
|
148
|
+
const res = new Uint8Array(ipc_raw);
|
|
149
|
+
|
|
150
|
+
this._depleted = res.length == 0;
|
|
151
|
+
return {
|
|
152
|
+
done: this._depleted,
|
|
153
|
+
value: res,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
[Symbol.asyncIterator]() {
|
|
158
|
+
return this;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Materialize the IPC stream into a list of Uint8Arrays
|
|
162
|
+
async toArray () {
|
|
163
|
+
const retval = []
|
|
164
|
+
|
|
165
|
+
for await (const ipc_buf of this) {
|
|
166
|
+
retval.push(ipc_buf);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Push EOS message containing 4 bytes of 0
|
|
170
|
+
retval.push(new Uint8Array([0,0,0,0]));
|
|
171
|
+
|
|
172
|
+
return retval;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Run a SQL query and serialize the result into the Apache Arrow IPC format (requires arrow extension to be loaded)
|
|
178
|
+
* @arg sql
|
|
179
|
+
* @param {...*} params
|
|
180
|
+
* @param callback
|
|
181
|
+
* @return {void}
|
|
182
|
+
*/
|
|
183
|
+
Connection.prototype.arrowIPCAll = function (sql) {
|
|
184
|
+
const query = "SELECT * FROM to_arrow_ipc((" + sql + "));";
|
|
185
|
+
var statement = new Statement(this, query);
|
|
186
|
+
return statement.arrowIPCAll.apply(statement, arguments);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Run a SQL query, returns a IpcResultStreamIterator that allows streaming the result into the Apache Arrow IPC format
|
|
191
|
+
* (requires arrow extension to be loaded)
|
|
192
|
+
*
|
|
193
|
+
* @arg sql
|
|
194
|
+
* @param {...*} params
|
|
195
|
+
* @param callback
|
|
196
|
+
* @return Promise<IpcResultStreamIterator>
|
|
197
|
+
*/
|
|
198
|
+
Connection.prototype.arrowIPCStream = async function (sql) {
|
|
199
|
+
const query = "SELECT * FROM to_arrow_ipc((" + sql + "));";
|
|
200
|
+
const statement = new Statement(this, query);
|
|
201
|
+
return new IpcResultStreamIterator(await statement.stream.apply(statement, arguments));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Runs a SQL query and triggers the callback for each result row
|
|
206
|
+
* @arg sql
|
|
207
|
+
* @param {...*} params
|
|
208
|
+
* @param callback
|
|
209
|
+
* @return {void}
|
|
210
|
+
*/
|
|
211
|
+
Connection.prototype.each = function (sql) {
|
|
212
|
+
var statement = new Statement(this, sql);
|
|
213
|
+
return statement.each.apply(statement, arguments);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* @arg sql
|
|
218
|
+
* @param {...*} params
|
|
219
|
+
* @yields row chunks
|
|
220
|
+
*/
|
|
221
|
+
Connection.prototype.stream = async function* (sql) {
|
|
222
|
+
const statement = new Statement(this, sql);
|
|
223
|
+
const queryResult = await statement.stream.apply(statement, arguments);
|
|
224
|
+
for await (const result of queryResult) {
|
|
225
|
+
yield result;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Register a User Defined Function
|
|
231
|
+
*
|
|
232
|
+
* @arg name
|
|
233
|
+
* @arg return_type
|
|
234
|
+
* @arg fun
|
|
235
|
+
* @return {void}
|
|
236
|
+
* @note this follows the wasm udfs somewhat but is simpler because we can pass data much more cleanly
|
|
237
|
+
*/
|
|
238
|
+
Connection.prototype.register_udf = function (name, return_type, fun) {
|
|
239
|
+
// TODO what if this throws an error somewhere? do we need a try/catch?
|
|
240
|
+
return this.register_udf_bulk(name, return_type, function (desc) {
|
|
241
|
+
try {
|
|
242
|
+
// Build an argument resolver
|
|
243
|
+
const buildResolver = (arg) => {
|
|
244
|
+
let validity = arg.validity || null;
|
|
245
|
+
switch (arg.physicalType) {
|
|
246
|
+
case 'STRUCT': {
|
|
247
|
+
const tmp = {};
|
|
248
|
+
const children = [];
|
|
249
|
+
for (let j = 0; j < (arg.children.length || 0); ++j) {
|
|
250
|
+
const attr = arg.children[j];
|
|
251
|
+
const child = buildResolver(attr);
|
|
252
|
+
children.push((row) => {
|
|
253
|
+
tmp[attr.name] = child(row);
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
if (validity != null) {
|
|
257
|
+
return (row) => {
|
|
258
|
+
if (!validity[row]) {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
for (const resolver of children) {
|
|
262
|
+
resolver(row);
|
|
263
|
+
}
|
|
264
|
+
return tmp;
|
|
265
|
+
};
|
|
266
|
+
} else {
|
|
267
|
+
return (row) => {
|
|
268
|
+
for (const resolver of children) {
|
|
269
|
+
resolver(row);
|
|
270
|
+
}
|
|
271
|
+
return tmp;
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
default: {
|
|
276
|
+
if (arg.data === undefined) {
|
|
277
|
+
throw new Error(
|
|
278
|
+
'malformed data view, expected data buffer for argument of type: ' + arg.physicalType,
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
const data = arg.data;
|
|
282
|
+
if (validity != null) {
|
|
283
|
+
return (row) => (!validity[row] ? null : data[row]);
|
|
284
|
+
} else {
|
|
285
|
+
return (row) => data[row];
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
// Translate argument data
|
|
292
|
+
const argResolvers = [];
|
|
293
|
+
for (let i = 0; i < desc.args.length; ++i) {
|
|
294
|
+
argResolvers.push(buildResolver(desc.args[i]));
|
|
295
|
+
}
|
|
296
|
+
const args = [];
|
|
297
|
+
for (let i = 0; i < desc.args.length; ++i) {
|
|
298
|
+
args.push(null);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Return type
|
|
302
|
+
desc.ret.validity = new Uint8Array(desc.rows);
|
|
303
|
+
switch (desc.ret.physicalType) {
|
|
304
|
+
case 'INT8':
|
|
305
|
+
desc.ret.data = new Int8Array(desc.rows);
|
|
306
|
+
break;
|
|
307
|
+
case 'INT16':
|
|
308
|
+
desc.ret.data = new Int16Array(desc.rows);
|
|
309
|
+
break;
|
|
310
|
+
case 'INT32':
|
|
311
|
+
desc.ret.data = new Int32Array(desc.rows);
|
|
312
|
+
break;
|
|
313
|
+
case 'DOUBLE':
|
|
314
|
+
desc.ret.data = new Float64Array(desc.rows);
|
|
315
|
+
break;
|
|
316
|
+
case 'DATE64':
|
|
317
|
+
case 'TIME64':
|
|
318
|
+
case 'TIMESTAMP':
|
|
319
|
+
case 'INT64':
|
|
320
|
+
desc.ret.data = new BigInt64Array(desc.rows);
|
|
321
|
+
break;
|
|
322
|
+
case 'UINT64':
|
|
323
|
+
desc.ret.data = new BigUint64Array(desc.rows);
|
|
324
|
+
break;
|
|
325
|
+
case 'BLOB':
|
|
326
|
+
case 'VARCHAR':
|
|
327
|
+
desc.ret.data = new Array(desc.rows);
|
|
328
|
+
break;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Call the function
|
|
332
|
+
for (let i = 0; i < desc.rows; ++i) {
|
|
333
|
+
for (let j = 0; j < desc.args.length; ++j) {
|
|
334
|
+
args[j] = argResolvers[j](i);
|
|
335
|
+
}
|
|
336
|
+
const res = fun(...args);
|
|
337
|
+
desc.ret.data[i] = res;
|
|
338
|
+
desc.ret.validity[i] = res === undefined || res === null ? 0 : 1;
|
|
339
|
+
}
|
|
340
|
+
} catch (error) { // work around recently fixed napi bug https://github.com/nodejs/node-addon-api/issues/912
|
|
341
|
+
msg = error;
|
|
342
|
+
if (typeof error == 'object' && 'message' in error) {
|
|
343
|
+
msg = error.message
|
|
344
|
+
}
|
|
345
|
+
throw { name: 'DuckDB-UDF-Exception', message: msg };
|
|
346
|
+
}
|
|
347
|
+
})
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Prepare a SQL query for execution
|
|
352
|
+
* @method
|
|
353
|
+
* @arg sql
|
|
354
|
+
* @param {...*} params
|
|
355
|
+
* @param callback
|
|
356
|
+
* @return {Statement}
|
|
357
|
+
*/
|
|
358
|
+
Connection.prototype.prepare;
|
|
359
|
+
/**
|
|
360
|
+
* Execute a SQL query
|
|
361
|
+
* @method
|
|
362
|
+
* @arg sql
|
|
363
|
+
* @param {...*} params
|
|
364
|
+
* @param callback
|
|
365
|
+
* @return {void}
|
|
366
|
+
*/
|
|
367
|
+
Connection.prototype.exec;
|
|
368
|
+
/**
|
|
369
|
+
* Register a User Defined Function
|
|
370
|
+
*
|
|
371
|
+
* @method
|
|
372
|
+
* @arg name
|
|
373
|
+
* @arg return_type
|
|
374
|
+
* @param callback
|
|
375
|
+
* @return {void}
|
|
376
|
+
*/
|
|
377
|
+
Connection.prototype.register_udf_bulk;
|
|
378
|
+
/**
|
|
379
|
+
* Unregister a User Defined Function
|
|
380
|
+
*
|
|
381
|
+
* @method
|
|
382
|
+
* @arg name
|
|
383
|
+
* @arg return_type
|
|
384
|
+
* @param callback
|
|
385
|
+
* @return {void}
|
|
386
|
+
*/
|
|
387
|
+
Connection.prototype.unregister_udf;
|
|
388
|
+
|
|
389
|
+
var default_connection = function (o) {
|
|
390
|
+
if (o.default_connection == undefined) {
|
|
391
|
+
o.default_connection = new duckdb.Connection(o);
|
|
392
|
+
}
|
|
393
|
+
return o.default_connection;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Register a Buffer to be scanned using the Apache Arrow IPC scanner
|
|
398
|
+
* (requires arrow extension to be loaded)
|
|
399
|
+
*
|
|
400
|
+
* @method
|
|
401
|
+
* @arg name
|
|
402
|
+
* @arg array
|
|
403
|
+
* @arg force
|
|
404
|
+
* @param callback
|
|
405
|
+
* @return {void}
|
|
406
|
+
*/
|
|
407
|
+
Connection.prototype.register_buffer;
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Unregister the Buffer
|
|
411
|
+
*
|
|
412
|
+
* @method
|
|
413
|
+
* @arg name
|
|
414
|
+
* @param callback
|
|
415
|
+
* @return {void}
|
|
416
|
+
*/
|
|
417
|
+
Connection.prototype.unregister_buffer;
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Closes connection
|
|
421
|
+
* @method
|
|
422
|
+
* @param callback
|
|
423
|
+
* @return {void}
|
|
424
|
+
*/
|
|
425
|
+
Connection.prototype.close;
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Closes database instance
|
|
429
|
+
* @method
|
|
430
|
+
* @param callback
|
|
431
|
+
* @return {void}
|
|
432
|
+
*/
|
|
433
|
+
Database.prototype.close = function() {
|
|
434
|
+
if (this.default_connection) {
|
|
435
|
+
this.default_connection.close(); // this queues up a job in the internals, which blocks the below close call
|
|
436
|
+
this.default_connection = null;
|
|
437
|
+
}
|
|
438
|
+
this.close_internal.apply(this, arguments);
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Internal method. Do not use, call Connection#close instead
|
|
443
|
+
* @method
|
|
444
|
+
* @param callback
|
|
445
|
+
* @return {void}
|
|
446
|
+
*/
|
|
447
|
+
Database.prototype.close_internal;
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Triggers callback when all scheduled database tasks have completed.
|
|
451
|
+
* @method
|
|
452
|
+
* @param callback
|
|
453
|
+
* @return {void}
|
|
454
|
+
*/
|
|
455
|
+
Database.prototype.wait;
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Currently a no-op. Provided for SQLite compatibility
|
|
459
|
+
* @method
|
|
460
|
+
* @param callback
|
|
461
|
+
* @return {void}
|
|
462
|
+
*/
|
|
463
|
+
Database.prototype.serialize;
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Currently a no-op. Provided for SQLite compatibility
|
|
467
|
+
* @method
|
|
468
|
+
* @param callback
|
|
469
|
+
* @return {void}
|
|
470
|
+
*/
|
|
471
|
+
Database.prototype.parallelize;
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Create a new database connection
|
|
475
|
+
* @method
|
|
476
|
+
* @arg path the database to connect to, either a file path, or `:memory:`
|
|
477
|
+
* @return {Connection}
|
|
478
|
+
*/
|
|
479
|
+
Database.prototype.connect;
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Supposedly interrupt queries, but currently does not do anything.
|
|
483
|
+
* @method
|
|
484
|
+
* @param callback
|
|
485
|
+
* @return {void}
|
|
486
|
+
*/
|
|
487
|
+
Database.prototype.interrupt;
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Prepare a SQL query for execution
|
|
491
|
+
* @arg sql
|
|
492
|
+
* @return {Statement}
|
|
493
|
+
*/
|
|
494
|
+
Database.prototype.prepare = function () {
|
|
495
|
+
return default_connection(this).prepare.apply(this.default_connection, arguments);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Convenience method for Connection#run using a built-in default connection
|
|
500
|
+
* @arg sql
|
|
501
|
+
* @param {...*} params
|
|
502
|
+
* @param callback
|
|
503
|
+
* @return {void}
|
|
504
|
+
*/
|
|
505
|
+
Database.prototype.run = function () {
|
|
506
|
+
default_connection(this).run.apply(this.default_connection, arguments);
|
|
507
|
+
return this;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Convenience method for Connection#scanArrowIpc using a built-in default connection
|
|
512
|
+
* @arg sql
|
|
513
|
+
* @param {...*} params
|
|
514
|
+
* @param callback
|
|
515
|
+
* @return {void}
|
|
516
|
+
*/
|
|
517
|
+
Database.prototype.scanArrowIpc = function () {
|
|
518
|
+
default_connection(this).scanArrowIpc.apply(this.default_connection, arguments);
|
|
519
|
+
return this;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* @arg sql
|
|
524
|
+
* @param {...*} params
|
|
525
|
+
* @param callback
|
|
526
|
+
* @return {void}
|
|
527
|
+
*/
|
|
528
|
+
Database.prototype.each = function () {
|
|
529
|
+
default_connection(this).each.apply(this.default_connection, arguments);
|
|
530
|
+
return this;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* @arg sql
|
|
536
|
+
* @param {...*} params
|
|
537
|
+
* @yields row chunks
|
|
538
|
+
*/
|
|
539
|
+
Database.prototype.stream = function() {
|
|
540
|
+
return default_connection(this).stream.apply(this.default_connection, arguments);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Convenience method for Connection#apply using a built-in default connection
|
|
546
|
+
* @arg sql
|
|
547
|
+
* @param {...*} params
|
|
548
|
+
* @param callback
|
|
549
|
+
* @return {void}
|
|
550
|
+
*/
|
|
551
|
+
Database.prototype.all = function () {
|
|
552
|
+
default_connection(this).all.apply(this.default_connection, arguments);
|
|
553
|
+
return this;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* Convenience method for Connection#arrowIPCAll using a built-in default connection
|
|
558
|
+
* @arg sql
|
|
559
|
+
* @param {...*} params
|
|
560
|
+
* @param callback
|
|
561
|
+
* @return {void}
|
|
562
|
+
*/
|
|
563
|
+
Database.prototype.arrowIPCAll = function () {
|
|
564
|
+
default_connection(this).arrowIPCAll.apply(this.default_connection, arguments);
|
|
565
|
+
return this;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Convenience method for Connection#arrowIPCStream using a built-in default connection
|
|
570
|
+
* @arg sql
|
|
571
|
+
* @param {...*} params
|
|
572
|
+
* @param callback
|
|
573
|
+
* @return {void}
|
|
574
|
+
*/
|
|
575
|
+
Database.prototype.arrowIPCStream = function () {
|
|
576
|
+
return default_connection(this).arrowIPCStream.apply(this.default_connection, arguments);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* @arg sql
|
|
581
|
+
* @param {...*} params
|
|
582
|
+
* @param callback
|
|
583
|
+
* @return {void}
|
|
584
|
+
*/
|
|
585
|
+
Database.prototype.exec = function () {
|
|
586
|
+
default_connection(this).exec.apply(this.default_connection, arguments);
|
|
587
|
+
return this;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* Register a User Defined Function
|
|
592
|
+
*
|
|
593
|
+
* Convenience method for Connection#register_udf
|
|
594
|
+
* @arg name
|
|
595
|
+
* @arg return_type
|
|
596
|
+
* @arg fun
|
|
597
|
+
* @return {this}
|
|
598
|
+
*/
|
|
599
|
+
Database.prototype.register_udf = function () {
|
|
600
|
+
default_connection(this).register_udf.apply(this.default_connection, arguments);
|
|
601
|
+
return this;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Register a buffer containing serialized data to be scanned from DuckDB.
|
|
606
|
+
*
|
|
607
|
+
* Convenience method for Connection#unregister_buffer
|
|
608
|
+
* @arg name
|
|
609
|
+
* @return {this}
|
|
610
|
+
*/
|
|
611
|
+
Database.prototype.register_buffer = function () {
|
|
612
|
+
default_connection(this).register_buffer.apply(this.default_connection, arguments);
|
|
613
|
+
return this;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Unregister a Buffer
|
|
618
|
+
*
|
|
619
|
+
* Convenience method for Connection#unregister_buffer
|
|
620
|
+
* @arg name
|
|
621
|
+
* @return {this}
|
|
622
|
+
*/
|
|
623
|
+
Database.prototype.unregister_buffer = function () {
|
|
624
|
+
default_connection(this).unregister_buffer.apply(this.default_connection, arguments);
|
|
625
|
+
return this;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Unregister a UDF
|
|
630
|
+
*
|
|
631
|
+
* Convenience method for Connection#unregister_udf
|
|
632
|
+
* @arg name
|
|
633
|
+
* @return {this}
|
|
634
|
+
*/
|
|
635
|
+
Database.prototype.unregister_udf = function () {
|
|
636
|
+
default_connection(this).unregister_udf.apply(this.default_connection, arguments);
|
|
637
|
+
return this;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* Register a table replace scan function
|
|
642
|
+
* @method
|
|
643
|
+
* @arg fun Replacement scan function
|
|
644
|
+
* @return {this}
|
|
645
|
+
*/
|
|
646
|
+
|
|
647
|
+
Database.prototype.registerReplacementScan;
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* Return positions and types of tokens in given text
|
|
651
|
+
* @method
|
|
652
|
+
* @arg text
|
|
653
|
+
* @return {ScriptTokens}
|
|
654
|
+
*/
|
|
655
|
+
Database.prototype.tokenize;
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Not implemented
|
|
659
|
+
*/
|
|
660
|
+
Database.prototype.get = function () {
|
|
661
|
+
throw "get() is not implemented because it's evil";
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
/**
|
|
665
|
+
* Not implemented
|
|
666
|
+
*/
|
|
667
|
+
Statement.prototype.get = function () {
|
|
668
|
+
throw "get() is not implemented because it's evil";
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* @method
|
|
673
|
+
* @arg sql
|
|
674
|
+
* @param {...*} params
|
|
675
|
+
* @param callback
|
|
676
|
+
* @return {void}
|
|
677
|
+
*/
|
|
678
|
+
Statement.prototype.run;
|
|
679
|
+
/**
|
|
680
|
+
* @method
|
|
681
|
+
* @arg sql
|
|
682
|
+
* @param {...*} params
|
|
683
|
+
* @param callback
|
|
684
|
+
* @return {void}
|
|
685
|
+
*/
|
|
686
|
+
Statement.prototype.all;
|
|
687
|
+
/**
|
|
688
|
+
* @method
|
|
689
|
+
* @arg sql
|
|
690
|
+
* @param {...*} params
|
|
691
|
+
* @param callback
|
|
692
|
+
* @return {void}
|
|
693
|
+
*/
|
|
694
|
+
Statement.prototype.arrowIPCAll;
|
|
695
|
+
/**
|
|
696
|
+
* @method
|
|
697
|
+
* @arg sql
|
|
698
|
+
* @param {...*} params
|
|
699
|
+
* @param callback
|
|
700
|
+
* @return {void}
|
|
701
|
+
*/
|
|
702
|
+
Statement.prototype.each;
|
|
703
|
+
/**
|
|
704
|
+
* @method
|
|
705
|
+
* @arg sql
|
|
706
|
+
* @param {...*} params
|
|
707
|
+
* @param callback
|
|
708
|
+
* @return {void}
|
|
709
|
+
*/
|
|
710
|
+
Statement.prototype.finalize
|
|
711
|
+
/**
|
|
712
|
+
* @method
|
|
713
|
+
* @arg sql
|
|
714
|
+
* @param {...*} params
|
|
715
|
+
* @yield callback
|
|
716
|
+
*/
|
|
717
|
+
Statement.prototype.stream;
|
|
718
|
+
|
|
719
|
+
/**
|
|
720
|
+
* @field
|
|
721
|
+
* @returns sql contained in statement
|
|
722
|
+
*/
|
|
723
|
+
Statement.prototype.sql;
|
|
724
|
+
|
|
725
|
+
/**
|
|
726
|
+
* @method
|
|
727
|
+
* @return {ColumnInfo[]} - Array of column names and types
|
|
728
|
+
*/
|
|
729
|
+
Statement.prototype.columns;
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* @typedef ColumnInfo
|
|
733
|
+
* @type {object}
|
|
734
|
+
* @property {string} name - Column name
|
|
735
|
+
* @property {TypeInfo} type - Column type
|
|
736
|
+
*/
|
|
737
|
+
|
|
738
|
+
/**
|
|
739
|
+
* @typedef TypeInfo
|
|
740
|
+
* @type {object}
|
|
741
|
+
* @property {string} id - Type ID
|
|
742
|
+
* @property {string} [alias] - SQL type alias
|
|
743
|
+
* @property {string} sql_type - SQL type name
|
|
744
|
+
*/
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* @typedef DuckDbError
|
|
748
|
+
* @type {object}
|
|
749
|
+
* @property {number} errno - -1 for DuckDB errors
|
|
750
|
+
* @property {string} message - Error message
|
|
751
|
+
* @property {string} code - 'DUCKDB_NODEJS_ERROR' for DuckDB errors
|
|
752
|
+
* @property {string} errorType - DuckDB error type code (eg, HTTP, IO, Catalog)
|
|
753
|
+
*/
|
|
754
|
+
|
|
755
|
+
/**
|
|
756
|
+
* @typedef HTTPError
|
|
757
|
+
* @type {object}
|
|
758
|
+
* @extends {DuckDbError}
|
|
759
|
+
* @property {number} statusCode - HTTP response status code
|
|
760
|
+
* @property {string} reason - HTTP response reason
|
|
761
|
+
* @property {string} response - HTTP response body
|
|
762
|
+
* @property {object} headers - HTTP headers
|
|
763
|
+
*/
|
package/lib/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./duckdb');
|
package/package.json
CHANGED
|
@@ -1,6 +1,46 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ohos-ports/duckdb",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.4.2-beta.0",
|
|
4
|
+
"description": "DuckDB node.js API (HarmonyOS openharmony/arm64 port with vendored prebuilt native binding; companion package of @ohos-ports/duckdb-async)",
|
|
5
|
+
"main": "./lib/duckdb.js",
|
|
6
|
+
"types": "./lib/duckdb.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"lib",
|
|
9
|
+
"duckdb.js",
|
|
10
|
+
"LICENSE",
|
|
11
|
+
"README.md"
|
|
12
|
+
],
|
|
13
|
+
"os": [
|
|
14
|
+
"openharmony"
|
|
15
|
+
],
|
|
16
|
+
"cpu": [
|
|
17
|
+
"arm64"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {},
|
|
20
|
+
"dependencies": {},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/ohos-ports/ohos-ports.git",
|
|
24
|
+
"directory": "ports/duckdb/1.4.2"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"database",
|
|
28
|
+
"sql",
|
|
29
|
+
"duckdb",
|
|
30
|
+
"openharmony",
|
|
31
|
+
"harmonyos"
|
|
32
|
+
],
|
|
33
|
+
"author": "Hannes Mühleisen",
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/ohos-ports/ohos-ports/issues"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/ohos-ports/ohos-ports/tree/main/ports/duckdb/1.4.2",
|
|
39
|
+
"ohos-ports": {
|
|
40
|
+
"upstream": "duckdb@1.4.2",
|
|
41
|
+
"platform": "openharmony",
|
|
42
|
+
"arch": "arm64",
|
|
43
|
+
"native_artifact": "lib/binding/duckdb.node",
|
|
44
|
+
"content_delta": "statement.cpp each()-completion persistent-handle fix + exception hardening, compiled from source for openharmony/arm64 and signed; binding vendored in lib/binding (no node-pre-gyp download at install time)"
|
|
45
|
+
}
|
|
46
|
+
}
|