@crvouga/sqlite-mem 1.0.0 → 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/README.md +1 -1
- package/dist/executor/pragma-engine.d.ts +25 -0
- package/dist/functions/pragma-tvf.d.ts +8 -0
- package/dist/functions/table-valued-registry.d.ts +11 -0
- package/dist/functions/table-valued.d.ts +4 -4
- package/dist/index.js +622 -165
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9190,8 +9190,579 @@ function executeDetach(stmt, env) {
|
|
|
9190
9190
|
return emptyResult(0, env.state.lastInsertRowid);
|
|
9191
9191
|
}
|
|
9192
9192
|
|
|
9193
|
-
// src/functions/
|
|
9193
|
+
// src/functions/window.ts
|
|
9194
|
+
function rowsEqual(left, right) {
|
|
9195
|
+
if (left.length !== right.length) return false;
|
|
9196
|
+
return left.every((value, index) => {
|
|
9197
|
+
const other = right[index];
|
|
9198
|
+
return value === null && other === null || other !== void 0 && compareSql(value, other) === 0;
|
|
9199
|
+
});
|
|
9200
|
+
}
|
|
9201
|
+
function rowNumber(_partition, index) {
|
|
9202
|
+
return index + 1;
|
|
9203
|
+
}
|
|
9204
|
+
function rank(partition, index, orderKeys = partition) {
|
|
9205
|
+
if (index <= 0) return 1;
|
|
9206
|
+
let firstPeer = index;
|
|
9207
|
+
while (firstPeer > 0 && rowsEqual(orderKeys[firstPeer], orderKeys[firstPeer - 1])) firstPeer--;
|
|
9208
|
+
return firstPeer + 1;
|
|
9209
|
+
}
|
|
9210
|
+
function denseRank(partition, index, orderKeys = partition) {
|
|
9211
|
+
if (index <= 0) return 1;
|
|
9212
|
+
let result = 1;
|
|
9213
|
+
for (let i = 1; i <= index; i++) {
|
|
9214
|
+
if (!rowsEqual(orderKeys[i], orderKeys[i - 1])) result++;
|
|
9215
|
+
}
|
|
9216
|
+
return result;
|
|
9217
|
+
}
|
|
9218
|
+
function lag(partition, index, valueIndex = 0, offset = 1, defaultValue = null) {
|
|
9219
|
+
const target = index - Math.max(0, Math.trunc(offset));
|
|
9220
|
+
return target < 0 ? defaultValue : partition[target]?.[valueIndex] ?? null;
|
|
9221
|
+
}
|
|
9222
|
+
function lead(partition, index, valueIndex = 0, offset = 1, defaultValue = null) {
|
|
9223
|
+
const target = index + Math.max(0, Math.trunc(offset));
|
|
9224
|
+
return target >= partition.length ? defaultValue : partition[target]?.[valueIndex] ?? null;
|
|
9225
|
+
}
|
|
9226
|
+
function firstValue(partition, valueIndex = 0, frameStart = 0) {
|
|
9227
|
+
return partition[frameStart]?.[valueIndex] ?? null;
|
|
9228
|
+
}
|
|
9229
|
+
function lastValue(partition, valueIndex = 0, frameEnd = partition.length - 1) {
|
|
9230
|
+
return partition[frameEnd]?.[valueIndex] ?? null;
|
|
9231
|
+
}
|
|
9232
|
+
function nthValue(partition, n, valueIndex = 0, frameStart = 0) {
|
|
9233
|
+
const offset = Math.trunc(n);
|
|
9234
|
+
if (offset <= 0) return null;
|
|
9235
|
+
return partition[frameStart + offset - 1]?.[valueIndex] ?? null;
|
|
9236
|
+
}
|
|
9237
|
+
var windowFunctions = {
|
|
9238
|
+
row_number: rowNumber,
|
|
9239
|
+
rank,
|
|
9240
|
+
dense_rank: denseRank,
|
|
9241
|
+
lag,
|
|
9242
|
+
lead,
|
|
9243
|
+
first_value: firstValue,
|
|
9244
|
+
last_value: lastValue,
|
|
9245
|
+
nth_value: nthValue,
|
|
9246
|
+
ntile: () => 0,
|
|
9247
|
+
cume_dist: () => 0,
|
|
9248
|
+
percent_rank: () => 0
|
|
9249
|
+
};
|
|
9250
|
+
|
|
9251
|
+
// src/executor/pragma-engine.ts
|
|
9252
|
+
var PRAGMA_TVF_NAMES = [
|
|
9253
|
+
"analysis_limit",
|
|
9254
|
+
"application_id",
|
|
9255
|
+
"auto_vacuum",
|
|
9256
|
+
"automatic_index",
|
|
9257
|
+
"busy_timeout",
|
|
9258
|
+
"cache_size",
|
|
9259
|
+
"cache_spill",
|
|
9260
|
+
"cell_size_check",
|
|
9261
|
+
"checkpoint_fullfsync",
|
|
9262
|
+
"collation_list",
|
|
9263
|
+
"compile_options",
|
|
9264
|
+
"count_changes",
|
|
9265
|
+
"data_version",
|
|
9266
|
+
"database_list",
|
|
9267
|
+
"default_cache_size",
|
|
9268
|
+
"defer_foreign_keys",
|
|
9269
|
+
"empty_result_callbacks",
|
|
9270
|
+
"encoding",
|
|
9271
|
+
"foreign_key_check",
|
|
9272
|
+
"foreign_key_list",
|
|
9273
|
+
"foreign_keys",
|
|
9274
|
+
"freelist_count",
|
|
9275
|
+
"full_column_names",
|
|
9276
|
+
"fullfsync",
|
|
9277
|
+
"function_list",
|
|
9278
|
+
"hard_heap_limit",
|
|
9279
|
+
"ignore_check_constraints",
|
|
9280
|
+
"index_info",
|
|
9281
|
+
"index_list",
|
|
9282
|
+
"index_xinfo",
|
|
9283
|
+
"integrity_check",
|
|
9284
|
+
"journal_mode",
|
|
9285
|
+
"journal_size_limit",
|
|
9286
|
+
"legacy_alter_table",
|
|
9287
|
+
"locking_mode",
|
|
9288
|
+
"max_page_count",
|
|
9289
|
+
"module_list",
|
|
9290
|
+
"optimize",
|
|
9291
|
+
"page_count",
|
|
9292
|
+
"page_size",
|
|
9293
|
+
"pragma_list",
|
|
9294
|
+
"query_only",
|
|
9295
|
+
"quick_check",
|
|
9296
|
+
"read_uncommitted",
|
|
9297
|
+
"recursive_triggers",
|
|
9298
|
+
"reverse_unordered_selects",
|
|
9299
|
+
"schema_version",
|
|
9300
|
+
"secure_delete",
|
|
9301
|
+
"short_column_names",
|
|
9302
|
+
"soft_heap_limit",
|
|
9303
|
+
"synchronous",
|
|
9304
|
+
"table_info",
|
|
9305
|
+
"table_list",
|
|
9306
|
+
"table_xinfo",
|
|
9307
|
+
"temp_store",
|
|
9308
|
+
"threads",
|
|
9309
|
+
"trusted_schema",
|
|
9310
|
+
"user_version",
|
|
9311
|
+
"writable_schema"
|
|
9312
|
+
];
|
|
9313
|
+
var PRAGMA_LIST_NAMES = [
|
|
9314
|
+
"activate_extensions",
|
|
9315
|
+
...PRAGMA_TVF_NAMES,
|
|
9316
|
+
"case_sensitive_like",
|
|
9317
|
+
"hexkey",
|
|
9318
|
+
"hexrekey",
|
|
9319
|
+
"incremental_vacuum",
|
|
9320
|
+
"key",
|
|
9321
|
+
"lock_proxy_file",
|
|
9322
|
+
"mmap_size",
|
|
9323
|
+
"rekey",
|
|
9324
|
+
"shrink_memory",
|
|
9325
|
+
"temp_store_directory",
|
|
9326
|
+
"textkey",
|
|
9327
|
+
"textrekey",
|
|
9328
|
+
"wal_autocheckpoint",
|
|
9329
|
+
"wal_checkpoint"
|
|
9330
|
+
].sort((a, b) => a.localeCompare(b));
|
|
9331
|
+
var MEMORY_VTABLE_MODULES = [
|
|
9332
|
+
"bytecode",
|
|
9333
|
+
"dbstat",
|
|
9334
|
+
"fts3",
|
|
9335
|
+
"fts3tokenize",
|
|
9336
|
+
"fts4",
|
|
9337
|
+
"fts4aux",
|
|
9338
|
+
"fts5",
|
|
9339
|
+
"fts5vocab",
|
|
9340
|
+
"json_each",
|
|
9341
|
+
"json_tree",
|
|
9342
|
+
"rtree",
|
|
9343
|
+
"rtree_i32",
|
|
9344
|
+
"tables_used"
|
|
9345
|
+
];
|
|
9346
|
+
var COMPILE_OPTIONS2 = [
|
|
9347
|
+
"COMPILER=typescript",
|
|
9348
|
+
"ENABLE_FTS3",
|
|
9349
|
+
"ENABLE_FTS4",
|
|
9350
|
+
"ENABLE_FTS5",
|
|
9351
|
+
"ENABLE_JSON1",
|
|
9352
|
+
"ENABLE_RTREE",
|
|
9353
|
+
"THREADSAFE=0"
|
|
9354
|
+
];
|
|
9355
|
+
var STORAGE_DEFAULTS = {
|
|
9356
|
+
analysis_limit: { column: "analysis_limit", value: 0 },
|
|
9357
|
+
application_id: { column: "application_id", value: 0 },
|
|
9358
|
+
auto_vacuum: { column: "auto_vacuum", value: 0 },
|
|
9359
|
+
automatic_index: { column: "automatic_index", value: 1 },
|
|
9360
|
+
busy_timeout: { column: "timeout", value: 0 },
|
|
9361
|
+
cache_size: { column: "cache_size", value: 2e3 },
|
|
9362
|
+
cache_spill: { column: "cache_spill", value: 2e4 },
|
|
9363
|
+
cell_size_check: { column: "cell_size_check", value: 0 },
|
|
9364
|
+
checkpoint_fullfsync: { column: "checkpoint_fullfsync", value: 1 },
|
|
9365
|
+
count_changes: { column: "count_changes", value: 0 },
|
|
9366
|
+
data_version: { column: "data_version", value: 1 },
|
|
9367
|
+
default_cache_size: { column: "cache_size", value: 2e3 },
|
|
9368
|
+
defer_foreign_keys: { column: "defer_foreign_keys", value: 0 },
|
|
9369
|
+
empty_result_callbacks: { column: "empty_result_callbacks", value: 0 },
|
|
9370
|
+
encoding: { column: "encoding", value: "UTF-8" },
|
|
9371
|
+
freelist_count: { column: "freelist_count", value: 0 },
|
|
9372
|
+
full_column_names: { column: "full_column_names", value: 0 },
|
|
9373
|
+
fullfsync: { column: "fullfsync", value: 0 },
|
|
9374
|
+
hard_heap_limit: { column: "hard_heap_limit", value: 0 },
|
|
9375
|
+
ignore_check_constraints: { column: "ignore_check_constraints", value: 0 },
|
|
9376
|
+
journal_mode: { column: "journal_mode", value: "memory" },
|
|
9377
|
+
journal_size_limit: { column: "journal_size_limit", value: 32768 },
|
|
9378
|
+
legacy_alter_table: { column: "legacy_alter_table", value: 1 },
|
|
9379
|
+
locking_mode: { column: "locking_mode", value: "normal" },
|
|
9380
|
+
max_page_count: { column: "max_page_count", value: 1073741823 },
|
|
9381
|
+
page_size: { column: "page_size", value: 4096 },
|
|
9382
|
+
query_only: { column: "query_only", value: 0 },
|
|
9383
|
+
read_uncommitted: { column: "read_uncommitted", value: 0 },
|
|
9384
|
+
recursive_triggers: { column: "recursive_triggers", value: 0 },
|
|
9385
|
+
reverse_unordered_selects: { column: "reverse_unordered_selects", value: 0 },
|
|
9386
|
+
secure_delete: { column: "secure_delete", value: 2 },
|
|
9387
|
+
short_column_names: { column: "short_column_names", value: 1 },
|
|
9388
|
+
soft_heap_limit: { column: "soft_heap_limit", value: 0 },
|
|
9389
|
+
synchronous: { column: "synchronous", value: 2 },
|
|
9390
|
+
temp_store: { column: "temp_store", value: 0 },
|
|
9391
|
+
threads: { column: "threads", value: 0 },
|
|
9392
|
+
trusted_schema: { column: "trusted_schema", value: 1 },
|
|
9393
|
+
writable_schema: { column: "writable_schema", value: 0 }
|
|
9394
|
+
};
|
|
9395
|
+
function isPragmaTvfName(name) {
|
|
9396
|
+
const lower = name.toLowerCase();
|
|
9397
|
+
if (PRAGMA_TVF_NAMES.includes(lower)) return true;
|
|
9398
|
+
if (lower.startsWith("pragma_")) {
|
|
9399
|
+
return PRAGMA_TVF_NAMES.includes(lower.slice("pragma_".length));
|
|
9400
|
+
}
|
|
9401
|
+
return false;
|
|
9402
|
+
}
|
|
9403
|
+
function normalizePragmaKey(name) {
|
|
9404
|
+
const lower = name.toLowerCase();
|
|
9405
|
+
if (PRAGMA_TVF_NAMES.includes(lower)) return lower;
|
|
9406
|
+
if (lower.startsWith("pragma_")) {
|
|
9407
|
+
const stripped = lower.slice("pragma_".length);
|
|
9408
|
+
if (PRAGMA_TVF_NAMES.includes(stripped)) return stripped;
|
|
9409
|
+
return stripped;
|
|
9410
|
+
}
|
|
9411
|
+
return lower;
|
|
9412
|
+
}
|
|
9413
|
+
function queryPragma(name, args, env) {
|
|
9414
|
+
const key = normalizePragmaKey(name);
|
|
9415
|
+
switch (key) {
|
|
9416
|
+
case "foreign_keys":
|
|
9417
|
+
return single("foreign_keys", env.state.foreignKeysEnabled ? 1 : 0);
|
|
9418
|
+
case "user_version":
|
|
9419
|
+
return single("user_version", env.state.userVersion);
|
|
9420
|
+
case "schema_version":
|
|
9421
|
+
return single("schema_version", env.state.schemaVersion);
|
|
9422
|
+
case "table_info":
|
|
9423
|
+
return pragmaTableInfo(args, env, false);
|
|
9424
|
+
case "table_xinfo":
|
|
9425
|
+
return pragmaTableInfo(args, env, true);
|
|
9426
|
+
case "index_list":
|
|
9427
|
+
return pragmaIndexList(args, env);
|
|
9428
|
+
case "index_info":
|
|
9429
|
+
return pragmaIndexInfo(args, env, false);
|
|
9430
|
+
case "index_xinfo":
|
|
9431
|
+
return pragmaIndexInfo(args, env, true);
|
|
9432
|
+
case "foreign_key_list":
|
|
9433
|
+
return pragmaForeignKeyList(args, env);
|
|
9434
|
+
case "foreign_key_check":
|
|
9435
|
+
return pragmaForeignKeyCheck(args, env);
|
|
9436
|
+
case "database_list":
|
|
9437
|
+
return pragmaDatabaseList(env);
|
|
9438
|
+
case "table_list":
|
|
9439
|
+
return pragmaTableList(env);
|
|
9440
|
+
case "collation_list":
|
|
9441
|
+
return {
|
|
9442
|
+
columns: ["seq", "name"],
|
|
9443
|
+
rows: [
|
|
9444
|
+
[0, "RTRIM"],
|
|
9445
|
+
[1, "NOCASE"],
|
|
9446
|
+
[2, "BINARY"]
|
|
9447
|
+
]
|
|
9448
|
+
};
|
|
9449
|
+
case "compile_options":
|
|
9450
|
+
return { columns: ["compile_options"], rows: COMPILE_OPTIONS2.map((opt) => [opt]) };
|
|
9451
|
+
case "function_list":
|
|
9452
|
+
return pragmaFunctionList();
|
|
9453
|
+
case "module_list":
|
|
9454
|
+
return pragmaModuleList();
|
|
9455
|
+
case "pragma_list":
|
|
9456
|
+
return { columns: ["name"], rows: PRAGMA_LIST_NAMES.map((n) => [n]) };
|
|
9457
|
+
case "integrity_check":
|
|
9458
|
+
case "quick_check":
|
|
9459
|
+
return single(key, "ok");
|
|
9460
|
+
case "optimize":
|
|
9461
|
+
return { columns: ["optimize"], rows: [] };
|
|
9462
|
+
case "page_count":
|
|
9463
|
+
return single("page_count", estimatePageCount(env));
|
|
9464
|
+
default: {
|
|
9465
|
+
const storage = STORAGE_DEFAULTS[key];
|
|
9466
|
+
if (storage) return single(storage.column, storage.value);
|
|
9467
|
+
return { columns: [], rows: [] };
|
|
9468
|
+
}
|
|
9469
|
+
}
|
|
9470
|
+
}
|
|
9471
|
+
function single(column, value) {
|
|
9472
|
+
return { columns: [column], rows: [[value]] };
|
|
9473
|
+
}
|
|
9474
|
+
function estimatePageCount(env) {
|
|
9475
|
+
const objects = env.state.tables.size + env.state.indexes.size + env.state.views.size + env.state.virtualTables.size;
|
|
9476
|
+
return objects === 0 ? 0 : Math.max(1, objects);
|
|
9477
|
+
}
|
|
9478
|
+
function pragmaTableInfo(args, env, xinfo) {
|
|
9479
|
+
const tableName = requireNameArg(args, "table_info");
|
|
9480
|
+
const table = env.state.tables.get(tableName.toLowerCase());
|
|
9481
|
+
if (!table) return { columns: xinfoColumns(xinfo), rows: [] };
|
|
9482
|
+
const rows = table.columns.map((column, cid) => {
|
|
9483
|
+
const pkIndex = table.columns.filter((c) => c.primaryKey).findIndex((c) => c.name === column.name);
|
|
9484
|
+
const pk = column.primaryKey ? pkIndex >= 0 ? pkIndex + 1 : 1 : 0;
|
|
9485
|
+
const dflt = column.defaultExpr ? defaultLiteral(column.defaultExpr) : null;
|
|
9486
|
+
const base = [cid, column.name, column.typeName ?? "", column.notNull ? 1 : 0, dflt, pk];
|
|
9487
|
+
if (xinfo) {
|
|
9488
|
+
let hidden = 0;
|
|
9489
|
+
if (column.generated && !column.generated.stored) hidden = 2;
|
|
9490
|
+
if (column.generated?.stored) hidden = 3;
|
|
9491
|
+
base.push(hidden);
|
|
9492
|
+
}
|
|
9493
|
+
return base;
|
|
9494
|
+
});
|
|
9495
|
+
return { columns: xinfoColumns(xinfo), rows };
|
|
9496
|
+
}
|
|
9497
|
+
function xinfoColumns(xinfo) {
|
|
9498
|
+
return xinfo ? ["cid", "name", "type", "notnull", "dflt_value", "pk", "hidden"] : ["cid", "name", "type", "notnull", "dflt_value", "pk"];
|
|
9499
|
+
}
|
|
9500
|
+
function defaultLiteral(expr) {
|
|
9501
|
+
if (expr.type === "literal")
|
|
9502
|
+
return typeof expr.value === "string" ? `'${expr.value.replace(/'/g, "''")}'` : expr.value;
|
|
9503
|
+
if (expr.type === "null") return "NULL";
|
|
9504
|
+
return null;
|
|
9505
|
+
}
|
|
9506
|
+
function pragmaIndexList(args, env) {
|
|
9507
|
+
const tableName = requireNameArg(args, "index_list");
|
|
9508
|
+
const table = env.state.tables.get(tableName.toLowerCase());
|
|
9509
|
+
if (!table) return { columns: ["seq", "name", "unique", "origin", "partial"], rows: [] };
|
|
9510
|
+
const rows = [];
|
|
9511
|
+
let seq = 0;
|
|
9512
|
+
for (const name of table.indexes) {
|
|
9513
|
+
const index = env.state.indexes.get(name.toLowerCase());
|
|
9514
|
+
if (!index) continue;
|
|
9515
|
+
rows.push([seq++, index.name, index.unique ? 1 : 0, indexOrigin(index), index.where ? 1 : 0]);
|
|
9516
|
+
}
|
|
9517
|
+
return { columns: ["seq", "name", "unique", "origin", "partial"], rows };
|
|
9518
|
+
}
|
|
9519
|
+
function indexOrigin(index) {
|
|
9520
|
+
if (index.originalSql) return "c";
|
|
9521
|
+
if (index.name.toLowerCase().startsWith("sqlite_autoindex_") && index.unique) return "u";
|
|
9522
|
+
return "c";
|
|
9523
|
+
}
|
|
9524
|
+
function pragmaIndexInfo(args, env, xinfo) {
|
|
9525
|
+
const indexName = requireNameArg(args, "index_info");
|
|
9526
|
+
const index = env.state.indexes.get(indexName.toLowerCase());
|
|
9527
|
+
const columns = xinfo ? ["seqno", "cid", "name", "desc", "coll", "key"] : ["seqno", "cid", "name"];
|
|
9528
|
+
if (!index) return { columns, rows: [] };
|
|
9529
|
+
const table = env.state.tables.get(index.tableName.toLowerCase());
|
|
9530
|
+
const rows = index.columns.map((column, seqno) => {
|
|
9531
|
+
const cid = table?.columns.findIndex((c) => c.name.toLowerCase() === column.name.toLowerCase()) ?? -1;
|
|
9532
|
+
const base = [seqno, cid, column.name];
|
|
9533
|
+
if (xinfo) {
|
|
9534
|
+
base.push(column.order === "DESC" ? 1 : 0, (column.collate ?? "BINARY").toUpperCase(), 1);
|
|
9535
|
+
}
|
|
9536
|
+
return base;
|
|
9537
|
+
});
|
|
9538
|
+
if (xinfo) {
|
|
9539
|
+
rows.push([index.columns.length, -1, null, 0, "BINARY", 0]);
|
|
9540
|
+
}
|
|
9541
|
+
return { columns, rows };
|
|
9542
|
+
}
|
|
9543
|
+
function pragmaForeignKeyList(args, env) {
|
|
9544
|
+
const tableName = requireNameArg(args, "foreign_key_list");
|
|
9545
|
+
const table = env.state.tables.get(tableName.toLowerCase());
|
|
9546
|
+
const columns = ["id", "seq", "table", "from", "to", "on_update", "on_delete", "match"];
|
|
9547
|
+
if (!table) return { columns, rows: [] };
|
|
9548
|
+
const rows = [];
|
|
9549
|
+
let id = 0;
|
|
9550
|
+
for (const constraint of table.constraints) {
|
|
9551
|
+
if (constraint.type !== "foreign_key") continue;
|
|
9552
|
+
const refColumns = constraint.refColumns ?? env.state.tables.get(constraint.refTable.toLowerCase())?.columns.filter((c) => c.primaryKey).map((c) => c.name) ?? [];
|
|
9553
|
+
constraint.columns.forEach((column, seq) => {
|
|
9554
|
+
rows.push([
|
|
9555
|
+
id,
|
|
9556
|
+
seq,
|
|
9557
|
+
constraint.refTable,
|
|
9558
|
+
column,
|
|
9559
|
+
refColumns[seq] ?? null,
|
|
9560
|
+
constraint.onUpdate ?? "NO ACTION",
|
|
9561
|
+
constraint.onDelete ?? "NO ACTION",
|
|
9562
|
+
"NONE"
|
|
9563
|
+
]);
|
|
9564
|
+
});
|
|
9565
|
+
id++;
|
|
9566
|
+
}
|
|
9567
|
+
return { columns, rows };
|
|
9568
|
+
}
|
|
9569
|
+
function pragmaForeignKeyCheck(args, env) {
|
|
9570
|
+
const columns = ["table", "rowid", "parent", "fkid"];
|
|
9571
|
+
const filter = args[0] != null && args[0] !== null ? String(args[0]).toLowerCase() : null;
|
|
9572
|
+
const rows = [];
|
|
9573
|
+
for (const table of env.state.tables.values()) {
|
|
9574
|
+
if (filter && table.name.toLowerCase() !== filter) continue;
|
|
9575
|
+
let fkid = 0;
|
|
9576
|
+
for (const constraint of table.constraints) {
|
|
9577
|
+
if (constraint.type !== "foreign_key") continue;
|
|
9578
|
+
const parent = env.state.tables.get(constraint.refTable.toLowerCase());
|
|
9579
|
+
const refColumns = constraint.refColumns ?? parent?.columns.filter((c) => c.primaryKey).map((c) => c.name) ?? [];
|
|
9580
|
+
for (const row of table.scan()) {
|
|
9581
|
+
let allNull = true;
|
|
9582
|
+
const childValues = [];
|
|
9583
|
+
for (const col of constraint.columns) {
|
|
9584
|
+
const value = row.values.get(col.toLowerCase()) ?? null;
|
|
9585
|
+
childValues.push(value);
|
|
9586
|
+
if (value !== null) allNull = false;
|
|
9587
|
+
}
|
|
9588
|
+
if (allNull) continue;
|
|
9589
|
+
if (!parent || !parentHasMatch(parent, refColumns, childValues)) {
|
|
9590
|
+
rows.push([table.name, row.rowid, constraint.refTable, fkid]);
|
|
9591
|
+
}
|
|
9592
|
+
}
|
|
9593
|
+
fkid++;
|
|
9594
|
+
}
|
|
9595
|
+
}
|
|
9596
|
+
return { columns, rows };
|
|
9597
|
+
}
|
|
9598
|
+
function parentHasMatch(parent, refColumns, childValues) {
|
|
9599
|
+
if (refColumns.length === 0) return false;
|
|
9600
|
+
for (const row of parent.scan()) {
|
|
9601
|
+
let ok = true;
|
|
9602
|
+
for (let i = 0; i < refColumns.length; i++) {
|
|
9603
|
+
const parentVal = row.values.get(refColumns[i].toLowerCase()) ?? null;
|
|
9604
|
+
if (!sqlValuesEqual(parentVal, childValues[i] ?? null)) {
|
|
9605
|
+
ok = false;
|
|
9606
|
+
break;
|
|
9607
|
+
}
|
|
9608
|
+
}
|
|
9609
|
+
if (ok) return true;
|
|
9610
|
+
}
|
|
9611
|
+
return false;
|
|
9612
|
+
}
|
|
9613
|
+
function sqlValuesEqual(a, b) {
|
|
9614
|
+
if (a === null || b === null) return a === b;
|
|
9615
|
+
if (typeof a === "number" && typeof b === "number") return a === b;
|
|
9616
|
+
if (typeof a === "bigint" || typeof b === "bigint") {
|
|
9617
|
+
return BigInt(a) === BigInt(b);
|
|
9618
|
+
}
|
|
9619
|
+
if (a instanceof Uint8Array || b instanceof Uint8Array) return false;
|
|
9620
|
+
return String(a) === String(b);
|
|
9621
|
+
}
|
|
9622
|
+
function pragmaDatabaseList(env) {
|
|
9623
|
+
const rows = [[0, "main", ""]];
|
|
9624
|
+
let seq = 2;
|
|
9625
|
+
for (const [name, attached] of env.state.attached) {
|
|
9626
|
+
const file = attached.filename === ":memory:" ? "" : attached.filename;
|
|
9627
|
+
rows.push([seq++, name, file]);
|
|
9628
|
+
}
|
|
9629
|
+
return { columns: ["seq", "name", "file"], rows };
|
|
9630
|
+
}
|
|
9631
|
+
function pragmaTableList(env) {
|
|
9632
|
+
const columns = ["schema", "name", "type", "ncol", "wr", "strict"];
|
|
9633
|
+
const rows = [];
|
|
9634
|
+
for (const table of env.state.tables.values()) {
|
|
9635
|
+
rows.push(["main", table.name, "table", table.columns.length, table.withoutRowid ? 1 : 0, table.strict ? 1 : 0]);
|
|
9636
|
+
}
|
|
9637
|
+
for (const view of env.state.views.values()) {
|
|
9638
|
+
const ncol = view.columns?.length ?? 0;
|
|
9639
|
+
rows.push(["main", view.name, "view", ncol, 0, 0]);
|
|
9640
|
+
}
|
|
9641
|
+
for (const vt of env.state.virtualTables.values()) {
|
|
9642
|
+
rows.push(["main", vt.name, "virtual", vt.columns.length, 0, 0]);
|
|
9643
|
+
}
|
|
9644
|
+
rows.push(["main", "sqlite_schema", "table", 5, 0, 0]);
|
|
9645
|
+
rows.push(["temp", "sqlite_temp_schema", "table", 5, 0, 0]);
|
|
9646
|
+
for (const [schema] of env.state.attached) {
|
|
9647
|
+
rows.push([schema, "sqlite_schema", "table", 5, 0, 0]);
|
|
9648
|
+
}
|
|
9649
|
+
return { columns, rows };
|
|
9650
|
+
}
|
|
9651
|
+
function pragmaFunctionList() {
|
|
9652
|
+
const columns = ["name", "builtin", "type", "enc", "narg", "flags"];
|
|
9653
|
+
const rows = [];
|
|
9654
|
+
const add = (name, type, narg, flags) => {
|
|
9655
|
+
rows.push([name, 1, type, "utf8", narg, flags]);
|
|
9656
|
+
};
|
|
9657
|
+
for (const name of Object.keys(getScalarFunctions())) add(name, "s", -1, 2099200);
|
|
9658
|
+
for (const name of Object.keys(dateTimeFunctions)) add(name, "s", -1, 2099200);
|
|
9659
|
+
for (const name of Object.keys(jsonScalarFunctions)) add(name, "s", -1, 2099200);
|
|
9660
|
+
for (const name of Object.keys(mathFunctions)) add(name, "s", -1, 2099200);
|
|
9661
|
+
for (const name of Object.keys(ftsAuxFunctions)) add(name, "s", -1, 2099200);
|
|
9662
|
+
for (const name of Object.keys(rtreeAuxFunctions)) add(name, "s", -1, 2099200);
|
|
9663
|
+
for (const name of Object.keys(aggregateFunctions)) {
|
|
9664
|
+
add(name, "w", name === "count" ? 0 : 1, 2097152);
|
|
9665
|
+
if (name === "count") add(name, "w", 1, 2097152);
|
|
9666
|
+
}
|
|
9667
|
+
for (const name of Object.keys(jsonAggregateFunctions)) add(name, "w", -1, 2097152);
|
|
9668
|
+
for (const name of Object.keys(windowFunctions)) add(name, "w", -1, 2097152);
|
|
9669
|
+
for (const name of ["generate_series", "json_each", "json_tree"]) {
|
|
9670
|
+
add(name, "s", -1, 2099200);
|
|
9671
|
+
}
|
|
9672
|
+
rows.sort((a, b) => String(a[0]).localeCompare(String(b[0])) || Number(a[4]) - Number(b[4]));
|
|
9673
|
+
return { columns, rows };
|
|
9674
|
+
}
|
|
9675
|
+
function pragmaModuleList() {
|
|
9676
|
+
const names = /* @__PURE__ */ new Set([
|
|
9677
|
+
...MEMORY_VTABLE_MODULES,
|
|
9678
|
+
...PRAGMA_TVF_NAMES.map((n) => `pragma_${n}`),
|
|
9679
|
+
"generate_series",
|
|
9680
|
+
"json_each",
|
|
9681
|
+
"json_tree"
|
|
9682
|
+
]);
|
|
9683
|
+
return {
|
|
9684
|
+
columns: ["name"],
|
|
9685
|
+
rows: [...names].sort((a, b) => a.localeCompare(b)).map((name) => [name])
|
|
9686
|
+
};
|
|
9687
|
+
}
|
|
9688
|
+
function requireNameArg(args, pragma) {
|
|
9689
|
+
if (args.length === 0 || args[0] == null) {
|
|
9690
|
+
throw new SqliteError(`missing pragma argument for ${pragma}`, "misuse");
|
|
9691
|
+
}
|
|
9692
|
+
const value = args[0];
|
|
9693
|
+
if (typeof value === "string") return value;
|
|
9694
|
+
if (typeof value === "number" || typeof value === "bigint") return String(value);
|
|
9695
|
+
throw new SqliteError(`invalid pragma argument for ${pragma}`, "misuse");
|
|
9696
|
+
}
|
|
9697
|
+
function evalPragmaArgs(expr, env) {
|
|
9698
|
+
if (expr === null) return [];
|
|
9699
|
+
if (expr.type === "column" && expr.table === null) return [expr.name];
|
|
9700
|
+
if (expr.type === "literal") return [expr.value];
|
|
9701
|
+
return [evalExpr(expr, env.createEvalContext())];
|
|
9702
|
+
}
|
|
9703
|
+
function evalPragmaSetValue(expr, env) {
|
|
9704
|
+
if (expr.type === "column" && expr.table === null) {
|
|
9705
|
+
const keyword = expr.name.toLowerCase();
|
|
9706
|
+
if (keyword === "on" || keyword === "true" || keyword === "yes") return 1;
|
|
9707
|
+
if (keyword === "off" || keyword === "false" || keyword === "no") return 0;
|
|
9708
|
+
return expr.name;
|
|
9709
|
+
}
|
|
9710
|
+
return evalExpr(expr, env.createEvalContext());
|
|
9711
|
+
}
|
|
9712
|
+
function coercePragmaInt(value) {
|
|
9713
|
+
if (typeof value === "number") return Math.trunc(value);
|
|
9714
|
+
if (typeof value === "bigint") return Number(value);
|
|
9715
|
+
if (typeof value === "string") {
|
|
9716
|
+
const n = Number.parseInt(value, 10);
|
|
9717
|
+
return Number.isFinite(n) ? n : 0;
|
|
9718
|
+
}
|
|
9719
|
+
const asInt = toInteger(value);
|
|
9720
|
+
return asInt === null ? 0 : typeof asInt === "bigint" ? Number(asInt) : asInt;
|
|
9721
|
+
}
|
|
9722
|
+
function coercePragmaTruthy(value) {
|
|
9723
|
+
return isTruthySql(value) === true;
|
|
9724
|
+
}
|
|
9725
|
+
|
|
9726
|
+
// src/functions/table-valued-registry.ts
|
|
9194
9727
|
var registry = /* @__PURE__ */ new Map();
|
|
9728
|
+
function registerTableValuedFunction(name, fn) {
|
|
9729
|
+
registry.set(name.toLowerCase(), fn);
|
|
9730
|
+
}
|
|
9731
|
+
function getTableValuedFunction(name) {
|
|
9732
|
+
return registry.get(name.toLowerCase());
|
|
9733
|
+
}
|
|
9734
|
+
function hasRegisteredTableValuedFunction(name) {
|
|
9735
|
+
return registry.has(name.toLowerCase());
|
|
9736
|
+
}
|
|
9737
|
+
|
|
9738
|
+
// src/functions/pragma-tvf.ts
|
|
9739
|
+
function toTvfResult(alias, defaultName, columns, rows) {
|
|
9740
|
+
const table = alias ?? defaultName;
|
|
9741
|
+
return {
|
|
9742
|
+
columns,
|
|
9743
|
+
rows: rows.map((row) => ({
|
|
9744
|
+
cells: columns.map((name, index) => ({
|
|
9745
|
+
table,
|
|
9746
|
+
name,
|
|
9747
|
+
value: row[index] ?? null
|
|
9748
|
+
}))
|
|
9749
|
+
}))
|
|
9750
|
+
};
|
|
9751
|
+
}
|
|
9752
|
+
var registered = false;
|
|
9753
|
+
function ensurePragmaTvfsRegistered() {
|
|
9754
|
+
if (registered) return;
|
|
9755
|
+
registered = true;
|
|
9756
|
+
for (const baseName of PRAGMA_TVF_NAMES) {
|
|
9757
|
+
const tvfName = `pragma_${baseName}`;
|
|
9758
|
+
registerTableValuedFunction(tvfName, (args, alias, env) => {
|
|
9759
|
+
const result = queryPragma(baseName, args, env);
|
|
9760
|
+
return toTvfResult(alias, tvfName, result.columns, result.rows);
|
|
9761
|
+
});
|
|
9762
|
+
}
|
|
9763
|
+
}
|
|
9764
|
+
|
|
9765
|
+
// src/functions/table-valued.ts
|
|
9195
9766
|
var JSON_TVF_COLUMNS = ["key", "value", "type", "atom", "id", "parent", "fullkey", "path"];
|
|
9196
9767
|
function jsonTvfResult(alias, defaultName, rows) {
|
|
9197
9768
|
const table = alias ?? defaultName;
|
|
@@ -9206,7 +9777,7 @@ function jsonTvfResult(alias, defaultName, rows) {
|
|
|
9206
9777
|
}))
|
|
9207
9778
|
};
|
|
9208
9779
|
}
|
|
9209
|
-
|
|
9780
|
+
registerTableValuedFunction("generate_series", (args, alias) => {
|
|
9210
9781
|
if (args.length < 2 || args.length > 3) {
|
|
9211
9782
|
throw new SqliteError("wrong number of arguments to function generate_series()", "misuse");
|
|
9212
9783
|
}
|
|
@@ -9237,13 +9808,13 @@ registry.set("generate_series", (args, alias) => {
|
|
|
9237
9808
|
}
|
|
9238
9809
|
return { columns: ["value"], rows };
|
|
9239
9810
|
});
|
|
9240
|
-
|
|
9811
|
+
registerTableValuedFunction("json_each", (args, alias) => {
|
|
9241
9812
|
if (args.length < 1 || args.length > 2) {
|
|
9242
9813
|
throw new SqliteError("wrong number of arguments to function json_each()", "misuse");
|
|
9243
9814
|
}
|
|
9244
9815
|
return jsonTvfResult(alias, "json_each", jsonEachRows(args[0], args[1]));
|
|
9245
9816
|
});
|
|
9246
|
-
|
|
9817
|
+
registerTableValuedFunction("json_tree", (args, alias) => {
|
|
9247
9818
|
if (args.length < 1 || args.length > 2) {
|
|
9248
9819
|
throw new SqliteError("wrong number of arguments to function json_tree()", "misuse");
|
|
9249
9820
|
}
|
|
@@ -9253,11 +9824,16 @@ function safeInt(value) {
|
|
|
9253
9824
|
return value <= BigInt(Number.MAX_SAFE_INTEGER) && value >= BigInt(Number.MIN_SAFE_INTEGER) ? Number(value) : value;
|
|
9254
9825
|
}
|
|
9255
9826
|
function evaluateTableFunction(name, args, alias, env, scope, parent) {
|
|
9256
|
-
|
|
9827
|
+
ensurePragmaTvfsRegistered();
|
|
9828
|
+
const fn = getTableValuedFunction(name);
|
|
9257
9829
|
if (!fn) throw new SqliteError(`no such table-valued function: ${name}`, "no_such_table");
|
|
9258
9830
|
const values = args.map((arg) => evalExpr(arg, env.createEvalContext(scope ?? null, parent)));
|
|
9259
9831
|
return fn(values, alias, env);
|
|
9260
9832
|
}
|
|
9833
|
+
function hasTableValuedFunction(name) {
|
|
9834
|
+
ensurePragmaTvfsRegistered();
|
|
9835
|
+
return hasRegisteredTableValuedFunction(name);
|
|
9836
|
+
}
|
|
9261
9837
|
|
|
9262
9838
|
// src/schema/catalog.ts
|
|
9263
9839
|
function schemaCatalogRows(state) {
|
|
@@ -9988,10 +10564,10 @@ function executeSelect2(stmt, env, parent) {
|
|
|
9988
10564
|
rows = uniqueRows([...leftRows, ...rightRows]);
|
|
9989
10565
|
break;
|
|
9990
10566
|
case "INTERSECT":
|
|
9991
|
-
rows = uniqueRows(leftRows).filter((row) => rightRows.some((other) =>
|
|
10567
|
+
rows = uniqueRows(leftRows).filter((row) => rightRows.some((other) => rowsEqual2(row, other)));
|
|
9992
10568
|
break;
|
|
9993
10569
|
case "EXCEPT":
|
|
9994
|
-
rows = uniqueRows(leftRows).filter((row) => !rightRows.some((other) =>
|
|
10570
|
+
rows = uniqueRows(leftRows).filter((row) => !rightRows.some((other) => rowsEqual2(row, other)));
|
|
9995
10571
|
break;
|
|
9996
10572
|
}
|
|
9997
10573
|
if (stmt.orderBy.length > 0) rows.sort((a, b) => compareCompoundRows(a, b, stmt.orderBy, base.columns));
|
|
@@ -10025,7 +10601,7 @@ function executeWith(stmt, env, parent) {
|
|
|
10025
10601
|
env.ctes.set(key, valuesToResult(columns, delta));
|
|
10026
10602
|
const nextResult = executeSelect2(cte.select.compound.select, env, parent);
|
|
10027
10603
|
const candidates = resultValues(nextResult);
|
|
10028
|
-
const additions = cte.select.compound.op === "UNION ALL" ? candidates : candidates.filter((row) => !accumulated.some((existing) =>
|
|
10604
|
+
const additions = cte.select.compound.op === "UNION ALL" ? candidates : candidates.filter((row) => !accumulated.some((existing) => rowsEqual2(existing, row)));
|
|
10029
10605
|
if (additions.length === 0) break;
|
|
10030
10606
|
accumulated = [...accumulated, ...additions];
|
|
10031
10607
|
delta = additions;
|
|
@@ -10327,6 +10903,9 @@ function scanFrom(item, env, parent) {
|
|
|
10327
10903
|
if (item.type === "table_func") {
|
|
10328
10904
|
return evaluateTableFunction(item.name, item.args, item.alias, env).rows;
|
|
10329
10905
|
}
|
|
10906
|
+
if (item.type === "table" && isPragmaTvfName(item.name) && hasTableValuedFunction(item.name.toLowerCase())) {
|
|
10907
|
+
return evaluateTableFunction(item.name, [], item.alias, env, null, parent).rows;
|
|
10908
|
+
}
|
|
10330
10909
|
const alias = item.alias ?? item.name;
|
|
10331
10910
|
const qualified = item.schema ? `${item.schema}.${item.name}` : item.name;
|
|
10332
10911
|
const db = env.state.databaseForSchema(item.schema, qualified);
|
|
@@ -10499,6 +11078,14 @@ function shapeOf(item, env) {
|
|
|
10499
11078
|
value: null
|
|
10500
11079
|
}));
|
|
10501
11080
|
}
|
|
11081
|
+
if (item.type === "table" && isPragmaTvfName(item.name) && hasTableValuedFunction(item.name.toLowerCase())) {
|
|
11082
|
+
const columns = evaluateTableFunction(item.name, [], item.alias, env).columns;
|
|
11083
|
+
return columns.map((name) => ({
|
|
11084
|
+
table: item.alias ?? item.name,
|
|
11085
|
+
name,
|
|
11086
|
+
value: null
|
|
11087
|
+
}));
|
|
11088
|
+
}
|
|
10502
11089
|
const alias = item.alias ?? item.name;
|
|
10503
11090
|
const qualified = item.schema ? `${item.schema}.${item.name}` : item.name;
|
|
10504
11091
|
const db = env.state.databaseForSchema(item.schema, qualified);
|
|
@@ -10568,7 +11155,7 @@ function aggregateValue(expr, rows, env, parent) {
|
|
|
10568
11155
|
const ctx = env.createEvalContext(row, parent);
|
|
10569
11156
|
if (expr.filter && isTruthySql(evalExpr(expr.filter, ctx)) !== true) continue;
|
|
10570
11157
|
const args = expr.args === "*" ? [] : expr.args.map((arg) => evalExpr(arg, ctx));
|
|
10571
|
-
if (expr.distinct && seen.some((values) =>
|
|
11158
|
+
if (expr.distinct && seen.some((values) => rowsEqual2(values, args))) continue;
|
|
10572
11159
|
seen.push(args);
|
|
10573
11160
|
accumulator.step(args);
|
|
10574
11161
|
}
|
|
@@ -10579,7 +11166,7 @@ function windowValue(expr, current, rows, env, parent, namedWindows) {
|
|
|
10579
11166
|
const currentCtx = env.createEvalContext(current, parent);
|
|
10580
11167
|
const partitionKey = spec.partitionBy.map((item) => evalExpr(item, currentCtx));
|
|
10581
11168
|
const partition = rows.filter(
|
|
10582
|
-
(row) =>
|
|
11169
|
+
(row) => rowsEqual2(
|
|
10583
11170
|
partitionKey,
|
|
10584
11171
|
spec.partitionBy.map((item) => evalExpr(item, env.createEvalContext(row, parent)))
|
|
10585
11172
|
)
|
|
@@ -10608,13 +11195,13 @@ function windowValue(expr, current, rows, env, parent, namedWindows) {
|
|
|
10608
11195
|
if (name === "row_number") return index + 1;
|
|
10609
11196
|
if (name === "rank") {
|
|
10610
11197
|
let first = index;
|
|
10611
|
-
while (first > 0 &&
|
|
11198
|
+
while (first > 0 && rowsEqual2(orderKeys[first], orderKeys[first - 1])) first--;
|
|
10612
11199
|
return first + 1;
|
|
10613
11200
|
}
|
|
10614
11201
|
if (name === "dense_rank") {
|
|
10615
|
-
let
|
|
10616
|
-
for (let i = 1; i <= index; i++) if (!
|
|
10617
|
-
return
|
|
11202
|
+
let rank2 = 1;
|
|
11203
|
+
for (let i = 1; i <= index; i++) if (!rowsEqual2(orderKeys[i], orderKeys[i - 1])) rank2++;
|
|
11204
|
+
return rank2;
|
|
10618
11205
|
}
|
|
10619
11206
|
const evaluated = args.map((arg) => evalExpr(arg, currentCtx));
|
|
10620
11207
|
if (name === "lag" || name === "lead") {
|
|
@@ -10648,7 +11235,7 @@ function windowValue(expr, current, rows, env, parent, namedWindows) {
|
|
|
10648
11235
|
if (name === "cume_dist") {
|
|
10649
11236
|
if (partition.length === 0) return null;
|
|
10650
11237
|
let lastPeer = index;
|
|
10651
|
-
while (lastPeer + 1 < partition.length &&
|
|
11238
|
+
while (lastPeer + 1 < partition.length && rowsEqual2(orderKeys[lastPeer + 1], orderKeys[index])) {
|
|
10652
11239
|
lastPeer++;
|
|
10653
11240
|
}
|
|
10654
11241
|
return (lastPeer + 1) / partition.length;
|
|
@@ -10656,7 +11243,7 @@ function windowValue(expr, current, rows, env, parent, namedWindows) {
|
|
|
10656
11243
|
if (name === "percent_rank") {
|
|
10657
11244
|
if (partition.length <= 1) return 0;
|
|
10658
11245
|
let first = index;
|
|
10659
|
-
while (first > 0 &&
|
|
11246
|
+
while (first > 0 && rowsEqual2(orderKeys[first], orderKeys[first - 1])) first--;
|
|
10660
11247
|
return first / (partition.length - 1);
|
|
10661
11248
|
}
|
|
10662
11249
|
throw new SqliteError(`no such window function: ${expr.func.name}`, "other");
|
|
@@ -10681,7 +11268,7 @@ function frameBounds(spec, index, length, ctx, defaultFrameEnd, orderKeys) {
|
|
|
10681
11268
|
const isRangeLike = spec.frame.type === "RANGE" || spec.frame.type === "GROUPS";
|
|
10682
11269
|
let peerFirst = index;
|
|
10683
11270
|
if (isRangeLike && spec.orderBy.length > 0) {
|
|
10684
|
-
while (peerFirst > 0 &&
|
|
11271
|
+
while (peerFirst > 0 && rowsEqual2(orderKeys[peerFirst], orderKeys[peerFirst - 1])) peerFirst--;
|
|
10685
11272
|
}
|
|
10686
11273
|
const bound = (item, isStart) => {
|
|
10687
11274
|
switch (item.kind) {
|
|
@@ -10703,8 +11290,8 @@ function frameBounds(spec, index, length, ctx, defaultFrameEnd, orderKeys) {
|
|
|
10703
11290
|
function frameRows(partition, start, end, index, orderKeys, exclude) {
|
|
10704
11291
|
let peerFirst = index;
|
|
10705
11292
|
let peerLast = index;
|
|
10706
|
-
while (peerFirst > 0 &&
|
|
10707
|
-
while (peerLast + 1 < partition.length &&
|
|
11293
|
+
while (peerFirst > 0 && rowsEqual2(orderKeys[peerFirst], orderKeys[peerFirst - 1])) peerFirst--;
|
|
11294
|
+
while (peerLast + 1 < partition.length && rowsEqual2(orderKeys[peerLast], orderKeys[peerLast + 1])) peerLast++;
|
|
10708
11295
|
const rows = [];
|
|
10709
11296
|
for (let i = Math.max(0, start); i <= end && i < partition.length; i++) {
|
|
10710
11297
|
if (exclude === "current_row" && i === index) continue;
|
|
@@ -10930,7 +11517,7 @@ function referencesTable(select, name) {
|
|
|
10930
11517
|
};
|
|
10931
11518
|
return visit(select.from) || (select.compound ? referencesTable(select.compound.select, name) : false);
|
|
10932
11519
|
}
|
|
10933
|
-
function
|
|
11520
|
+
function rowsEqual2(left, right) {
|
|
10934
11521
|
return left.length === right.length && left.every((value, index) => {
|
|
10935
11522
|
const other = right[index] ?? null;
|
|
10936
11523
|
return value === null && other === null || value !== null && other !== null && sqlValueEquals(value, other);
|
|
@@ -12355,154 +12942,24 @@ function asExplicitRowid(value) {
|
|
|
12355
12942
|
// src/executor/pragma.ts
|
|
12356
12943
|
function executePragma(name, expr, env) {
|
|
12357
12944
|
const key = name.toLowerCase();
|
|
12358
|
-
|
|
12359
|
-
|
|
12360
|
-
|
|
12361
|
-
|
|
12362
|
-
return pragmaTableInfo(expr, env, false);
|
|
12363
|
-
case "table_xinfo":
|
|
12364
|
-
return pragmaTableInfo(expr, env, true);
|
|
12365
|
-
case "index_list":
|
|
12366
|
-
return pragmaIndexList(expr, env);
|
|
12367
|
-
case "index_info":
|
|
12368
|
-
return pragmaIndexInfo(expr, env);
|
|
12369
|
-
case "foreign_key_list":
|
|
12370
|
-
return pragmaForeignKeyList(expr, env);
|
|
12371
|
-
case "database_list":
|
|
12372
|
-
return pragmaDatabaseList(env);
|
|
12373
|
-
case "user_version":
|
|
12374
|
-
return pragmaIntVersion("user_version", expr, env, "userVersion");
|
|
12375
|
-
case "schema_version":
|
|
12376
|
-
return pragmaIntVersion("schema_version", expr, env, "schemaVersion");
|
|
12377
|
-
default:
|
|
12378
|
-
return emptyResult(0, env.state.lastInsertRowid);
|
|
12379
|
-
}
|
|
12380
|
-
}
|
|
12381
|
-
function pragmaForeignKeys(expr, env) {
|
|
12382
|
-
if (expr === null) {
|
|
12383
|
-
return valuesToResult(["foreign_keys"], [[env.state.foreignKeysEnabled ? 1 : 0]], 0, env.state.lastInsertRowid);
|
|
12384
|
-
}
|
|
12385
|
-
const value = pragmaValue(expr, env);
|
|
12386
|
-
if (!env.transactions.inTransaction) env.state.foreignKeysEnabled = isTruthySql(value) === true;
|
|
12387
|
-
return emptyResult(0, env.state.lastInsertRowid);
|
|
12388
|
-
}
|
|
12389
|
-
function pragmaTableInfo(expr, env, xinfo) {
|
|
12390
|
-
const tableName = pragmaTableArg(expr, env);
|
|
12391
|
-
const table = env.state.tables.get(tableName.toLowerCase());
|
|
12392
|
-
if (!table) return emptyResult(0, env.state.lastInsertRowid);
|
|
12393
|
-
const columns = xinfo ? ["cid", "name", "type", "notnull", "dflt_value", "pk", "hidden"] : ["cid", "name", "type", "notnull", "dflt_value", "pk"];
|
|
12394
|
-
const rows = table.columns.map((column, cid) => {
|
|
12395
|
-
const pkIndex = table.columns.filter((c) => c.primaryKey).findIndex((c) => c.name === column.name);
|
|
12396
|
-
const pk = column.primaryKey ? pkIndex >= 0 ? pkIndex + 1 : 1 : 0;
|
|
12397
|
-
const dflt = column.defaultExpr ? defaultLiteral(column.defaultExpr) : null;
|
|
12398
|
-
const base = [cid, column.name, column.typeName ?? "", column.notNull ? 1 : 0, dflt, pk];
|
|
12399
|
-
if (xinfo) {
|
|
12400
|
-
let hidden = 0;
|
|
12401
|
-
if (column.generated?.stored) hidden = 2;
|
|
12402
|
-
else if (column.generated) hidden = 2;
|
|
12403
|
-
if (column.generated && !column.generated.stored) hidden = 2;
|
|
12404
|
-
if (column.generated?.stored) hidden = 3;
|
|
12405
|
-
base.push(hidden);
|
|
12406
|
-
}
|
|
12407
|
-
return base;
|
|
12408
|
-
});
|
|
12409
|
-
return valuesToResult(columns, rows, 0, env.state.lastInsertRowid);
|
|
12410
|
-
}
|
|
12411
|
-
function defaultLiteral(expr) {
|
|
12412
|
-
if (expr.type === "literal")
|
|
12413
|
-
return typeof expr.value === "string" ? `'${expr.value.replace(/'/g, "''")}'` : expr.value;
|
|
12414
|
-
if (expr.type === "null") return "NULL";
|
|
12415
|
-
return null;
|
|
12416
|
-
}
|
|
12417
|
-
function pragmaIndexList(expr, env) {
|
|
12418
|
-
const tableName = pragmaTableArg(expr, env);
|
|
12419
|
-
const table = env.state.tables.get(tableName.toLowerCase());
|
|
12420
|
-
if (!table) return emptyResult(0, env.state.lastInsertRowid);
|
|
12421
|
-
const rows = [];
|
|
12422
|
-
let seq = 0;
|
|
12423
|
-
for (const name of table.indexes) {
|
|
12424
|
-
const index = env.state.indexes.get(name.toLowerCase());
|
|
12425
|
-
if (!index) continue;
|
|
12426
|
-
rows.push([seq++, index.name, index.unique ? 1 : 0, "c", 0]);
|
|
12427
|
-
}
|
|
12428
|
-
return valuesToResult(["seq", "name", "unique", "origin", "partial"], rows, 0, env.state.lastInsertRowid);
|
|
12429
|
-
}
|
|
12430
|
-
function pragmaIndexInfo(expr, env) {
|
|
12431
|
-
const indexName = pragmaTableArg(expr, env);
|
|
12432
|
-
const index = env.state.indexes.get(indexName.toLowerCase());
|
|
12433
|
-
if (!index) return emptyResult(0, env.state.lastInsertRowid);
|
|
12434
|
-
const table = env.state.getTable(index.tableName);
|
|
12435
|
-
const rows = index.columns.map((column, seqno) => {
|
|
12436
|
-
const cid = table.columns.findIndex((c) => c.name.toLowerCase() === column.name.toLowerCase());
|
|
12437
|
-
return [seqno, cid, column.name];
|
|
12438
|
-
});
|
|
12439
|
-
return valuesToResult(["seqno", "cid", "name"], rows, 0, env.state.lastInsertRowid);
|
|
12440
|
-
}
|
|
12441
|
-
function pragmaForeignKeyList(expr, env) {
|
|
12442
|
-
const tableName = pragmaTableArg(expr, env);
|
|
12443
|
-
const table = env.state.tables.get(tableName.toLowerCase());
|
|
12444
|
-
if (!table) return emptyResult(0, env.state.lastInsertRowid);
|
|
12445
|
-
const rows = [];
|
|
12446
|
-
let id = 0;
|
|
12447
|
-
for (const constraint of table.constraints) {
|
|
12448
|
-
if (constraint.type !== "foreign_key") continue;
|
|
12449
|
-
const refColumns = constraint.refColumns ?? env.state.tables.get(constraint.refTable.toLowerCase())?.columns.filter((c) => c.primaryKey).map((c) => c.name) ?? [];
|
|
12450
|
-
constraint.columns.forEach((column, seq) => {
|
|
12451
|
-
rows.push([
|
|
12452
|
-
id,
|
|
12453
|
-
seq,
|
|
12454
|
-
constraint.refTable,
|
|
12455
|
-
column,
|
|
12456
|
-
refColumns[seq] ?? null,
|
|
12457
|
-
constraint.onUpdate ?? "NO ACTION",
|
|
12458
|
-
constraint.onDelete ?? "NO ACTION",
|
|
12459
|
-
"NONE"
|
|
12460
|
-
]);
|
|
12461
|
-
});
|
|
12462
|
-
id++;
|
|
12463
|
-
}
|
|
12464
|
-
return valuesToResult(
|
|
12465
|
-
["id", "seq", "table", "from", "to", "on_update", "on_delete", "match"],
|
|
12466
|
-
rows,
|
|
12467
|
-
0,
|
|
12468
|
-
env.state.lastInsertRowid
|
|
12469
|
-
);
|
|
12470
|
-
}
|
|
12471
|
-
function pragmaDatabaseList(env) {
|
|
12472
|
-
const rows = [[0, "main", ""]];
|
|
12473
|
-
let seq = 2;
|
|
12474
|
-
for (const [name, attached] of env.state.attached) {
|
|
12475
|
-
const file = attached.filename === ":memory:" ? "" : attached.filename;
|
|
12476
|
-
rows.push([seq++, name, file]);
|
|
12945
|
+
if (key === "foreign_keys" && expr !== null) {
|
|
12946
|
+
const value = evalPragmaSetValue(expr, env);
|
|
12947
|
+
if (!env.transactions.inTransaction) env.state.foreignKeysEnabled = coercePragmaTruthy(value);
|
|
12948
|
+
return emptyResult(0, env.state.lastInsertRowid);
|
|
12477
12949
|
}
|
|
12478
|
-
|
|
12479
|
-
|
|
12480
|
-
|
|
12481
|
-
|
|
12482
|
-
|
|
12950
|
+
if ((key === "user_version" || key === "schema_version") && expr !== null) {
|
|
12951
|
+
const value = evalPragmaSetValue(expr, env);
|
|
12952
|
+
const num2 = coercePragmaInt(value);
|
|
12953
|
+
if (key === "user_version") env.state.userVersion = num2;
|
|
12954
|
+
else env.state.schemaVersion = num2;
|
|
12955
|
+
return emptyResult(0, env.state.lastInsertRowid);
|
|
12483
12956
|
}
|
|
12484
|
-
const
|
|
12485
|
-
const
|
|
12486
|
-
if (
|
|
12487
|
-
|
|
12488
|
-
return emptyResult(0, env.state.lastInsertRowid);
|
|
12489
|
-
}
|
|
12490
|
-
function pragmaTableArg(expr, env) {
|
|
12491
|
-
if (!expr) throw new SqliteError("missing pragma argument", "misuse");
|
|
12492
|
-
if (expr.type === "column" && expr.table === null) return expr.name;
|
|
12493
|
-
if (expr.type === "literal" && typeof expr.value === "string") return expr.value;
|
|
12494
|
-
const value = evalExpr(expr, env.createEvalContext());
|
|
12495
|
-
if (typeof value === "string") return value;
|
|
12496
|
-
throw new SqliteError("invalid pragma argument", "misuse");
|
|
12497
|
-
}
|
|
12498
|
-
function pragmaValue(expr, env) {
|
|
12499
|
-
if (expr.type === "column" && expr.table === null) {
|
|
12500
|
-
const keyword = expr.name.toLowerCase();
|
|
12501
|
-
if (keyword === "on" || keyword === "true" || keyword === "yes") return 1;
|
|
12502
|
-
if (keyword === "off" || keyword === "false" || keyword === "no") return 0;
|
|
12503
|
-
return expr.name;
|
|
12957
|
+
const args = evalPragmaArgs(expr, env);
|
|
12958
|
+
const result = queryPragma(key, args, env);
|
|
12959
|
+
if (result.columns.length === 0 && result.rows.length === 0) {
|
|
12960
|
+
return emptyResult(0, env.state.lastInsertRowid);
|
|
12504
12961
|
}
|
|
12505
|
-
return
|
|
12962
|
+
return valuesToResult(result.columns, result.rows, 0, env.state.lastInsertRowid);
|
|
12506
12963
|
}
|
|
12507
12964
|
|
|
12508
12965
|
// src/executor/execute.ts
|