@crvouga/sqlite-mem 1.0.0 → 1.1.1
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 +31 -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 +9 -4
- package/dist/index.js +681 -166
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9190,8 +9190,629 @@ 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 pragmaTvfColumns(name) {
|
|
9404
|
+
const key = normalizePragmaKey(name);
|
|
9405
|
+
switch (key) {
|
|
9406
|
+
case "foreign_keys":
|
|
9407
|
+
return ["foreign_keys"];
|
|
9408
|
+
case "user_version":
|
|
9409
|
+
return ["user_version"];
|
|
9410
|
+
case "schema_version":
|
|
9411
|
+
return ["schema_version"];
|
|
9412
|
+
case "table_info":
|
|
9413
|
+
return ["cid", "name", "type", "notnull", "dflt_value", "pk"];
|
|
9414
|
+
case "table_xinfo":
|
|
9415
|
+
return ["cid", "name", "type", "notnull", "dflt_value", "pk", "hidden"];
|
|
9416
|
+
case "index_list":
|
|
9417
|
+
return ["seq", "name", "unique", "origin", "partial"];
|
|
9418
|
+
case "index_info":
|
|
9419
|
+
return ["seqno", "cid", "name"];
|
|
9420
|
+
case "index_xinfo":
|
|
9421
|
+
return ["seqno", "cid", "name", "desc", "coll", "key"];
|
|
9422
|
+
case "foreign_key_list":
|
|
9423
|
+
return ["id", "seq", "table", "from", "to", "on_update", "on_delete", "match"];
|
|
9424
|
+
case "foreign_key_check":
|
|
9425
|
+
return ["table", "rowid", "parent", "fkid"];
|
|
9426
|
+
case "database_list":
|
|
9427
|
+
return ["seq", "name", "file"];
|
|
9428
|
+
case "table_list":
|
|
9429
|
+
return ["schema", "name", "type", "ncol", "wr", "strict"];
|
|
9430
|
+
case "collation_list":
|
|
9431
|
+
return ["seq", "name"];
|
|
9432
|
+
case "compile_options":
|
|
9433
|
+
return ["compile_options"];
|
|
9434
|
+
case "function_list":
|
|
9435
|
+
return ["name", "builtin", "type", "enc", "narg", "flags"];
|
|
9436
|
+
case "module_list":
|
|
9437
|
+
case "pragma_list":
|
|
9438
|
+
return ["name"];
|
|
9439
|
+
case "integrity_check":
|
|
9440
|
+
case "quick_check":
|
|
9441
|
+
return [key];
|
|
9442
|
+
case "optimize":
|
|
9443
|
+
return ["optimize"];
|
|
9444
|
+
case "page_count":
|
|
9445
|
+
return ["page_count"];
|
|
9446
|
+
default: {
|
|
9447
|
+
const storage = STORAGE_DEFAULTS[key];
|
|
9448
|
+
if (storage) return [storage.column];
|
|
9449
|
+
return null;
|
|
9450
|
+
}
|
|
9451
|
+
}
|
|
9452
|
+
}
|
|
9453
|
+
function normalizePragmaKey(name) {
|
|
9454
|
+
const lower = name.toLowerCase();
|
|
9455
|
+
if (PRAGMA_TVF_NAMES.includes(lower)) return lower;
|
|
9456
|
+
if (lower.startsWith("pragma_")) {
|
|
9457
|
+
const stripped = lower.slice("pragma_".length);
|
|
9458
|
+
if (PRAGMA_TVF_NAMES.includes(stripped)) return stripped;
|
|
9459
|
+
return stripped;
|
|
9460
|
+
}
|
|
9461
|
+
return lower;
|
|
9462
|
+
}
|
|
9463
|
+
function queryPragma(name, args, env) {
|
|
9464
|
+
const key = normalizePragmaKey(name);
|
|
9465
|
+
switch (key) {
|
|
9466
|
+
case "foreign_keys":
|
|
9467
|
+
return single("foreign_keys", env.state.foreignKeysEnabled ? 1 : 0);
|
|
9468
|
+
case "user_version":
|
|
9469
|
+
return single("user_version", env.state.userVersion);
|
|
9470
|
+
case "schema_version":
|
|
9471
|
+
return single("schema_version", env.state.schemaVersion);
|
|
9472
|
+
case "table_info":
|
|
9473
|
+
return pragmaTableInfo(args, env, false);
|
|
9474
|
+
case "table_xinfo":
|
|
9475
|
+
return pragmaTableInfo(args, env, true);
|
|
9476
|
+
case "index_list":
|
|
9477
|
+
return pragmaIndexList(args, env);
|
|
9478
|
+
case "index_info":
|
|
9479
|
+
return pragmaIndexInfo(args, env, false);
|
|
9480
|
+
case "index_xinfo":
|
|
9481
|
+
return pragmaIndexInfo(args, env, true);
|
|
9482
|
+
case "foreign_key_list":
|
|
9483
|
+
return pragmaForeignKeyList(args, env);
|
|
9484
|
+
case "foreign_key_check":
|
|
9485
|
+
return pragmaForeignKeyCheck(args, env);
|
|
9486
|
+
case "database_list":
|
|
9487
|
+
return pragmaDatabaseList(env);
|
|
9488
|
+
case "table_list":
|
|
9489
|
+
return pragmaTableList(env);
|
|
9490
|
+
case "collation_list":
|
|
9491
|
+
return {
|
|
9492
|
+
columns: ["seq", "name"],
|
|
9493
|
+
rows: [
|
|
9494
|
+
[0, "RTRIM"],
|
|
9495
|
+
[1, "NOCASE"],
|
|
9496
|
+
[2, "BINARY"]
|
|
9497
|
+
]
|
|
9498
|
+
};
|
|
9499
|
+
case "compile_options":
|
|
9500
|
+
return { columns: ["compile_options"], rows: COMPILE_OPTIONS2.map((opt) => [opt]) };
|
|
9501
|
+
case "function_list":
|
|
9502
|
+
return pragmaFunctionList();
|
|
9503
|
+
case "module_list":
|
|
9504
|
+
return pragmaModuleList();
|
|
9505
|
+
case "pragma_list":
|
|
9506
|
+
return { columns: ["name"], rows: PRAGMA_LIST_NAMES.map((n) => [n]) };
|
|
9507
|
+
case "integrity_check":
|
|
9508
|
+
case "quick_check":
|
|
9509
|
+
return single(key, "ok");
|
|
9510
|
+
case "optimize":
|
|
9511
|
+
return { columns: ["optimize"], rows: [] };
|
|
9512
|
+
case "page_count":
|
|
9513
|
+
return single("page_count", estimatePageCount(env));
|
|
9514
|
+
default: {
|
|
9515
|
+
const storage = STORAGE_DEFAULTS[key];
|
|
9516
|
+
if (storage) return single(storage.column, storage.value);
|
|
9517
|
+
return { columns: [], rows: [] };
|
|
9518
|
+
}
|
|
9519
|
+
}
|
|
9520
|
+
}
|
|
9521
|
+
function single(column, value) {
|
|
9522
|
+
return { columns: [column], rows: [[value]] };
|
|
9523
|
+
}
|
|
9524
|
+
function estimatePageCount(env) {
|
|
9525
|
+
const objects = env.state.tables.size + env.state.indexes.size + env.state.views.size + env.state.virtualTables.size;
|
|
9526
|
+
return objects === 0 ? 0 : Math.max(1, objects);
|
|
9527
|
+
}
|
|
9528
|
+
function pragmaTableInfo(args, env, xinfo) {
|
|
9529
|
+
const tableName = requireNameArg(args, "table_info");
|
|
9530
|
+
const table = env.state.tables.get(tableName.toLowerCase());
|
|
9531
|
+
if (!table) return { columns: xinfoColumns(xinfo), rows: [] };
|
|
9532
|
+
const rows = table.columns.map((column, cid) => {
|
|
9533
|
+
const pkIndex = table.columns.filter((c) => c.primaryKey).findIndex((c) => c.name === column.name);
|
|
9534
|
+
const pk = column.primaryKey ? pkIndex >= 0 ? pkIndex + 1 : 1 : 0;
|
|
9535
|
+
const dflt = column.defaultExpr ? defaultLiteral(column.defaultExpr) : null;
|
|
9536
|
+
const base = [cid, column.name, column.typeName ?? "", column.notNull ? 1 : 0, dflt, pk];
|
|
9537
|
+
if (xinfo) {
|
|
9538
|
+
let hidden = 0;
|
|
9539
|
+
if (column.generated && !column.generated.stored) hidden = 2;
|
|
9540
|
+
if (column.generated?.stored) hidden = 3;
|
|
9541
|
+
base.push(hidden);
|
|
9542
|
+
}
|
|
9543
|
+
return base;
|
|
9544
|
+
});
|
|
9545
|
+
return { columns: xinfoColumns(xinfo), rows };
|
|
9546
|
+
}
|
|
9547
|
+
function xinfoColumns(xinfo) {
|
|
9548
|
+
return xinfo ? ["cid", "name", "type", "notnull", "dflt_value", "pk", "hidden"] : ["cid", "name", "type", "notnull", "dflt_value", "pk"];
|
|
9549
|
+
}
|
|
9550
|
+
function defaultLiteral(expr) {
|
|
9551
|
+
if (expr.type === "literal")
|
|
9552
|
+
return typeof expr.value === "string" ? `'${expr.value.replace(/'/g, "''")}'` : expr.value;
|
|
9553
|
+
if (expr.type === "null") return "NULL";
|
|
9554
|
+
return null;
|
|
9555
|
+
}
|
|
9556
|
+
function pragmaIndexList(args, env) {
|
|
9557
|
+
const tableName = requireNameArg(args, "index_list");
|
|
9558
|
+
const table = env.state.tables.get(tableName.toLowerCase());
|
|
9559
|
+
if (!table) return { columns: ["seq", "name", "unique", "origin", "partial"], rows: [] };
|
|
9560
|
+
const rows = [];
|
|
9561
|
+
let seq = 0;
|
|
9562
|
+
for (const name of table.indexes) {
|
|
9563
|
+
const index = env.state.indexes.get(name.toLowerCase());
|
|
9564
|
+
if (!index) continue;
|
|
9565
|
+
rows.push([seq++, index.name, index.unique ? 1 : 0, indexOrigin(index), index.where ? 1 : 0]);
|
|
9566
|
+
}
|
|
9567
|
+
return { columns: ["seq", "name", "unique", "origin", "partial"], rows };
|
|
9568
|
+
}
|
|
9569
|
+
function indexOrigin(index) {
|
|
9570
|
+
if (index.originalSql) return "c";
|
|
9571
|
+
if (index.name.toLowerCase().startsWith("sqlite_autoindex_") && index.unique) return "u";
|
|
9572
|
+
return "c";
|
|
9573
|
+
}
|
|
9574
|
+
function pragmaIndexInfo(args, env, xinfo) {
|
|
9575
|
+
const indexName = requireNameArg(args, "index_info");
|
|
9576
|
+
const index = env.state.indexes.get(indexName.toLowerCase());
|
|
9577
|
+
const columns = xinfo ? ["seqno", "cid", "name", "desc", "coll", "key"] : ["seqno", "cid", "name"];
|
|
9578
|
+
if (!index) return { columns, rows: [] };
|
|
9579
|
+
const table = env.state.tables.get(index.tableName.toLowerCase());
|
|
9580
|
+
const rows = index.columns.map((column, seqno) => {
|
|
9581
|
+
const cid = table?.columns.findIndex((c) => c.name.toLowerCase() === column.name.toLowerCase()) ?? -1;
|
|
9582
|
+
const base = [seqno, cid, column.name];
|
|
9583
|
+
if (xinfo) {
|
|
9584
|
+
base.push(column.order === "DESC" ? 1 : 0, (column.collate ?? "BINARY").toUpperCase(), 1);
|
|
9585
|
+
}
|
|
9586
|
+
return base;
|
|
9587
|
+
});
|
|
9588
|
+
if (xinfo) {
|
|
9589
|
+
rows.push([index.columns.length, -1, null, 0, "BINARY", 0]);
|
|
9590
|
+
}
|
|
9591
|
+
return { columns, rows };
|
|
9592
|
+
}
|
|
9593
|
+
function pragmaForeignKeyList(args, env) {
|
|
9594
|
+
const tableName = requireNameArg(args, "foreign_key_list");
|
|
9595
|
+
const table = env.state.tables.get(tableName.toLowerCase());
|
|
9596
|
+
const columns = ["id", "seq", "table", "from", "to", "on_update", "on_delete", "match"];
|
|
9597
|
+
if (!table) return { columns, rows: [] };
|
|
9598
|
+
const rows = [];
|
|
9599
|
+
let id = 0;
|
|
9600
|
+
for (const constraint of table.constraints) {
|
|
9601
|
+
if (constraint.type !== "foreign_key") continue;
|
|
9602
|
+
const refColumns = constraint.refColumns ?? env.state.tables.get(constraint.refTable.toLowerCase())?.columns.filter((c) => c.primaryKey).map((c) => c.name) ?? [];
|
|
9603
|
+
constraint.columns.forEach((column, seq) => {
|
|
9604
|
+
rows.push([
|
|
9605
|
+
id,
|
|
9606
|
+
seq,
|
|
9607
|
+
constraint.refTable,
|
|
9608
|
+
column,
|
|
9609
|
+
refColumns[seq] ?? null,
|
|
9610
|
+
constraint.onUpdate ?? "NO ACTION",
|
|
9611
|
+
constraint.onDelete ?? "NO ACTION",
|
|
9612
|
+
"NONE"
|
|
9613
|
+
]);
|
|
9614
|
+
});
|
|
9615
|
+
id++;
|
|
9616
|
+
}
|
|
9617
|
+
return { columns, rows };
|
|
9618
|
+
}
|
|
9619
|
+
function pragmaForeignKeyCheck(args, env) {
|
|
9620
|
+
const columns = ["table", "rowid", "parent", "fkid"];
|
|
9621
|
+
const filter = args[0] != null && args[0] !== null ? String(args[0]).toLowerCase() : null;
|
|
9622
|
+
const rows = [];
|
|
9623
|
+
for (const table of env.state.tables.values()) {
|
|
9624
|
+
if (filter && table.name.toLowerCase() !== filter) continue;
|
|
9625
|
+
let fkid = 0;
|
|
9626
|
+
for (const constraint of table.constraints) {
|
|
9627
|
+
if (constraint.type !== "foreign_key") continue;
|
|
9628
|
+
const parent = env.state.tables.get(constraint.refTable.toLowerCase());
|
|
9629
|
+
const refColumns = constraint.refColumns ?? parent?.columns.filter((c) => c.primaryKey).map((c) => c.name) ?? [];
|
|
9630
|
+
for (const row of table.scan()) {
|
|
9631
|
+
let allNull = true;
|
|
9632
|
+
const childValues = [];
|
|
9633
|
+
for (const col of constraint.columns) {
|
|
9634
|
+
const value = row.values.get(col.toLowerCase()) ?? null;
|
|
9635
|
+
childValues.push(value);
|
|
9636
|
+
if (value !== null) allNull = false;
|
|
9637
|
+
}
|
|
9638
|
+
if (allNull) continue;
|
|
9639
|
+
if (!parent || !parentHasMatch(parent, refColumns, childValues)) {
|
|
9640
|
+
rows.push([table.name, row.rowid, constraint.refTable, fkid]);
|
|
9641
|
+
}
|
|
9642
|
+
}
|
|
9643
|
+
fkid++;
|
|
9644
|
+
}
|
|
9645
|
+
}
|
|
9646
|
+
return { columns, rows };
|
|
9647
|
+
}
|
|
9648
|
+
function parentHasMatch(parent, refColumns, childValues) {
|
|
9649
|
+
if (refColumns.length === 0) return false;
|
|
9650
|
+
for (const row of parent.scan()) {
|
|
9651
|
+
let ok = true;
|
|
9652
|
+
for (let i = 0; i < refColumns.length; i++) {
|
|
9653
|
+
const parentVal = row.values.get(refColumns[i].toLowerCase()) ?? null;
|
|
9654
|
+
if (!sqlValuesEqual(parentVal, childValues[i] ?? null)) {
|
|
9655
|
+
ok = false;
|
|
9656
|
+
break;
|
|
9657
|
+
}
|
|
9658
|
+
}
|
|
9659
|
+
if (ok) return true;
|
|
9660
|
+
}
|
|
9661
|
+
return false;
|
|
9662
|
+
}
|
|
9663
|
+
function sqlValuesEqual(a, b) {
|
|
9664
|
+
if (a === null || b === null) return a === b;
|
|
9665
|
+
if (typeof a === "number" && typeof b === "number") return a === b;
|
|
9666
|
+
if (typeof a === "bigint" || typeof b === "bigint") {
|
|
9667
|
+
return BigInt(a) === BigInt(b);
|
|
9668
|
+
}
|
|
9669
|
+
if (a instanceof Uint8Array || b instanceof Uint8Array) return false;
|
|
9670
|
+
return String(a) === String(b);
|
|
9671
|
+
}
|
|
9672
|
+
function pragmaDatabaseList(env) {
|
|
9673
|
+
const rows = [[0, "main", ""]];
|
|
9674
|
+
let seq = 2;
|
|
9675
|
+
for (const [name, attached] of env.state.attached) {
|
|
9676
|
+
const file = attached.filename === ":memory:" ? "" : attached.filename;
|
|
9677
|
+
rows.push([seq++, name, file]);
|
|
9678
|
+
}
|
|
9679
|
+
return { columns: ["seq", "name", "file"], rows };
|
|
9680
|
+
}
|
|
9681
|
+
function pragmaTableList(env) {
|
|
9682
|
+
const columns = ["schema", "name", "type", "ncol", "wr", "strict"];
|
|
9683
|
+
const rows = [];
|
|
9684
|
+
for (const table of env.state.tables.values()) {
|
|
9685
|
+
rows.push(["main", table.name, "table", table.columns.length, table.withoutRowid ? 1 : 0, table.strict ? 1 : 0]);
|
|
9686
|
+
}
|
|
9687
|
+
for (const view of env.state.views.values()) {
|
|
9688
|
+
const ncol = view.columns?.length ?? 0;
|
|
9689
|
+
rows.push(["main", view.name, "view", ncol, 0, 0]);
|
|
9690
|
+
}
|
|
9691
|
+
for (const vt of env.state.virtualTables.values()) {
|
|
9692
|
+
rows.push(["main", vt.name, "virtual", vt.columns.length, 0, 0]);
|
|
9693
|
+
}
|
|
9694
|
+
rows.push(["main", "sqlite_schema", "table", 5, 0, 0]);
|
|
9695
|
+
rows.push(["temp", "sqlite_temp_schema", "table", 5, 0, 0]);
|
|
9696
|
+
for (const [schema] of env.state.attached) {
|
|
9697
|
+
rows.push([schema, "sqlite_schema", "table", 5, 0, 0]);
|
|
9698
|
+
}
|
|
9699
|
+
return { columns, rows };
|
|
9700
|
+
}
|
|
9701
|
+
function pragmaFunctionList() {
|
|
9702
|
+
const columns = ["name", "builtin", "type", "enc", "narg", "flags"];
|
|
9703
|
+
const rows = [];
|
|
9704
|
+
const add = (name, type, narg, flags) => {
|
|
9705
|
+
rows.push([name, 1, type, "utf8", narg, flags]);
|
|
9706
|
+
};
|
|
9707
|
+
for (const name of Object.keys(getScalarFunctions())) add(name, "s", -1, 2099200);
|
|
9708
|
+
for (const name of Object.keys(dateTimeFunctions)) add(name, "s", -1, 2099200);
|
|
9709
|
+
for (const name of Object.keys(jsonScalarFunctions)) add(name, "s", -1, 2099200);
|
|
9710
|
+
for (const name of Object.keys(mathFunctions)) add(name, "s", -1, 2099200);
|
|
9711
|
+
for (const name of Object.keys(ftsAuxFunctions)) add(name, "s", -1, 2099200);
|
|
9712
|
+
for (const name of Object.keys(rtreeAuxFunctions)) add(name, "s", -1, 2099200);
|
|
9713
|
+
for (const name of Object.keys(aggregateFunctions)) {
|
|
9714
|
+
add(name, "w", name === "count" ? 0 : 1, 2097152);
|
|
9715
|
+
if (name === "count") add(name, "w", 1, 2097152);
|
|
9716
|
+
}
|
|
9717
|
+
for (const name of Object.keys(jsonAggregateFunctions)) add(name, "w", -1, 2097152);
|
|
9718
|
+
for (const name of Object.keys(windowFunctions)) add(name, "w", -1, 2097152);
|
|
9719
|
+
for (const name of ["generate_series", "json_each", "json_tree"]) {
|
|
9720
|
+
add(name, "s", -1, 2099200);
|
|
9721
|
+
}
|
|
9722
|
+
rows.sort((a, b) => String(a[0]).localeCompare(String(b[0])) || Number(a[4]) - Number(b[4]));
|
|
9723
|
+
return { columns, rows };
|
|
9724
|
+
}
|
|
9725
|
+
function pragmaModuleList() {
|
|
9726
|
+
const names = /* @__PURE__ */ new Set([
|
|
9727
|
+
...MEMORY_VTABLE_MODULES,
|
|
9728
|
+
...PRAGMA_TVF_NAMES.map((n) => `pragma_${n}`),
|
|
9729
|
+
"generate_series",
|
|
9730
|
+
"json_each",
|
|
9731
|
+
"json_tree"
|
|
9732
|
+
]);
|
|
9733
|
+
return {
|
|
9734
|
+
columns: ["name"],
|
|
9735
|
+
rows: [...names].sort((a, b) => a.localeCompare(b)).map((name) => [name])
|
|
9736
|
+
};
|
|
9737
|
+
}
|
|
9738
|
+
function requireNameArg(args, pragma) {
|
|
9739
|
+
if (args.length === 0 || args[0] == null) {
|
|
9740
|
+
throw new SqliteError(`missing pragma argument for ${pragma}`, "misuse");
|
|
9741
|
+
}
|
|
9742
|
+
const value = args[0];
|
|
9743
|
+
if (typeof value === "string") return value;
|
|
9744
|
+
if (typeof value === "number" || typeof value === "bigint") return String(value);
|
|
9745
|
+
throw new SqliteError(`invalid pragma argument for ${pragma}`, "misuse");
|
|
9746
|
+
}
|
|
9747
|
+
function evalPragmaArgs(expr, env) {
|
|
9748
|
+
if (expr === null) return [];
|
|
9749
|
+
if (expr.type === "column" && expr.table === null) return [expr.name];
|
|
9750
|
+
if (expr.type === "literal") return [expr.value];
|
|
9751
|
+
return [evalExpr(expr, env.createEvalContext())];
|
|
9752
|
+
}
|
|
9753
|
+
function evalPragmaSetValue(expr, env) {
|
|
9754
|
+
if (expr.type === "column" && expr.table === null) {
|
|
9755
|
+
const keyword = expr.name.toLowerCase();
|
|
9756
|
+
if (keyword === "on" || keyword === "true" || keyword === "yes") return 1;
|
|
9757
|
+
if (keyword === "off" || keyword === "false" || keyword === "no") return 0;
|
|
9758
|
+
return expr.name;
|
|
9759
|
+
}
|
|
9760
|
+
return evalExpr(expr, env.createEvalContext());
|
|
9761
|
+
}
|
|
9762
|
+
function coercePragmaInt(value) {
|
|
9763
|
+
if (typeof value === "number") return Math.trunc(value);
|
|
9764
|
+
if (typeof value === "bigint") return Number(value);
|
|
9765
|
+
if (typeof value === "string") {
|
|
9766
|
+
const n = Number.parseInt(value, 10);
|
|
9767
|
+
return Number.isFinite(n) ? n : 0;
|
|
9768
|
+
}
|
|
9769
|
+
const asInt = toInteger(value);
|
|
9770
|
+
return asInt === null ? 0 : typeof asInt === "bigint" ? Number(asInt) : asInt;
|
|
9771
|
+
}
|
|
9772
|
+
function coercePragmaTruthy(value) {
|
|
9773
|
+
return isTruthySql(value) === true;
|
|
9774
|
+
}
|
|
9775
|
+
|
|
9776
|
+
// src/functions/table-valued-registry.ts
|
|
9194
9777
|
var registry = /* @__PURE__ */ new Map();
|
|
9778
|
+
function registerTableValuedFunction(name, fn) {
|
|
9779
|
+
registry.set(name.toLowerCase(), fn);
|
|
9780
|
+
}
|
|
9781
|
+
function getTableValuedFunction(name) {
|
|
9782
|
+
return registry.get(name.toLowerCase());
|
|
9783
|
+
}
|
|
9784
|
+
function hasRegisteredTableValuedFunction(name) {
|
|
9785
|
+
return registry.has(name.toLowerCase());
|
|
9786
|
+
}
|
|
9787
|
+
|
|
9788
|
+
// src/functions/pragma-tvf.ts
|
|
9789
|
+
function toTvfResult(alias, defaultName, columns, rows) {
|
|
9790
|
+
const table = alias ?? defaultName;
|
|
9791
|
+
return {
|
|
9792
|
+
columns,
|
|
9793
|
+
rows: rows.map((row) => ({
|
|
9794
|
+
cells: columns.map((name, index) => ({
|
|
9795
|
+
table,
|
|
9796
|
+
name,
|
|
9797
|
+
value: row[index] ?? null
|
|
9798
|
+
}))
|
|
9799
|
+
}))
|
|
9800
|
+
};
|
|
9801
|
+
}
|
|
9802
|
+
var registered = false;
|
|
9803
|
+
function ensurePragmaTvfsRegistered() {
|
|
9804
|
+
if (registered) return;
|
|
9805
|
+
registered = true;
|
|
9806
|
+
for (const baseName of PRAGMA_TVF_NAMES) {
|
|
9807
|
+
const tvfName = `pragma_${baseName}`;
|
|
9808
|
+
registerTableValuedFunction(tvfName, (args, alias, env) => {
|
|
9809
|
+
const result = queryPragma(baseName, args, env);
|
|
9810
|
+
return toTvfResult(alias, tvfName, result.columns, result.rows);
|
|
9811
|
+
});
|
|
9812
|
+
}
|
|
9813
|
+
}
|
|
9814
|
+
|
|
9815
|
+
// src/functions/table-valued.ts
|
|
9195
9816
|
var JSON_TVF_COLUMNS = ["key", "value", "type", "atom", "id", "parent", "fullkey", "path"];
|
|
9196
9817
|
function jsonTvfResult(alias, defaultName, rows) {
|
|
9197
9818
|
const table = alias ?? defaultName;
|
|
@@ -9206,7 +9827,7 @@ function jsonTvfResult(alias, defaultName, rows) {
|
|
|
9206
9827
|
}))
|
|
9207
9828
|
};
|
|
9208
9829
|
}
|
|
9209
|
-
|
|
9830
|
+
registerTableValuedFunction("generate_series", (args, alias) => {
|
|
9210
9831
|
if (args.length < 2 || args.length > 3) {
|
|
9211
9832
|
throw new SqliteError("wrong number of arguments to function generate_series()", "misuse");
|
|
9212
9833
|
}
|
|
@@ -9237,13 +9858,13 @@ registry.set("generate_series", (args, alias) => {
|
|
|
9237
9858
|
}
|
|
9238
9859
|
return { columns: ["value"], rows };
|
|
9239
9860
|
});
|
|
9240
|
-
|
|
9861
|
+
registerTableValuedFunction("json_each", (args, alias) => {
|
|
9241
9862
|
if (args.length < 1 || args.length > 2) {
|
|
9242
9863
|
throw new SqliteError("wrong number of arguments to function json_each()", "misuse");
|
|
9243
9864
|
}
|
|
9244
9865
|
return jsonTvfResult(alias, "json_each", jsonEachRows(args[0], args[1]));
|
|
9245
9866
|
});
|
|
9246
|
-
|
|
9867
|
+
registerTableValuedFunction("json_tree", (args, alias) => {
|
|
9247
9868
|
if (args.length < 1 || args.length > 2) {
|
|
9248
9869
|
throw new SqliteError("wrong number of arguments to function json_tree()", "misuse");
|
|
9249
9870
|
}
|
|
@@ -9252,12 +9873,24 @@ registry.set("json_tree", (args, alias) => {
|
|
|
9252
9873
|
function safeInt(value) {
|
|
9253
9874
|
return value <= BigInt(Number.MAX_SAFE_INTEGER) && value >= BigInt(Number.MIN_SAFE_INTEGER) ? Number(value) : value;
|
|
9254
9875
|
}
|
|
9876
|
+
function tableValuedColumns(name) {
|
|
9877
|
+
ensurePragmaTvfsRegistered();
|
|
9878
|
+
const lower = name.toLowerCase();
|
|
9879
|
+
if (lower === "generate_series") return ["value"];
|
|
9880
|
+
if (lower === "json_each" || lower === "json_tree") return [...JSON_TVF_COLUMNS];
|
|
9881
|
+
return pragmaTvfColumns(name);
|
|
9882
|
+
}
|
|
9255
9883
|
function evaluateTableFunction(name, args, alias, env, scope, parent) {
|
|
9256
|
-
|
|
9884
|
+
ensurePragmaTvfsRegistered();
|
|
9885
|
+
const fn = getTableValuedFunction(name);
|
|
9257
9886
|
if (!fn) throw new SqliteError(`no such table-valued function: ${name}`, "no_such_table");
|
|
9258
9887
|
const values = args.map((arg) => evalExpr(arg, env.createEvalContext(scope ?? null, parent)));
|
|
9259
9888
|
return fn(values, alias, env);
|
|
9260
9889
|
}
|
|
9890
|
+
function hasTableValuedFunction(name) {
|
|
9891
|
+
ensurePragmaTvfsRegistered();
|
|
9892
|
+
return hasRegisteredTableValuedFunction(name);
|
|
9893
|
+
}
|
|
9261
9894
|
|
|
9262
9895
|
// src/schema/catalog.ts
|
|
9263
9896
|
function schemaCatalogRows(state) {
|
|
@@ -9988,10 +10621,10 @@ function executeSelect2(stmt, env, parent) {
|
|
|
9988
10621
|
rows = uniqueRows([...leftRows, ...rightRows]);
|
|
9989
10622
|
break;
|
|
9990
10623
|
case "INTERSECT":
|
|
9991
|
-
rows = uniqueRows(leftRows).filter((row) => rightRows.some((other) =>
|
|
10624
|
+
rows = uniqueRows(leftRows).filter((row) => rightRows.some((other) => rowsEqual2(row, other)));
|
|
9992
10625
|
break;
|
|
9993
10626
|
case "EXCEPT":
|
|
9994
|
-
rows = uniqueRows(leftRows).filter((row) => !rightRows.some((other) =>
|
|
10627
|
+
rows = uniqueRows(leftRows).filter((row) => !rightRows.some((other) => rowsEqual2(row, other)));
|
|
9995
10628
|
break;
|
|
9996
10629
|
}
|
|
9997
10630
|
if (stmt.orderBy.length > 0) rows.sort((a, b) => compareCompoundRows(a, b, stmt.orderBy, base.columns));
|
|
@@ -10025,7 +10658,7 @@ function executeWith(stmt, env, parent) {
|
|
|
10025
10658
|
env.ctes.set(key, valuesToResult(columns, delta));
|
|
10026
10659
|
const nextResult = executeSelect2(cte.select.compound.select, env, parent);
|
|
10027
10660
|
const candidates = resultValues(nextResult);
|
|
10028
|
-
const additions = cte.select.compound.op === "UNION ALL" ? candidates : candidates.filter((row) => !accumulated.some((existing) =>
|
|
10661
|
+
const additions = cte.select.compound.op === "UNION ALL" ? candidates : candidates.filter((row) => !accumulated.some((existing) => rowsEqual2(existing, row)));
|
|
10029
10662
|
if (additions.length === 0) break;
|
|
10030
10663
|
accumulated = [...accumulated, ...additions];
|
|
10031
10664
|
delta = additions;
|
|
@@ -10327,6 +10960,9 @@ function scanFrom(item, env, parent) {
|
|
|
10327
10960
|
if (item.type === "table_func") {
|
|
10328
10961
|
return evaluateTableFunction(item.name, item.args, item.alias, env).rows;
|
|
10329
10962
|
}
|
|
10963
|
+
if (item.type === "table" && isPragmaTvfName(item.name) && hasTableValuedFunction(item.name.toLowerCase())) {
|
|
10964
|
+
return evaluateTableFunction(item.name, [], item.alias, env, null, parent).rows;
|
|
10965
|
+
}
|
|
10330
10966
|
const alias = item.alias ?? item.name;
|
|
10331
10967
|
const qualified = item.schema ? `${item.schema}.${item.name}` : item.name;
|
|
10332
10968
|
const db = env.state.databaseForSchema(item.schema, qualified);
|
|
@@ -10492,7 +11128,16 @@ function shapeOf(item, env) {
|
|
|
10492
11128
|
if (item.type === "subquery")
|
|
10493
11129
|
return resultColumnNames(item.select.columns).map((name) => ({ table: item.alias, name, value: null }));
|
|
10494
11130
|
if (item.type === "table_func") {
|
|
10495
|
-
const
|
|
11131
|
+
const known = tableValuedColumns(item.name);
|
|
11132
|
+
const columns = known ?? evaluateTableFunction(item.name, item.args, item.alias, env).columns;
|
|
11133
|
+
return columns.map((name) => ({
|
|
11134
|
+
table: item.alias ?? item.name,
|
|
11135
|
+
name,
|
|
11136
|
+
value: null
|
|
11137
|
+
}));
|
|
11138
|
+
}
|
|
11139
|
+
if (item.type === "table" && isPragmaTvfName(item.name) && hasTableValuedFunction(item.name.toLowerCase())) {
|
|
11140
|
+
const columns = tableValuedColumns(item.name) ?? evaluateTableFunction(item.name, [], item.alias, env).columns;
|
|
10496
11141
|
return columns.map((name) => ({
|
|
10497
11142
|
table: item.alias ?? item.name,
|
|
10498
11143
|
name,
|
|
@@ -10568,7 +11213,7 @@ function aggregateValue(expr, rows, env, parent) {
|
|
|
10568
11213
|
const ctx = env.createEvalContext(row, parent);
|
|
10569
11214
|
if (expr.filter && isTruthySql(evalExpr(expr.filter, ctx)) !== true) continue;
|
|
10570
11215
|
const args = expr.args === "*" ? [] : expr.args.map((arg) => evalExpr(arg, ctx));
|
|
10571
|
-
if (expr.distinct && seen.some((values) =>
|
|
11216
|
+
if (expr.distinct && seen.some((values) => rowsEqual2(values, args))) continue;
|
|
10572
11217
|
seen.push(args);
|
|
10573
11218
|
accumulator.step(args);
|
|
10574
11219
|
}
|
|
@@ -10579,7 +11224,7 @@ function windowValue(expr, current, rows, env, parent, namedWindows) {
|
|
|
10579
11224
|
const currentCtx = env.createEvalContext(current, parent);
|
|
10580
11225
|
const partitionKey = spec.partitionBy.map((item) => evalExpr(item, currentCtx));
|
|
10581
11226
|
const partition = rows.filter(
|
|
10582
|
-
(row) =>
|
|
11227
|
+
(row) => rowsEqual2(
|
|
10583
11228
|
partitionKey,
|
|
10584
11229
|
spec.partitionBy.map((item) => evalExpr(item, env.createEvalContext(row, parent)))
|
|
10585
11230
|
)
|
|
@@ -10608,13 +11253,13 @@ function windowValue(expr, current, rows, env, parent, namedWindows) {
|
|
|
10608
11253
|
if (name === "row_number") return index + 1;
|
|
10609
11254
|
if (name === "rank") {
|
|
10610
11255
|
let first = index;
|
|
10611
|
-
while (first > 0 &&
|
|
11256
|
+
while (first > 0 && rowsEqual2(orderKeys[first], orderKeys[first - 1])) first--;
|
|
10612
11257
|
return first + 1;
|
|
10613
11258
|
}
|
|
10614
11259
|
if (name === "dense_rank") {
|
|
10615
|
-
let
|
|
10616
|
-
for (let i = 1; i <= index; i++) if (!
|
|
10617
|
-
return
|
|
11260
|
+
let rank2 = 1;
|
|
11261
|
+
for (let i = 1; i <= index; i++) if (!rowsEqual2(orderKeys[i], orderKeys[i - 1])) rank2++;
|
|
11262
|
+
return rank2;
|
|
10618
11263
|
}
|
|
10619
11264
|
const evaluated = args.map((arg) => evalExpr(arg, currentCtx));
|
|
10620
11265
|
if (name === "lag" || name === "lead") {
|
|
@@ -10648,7 +11293,7 @@ function windowValue(expr, current, rows, env, parent, namedWindows) {
|
|
|
10648
11293
|
if (name === "cume_dist") {
|
|
10649
11294
|
if (partition.length === 0) return null;
|
|
10650
11295
|
let lastPeer = index;
|
|
10651
|
-
while (lastPeer + 1 < partition.length &&
|
|
11296
|
+
while (lastPeer + 1 < partition.length && rowsEqual2(orderKeys[lastPeer + 1], orderKeys[index])) {
|
|
10652
11297
|
lastPeer++;
|
|
10653
11298
|
}
|
|
10654
11299
|
return (lastPeer + 1) / partition.length;
|
|
@@ -10656,7 +11301,7 @@ function windowValue(expr, current, rows, env, parent, namedWindows) {
|
|
|
10656
11301
|
if (name === "percent_rank") {
|
|
10657
11302
|
if (partition.length <= 1) return 0;
|
|
10658
11303
|
let first = index;
|
|
10659
|
-
while (first > 0 &&
|
|
11304
|
+
while (first > 0 && rowsEqual2(orderKeys[first], orderKeys[first - 1])) first--;
|
|
10660
11305
|
return first / (partition.length - 1);
|
|
10661
11306
|
}
|
|
10662
11307
|
throw new SqliteError(`no such window function: ${expr.func.name}`, "other");
|
|
@@ -10681,7 +11326,7 @@ function frameBounds(spec, index, length, ctx, defaultFrameEnd, orderKeys) {
|
|
|
10681
11326
|
const isRangeLike = spec.frame.type === "RANGE" || spec.frame.type === "GROUPS";
|
|
10682
11327
|
let peerFirst = index;
|
|
10683
11328
|
if (isRangeLike && spec.orderBy.length > 0) {
|
|
10684
|
-
while (peerFirst > 0 &&
|
|
11329
|
+
while (peerFirst > 0 && rowsEqual2(orderKeys[peerFirst], orderKeys[peerFirst - 1])) peerFirst--;
|
|
10685
11330
|
}
|
|
10686
11331
|
const bound = (item, isStart) => {
|
|
10687
11332
|
switch (item.kind) {
|
|
@@ -10703,8 +11348,8 @@ function frameBounds(spec, index, length, ctx, defaultFrameEnd, orderKeys) {
|
|
|
10703
11348
|
function frameRows(partition, start, end, index, orderKeys, exclude) {
|
|
10704
11349
|
let peerFirst = index;
|
|
10705
11350
|
let peerLast = index;
|
|
10706
|
-
while (peerFirst > 0 &&
|
|
10707
|
-
while (peerLast + 1 < partition.length &&
|
|
11351
|
+
while (peerFirst > 0 && rowsEqual2(orderKeys[peerFirst], orderKeys[peerFirst - 1])) peerFirst--;
|
|
11352
|
+
while (peerLast + 1 < partition.length && rowsEqual2(orderKeys[peerLast], orderKeys[peerLast + 1])) peerLast++;
|
|
10708
11353
|
const rows = [];
|
|
10709
11354
|
for (let i = Math.max(0, start); i <= end && i < partition.length; i++) {
|
|
10710
11355
|
if (exclude === "current_row" && i === index) continue;
|
|
@@ -10930,7 +11575,7 @@ function referencesTable(select, name) {
|
|
|
10930
11575
|
};
|
|
10931
11576
|
return visit(select.from) || (select.compound ? referencesTable(select.compound.select, name) : false);
|
|
10932
11577
|
}
|
|
10933
|
-
function
|
|
11578
|
+
function rowsEqual2(left, right) {
|
|
10934
11579
|
return left.length === right.length && left.every((value, index) => {
|
|
10935
11580
|
const other = right[index] ?? null;
|
|
10936
11581
|
return value === null && other === null || value !== null && other !== null && sqlValueEquals(value, other);
|
|
@@ -12355,154 +13000,24 @@ function asExplicitRowid(value) {
|
|
|
12355
13000
|
// src/executor/pragma.ts
|
|
12356
13001
|
function executePragma(name, expr, env) {
|
|
12357
13002
|
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]);
|
|
13003
|
+
if (key === "foreign_keys" && expr !== null) {
|
|
13004
|
+
const value = evalPragmaSetValue(expr, env);
|
|
13005
|
+
if (!env.transactions.inTransaction) env.state.foreignKeysEnabled = coercePragmaTruthy(value);
|
|
13006
|
+
return emptyResult(0, env.state.lastInsertRowid);
|
|
12477
13007
|
}
|
|
12478
|
-
|
|
12479
|
-
|
|
12480
|
-
|
|
12481
|
-
|
|
12482
|
-
|
|
13008
|
+
if ((key === "user_version" || key === "schema_version") && expr !== null) {
|
|
13009
|
+
const value = evalPragmaSetValue(expr, env);
|
|
13010
|
+
const num2 = coercePragmaInt(value);
|
|
13011
|
+
if (key === "user_version") env.state.userVersion = num2;
|
|
13012
|
+
else env.state.schemaVersion = num2;
|
|
13013
|
+
return emptyResult(0, env.state.lastInsertRowid);
|
|
12483
13014
|
}
|
|
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;
|
|
13015
|
+
const args = evalPragmaArgs(expr, env);
|
|
13016
|
+
const result = queryPragma(key, args, env);
|
|
13017
|
+
if (result.columns.length === 0 && result.rows.length === 0) {
|
|
13018
|
+
return emptyResult(0, env.state.lastInsertRowid);
|
|
12504
13019
|
}
|
|
12505
|
-
return
|
|
13020
|
+
return valuesToResult(result.columns, result.rows, 0, env.state.lastInsertRowid);
|
|
12506
13021
|
}
|
|
12507
13022
|
|
|
12508
13023
|
// src/executor/execute.ts
|