remult 3.0.0 → 3.0.2
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.
|
@@ -36,7 +36,7 @@ export async function generateMigrations(options) {
|
|
|
36
36
|
const code = {
|
|
37
37
|
//https://marketplace.visualstudio.com/items?itemName=qufiwefefwoyn.inline-sql-syntax
|
|
38
38
|
addSql: (sql) => {
|
|
39
|
-
steps.push('await sql(`--sql\n' + sql + '`)');
|
|
39
|
+
steps.push('await sql(`--sql\n' + escapeForTpl(sql) + '`)');
|
|
40
40
|
hasSql = true;
|
|
41
41
|
},
|
|
42
42
|
addTypescriptCode: (code) => steps.push(code),
|
|
@@ -66,3 +66,7 @@ export async function generateMigrations(options) {
|
|
|
66
66
|
}
|
|
67
67
|
return steps.length > 0;
|
|
68
68
|
}
|
|
69
|
+
function escapeForTpl(str) {
|
|
70
|
+
// escape backticks, dollar-signs and backslashes
|
|
71
|
+
return str.replace(/[`\\$]/g, (m) => "\\" + m);
|
|
72
|
+
}
|
package/esm/remult-duckdb.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import { DuckDBTypeId } from '@duckdb/node-api';
|
|
1
2
|
import { SqliteCoreDataProvider } from './remult-sqlite-core.js';
|
|
2
3
|
import { ValueConverters, dbNamesOf, } from './index.js';
|
|
3
4
|
import { shouldNotCreateField } from './src/filter/filter-consumer-bridge-to-sql-request.js';
|
|
4
5
|
import { isAutoIncrement } from './src/remult3/RepositoryImplementation.js';
|
|
5
6
|
export class DuckDBDataProvider extends SqliteCoreDataProvider {
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
connection;
|
|
8
|
+
constructor(connection) {
|
|
9
|
+
super(() => new DuckDBCommand(this.connection), async () => this.connection.disconnectSync(), false, true);
|
|
10
|
+
this.connection = connection;
|
|
8
11
|
}
|
|
9
12
|
wrapIdentifier(name) {
|
|
10
13
|
return `"${name}"`;
|
|
@@ -12,7 +15,8 @@ export class DuckDBDataProvider extends SqliteCoreDataProvider {
|
|
|
12
15
|
async getCreateTableSql(entity) {
|
|
13
16
|
let result = '';
|
|
14
17
|
let e = await dbNamesOf(entity, this.wrapIdentifier);
|
|
15
|
-
|
|
18
|
+
const createSequenceStatements = [];
|
|
19
|
+
let createTableSql = '';
|
|
16
20
|
for (const x of entity.fields) {
|
|
17
21
|
if (!shouldNotCreateField(x, e) || isAutoIncrement(x)) {
|
|
18
22
|
if (result.length != 0)
|
|
@@ -20,7 +24,7 @@ export class DuckDBDataProvider extends SqliteCoreDataProvider {
|
|
|
20
24
|
result += '\r\n ';
|
|
21
25
|
if (isAutoIncrement(x)) {
|
|
22
26
|
const sequenceName = `${entity.dbName}_${x.dbName}_seq`;
|
|
23
|
-
|
|
27
|
+
createSequenceStatements.push(`create sequence if not exists "${sequenceName}";`);
|
|
24
28
|
result += `${e.$dbNameOf(x)} integer default nextval('${sequenceName}')`;
|
|
25
29
|
}
|
|
26
30
|
else {
|
|
@@ -31,9 +35,9 @@ export class DuckDBDataProvider extends SqliteCoreDataProvider {
|
|
|
31
35
|
result += `,\r\n primary key (${entity.idMetadata.fields
|
|
32
36
|
.map((f) => e.$dbNameOf(f))
|
|
33
37
|
.join(',')})`;
|
|
34
|
-
|
|
38
|
+
createTableSql =
|
|
35
39
|
'create table if not exists ' + e.$entityName + ' (' + result + '\r\n)';
|
|
36
|
-
return [
|
|
40
|
+
return [...createSequenceStatements, createTableSql];
|
|
37
41
|
}
|
|
38
42
|
addColumnSqlSyntax(x, dbName, isAlterColumn) {
|
|
39
43
|
let result = dbName;
|
|
@@ -74,38 +78,83 @@ export class DuckDBDataProvider extends SqliteCoreDataProvider {
|
|
|
74
78
|
}
|
|
75
79
|
}
|
|
76
80
|
class DuckDBCommand {
|
|
77
|
-
|
|
81
|
+
connection;
|
|
78
82
|
values = [];
|
|
79
|
-
constructor(
|
|
80
|
-
this.
|
|
83
|
+
constructor(connection) {
|
|
84
|
+
this.connection = connection;
|
|
81
85
|
}
|
|
82
86
|
async execute(sql) {
|
|
83
|
-
|
|
84
|
-
this.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
try {
|
|
88
|
+
const result = await this.connection.run(sql, this.values);
|
|
89
|
+
this.values = [];
|
|
90
|
+
return new DuckDBSqlResult(result);
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
this.values = [];
|
|
94
|
+
throw err;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
addParamInternal(val) {
|
|
98
|
+
if (val === undefined) {
|
|
99
|
+
this.values.push(null);
|
|
100
|
+
}
|
|
101
|
+
else if (val instanceof Date) {
|
|
102
|
+
this.values.push(val.toISOString());
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
this.values.push(val);
|
|
106
|
+
}
|
|
107
|
+
return '?';
|
|
91
108
|
}
|
|
92
109
|
addParameterAndReturnSqlToken(val) {
|
|
93
|
-
return this.
|
|
110
|
+
return this.addParamInternal(val);
|
|
94
111
|
}
|
|
95
112
|
param(val) {
|
|
96
|
-
|
|
97
|
-
this.values.push(val);
|
|
98
|
-
return key;
|
|
113
|
+
return this.addParamInternal(val);
|
|
99
114
|
}
|
|
100
115
|
}
|
|
101
116
|
class DuckDBSqlResult {
|
|
102
|
-
|
|
103
|
-
constructor(result) {
|
|
104
|
-
this.result = result;
|
|
105
|
-
this.rows = result;
|
|
106
|
-
}
|
|
117
|
+
duckDbResult;
|
|
107
118
|
rows;
|
|
119
|
+
constructor(duckDbResult) {
|
|
120
|
+
this.duckDbResult = duckDbResult;
|
|
121
|
+
this.rows = [];
|
|
122
|
+
const columnNames = this.duckDbResult.columnNames();
|
|
123
|
+
const columnTypes = this.duckDbResult.columnTypes();
|
|
124
|
+
const chunkCount = this.duckDbResult.chunkCount;
|
|
125
|
+
for (let i = 0; i < chunkCount; i++) {
|
|
126
|
+
const chunk = this.duckDbResult.getChunk(i);
|
|
127
|
+
const chunkRowObjects = chunk.getRowObjects(columnNames).map((row) => {
|
|
128
|
+
const convertedRow = {};
|
|
129
|
+
columnNames.forEach((colName, colIndex) => {
|
|
130
|
+
const value = row[colName];
|
|
131
|
+
if (value === null) {
|
|
132
|
+
convertedRow[colName] = null;
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
const colType = columnTypes[colIndex];
|
|
136
|
+
const typeId = colType.typeId;
|
|
137
|
+
if (typeId === DuckDBTypeId.TIMESTAMP) {
|
|
138
|
+
const timestampValue = value;
|
|
139
|
+
const parts = timestampValue.toParts();
|
|
140
|
+
convertedRow[colName] = new Date(Date.UTC(parts.date.year, parts.date.month - 1, parts.date.day, parts.time.hour, parts.time.min, parts.time.sec, Math.floor(parts.time.micros / 1000)));
|
|
141
|
+
}
|
|
142
|
+
else if (typeId === DuckDBTypeId.DATE) {
|
|
143
|
+
const dateValue = value;
|
|
144
|
+
const parts = dateValue.toParts();
|
|
145
|
+
convertedRow[colName] = new Date(Date.UTC(parts.year, parts.month - 1, parts.day));
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
convertedRow[colName] = value;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
return convertedRow;
|
|
153
|
+
});
|
|
154
|
+
this.rows.push(...chunkRowObjects);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
108
157
|
getColumnKeyInResultForIndexInSelect(index) {
|
|
109
|
-
return
|
|
158
|
+
return this.duckDbResult.columnName(index);
|
|
110
159
|
}
|
|
111
160
|
}
|
|
@@ -58,7 +58,7 @@ function generateMigrations(options) {
|
|
|
58
58
|
code = {
|
|
59
59
|
//https://marketplace.visualstudio.com/items?itemName=qufiwefefwoyn.inline-sql-syntax
|
|
60
60
|
addSql: function (sql) {
|
|
61
|
-
steps.push('await sql(`--sql\n' + sql + '`)');
|
|
61
|
+
steps.push('await sql(`--sql\n' + escapeForTpl(sql) + '`)');
|
|
62
62
|
hasSql = true;
|
|
63
63
|
},
|
|
64
64
|
addTypescriptCode: function (code) { return steps.push(code); },
|
|
@@ -101,3 +101,7 @@ function generateMigrations(options) {
|
|
|
101
101
|
});
|
|
102
102
|
});
|
|
103
103
|
}
|
|
104
|
+
function escapeForTpl(str) {
|
|
105
|
+
// escape backticks, dollar-signs and backslashes
|
|
106
|
+
return str.replace(/[`\\$]/g, function (m) { return "\\" + m; });
|
|
107
|
+
}
|
package/package.json
CHANGED
package/remult-duckdb.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DuckDBConnection } from '@duckdb/node-api';
|
|
2
2
|
import { SqliteCoreDataProvider } from './remult-sqlite-core.js';
|
|
3
3
|
import { type FieldMetadata, type EntityMetadata } from './index.js';
|
|
4
4
|
export declare class DuckDBDataProvider extends SqliteCoreDataProvider {
|
|
5
|
-
|
|
5
|
+
private connection;
|
|
6
|
+
constructor(connection: DuckDBConnection);
|
|
6
7
|
wrapIdentifier(name: string): string;
|
|
7
8
|
getCreateTableSql(entity: EntityMetadata<any>): Promise<string[]>;
|
|
8
9
|
addColumnSqlSyntax(x: FieldMetadata, dbName: string, isAlterColumn: boolean): string;
|
package/remult-duckdb.js
CHANGED
|
@@ -2,19 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DuckDBDataProvider = void 0;
|
|
4
4
|
var tslib_1 = require("tslib");
|
|
5
|
+
var node_api_1 = require("@duckdb/node-api");
|
|
5
6
|
var remult_sqlite_core_js_1 = require("./remult-sqlite-core.js");
|
|
6
7
|
var index_js_1 = require("./index.js");
|
|
7
8
|
var filter_consumer_bridge_to_sql_request_js_1 = require("./src/filter/filter-consumer-bridge-to-sql-request.js");
|
|
8
9
|
var RepositoryImplementation_js_1 = require("./src/remult3/RepositoryImplementation.js");
|
|
9
10
|
var DuckDBDataProvider = /** @class */ (function (_super) {
|
|
10
11
|
tslib_1.__extends(DuckDBDataProvider, _super);
|
|
11
|
-
function DuckDBDataProvider(
|
|
12
|
-
var _this = _super.call(this, function () { return new DuckDBCommand(
|
|
13
|
-
|
|
14
|
-
case 0: return [4 /*yield*/, db];
|
|
15
|
-
case 1: return [2 /*return*/, (_a.sent()).close()];
|
|
16
|
-
}
|
|
12
|
+
function DuckDBDataProvider(connection) {
|
|
13
|
+
var _this = _super.call(this, function () { return new DuckDBCommand(_this.connection); }, function () { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) {
|
|
14
|
+
return [2 /*return*/, this.connection.disconnectSync()];
|
|
17
15
|
}); }); }, false, true) || this;
|
|
16
|
+
_this.connection = connection;
|
|
18
17
|
return _this;
|
|
19
18
|
}
|
|
20
19
|
DuckDBDataProvider.prototype.wrapIdentifier = function (name) {
|
|
@@ -22,7 +21,7 @@ var DuckDBDataProvider = /** @class */ (function (_super) {
|
|
|
22
21
|
};
|
|
23
22
|
DuckDBDataProvider.prototype.getCreateTableSql = function (entity) {
|
|
24
23
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
25
|
-
var result, e,
|
|
24
|
+
var result, e, createSequenceStatements, createTableSql, _a, _b, x, sequenceName;
|
|
26
25
|
var e_1, _c;
|
|
27
26
|
return tslib_1.__generator(this, function (_d) {
|
|
28
27
|
switch (_d.label) {
|
|
@@ -31,7 +30,8 @@ var DuckDBDataProvider = /** @class */ (function (_super) {
|
|
|
31
30
|
return [4 /*yield*/, (0, index_js_1.dbNamesOf)(entity, this.wrapIdentifier)];
|
|
32
31
|
case 1:
|
|
33
32
|
e = _d.sent();
|
|
34
|
-
|
|
33
|
+
createSequenceStatements = [];
|
|
34
|
+
createTableSql = '';
|
|
35
35
|
try {
|
|
36
36
|
for (_a = tslib_1.__values(entity.fields), _b = _a.next(); !_b.done; _b = _a.next()) {
|
|
37
37
|
x = _b.value;
|
|
@@ -41,7 +41,7 @@ var DuckDBDataProvider = /** @class */ (function (_super) {
|
|
|
41
41
|
result += '\r\n ';
|
|
42
42
|
if ((0, RepositoryImplementation_js_1.isAutoIncrement)(x)) {
|
|
43
43
|
sequenceName = "".concat(entity.dbName, "_").concat(x.dbName, "_seq");
|
|
44
|
-
|
|
44
|
+
createSequenceStatements.push("create sequence if not exists \"".concat(sequenceName, "\";"));
|
|
45
45
|
result += "".concat(e.$dbNameOf(x), " integer default nextval('").concat(sequenceName, "')");
|
|
46
46
|
}
|
|
47
47
|
else {
|
|
@@ -60,9 +60,9 @@ var DuckDBDataProvider = /** @class */ (function (_super) {
|
|
|
60
60
|
result += ",\r\n primary key (".concat(entity.idMetadata.fields
|
|
61
61
|
.map(function (f) { return e.$dbNameOf(f); })
|
|
62
62
|
.join(','), ")");
|
|
63
|
-
|
|
63
|
+
createTableSql =
|
|
64
64
|
'create table if not exists ' + e.$entityName + ' (' + result + '\r\n)';
|
|
65
|
-
return [2 /*return*/, [
|
|
65
|
+
return [2 /*return*/, tslib_1.__spreadArray(tslib_1.__spreadArray([], tslib_1.__read(createSequenceStatements), false), [createTableSql], false)];
|
|
66
66
|
}
|
|
67
67
|
});
|
|
68
68
|
});
|
|
@@ -108,43 +108,93 @@ var DuckDBDataProvider = /** @class */ (function (_super) {
|
|
|
108
108
|
}(remult_sqlite_core_js_1.SqliteCoreDataProvider));
|
|
109
109
|
exports.DuckDBDataProvider = DuckDBDataProvider;
|
|
110
110
|
var DuckDBCommand = /** @class */ (function () {
|
|
111
|
-
function DuckDBCommand(
|
|
112
|
-
this.
|
|
111
|
+
function DuckDBCommand(connection) {
|
|
112
|
+
this.connection = connection;
|
|
113
113
|
this.values = [];
|
|
114
114
|
}
|
|
115
115
|
DuckDBCommand.prototype.execute = function (sql) {
|
|
116
116
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
117
|
-
var
|
|
117
|
+
var result, err_1;
|
|
118
118
|
return tslib_1.__generator(this, function (_a) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
119
|
+
switch (_a.label) {
|
|
120
|
+
case 0:
|
|
121
|
+
_a.trys.push([0, 2, , 3]);
|
|
122
|
+
return [4 /*yield*/, this.connection.run(sql, this.values)];
|
|
123
|
+
case 1:
|
|
124
|
+
result = _a.sent();
|
|
125
|
+
this.values = [];
|
|
126
|
+
return [2 /*return*/, new DuckDBSqlResult(result)];
|
|
127
|
+
case 2:
|
|
128
|
+
err_1 = _a.sent();
|
|
129
|
+
this.values = [];
|
|
130
|
+
throw err_1;
|
|
131
|
+
case 3: return [2 /*return*/];
|
|
132
|
+
}
|
|
128
133
|
});
|
|
129
134
|
});
|
|
130
135
|
};
|
|
136
|
+
DuckDBCommand.prototype.addParamInternal = function (val) {
|
|
137
|
+
if (val === undefined) {
|
|
138
|
+
this.values.push(null);
|
|
139
|
+
}
|
|
140
|
+
else if (val instanceof Date) {
|
|
141
|
+
this.values.push(val.toISOString());
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
this.values.push(val);
|
|
145
|
+
}
|
|
146
|
+
return '?';
|
|
147
|
+
};
|
|
131
148
|
DuckDBCommand.prototype.addParameterAndReturnSqlToken = function (val) {
|
|
132
|
-
return this.
|
|
149
|
+
return this.addParamInternal(val);
|
|
133
150
|
};
|
|
134
151
|
DuckDBCommand.prototype.param = function (val) {
|
|
135
|
-
|
|
136
|
-
this.values.push(val);
|
|
137
|
-
return key;
|
|
152
|
+
return this.addParamInternal(val);
|
|
138
153
|
};
|
|
139
154
|
return DuckDBCommand;
|
|
140
155
|
}());
|
|
141
156
|
var DuckDBSqlResult = /** @class */ (function () {
|
|
142
|
-
function DuckDBSqlResult(
|
|
143
|
-
|
|
144
|
-
this.
|
|
157
|
+
function DuckDBSqlResult(duckDbResult) {
|
|
158
|
+
var _a;
|
|
159
|
+
this.duckDbResult = duckDbResult;
|
|
160
|
+
this.rows = [];
|
|
161
|
+
var columnNames = this.duckDbResult.columnNames();
|
|
162
|
+
var columnTypes = this.duckDbResult.columnTypes();
|
|
163
|
+
var chunkCount = this.duckDbResult.chunkCount;
|
|
164
|
+
for (var i = 0; i < chunkCount; i++) {
|
|
165
|
+
var chunk = this.duckDbResult.getChunk(i);
|
|
166
|
+
var chunkRowObjects = chunk.getRowObjects(columnNames).map(function (row) {
|
|
167
|
+
var convertedRow = {};
|
|
168
|
+
columnNames.forEach(function (colName, colIndex) {
|
|
169
|
+
var value = row[colName];
|
|
170
|
+
if (value === null) {
|
|
171
|
+
convertedRow[colName] = null;
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
var colType = columnTypes[colIndex];
|
|
175
|
+
var typeId = colType.typeId;
|
|
176
|
+
if (typeId === node_api_1.DuckDBTypeId.TIMESTAMP) {
|
|
177
|
+
var timestampValue = value;
|
|
178
|
+
var parts = timestampValue.toParts();
|
|
179
|
+
convertedRow[colName] = new Date(Date.UTC(parts.date.year, parts.date.month - 1, parts.date.day, parts.time.hour, parts.time.min, parts.time.sec, Math.floor(parts.time.micros / 1000)));
|
|
180
|
+
}
|
|
181
|
+
else if (typeId === node_api_1.DuckDBTypeId.DATE) {
|
|
182
|
+
var dateValue = value;
|
|
183
|
+
var parts = dateValue.toParts();
|
|
184
|
+
convertedRow[colName] = new Date(Date.UTC(parts.year, parts.month - 1, parts.day));
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
convertedRow[colName] = value;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
return convertedRow;
|
|
192
|
+
});
|
|
193
|
+
(_a = this.rows).push.apply(_a, tslib_1.__spreadArray([], tslib_1.__read(chunkRowObjects), false));
|
|
194
|
+
}
|
|
145
195
|
}
|
|
146
196
|
DuckDBSqlResult.prototype.getColumnKeyInResultForIndexInSelect = function (index) {
|
|
147
|
-
return
|
|
197
|
+
return this.duckDbResult.columnName(index);
|
|
148
198
|
};
|
|
149
199
|
return DuckDBSqlResult;
|
|
150
200
|
}());
|