@peerbit/indexer-sqlite3 1.0.7 → 1.1.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/dist/peerbit/sqlite3.min.js +542 -626
- package/dist/peerbit/sqlite3.worker.min.js +25 -19
- package/dist/src/engine.d.ts +10 -20
- package/dist/src/engine.d.ts.map +1 -1
- package/dist/src/engine.js +104 -87
- package/dist/src/engine.js.map +1 -1
- package/dist/src/schema.d.ts +21 -8
- package/dist/src/schema.d.ts.map +1 -1
- package/dist/src/schema.js +141 -62
- package/dist/src/schema.js.map +1 -1
- package/dist/src/sqlite3.browser.d.ts.map +1 -1
- package/dist/src/sqlite3.browser.js +11 -1
- package/dist/src/sqlite3.browser.js.map +1 -1
- package/dist/src/sqlite3.d.ts.map +1 -1
- package/dist/src/sqlite3.js +19 -2
- package/dist/src/sqlite3.js.map +1 -1
- package/dist/src/sqlite3.wasm.d.ts +5 -5
- package/dist/src/sqlite3.wasm.d.ts.map +1 -1
- package/dist/src/sqlite3.wasm.js +9 -3
- package/dist/src/sqlite3.wasm.js.map +1 -1
- package/dist/src/types.d.ts +5 -1
- package/dist/src/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/engine.ts +165 -151
- package/src/schema.ts +206 -92
- package/src/sqlite3.browser.ts +15 -2
- package/src/sqlite3.ts +22 -2
- package/src/sqlite3.wasm.ts +19 -12
- package/src/types.ts +6 -1
package/src/schema.ts
CHANGED
|
@@ -823,15 +823,25 @@ export const getTableNameFromPrefixedField = (prefixedField: string) =>
|
|
|
823
823
|
prefixedField.split("#")[0];
|
|
824
824
|
|
|
825
825
|
export const getInlineTableFieldName = (
|
|
826
|
-
path: string[] | undefined,
|
|
826
|
+
path: string[] | string | undefined,
|
|
827
827
|
key?: string,
|
|
828
|
-
) => {
|
|
828
|
+
): string => {
|
|
829
829
|
if (key) {
|
|
830
|
-
|
|
830
|
+
if (Array.isArray(path)) {
|
|
831
|
+
return path && path.length > 0 ? `${path.join("_")}__${key}` : key;
|
|
832
|
+
}
|
|
833
|
+
return path + "__" + key;
|
|
831
834
|
} else {
|
|
832
835
|
// last element in the path is the key, the rest is the path
|
|
833
836
|
// join key with __ , rest with _
|
|
834
837
|
|
|
838
|
+
if (!Array.isArray(path)) {
|
|
839
|
+
if (!path) {
|
|
840
|
+
throw new Error("Unexpected missing path");
|
|
841
|
+
}
|
|
842
|
+
return path;
|
|
843
|
+
}
|
|
844
|
+
|
|
835
845
|
return path!.length > 2
|
|
836
846
|
? `${path!.slice(0, -1).join("_")}__${path![path!.length - 1]}`
|
|
837
847
|
: path!.join("__");
|
|
@@ -840,7 +850,7 @@ export const getInlineTableFieldName = (
|
|
|
840
850
|
|
|
841
851
|
const matchFieldInShape = (
|
|
842
852
|
shape: types.Shape | undefined,
|
|
843
|
-
path: string[] | undefined,
|
|
853
|
+
path: string[] | string | undefined,
|
|
844
854
|
field: SQLField,
|
|
845
855
|
) => {
|
|
846
856
|
if (!shape) {
|
|
@@ -860,7 +870,11 @@ const matchFieldInShape = (
|
|
|
860
870
|
if (nextShape === true) {
|
|
861
871
|
return true;
|
|
862
872
|
}
|
|
863
|
-
|
|
873
|
+
if (Array.isArray(nextShape)) {
|
|
874
|
+
currentShape = nextShape[0];
|
|
875
|
+
} else {
|
|
876
|
+
currentShape = nextShape;
|
|
877
|
+
}
|
|
864
878
|
}
|
|
865
879
|
}
|
|
866
880
|
|
|
@@ -969,7 +983,12 @@ export const selectAllFieldsFromTable = (
|
|
|
969
983
|
continue;
|
|
970
984
|
}
|
|
971
985
|
|
|
972
|
-
childShape =
|
|
986
|
+
childShape =
|
|
987
|
+
maybeShape === true
|
|
988
|
+
? undefined
|
|
989
|
+
: Array.isArray(maybeShape)
|
|
990
|
+
? maybeShape[0]
|
|
991
|
+
: maybeShape;
|
|
973
992
|
}
|
|
974
993
|
|
|
975
994
|
stack.push({ table: child, shape: childShape });
|
|
@@ -1001,14 +1020,17 @@ const getNonInlinedTable = (from: Table) => {
|
|
|
1001
1020
|
};
|
|
1002
1021
|
|
|
1003
1022
|
// the inverse of resolveFieldValues
|
|
1004
|
-
export const resolveInstanceFromValue = async <
|
|
1023
|
+
export const resolveInstanceFromValue = async <
|
|
1024
|
+
T,
|
|
1025
|
+
S extends types.Shape | undefined,
|
|
1026
|
+
>(
|
|
1005
1027
|
fromTablePrefixedValues: Record<string, any>,
|
|
1006
1028
|
tables: Map<string, Table>,
|
|
1007
1029
|
table: Table,
|
|
1008
1030
|
resolveChildren: (parentId: any, table: Table) => Promise<any[]>,
|
|
1009
1031
|
tablePrefixed: boolean,
|
|
1010
|
-
shape
|
|
1011
|
-
): Promise<T
|
|
1032
|
+
shape?: S,
|
|
1033
|
+
): Promise<types.ReturnTypeFromShape<T, S>> => {
|
|
1012
1034
|
const fields = getSchema(table.ctor).fields;
|
|
1013
1035
|
const obj: any = {};
|
|
1014
1036
|
|
|
@@ -1020,7 +1042,23 @@ export const resolveInstanceFromValue = async <T>(
|
|
|
1020
1042
|
const subTables = getTableFromField(table, tables, field); // TODO fix
|
|
1021
1043
|
|
|
1022
1044
|
let maybeShape = shape?.[field.key];
|
|
1023
|
-
|
|
1045
|
+
const subshapeIsArray = Array.isArray(maybeShape);
|
|
1046
|
+
|
|
1047
|
+
if (isArray && maybeShape && !subshapeIsArray && maybeShape !== true) {
|
|
1048
|
+
throw new Error(
|
|
1049
|
+
"Shape is not matching the array field type: " +
|
|
1050
|
+
field.key +
|
|
1051
|
+
". Shape: " +
|
|
1052
|
+
JSON.stringify(shape),
|
|
1053
|
+
);
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
let subshape =
|
|
1057
|
+
maybeShape === true
|
|
1058
|
+
? undefined
|
|
1059
|
+
: subshapeIsArray
|
|
1060
|
+
? maybeShape[0]
|
|
1061
|
+
: maybeShape;
|
|
1024
1062
|
|
|
1025
1063
|
if (isArray) {
|
|
1026
1064
|
let once = false;
|
|
@@ -1189,35 +1227,62 @@ export const fromRowToObj = (row: any, ctor: Constructor<any>) => {
|
|
|
1189
1227
|
};
|
|
1190
1228
|
|
|
1191
1229
|
export const convertDeleteRequestToQuery = (
|
|
1192
|
-
request: types.
|
|
1230
|
+
request: types.DeleteOptions,
|
|
1193
1231
|
tables: Map<string, Table>,
|
|
1194
1232
|
table: Table,
|
|
1195
|
-
) => {
|
|
1196
|
-
|
|
1233
|
+
): { sql: string; bindable: any[] } => {
|
|
1234
|
+
const { query, bindable } = convertRequestToQuery(
|
|
1235
|
+
"delete",
|
|
1236
|
+
request,
|
|
1237
|
+
tables,
|
|
1238
|
+
table,
|
|
1239
|
+
);
|
|
1240
|
+
return {
|
|
1241
|
+
sql: `DELETE FROM ${table.name} WHERE ${table.primary} IN (SELECT ${table.primary} from ${table.name} ${query}) returning ${table.primary}`,
|
|
1242
|
+
bindable,
|
|
1243
|
+
};
|
|
1197
1244
|
};
|
|
1198
1245
|
|
|
1199
1246
|
export const convertSumRequestToQuery = (
|
|
1200
|
-
request: types.
|
|
1247
|
+
request: types.SumOptions,
|
|
1201
1248
|
tables: Map<string, Table>,
|
|
1202
1249
|
table: Table,
|
|
1203
|
-
) => {
|
|
1204
|
-
|
|
1250
|
+
): { sql: string; bindable: any[] } => {
|
|
1251
|
+
const { query, bindable } = convertRequestToQuery(
|
|
1252
|
+
"sum",
|
|
1253
|
+
request,
|
|
1254
|
+
tables,
|
|
1255
|
+
table,
|
|
1256
|
+
);
|
|
1257
|
+
return {
|
|
1258
|
+
sql: `SELECT SUM(${table.name}.${getInlineTableFieldName(request.key)}) as sum FROM ${table.name} ${query}`,
|
|
1259
|
+
bindable,
|
|
1260
|
+
};
|
|
1205
1261
|
};
|
|
1206
1262
|
|
|
1207
1263
|
export const convertCountRequestToQuery = (
|
|
1208
|
-
request: types.
|
|
1264
|
+
request: types.CountOptions | undefined,
|
|
1209
1265
|
tables: Map<string, Table>,
|
|
1210
1266
|
table: Table,
|
|
1211
|
-
) => {
|
|
1212
|
-
|
|
1267
|
+
): { sql: string; bindable: any[] } => {
|
|
1268
|
+
const { query, bindable } = convertRequestToQuery(
|
|
1269
|
+
"count",
|
|
1270
|
+
request,
|
|
1271
|
+
tables,
|
|
1272
|
+
table,
|
|
1273
|
+
);
|
|
1274
|
+
return {
|
|
1275
|
+
sql: `SELECT count(*) as count FROM ${table.name} ${query}`,
|
|
1276
|
+
bindable,
|
|
1277
|
+
};
|
|
1213
1278
|
};
|
|
1214
1279
|
|
|
1215
1280
|
export const convertSearchRequestToQuery = (
|
|
1216
|
-
request: types.
|
|
1281
|
+
request: types.IterateOptions | undefined,
|
|
1217
1282
|
tables: Map<string, Table>,
|
|
1218
1283
|
rootTables: Table[],
|
|
1219
1284
|
shape: types.Shape | undefined,
|
|
1220
|
-
) => {
|
|
1285
|
+
): { sql: string; bindable: any[] } => {
|
|
1221
1286
|
let unionBuilder = "";
|
|
1222
1287
|
let orderByClause: string = "";
|
|
1223
1288
|
|
|
@@ -1225,12 +1290,13 @@ export const convertSearchRequestToQuery = (
|
|
|
1225
1290
|
let lastError: Error | undefined = undefined;
|
|
1226
1291
|
|
|
1227
1292
|
const selectsPerTable = selectAllFieldsFromTables(rootTables, shape);
|
|
1228
|
-
|
|
1293
|
+
let bindableBuilder: any[] = [];
|
|
1229
1294
|
for (const [i, table] of rootTables.entries()) {
|
|
1230
1295
|
const { selects, joins: joinFromSelect } = selectsPerTable[i];
|
|
1231
1296
|
const selectQuery = generateSelectQuery(table, selects);
|
|
1232
1297
|
try {
|
|
1233
|
-
const { orderBy, query } = convertRequestToQuery(
|
|
1298
|
+
const { orderBy, query, bindable } = convertRequestToQuery(
|
|
1299
|
+
"iterate",
|
|
1234
1300
|
request,
|
|
1235
1301
|
tables,
|
|
1236
1302
|
table,
|
|
@@ -1244,6 +1310,7 @@ export const convertSearchRequestToQuery = (
|
|
|
1244
1310
|
: orderBy
|
|
1245
1311
|
: orderByClause;
|
|
1246
1312
|
matchedOnce = true;
|
|
1313
|
+
bindableBuilder.push(...bindable);
|
|
1247
1314
|
} catch (error) {
|
|
1248
1315
|
if (error instanceof MissingFieldError) {
|
|
1249
1316
|
lastError = error;
|
|
@@ -1254,78 +1321,103 @@ export const convertSearchRequestToQuery = (
|
|
|
1254
1321
|
}
|
|
1255
1322
|
|
|
1256
1323
|
if (!matchedOnce) {
|
|
1257
|
-
throw lastError
|
|
1324
|
+
throw lastError!;
|
|
1258
1325
|
}
|
|
1259
1326
|
|
|
1260
|
-
return
|
|
1327
|
+
return {
|
|
1328
|
+
sql: `${unionBuilder} ${orderByClause ? "ORDER BY " + orderByClause : ""} limit ? offset ?`,
|
|
1329
|
+
bindable: bindableBuilder,
|
|
1330
|
+
};
|
|
1261
1331
|
};
|
|
1262
1332
|
|
|
1263
|
-
type SearchQueryParts = { query: string; orderBy: string };
|
|
1264
|
-
type CountQueryParts = { query: string; join: string };
|
|
1333
|
+
type SearchQueryParts = { query: string; orderBy: string; bindable: any[] };
|
|
1334
|
+
type CountQueryParts = { query: string; join: string; bindable: any[] };
|
|
1335
|
+
|
|
1336
|
+
function isIterateRequest(
|
|
1337
|
+
request: any,
|
|
1338
|
+
type: string,
|
|
1339
|
+
): request is types.IterateOptions | undefined {
|
|
1340
|
+
return type === "iterate";
|
|
1341
|
+
}
|
|
1265
1342
|
|
|
1266
1343
|
const convertRequestToQuery = <
|
|
1267
|
-
T extends
|
|
1268
|
-
R = T extends
|
|
1344
|
+
T extends "iterate" | "count" | "sum" | "delete",
|
|
1345
|
+
R = T extends "iterate" ? SearchQueryParts : CountQueryParts,
|
|
1269
1346
|
>(
|
|
1270
|
-
|
|
1347
|
+
type: T,
|
|
1348
|
+
request:
|
|
1349
|
+
| (T extends "iterate"
|
|
1350
|
+
? types.IterateOptions
|
|
1351
|
+
: T extends "count"
|
|
1352
|
+
? types.CountOptions
|
|
1353
|
+
: T extends "delete"
|
|
1354
|
+
? types.DeleteOptions
|
|
1355
|
+
: types.SumOptions)
|
|
1356
|
+
| undefined,
|
|
1271
1357
|
tables: Map<string, Table>,
|
|
1272
1358
|
table: Table,
|
|
1273
1359
|
extraJoin?: Map<string, JoinTable>,
|
|
1274
1360
|
path: string[] = [],
|
|
1275
1361
|
): R => {
|
|
1276
1362
|
let whereBuilder = "";
|
|
1363
|
+
let bindableBuilder: any[] = [];
|
|
1277
1364
|
let orderByBuilder: string | undefined = undefined;
|
|
1278
1365
|
/* let tablesToSelect: string[] = [table.name]; */
|
|
1279
1366
|
let joinBuilder: Map<string, JoinTable> = extraJoin || new Map();
|
|
1280
|
-
|
|
1281
|
-
if (
|
|
1282
|
-
const { where } = convertQueryToSQLQuery(
|
|
1283
|
-
|
|
1367
|
+
const coercedQuery = types.toQuery(request?.query);
|
|
1368
|
+
if (coercedQuery.length === 1) {
|
|
1369
|
+
const { where, bindable } = convertQueryToSQLQuery(
|
|
1370
|
+
coercedQuery[0],
|
|
1284
1371
|
tables,
|
|
1285
1372
|
table,
|
|
1286
1373
|
joinBuilder,
|
|
1287
1374
|
path,
|
|
1288
1375
|
);
|
|
1289
1376
|
whereBuilder += where;
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1377
|
+
bindableBuilder.push(...bindable);
|
|
1378
|
+
} else if (coercedQuery.length > 1) {
|
|
1379
|
+
const { where, bindable } = convertQueryToSQLQuery(
|
|
1380
|
+
new types.And(coercedQuery),
|
|
1293
1381
|
tables,
|
|
1294
1382
|
table,
|
|
1295
1383
|
joinBuilder,
|
|
1296
1384
|
path,
|
|
1297
1385
|
);
|
|
1298
1386
|
whereBuilder += where;
|
|
1387
|
+
bindableBuilder.push(...bindable);
|
|
1299
1388
|
}
|
|
1300
1389
|
|
|
1301
|
-
if (request
|
|
1302
|
-
if (request
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1390
|
+
if (isIterateRequest(request, type)) {
|
|
1391
|
+
if (request?.sort) {
|
|
1392
|
+
let sortArr = Array.isArray(request.sort) ? request.sort : [request.sort];
|
|
1393
|
+
if (sortArr.length > 0) {
|
|
1394
|
+
orderByBuilder = "";
|
|
1395
|
+
let once = false;
|
|
1396
|
+
for (const sort of sortArr) {
|
|
1397
|
+
const { foreignTables, queryKey } = resolveTableToQuery(
|
|
1398
|
+
table,
|
|
1399
|
+
tables,
|
|
1400
|
+
joinBuilder,
|
|
1401
|
+
[...path, ...sort.key],
|
|
1402
|
+
undefined,
|
|
1403
|
+
true,
|
|
1404
|
+
);
|
|
1405
|
+
for (const table of foreignTables) {
|
|
1406
|
+
if (once) {
|
|
1407
|
+
orderByBuilder += ", ";
|
|
1408
|
+
}
|
|
1409
|
+
once = true;
|
|
1410
|
+
orderByBuilder += `${table.as}.${queryKey} ${sort.direction === types.SortDirection.ASC ? "ASC" : "DESC"}`;
|
|
1317
1411
|
}
|
|
1318
|
-
once = true;
|
|
1319
|
-
orderByBuilder += `${table.as}.${queryKey} ${sort.direction === types.SortDirection.ASC ? "ASC" : "DESC"}`;
|
|
1320
1412
|
}
|
|
1321
|
-
}
|
|
1322
1413
|
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1414
|
+
/* orderByBuilder += request.sort
|
|
1415
|
+
.map(
|
|
1416
|
+
(sort) =>
|
|
1417
|
+
`${table.name}.${sort.key} ${sort.direction === types.SortDirection.ASC ? "ASC" : "DESC"}`
|
|
1418
|
+
)
|
|
1419
|
+
.join(", "); */
|
|
1420
|
+
}
|
|
1329
1421
|
}
|
|
1330
1422
|
}
|
|
1331
1423
|
const where = whereBuilder.length > 0 ? "where " + whereBuilder : undefined;
|
|
@@ -1333,16 +1425,14 @@ const convertRequestToQuery = <
|
|
|
1333
1425
|
if (extraJoin && extraJoin.size > 0) {
|
|
1334
1426
|
insertMapIntoMap(joinBuilder, extraJoin);
|
|
1335
1427
|
}
|
|
1336
|
-
let join = buildJoin(
|
|
1337
|
-
joinBuilder,
|
|
1338
|
-
request instanceof types.SearchRequest ? true : false,
|
|
1339
|
-
);
|
|
1428
|
+
let join = buildJoin(joinBuilder, type === "iterate" ? true : false);
|
|
1340
1429
|
|
|
1341
1430
|
const query = `${join ? join : ""} ${where ? where : ""}`;
|
|
1342
1431
|
|
|
1343
1432
|
return {
|
|
1344
1433
|
query,
|
|
1345
1434
|
orderBy: orderByBuilder,
|
|
1435
|
+
bindable: bindableBuilder,
|
|
1346
1436
|
} as R;
|
|
1347
1437
|
};
|
|
1348
1438
|
|
|
@@ -1382,8 +1472,9 @@ export const convertQueryToSQLQuery = (
|
|
|
1382
1472
|
joinBuilder: Map<string, JoinTable>,
|
|
1383
1473
|
path: string[] = [],
|
|
1384
1474
|
tableAlias: string | undefined = undefined,
|
|
1385
|
-
): { where: string } => {
|
|
1475
|
+
): { where: string; bindable: any[] } => {
|
|
1386
1476
|
let whereBuilder = "";
|
|
1477
|
+
let bindableBuilder: any[] = [];
|
|
1387
1478
|
/* let tablesToSelect: string[] = []; */
|
|
1388
1479
|
|
|
1389
1480
|
const handleAnd = (
|
|
@@ -1392,7 +1483,7 @@ export const convertQueryToSQLQuery = (
|
|
|
1392
1483
|
tableAlias?: string,
|
|
1393
1484
|
) => {
|
|
1394
1485
|
for (const query of queries) {
|
|
1395
|
-
const { where } = convertQueryToSQLQuery(
|
|
1486
|
+
const { where, bindable } = convertQueryToSQLQuery(
|
|
1396
1487
|
query,
|
|
1397
1488
|
tables,
|
|
1398
1489
|
table,
|
|
@@ -1402,11 +1493,12 @@ export const convertQueryToSQLQuery = (
|
|
|
1402
1493
|
);
|
|
1403
1494
|
whereBuilder =
|
|
1404
1495
|
whereBuilder.length > 0 ? `(${whereBuilder}) AND (${where})` : where;
|
|
1496
|
+
bindableBuilder.push(...bindable);
|
|
1405
1497
|
}
|
|
1406
1498
|
};
|
|
1407
1499
|
|
|
1408
1500
|
if (query instanceof types.StateFieldQuery) {
|
|
1409
|
-
const { where } = convertStateFieldQuery(
|
|
1501
|
+
const { where, bindable } = convertStateFieldQuery(
|
|
1410
1502
|
query,
|
|
1411
1503
|
tables,
|
|
1412
1504
|
table,
|
|
@@ -1415,6 +1507,7 @@ export const convertQueryToSQLQuery = (
|
|
|
1415
1507
|
tableAlias,
|
|
1416
1508
|
);
|
|
1417
1509
|
whereBuilder += where;
|
|
1510
|
+
bindableBuilder.push(...bindable);
|
|
1418
1511
|
} else if (query instanceof types.Nested) {
|
|
1419
1512
|
let joinPrefix = "__" + String(tables.size);
|
|
1420
1513
|
path = [...path, query.path];
|
|
@@ -1424,7 +1517,7 @@ export const convertQueryToSQLQuery = (
|
|
|
1424
1517
|
handleAnd(query.and, path, tableAlias);
|
|
1425
1518
|
} else if (query instanceof types.Or) {
|
|
1426
1519
|
for (const subquery of query.or) {
|
|
1427
|
-
const { where } = convertQueryToSQLQuery(
|
|
1520
|
+
const { where, bindable } = convertQueryToSQLQuery(
|
|
1428
1521
|
subquery,
|
|
1429
1522
|
tables,
|
|
1430
1523
|
table,
|
|
@@ -1434,9 +1527,10 @@ export const convertQueryToSQLQuery = (
|
|
|
1434
1527
|
);
|
|
1435
1528
|
whereBuilder =
|
|
1436
1529
|
whereBuilder.length > 0 ? `(${whereBuilder}) OR (${where})` : where;
|
|
1530
|
+
bindableBuilder.push(...bindable);
|
|
1437
1531
|
}
|
|
1438
1532
|
} else if (query instanceof types.Not) {
|
|
1439
|
-
const { where } = convertQueryToSQLQuery(
|
|
1533
|
+
const { where, bindable } = convertQueryToSQLQuery(
|
|
1440
1534
|
query.not,
|
|
1441
1535
|
tables,
|
|
1442
1536
|
table,
|
|
@@ -1445,6 +1539,7 @@ export const convertQueryToSQLQuery = (
|
|
|
1445
1539
|
tableAlias,
|
|
1446
1540
|
);
|
|
1447
1541
|
whereBuilder = `NOT (${where})`;
|
|
1542
|
+
bindableBuilder.push(...bindable);
|
|
1448
1543
|
} else {
|
|
1449
1544
|
throw new Error("Unsupported query type: " + query.constructor.name);
|
|
1450
1545
|
}
|
|
@@ -1454,6 +1549,7 @@ export const convertQueryToSQLQuery = (
|
|
|
1454
1549
|
|
|
1455
1550
|
return {
|
|
1456
1551
|
where: whereBuilder,
|
|
1552
|
+
bindable: bindableBuilder,
|
|
1457
1553
|
};
|
|
1458
1554
|
};
|
|
1459
1555
|
|
|
@@ -1607,7 +1703,7 @@ const convertStateFieldQuery = (
|
|
|
1607
1703
|
join: Map<string, JoinTable>,
|
|
1608
1704
|
path: string[],
|
|
1609
1705
|
tableAlias: string | undefined = undefined,
|
|
1610
|
-
): { where: string } => {
|
|
1706
|
+
): { where: string; bindable: any[] } => {
|
|
1611
1707
|
// if field id represented as foreign table, do join and compare
|
|
1612
1708
|
const inlinedName = getInlineTableFieldName(query.key);
|
|
1613
1709
|
const tableField = table.fields.find(
|
|
@@ -1626,11 +1722,13 @@ const convertStateFieldQuery = (
|
|
|
1626
1722
|
query = cloneQuery(query);
|
|
1627
1723
|
query.key = [queryKey];
|
|
1628
1724
|
let whereBuilder: string[] = [];
|
|
1725
|
+
let bindableBuilder: any[][] = [];
|
|
1726
|
+
|
|
1629
1727
|
for (const ftable of foreignTables) {
|
|
1630
1728
|
if (ftable.table === table) {
|
|
1631
1729
|
throw new Error("Unexpected");
|
|
1632
1730
|
}
|
|
1633
|
-
const { where } = convertQueryToSQLQuery(
|
|
1731
|
+
const { where, bindable } = convertQueryToSQLQuery(
|
|
1634
1732
|
query,
|
|
1635
1733
|
tables,
|
|
1636
1734
|
ftable.table,
|
|
@@ -1639,10 +1737,15 @@ const convertStateFieldQuery = (
|
|
|
1639
1737
|
ftable.as,
|
|
1640
1738
|
);
|
|
1641
1739
|
whereBuilder.push(where);
|
|
1740
|
+
bindableBuilder.push(bindable);
|
|
1642
1741
|
}
|
|
1643
|
-
return {
|
|
1742
|
+
return {
|
|
1743
|
+
where: whereBuilder.join(" OR "),
|
|
1744
|
+
bindable: bindableBuilder.flat(),
|
|
1745
|
+
};
|
|
1644
1746
|
}
|
|
1645
1747
|
|
|
1748
|
+
let bindable: any[] = [];
|
|
1646
1749
|
const keyWithTable =
|
|
1647
1750
|
(tableAlias || table.name) + "." + escapeColumnName(inlinedName);
|
|
1648
1751
|
let where: string;
|
|
@@ -1650,11 +1753,14 @@ const convertStateFieldQuery = (
|
|
|
1650
1753
|
let statement = "";
|
|
1651
1754
|
|
|
1652
1755
|
if (query.method === types.StringMatchMethod.contains) {
|
|
1653
|
-
statement = `${keyWithTable} LIKE
|
|
1756
|
+
statement = `${keyWithTable} LIKE ?`;
|
|
1757
|
+
bindable.push(`%${query.value}%`);
|
|
1654
1758
|
} else if (query.method === types.StringMatchMethod.prefix) {
|
|
1655
|
-
statement = `${keyWithTable} LIKE
|
|
1759
|
+
statement = `${keyWithTable} LIKE ?`;
|
|
1760
|
+
bindable.push(`${query.value}%`);
|
|
1656
1761
|
} else if (query.method === types.StringMatchMethod.exact) {
|
|
1657
|
-
statement = `${keyWithTable} =
|
|
1762
|
+
statement = `${keyWithTable} = ?`;
|
|
1763
|
+
bindable.push(`${query.value}`);
|
|
1658
1764
|
}
|
|
1659
1765
|
if (query.caseInsensitive) {
|
|
1660
1766
|
statement += " COLLATE NOCASE";
|
|
@@ -1663,31 +1769,39 @@ const convertStateFieldQuery = (
|
|
|
1663
1769
|
} else if (query instanceof types.ByteMatchQuery) {
|
|
1664
1770
|
// compare Blob compule with f.value
|
|
1665
1771
|
|
|
1666
|
-
const statement = `${keyWithTable} =
|
|
1772
|
+
const statement = `${keyWithTable} = ?`;
|
|
1773
|
+
bindable.push(query.value);
|
|
1667
1774
|
where = statement;
|
|
1668
1775
|
} else if (query instanceof types.IntegerCompare) {
|
|
1669
1776
|
if (tableField!.type === "BLOB") {
|
|
1670
1777
|
// TODO perf
|
|
1671
|
-
where = `hex(${keyWithTable}) LIKE
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
where = `${keyWithTable} > ${query.value.value}`;
|
|
1676
|
-
} else if (query.compare === types.Compare.Less) {
|
|
1677
|
-
where = `${keyWithTable} < ${query.value.value}`;
|
|
1678
|
-
} else if (query.compare === types.Compare.GreaterOrEqual) {
|
|
1679
|
-
where = `${keyWithTable} >= ${query.value.value}`;
|
|
1680
|
-
} else if (query.compare === types.Compare.LessOrEqual) {
|
|
1681
|
-
where = `${keyWithTable} <= ${query.value.value}`;
|
|
1778
|
+
where = `hex(${keyWithTable}) LIKE ?`;
|
|
1779
|
+
bindable.push(
|
|
1780
|
+
`%${toHexString(new Uint8Array([Number(query.value.value)]))}%`,
|
|
1781
|
+
);
|
|
1682
1782
|
} else {
|
|
1683
|
-
|
|
1783
|
+
if (query.compare === types.Compare.Equal) {
|
|
1784
|
+
where = `${keyWithTable} = ?`;
|
|
1785
|
+
} else if (query.compare === types.Compare.Greater) {
|
|
1786
|
+
where = `${keyWithTable} > ?`;
|
|
1787
|
+
} else if (query.compare === types.Compare.Less) {
|
|
1788
|
+
where = `${keyWithTable} < ?`;
|
|
1789
|
+
} else if (query.compare === types.Compare.GreaterOrEqual) {
|
|
1790
|
+
where = `${keyWithTable} >= ?`;
|
|
1791
|
+
} else if (query.compare === types.Compare.LessOrEqual) {
|
|
1792
|
+
where = `${keyWithTable} <= ?`;
|
|
1793
|
+
} else {
|
|
1794
|
+
throw new Error(`Unsupported compare type: ${query.compare}`);
|
|
1795
|
+
}
|
|
1796
|
+
bindable.push(query.value.value);
|
|
1684
1797
|
}
|
|
1685
1798
|
} else if (query instanceof types.IsNull) {
|
|
1686
1799
|
where = `${keyWithTable} IS NULL`;
|
|
1687
1800
|
} else if (query instanceof types.BoolQuery) {
|
|
1688
|
-
where = `${keyWithTable} =
|
|
1801
|
+
where = `${keyWithTable} = ?`;
|
|
1802
|
+
bindable.push(query.value ? 1 : 0);
|
|
1689
1803
|
} else {
|
|
1690
1804
|
throw new Error("Unsupported query type: " + query.constructor.name);
|
|
1691
1805
|
}
|
|
1692
|
-
return { where };
|
|
1806
|
+
return { where, bindable };
|
|
1693
1807
|
};
|
package/src/sqlite3.browser.ts
CHANGED
|
@@ -93,13 +93,14 @@ class ProxyStatement implements IStatement {
|
|
|
93
93
|
|
|
94
94
|
class ProxyDatabase implements IDatabase {
|
|
95
95
|
statements: Map<string, ProxyStatement> = new Map();
|
|
96
|
+
|
|
96
97
|
resolvers: {
|
|
97
98
|
[hash in string]: {
|
|
98
99
|
resolve: (...args: any) => void;
|
|
99
100
|
reject: (...args: any) => void;
|
|
100
101
|
};
|
|
101
102
|
} = {};
|
|
102
|
-
databaseId
|
|
103
|
+
databaseId!: string;
|
|
103
104
|
constructor(
|
|
104
105
|
readonly send: <T>(
|
|
105
106
|
message: messages.DatabaseMessages | messages.StatementMessages,
|
|
@@ -125,7 +126,14 @@ class ProxyDatabase implements IDatabase {
|
|
|
125
126
|
});
|
|
126
127
|
}
|
|
127
128
|
|
|
128
|
-
async prepare(sql: string) {
|
|
129
|
+
async prepare(sql: string, id?: string) {
|
|
130
|
+
if (id != null) {
|
|
131
|
+
const prev = this.statements.get(id);
|
|
132
|
+
if (prev) {
|
|
133
|
+
await prev.reset();
|
|
134
|
+
return prev;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
129
137
|
const statementId = await this.send<string>({
|
|
130
138
|
type: "prepare",
|
|
131
139
|
sql,
|
|
@@ -138,6 +146,11 @@ class ProxyDatabase implements IDatabase {
|
|
|
138
146
|
statementId,
|
|
139
147
|
);
|
|
140
148
|
this.statements.set(statementId, statement);
|
|
149
|
+
|
|
150
|
+
if (id != null) {
|
|
151
|
+
this.statements.set(id, statement);
|
|
152
|
+
}
|
|
153
|
+
|
|
141
154
|
return statement;
|
|
142
155
|
}
|
|
143
156
|
|
package/src/sqlite3.ts
CHANGED
|
@@ -7,7 +7,14 @@ import type {
|
|
|
7
7
|
|
|
8
8
|
let create = async (directory?: string) => {
|
|
9
9
|
let db: DB.Database | undefined = undefined;
|
|
10
|
+
let statements: Map<string, IStatement> = new Map();
|
|
11
|
+
|
|
10
12
|
let close = () => {
|
|
13
|
+
for (const stmt of statements.values()) {
|
|
14
|
+
stmt.finalize?.();
|
|
15
|
+
}
|
|
16
|
+
statements.clear();
|
|
17
|
+
|
|
11
18
|
if (db) {
|
|
12
19
|
db.close();
|
|
13
20
|
db = undefined;
|
|
@@ -43,10 +50,23 @@ let create = async (directory?: string) => {
|
|
|
43
50
|
if (!db) throw new Error("Database not open");
|
|
44
51
|
return db.exec(sql);
|
|
45
52
|
},
|
|
46
|
-
prepare(sql: string) {
|
|
53
|
+
async prepare(sql: string, id?: string) {
|
|
47
54
|
if (!db) throw new Error("Database not open");
|
|
48
|
-
|
|
55
|
+
if (id != null) {
|
|
56
|
+
let prev = statements.get(id);
|
|
57
|
+
|
|
58
|
+
if (prev) {
|
|
59
|
+
await prev.reset?.();
|
|
60
|
+
return prev;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const stmt = db.prepare(sql) as any as IStatement; // TODO types
|
|
64
|
+
if (id != null) {
|
|
65
|
+
statements.set(id, stmt);
|
|
66
|
+
}
|
|
67
|
+
return stmt;
|
|
49
68
|
},
|
|
69
|
+
statements,
|
|
50
70
|
close,
|
|
51
71
|
open,
|
|
52
72
|
status: () => (db ? "open" : "closed"),
|