@poe-platform/safe-bash 0.1.839 → 0.1.840
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mp4-ast/types.d.ts +4 -2
- package/dist/pdf-ast/cos/security.d.ts +10 -0
- package/dist/pdf-ast/edit/retained-attachment-edits.d.ts +4 -0
- package/dist/pdf-ast/edit/retained-graph.d.ts +1 -1
- package/dist/pdf-ast/image.js +1 -1
- package/dist/pdf-ast/index.d.ts +2 -1
- package/dist/pdf-ast/index.js +7 -1
- package/dist/pdf-ast/vendor/pdfjs-fonts.d.mts +8 -0
- package/dist/pdf-ast/vendor/pdfjs-fonts.mjs +28 -0
- package/dist/safe-bash/command-chunks/{chunk-SG2KOOD4.js → chunk-3SAYZFMD.js} +2 -2
- package/dist/safe-bash/command-chunks/{chunk-FH5VMAPS.js → chunk-45ZH6CNF.js} +20 -4
- package/dist/safe-bash/command-chunks/{chunk-T6OXG7QQ.js → chunk-AAOPVEPF.js} +66 -1
- package/dist/safe-bash/command-chunks/{chunk-46GA576V.js → chunk-CPKVUB7S.js} +2 -2
- package/dist/safe-bash/command-chunks/{chunk-MBXNG6C3.js → chunk-DLLN3C3Q.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-ZSQCROFE.js → chunk-DM5T5D2K.js} +5 -1
- package/dist/safe-bash/command-chunks/{chunk-3EAZRKI4.js → chunk-G7HQYFIU.js} +10 -1
- package/dist/safe-bash/command-chunks/{chunk-GYKQ3IOV.js → chunk-LMYQMJYY.js} +94 -18
- package/dist/safe-bash/command-chunks/{chunk-DX7KU6YU.js → chunk-N52AHO6S.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-4BSD2RGK.js → chunk-QPKL5GWH.js} +102 -42
- package/dist/safe-bash/command-chunks/{chunk-Z2T7E4ID.js → chunk-R7QLP5RH.js} +1212 -1119
- package/dist/safe-bash/command-chunks/{chunk-RSFKQE2U.js → chunk-T5WFJ44Z.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-77ROD2TR.js → chunk-X3WNWRVT.js} +11 -5
- package/dist/safe-bash/command-chunks/{chunk-TCXM7BSZ.js → chunk-YFMNXPLP.js} +4 -4
- package/dist/safe-bash/command-chunks/{chunk-DQVOBGI2.js → chunk-YVFQ5I36.js} +7335 -7162
- package/dist/safe-bash-command-exiftool/index.js +25 -1
- package/dist/safe-bash-command-ffmpeg/index.js +174 -41
- package/dist/safe-bash-command-ffprobe/index.js +2 -2
- package/dist/safe-bash-command-ffprobe/media.js +2 -2
- package/dist/safe-bash-command-imagemagick/index.js +482 -98
- package/dist/safe-bash-command-mdq/index.js +2 -0
- package/dist/safe-bash-command-pandoc/citeproc-filters.js +7 -7
- package/dist/safe-bash-command-pandoc/command.js +8 -8
- package/dist/safe-bash-command-pandoc/index.js +51 -51
- package/dist/safe-bash-command-qpdf/index.js +1037 -654
- package/dist/safe-bash-command-qpdf/page-range.d.ts +2 -0
- package/dist/safe-bash-command-soffice/index.js +28 -8
- package/dist/safe-bash-command-sqlite3/btree.d.ts +2 -1
- package/dist/safe-bash-command-sqlite3/engine.d.ts +15 -1
- package/dist/safe-bash-command-sqlite3/index.js +294 -68
- package/dist/safe-bash-command-tar/create.js +2 -2
- package/dist/safe-bash-command-tar/extract.js +2 -2
- package/dist/safe-bash-command-tar/format.js +1 -1
- package/dist/safe-bash-command-tar/index.js +4 -4
- package/dist/safe-bash-command-tar/modes.js +4 -4
- package/dist/safe-bash-command-unzip/index.js +1 -1
- package/dist/safe-bash-command-unzip/unzip.js +1 -1
- package/dist/safe-bash-markdown-engine/commonmark-blocks.d.ts +17 -1
- package/dist/safe-bash-markdown-engine/commonmark-blocks.js +3 -3
- package/dist/safe-bash-markdown-engine/commonmark-inlines.d.ts +1 -1
- package/dist/safe-bash-markdown-engine/commonmark-inlines.js +3 -3
- package/dist/safe-bash-markdown-engine/commonmark-syntax.d.ts +5 -0
- package/dist/safe-bash-markdown-engine/commonmark-syntax.js +5 -1
- package/dist/safe-bash-markdown-engine/gfm-syntax.js +2 -2
- package/dist/safe-bash-markdown-engine/index.js +4 -4
- package/dist/safe-bash-zip-engine/index.js +1 -1
- package/dist/safe-bash-zip-engine/zip/repair.js +1 -1
- package/dist/safe-bash-zip-engine/zip/sfx.js +1 -1
- package/dist/safe-bash-zip-engine/zip-format.d.ts +2 -0
- package/dist/safe-bash-zip-engine/zip-format.js +1 -1
- package/package.json +2 -2
- package/third-party/pdf-ast/THIRD_PARTY_NOTICES.md +2 -0
|
@@ -3,6 +3,75 @@ import "../safe-bash/command-chunks/chunk-65DS4IOB.js";
|
|
|
3
3
|
// packages/safe-bash-command-sqlite3/src/engine.ts
|
|
4
4
|
import { yieldTurn as yieldTurn2 } from "../safe-bash-contracts/yield.js";
|
|
5
5
|
|
|
6
|
+
// packages/safe-bash-command-sqlite3/src/real-output.ts
|
|
7
|
+
function formatReal(value, precision) {
|
|
8
|
+
if (!Number.isFinite(value)) return Number.isNaN(value) ? "NaN" : value < 0 ? "-Inf" : "Inf";
|
|
9
|
+
if (value === 0) return "0.0";
|
|
10
|
+
let high = Math.abs(value), low = 0, exponent = 0;
|
|
11
|
+
const bits = new DataView(new ArrayBuffer(8));
|
|
12
|
+
function upper(x) {
|
|
13
|
+
bits.setFloat64(0, x);
|
|
14
|
+
bits.setUint32(4, bits.getUint32(4) & 4227858432);
|
|
15
|
+
return bits.getFloat64(0);
|
|
16
|
+
}
|
|
17
|
+
function multiply(y, error) {
|
|
18
|
+
const hx = upper(high), hy = upper(y), tx = high - hx, ty = y - hy;
|
|
19
|
+
const p = hx * hy, q = hx * ty + tx * hy, c = p + q;
|
|
20
|
+
let cc = p - c + q + tx * ty;
|
|
21
|
+
cc = high * error + low * y + cc;
|
|
22
|
+
high = c + cc;
|
|
23
|
+
low = c - high + cc;
|
|
24
|
+
}
|
|
25
|
+
if (high > 9223372036854775e3) {
|
|
26
|
+
while (high > 9223372036854774e103) {
|
|
27
|
+
exponent += 100;
|
|
28
|
+
multiply(1e-100, -19991899802602883e-133);
|
|
29
|
+
}
|
|
30
|
+
while (high > 9223372036854774e13) {
|
|
31
|
+
exponent += 10;
|
|
32
|
+
multiply(1e-10, -3643219731549774e-42);
|
|
33
|
+
}
|
|
34
|
+
while (high > 9223372036854775e3) {
|
|
35
|
+
exponent++;
|
|
36
|
+
multiply(0.1, -5551115123125783e-33);
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
while (high < 9223372036854775e-98) {
|
|
40
|
+
exponent -= 100;
|
|
41
|
+
multiply(1e100, -15902891109759918e67);
|
|
42
|
+
}
|
|
43
|
+
while (high < 9223372036854775e-8) {
|
|
44
|
+
exponent -= 10;
|
|
45
|
+
multiply(1e10, 0);
|
|
46
|
+
}
|
|
47
|
+
while (high < 922337203685477500) {
|
|
48
|
+
exponent--;
|
|
49
|
+
multiply(10, 0);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
let digits = (BigInt(Math.trunc(high)) + BigInt(Math.trunc(low))).toString();
|
|
53
|
+
if (precision === 20 && Number(`${digits}e${exponent}`) !== Math.abs(value)) {
|
|
54
|
+
const [mantissa, power] = Math.abs(value).toExponential(19).split("e");
|
|
55
|
+
digits = mantissa.replace(".", "");
|
|
56
|
+
exponent = Number(power) - digits.length + 1;
|
|
57
|
+
}
|
|
58
|
+
let point = digits.length + exponent;
|
|
59
|
+
if (digits.length > precision) {
|
|
60
|
+
const roundUp = digits[precision] >= "5";
|
|
61
|
+
digits = (BigInt(digits.slice(0, precision)) + (roundUp ? 1n : 0n)).toString();
|
|
62
|
+
if (digits.length > precision) point++;
|
|
63
|
+
}
|
|
64
|
+
while (digits.endsWith("0")) digits = digits.slice(0, -1);
|
|
65
|
+
const sign = value < 0 ? "-" : "";
|
|
66
|
+
exponent = point - 1;
|
|
67
|
+
if (exponent < -4 || exponent >= precision) {
|
|
68
|
+
return `${sign}${digits[0]}.${digits.slice(1) || "0"}e${exponent < 0 ? "-" : "+"}${String(Math.abs(exponent)).padStart(2, "0")}`;
|
|
69
|
+
}
|
|
70
|
+
if (point <= 0) return `${sign}0.${"0".repeat(-point)}${digits}`;
|
|
71
|
+
if (point >= digits.length) return `${sign}${digits}${"0".repeat(point - digits.length)}.0`;
|
|
72
|
+
return `${sign}${digits.slice(0, point)}.${digits.slice(point)}`;
|
|
73
|
+
}
|
|
74
|
+
|
|
6
75
|
// packages/safe-bash-command-sqlite3/src/execution.ts
|
|
7
76
|
import { yieldTurn } from "../safe-bash-contracts/yield.js";
|
|
8
77
|
function runSynchronously(steps) {
|
|
@@ -725,7 +794,7 @@ function writeSqliteDatabaseBytes(image) {
|
|
|
725
794
|
});
|
|
726
795
|
} else if (item.type === "index") {
|
|
727
796
|
const idxRows = image.indexRows?.get(item.name) ?? [];
|
|
728
|
-
const built = buildIndexPages(idxRows, nextPageNumber);
|
|
797
|
+
const built = buildIndexPages(idxRows, nextPageNumber, item.indexPresorted);
|
|
729
798
|
extraPageChunks.push(...built.pages);
|
|
730
799
|
nextPageNumber += built.pages.length;
|
|
731
800
|
masterEntries.push({
|
|
@@ -763,7 +832,7 @@ function writeSqliteDatabaseBytes(image) {
|
|
|
763
832
|
reMasterEntries.push({ ...item, rootpage: built.rootPage });
|
|
764
833
|
} else if (item.type === "index") {
|
|
765
834
|
const idxRows = image.indexRows?.get(item.name) ?? [];
|
|
766
|
-
const built = buildIndexPages(idxRows, pNum);
|
|
835
|
+
const built = buildIndexPages(idxRows, pNum, item.indexPresorted);
|
|
767
836
|
reExtraChunks.push(...built.pages);
|
|
768
837
|
pNum += built.pages.length;
|
|
769
838
|
reMasterEntries.push({ ...item, rootpage: built.rootPage });
|
|
@@ -857,6 +926,7 @@ function tableStorageColumns(table) {
|
|
|
857
926
|
var textEncoder2 = new TextEncoder();
|
|
858
927
|
var textDecoder2 = new TextDecoder("utf-8", { fatal: false });
|
|
859
928
|
var SqliteConstraintError = class extends Error {
|
|
929
|
+
code = 19;
|
|
860
930
|
};
|
|
861
931
|
function cloneSqlValue(v) {
|
|
862
932
|
if (v instanceof Uint8Array) {
|
|
@@ -887,6 +957,7 @@ function cloneTableDef(t) {
|
|
|
887
957
|
strict: t.strict,
|
|
888
958
|
primaryKeyCols: [...t.primaryKeyCols],
|
|
889
959
|
primaryKeyOrder: t.primaryKeyOrder?.map((key) => ({ ...key })),
|
|
960
|
+
implicitIndexes: t.implicitIndexes?.map((index) => ({ ...index, columns: [...index.columns], order: index.order.map((key) => ({ ...key })) })),
|
|
890
961
|
uniqueColSets: t.uniqueColSets.map((u) => [...u])
|
|
891
962
|
};
|
|
892
963
|
}
|
|
@@ -1173,6 +1244,13 @@ function reconstructTokensSql(tokens) {
|
|
|
1173
1244
|
}
|
|
1174
1245
|
return out;
|
|
1175
1246
|
}
|
|
1247
|
+
function isFromClause(tokens, index) {
|
|
1248
|
+
const isWord = (offset, word) => {
|
|
1249
|
+
const token = tokens[index + offset];
|
|
1250
|
+
return token?.type === "word" && token.value.toUpperCase() === word;
|
|
1251
|
+
};
|
|
1252
|
+
return isWord(0, "FROM") && !(isWord(-1, "DISTINCT") && (isWord(-2, "IS") || isWord(-2, "NOT") && isWord(-3, "IS")));
|
|
1253
|
+
}
|
|
1176
1254
|
var ExprParser = class {
|
|
1177
1255
|
constructor(tokens) {
|
|
1178
1256
|
this.tokens = tokens;
|
|
@@ -1496,11 +1574,11 @@ var ExprParser = class {
|
|
|
1496
1574
|
}
|
|
1497
1575
|
if (upper === "TRUE") {
|
|
1498
1576
|
this.pos += 1;
|
|
1499
|
-
return { kind: "literal", value: 1 };
|
|
1577
|
+
return { kind: "literal", value: 1, booleanLiteral: true };
|
|
1500
1578
|
}
|
|
1501
1579
|
if (upper === "FALSE") {
|
|
1502
1580
|
this.pos += 1;
|
|
1503
|
-
return { kind: "literal", value: 0 };
|
|
1581
|
+
return { kind: "literal", value: 0, booleanLiteral: true };
|
|
1504
1582
|
}
|
|
1505
1583
|
if (upper === "CURRENT_TIMESTAMP") {
|
|
1506
1584
|
this.pos += 1;
|
|
@@ -1771,17 +1849,25 @@ function arithmeticNumber(value) {
|
|
|
1771
1849
|
}
|
|
1772
1850
|
return real ? new Number(Number(text.slice(0, end))) : integerResult(BigInt(text.slice(0, end)));
|
|
1773
1851
|
}
|
|
1852
|
+
function columnAffinity(declaredType) {
|
|
1853
|
+
const type = declaredType.toUpperCase();
|
|
1854
|
+
if (type.includes("INT")) return "INTEGER";
|
|
1855
|
+
if (["CHAR", "CLOB", "TEXT"].some((part) => type.includes(part))) return "TEXT";
|
|
1856
|
+
if (type === "" || type.includes("BLOB")) return "BLOB";
|
|
1857
|
+
if (["REAL", "FLOA", "DOUB"].some((part) => type.includes(part))) return "REAL";
|
|
1858
|
+
return "NUMERIC";
|
|
1859
|
+
}
|
|
1774
1860
|
function applyColumnAffinity(storedValue, declaredType, strict) {
|
|
1775
1861
|
let value = storedValue instanceof String ? storedValue.valueOf() : storedValue;
|
|
1776
1862
|
if (value === null || value instanceof Uint8Array) return value;
|
|
1777
1863
|
const type = declaredType.toUpperCase();
|
|
1778
1864
|
if (strict && type === "ANY") return value;
|
|
1779
|
-
const
|
|
1780
|
-
if (
|
|
1865
|
+
const affinity = columnAffinity(type);
|
|
1866
|
+
if (affinity === "TEXT") {
|
|
1781
1867
|
return toSqlString(value);
|
|
1782
1868
|
}
|
|
1783
|
-
if (
|
|
1784
|
-
const real =
|
|
1869
|
+
if (affinity === "BLOB") return value;
|
|
1870
|
+
const real = affinity === "REAL";
|
|
1785
1871
|
if (typeof value === "string") {
|
|
1786
1872
|
const text = value.trim();
|
|
1787
1873
|
if (!text || ![...text].every((char) => "0123456789.+-eE".includes(char)) || Number.isNaN(Number(text))) return value;
|
|
@@ -1812,11 +1898,10 @@ function toSqlString(v) {
|
|
|
1812
1898
|
return v.toString();
|
|
1813
1899
|
}
|
|
1814
1900
|
if (v instanceof Number) {
|
|
1815
|
-
|
|
1816
|
-
return Number.isFinite(n) && Number.isInteger(n) ? `${n}.0` : String(Number(n.toPrecision(15)));
|
|
1901
|
+
return formatReal(v.valueOf(), 15);
|
|
1817
1902
|
}
|
|
1818
1903
|
if (typeof v === "number") {
|
|
1819
|
-
return Number.isInteger(v) ? String(v) :
|
|
1904
|
+
return Number.isInteger(v) ? String(v) : formatReal(v, 15);
|
|
1820
1905
|
}
|
|
1821
1906
|
const nulIdx = v.indexOf(0);
|
|
1822
1907
|
const sub = nulIdx === -1 ? v : v.subarray(0, nulIdx);
|
|
@@ -1861,22 +1946,24 @@ function sqlEquals(a, b, collation = "BINARY") {
|
|
|
1861
1946
|
function matchLike(str, pattern, caseInsensitive, escapeChar = "") {
|
|
1862
1947
|
let regexStr = "^";
|
|
1863
1948
|
for (let i = 0; i < pattern.length; i += 1) {
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1949
|
+
let c = pattern[i];
|
|
1950
|
+
const escaped = escapeChar && c === escapeChar && i + 1 < pattern.length;
|
|
1951
|
+
if (escaped) {
|
|
1867
1952
|
i += 1;
|
|
1868
|
-
|
|
1953
|
+
c = pattern[i];
|
|
1869
1954
|
}
|
|
1870
|
-
if (c === "%") {
|
|
1955
|
+
if (!escaped && c === "%") {
|
|
1871
1956
|
regexStr += "[\\s\\S]*";
|
|
1872
|
-
} else if (c === "_") {
|
|
1957
|
+
} else if (!escaped && c === "_") {
|
|
1873
1958
|
regexStr += "[\\s\\S]";
|
|
1959
|
+
} else if (caseInsensitive && (c >= "a" && c <= "z" || c >= "A" && c <= "Z")) {
|
|
1960
|
+
regexStr += `[${c.toUpperCase()}${c.toLowerCase()}]`;
|
|
1874
1961
|
} else {
|
|
1875
1962
|
regexStr += c.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1876
1963
|
}
|
|
1877
1964
|
}
|
|
1878
1965
|
regexStr += "$";
|
|
1879
|
-
return new RegExp(regexStr
|
|
1966
|
+
return new RegExp(regexStr).test(str);
|
|
1880
1967
|
}
|
|
1881
1968
|
function matchGlob(str, pattern) {
|
|
1882
1969
|
let regexStr = "^";
|
|
@@ -2231,6 +2318,7 @@ var SqliteDatabase = class {
|
|
|
2231
2318
|
async executeStatementAsync(sql, signal) {
|
|
2232
2319
|
return runCooperatively(this.executeStatementSteps(sql), signal);
|
|
2233
2320
|
}
|
|
2321
|
+
rowTables = /* @__PURE__ */ new WeakMap();
|
|
2234
2322
|
tables = /* @__PURE__ */ new Map();
|
|
2235
2323
|
indexes = /* @__PURE__ */ new Map();
|
|
2236
2324
|
views = /* @__PURE__ */ new Map();
|
|
@@ -2246,7 +2334,9 @@ var SqliteDatabase = class {
|
|
|
2246
2334
|
lastInsertRowid = 0;
|
|
2247
2335
|
lastChanges = 0;
|
|
2248
2336
|
totalChanges = 0;
|
|
2249
|
-
inTransaction
|
|
2337
|
+
get inTransaction() {
|
|
2338
|
+
return this.txSnapshot !== null || this.savepoints.size > 0;
|
|
2339
|
+
}
|
|
2250
2340
|
foreignKeyDepth = 0;
|
|
2251
2341
|
outerRows = [];
|
|
2252
2342
|
preparing = false;
|
|
@@ -2448,6 +2538,41 @@ var SqliteDatabase = class {
|
|
|
2448
2538
|
};
|
|
2449
2539
|
}, this);
|
|
2450
2540
|
tableRows.set(tbl.name, rows);
|
|
2541
|
+
const indexes = [];
|
|
2542
|
+
for (const index of tbl.implicitIndexes ?? []) {
|
|
2543
|
+
yield;
|
|
2544
|
+
const columns = index.columns.map((name2) => tbl.columns.find((column) => column.name.toLowerCase() === name2.toLowerCase()));
|
|
2545
|
+
if (index.primary && !tbl.withoutRowId && columns.length === 1 && columns[0].type.toUpperCase() === "INTEGER") continue;
|
|
2546
|
+
if (indexes.some((existing) => existing.columns.length === index.columns.length && existing.columns.every((name2, i) => name2.toLowerCase() === index.columns[i].toLowerCase() && (existing.order[i]?.collation ?? columns[i].collate ?? "BINARY").toUpperCase() === (index.order[i]?.collation ?? columns[i].collate ?? "BINARY").toUpperCase()))) continue;
|
|
2547
|
+
indexes.push(index);
|
|
2548
|
+
if (index.primary && tbl.withoutRowId) continue;
|
|
2549
|
+
const name = `sqlite_autoindex_${tbl.name}_${indexes.length}`;
|
|
2550
|
+
const keyColumns = [...columns];
|
|
2551
|
+
const order = [...index.order];
|
|
2552
|
+
if (tbl.withoutRowId) {
|
|
2553
|
+
for (let i = 0; i < tbl.primaryKeyCols.length; i++) {
|
|
2554
|
+
const column = tbl.columns.find((column2) => column2.name.toLowerCase() === tbl.primaryKeyCols[i].toLowerCase());
|
|
2555
|
+
if (keyColumns.includes(column)) continue;
|
|
2556
|
+
keyColumns.push(column);
|
|
2557
|
+
order.push(tbl.primaryKeyOrder?.[i] ?? { desc: false, collation: column.collate });
|
|
2558
|
+
}
|
|
2559
|
+
}
|
|
2560
|
+
const entries = yield* stepMap(tbl.rows, function* (row) {
|
|
2561
|
+
yield;
|
|
2562
|
+
const values = keyColumns.map((column) => row.data[column.name] ?? null);
|
|
2563
|
+
if (!tbl.withoutRowId) values.push(row.rowid);
|
|
2564
|
+
return values;
|
|
2565
|
+
}, this);
|
|
2566
|
+
indexRows.set(name, yield* stepSort(entries, function* (left, right) {
|
|
2567
|
+
for (let i = 0; i < left.length; i++) {
|
|
2568
|
+
yield;
|
|
2569
|
+
const comparison = compareSqlValues(left[i], right[i], order[i]?.collation ?? keyColumns[i]?.collate ?? "BINARY");
|
|
2570
|
+
if (comparison) return order[i]?.desc ? -comparison : comparison;
|
|
2571
|
+
}
|
|
2572
|
+
return 0;
|
|
2573
|
+
}, this));
|
|
2574
|
+
master.push({ type: "index", name, tbl_name: tbl.name, rootpage: rootPageCounter++, sql: null, indexPresorted: true });
|
|
2575
|
+
}
|
|
2451
2576
|
}
|
|
2452
2577
|
if ((hasAutoIncTable || seqRows.length > 0) && !this.findTable("sqlite_sequence")) {
|
|
2453
2578
|
master.push({
|
|
@@ -2545,7 +2670,7 @@ var SqliteDatabase = class {
|
|
|
2545
2670
|
const candidate = { rowid, data };
|
|
2546
2671
|
const conflict = yield* this.checkConstraintsAndConflicts(tbl, candidate);
|
|
2547
2672
|
if (conflict) {
|
|
2548
|
-
throw new
|
|
2673
|
+
throw new SqliteConstraintError(`UNIQUE constraint failed: ${conflict.columns.map((column) => `${tbl.name}.${column}`).join(", ")}`);
|
|
2549
2674
|
}
|
|
2550
2675
|
this.checkRowCount(tbl.rows.length + 1);
|
|
2551
2676
|
tbl.rows.push(candidate);
|
|
@@ -2636,12 +2761,10 @@ var SqliteDatabase = class {
|
|
|
2636
2761
|
if (first === "BEGIN") {
|
|
2637
2762
|
if (!this.inTransaction) {
|
|
2638
2763
|
this.txSnapshot = yield* this.captureSnapshot();
|
|
2639
|
-
this.inTransaction = true;
|
|
2640
2764
|
}
|
|
2641
2765
|
return null;
|
|
2642
2766
|
}
|
|
2643
2767
|
if (first === "COMMIT" || first === "END") {
|
|
2644
|
-
this.inTransaction = false;
|
|
2645
2768
|
this.txSnapshot = null;
|
|
2646
2769
|
this.savepoints.clear();
|
|
2647
2770
|
return null;
|
|
@@ -2663,10 +2786,10 @@ var SqliteDatabase = class {
|
|
|
2663
2786
|
yield* this.restoreSnapshot(snap);
|
|
2664
2787
|
return null;
|
|
2665
2788
|
}
|
|
2666
|
-
|
|
2667
|
-
|
|
2789
|
+
const snapshot = this.txSnapshot ?? this.savepoints.values().next().value;
|
|
2790
|
+
if (snapshot) {
|
|
2791
|
+
yield* this.restoreSnapshot(snapshot);
|
|
2668
2792
|
}
|
|
2669
|
-
this.inTransaction = false;
|
|
2670
2793
|
this.txSnapshot = null;
|
|
2671
2794
|
this.savepoints.clear();
|
|
2672
2795
|
return null;
|
|
@@ -2679,7 +2802,11 @@ var SqliteDatabase = class {
|
|
|
2679
2802
|
if (first === "RELEASE") {
|
|
2680
2803
|
const spIdx = tokens[1]?.value.toUpperCase() === "SAVEPOINT" ? 2 : 1;
|
|
2681
2804
|
const spName = (tokens[spIdx]?.value ?? "").toLowerCase();
|
|
2682
|
-
|
|
2805
|
+
let releasing = false;
|
|
2806
|
+
for (const name of this.savepoints.keys()) {
|
|
2807
|
+
if (name === spName) releasing = true;
|
|
2808
|
+
if (releasing) this.savepoints.delete(name);
|
|
2809
|
+
}
|
|
2683
2810
|
return null;
|
|
2684
2811
|
}
|
|
2685
2812
|
if (first === "VACUUM" || first === "ANALYZE" || first === "REINDEX" || first === "ATTACH" || first === "DETACH") {
|
|
@@ -2704,9 +2831,12 @@ var SqliteDatabase = class {
|
|
|
2704
2831
|
return null;
|
|
2705
2832
|
}
|
|
2706
2833
|
if (["INSERT", "REPLACE", "UPDATE", "DELETE"].includes(first)) {
|
|
2707
|
-
const
|
|
2834
|
+
const rollbackOnConflict = first === "INSERT" && tokens[1]?.value.toUpperCase() === "OR" && tokens[2]?.value.toUpperCase() === "ROLLBACK";
|
|
2835
|
+
const rollbackSnapshot = rollbackOnConflict ? this.txSnapshot ?? this.savepoints.values().next().value ?? (yield* this.captureSnapshot()) : null;
|
|
2836
|
+
const failOnConflict = tokens[1]?.value.toUpperCase() === "OR" && tokens[2]?.value.toUpperCase() === "FAIL";
|
|
2837
|
+
const snapshot = this.foreignKeyDepth === 0 ? yield* this.captureSnapshot() : null;
|
|
2708
2838
|
const existingRows = /* @__PURE__ */ new Set();
|
|
2709
|
-
if (snapshot) {
|
|
2839
|
+
if (this.foreignKeys && snapshot) {
|
|
2710
2840
|
for (const table of this.tables.values()) {
|
|
2711
2841
|
for (const row of table.rows) {
|
|
2712
2842
|
yield;
|
|
@@ -2721,10 +2851,22 @@ var SqliteDatabase = class {
|
|
|
2721
2851
|
if (first === "UPDATE") result = yield* this.executeUpdate(tokens, positionalParams, cteScope);
|
|
2722
2852
|
else if (first === "DELETE") result = yield* this.executeDelete(tokens, positionalParams, cteScope);
|
|
2723
2853
|
else result = yield* this.executeInsert(sql, tokens, positionalParams, cteScope);
|
|
2724
|
-
if (snapshot) yield* this.validateForeignKeys(snapshot, existingRows);
|
|
2854
|
+
if (this.foreignKeys && snapshot) yield* this.validateForeignKeys(snapshot, existingRows);
|
|
2725
2855
|
return result;
|
|
2726
|
-
} catch (
|
|
2727
|
-
|
|
2856
|
+
} catch (caughtError) {
|
|
2857
|
+
let error = caughtError;
|
|
2858
|
+
if (this.foreignKeys && snapshot && failOnConflict && error instanceof SqliteConstraintError && error.message !== "FOREIGN KEY constraint failed") {
|
|
2859
|
+
try {
|
|
2860
|
+
yield* this.validateForeignKeys(snapshot, existingRows);
|
|
2861
|
+
} catch (foreignKeyError) {
|
|
2862
|
+
error = foreignKeyError;
|
|
2863
|
+
}
|
|
2864
|
+
}
|
|
2865
|
+
if (rollbackSnapshot && error instanceof SqliteConstraintError && error.message !== "FOREIGN KEY constraint failed") {
|
|
2866
|
+
yield* this.restoreSnapshot(rollbackSnapshot);
|
|
2867
|
+
this.txSnapshot = null;
|
|
2868
|
+
this.savepoints.clear();
|
|
2869
|
+
} else if (snapshot && !(failOnConflict && error instanceof SqliteConstraintError && error.message !== "FOREIGN KEY constraint failed")) {
|
|
2728
2870
|
yield* this.restoreSnapshot(snapshot);
|
|
2729
2871
|
[this.lastChanges, this.totalChanges, this.lastInsertRowid] = counters;
|
|
2730
2872
|
}
|
|
@@ -3046,6 +3188,7 @@ var SqliteDatabase = class {
|
|
|
3046
3188
|
const primaryKeyCols = [];
|
|
3047
3189
|
const primaryKeyOrder = [];
|
|
3048
3190
|
const uniqueColSets = [];
|
|
3191
|
+
const implicitIndexes = [];
|
|
3049
3192
|
const foreignKeys = [];
|
|
3050
3193
|
for (const part of bodyParts) {
|
|
3051
3194
|
yield;
|
|
@@ -3111,24 +3254,35 @@ var SqliteDatabase = class {
|
|
|
3111
3254
|
if (direction === "ASC" || direction === "DESC") pIdx++;
|
|
3112
3255
|
}
|
|
3113
3256
|
}
|
|
3257
|
+
implicitIndexes.push({ columns: primaryKeyCols, order: primaryKeyOrder, primary: true });
|
|
3114
3258
|
continue;
|
|
3115
3259
|
}
|
|
3116
3260
|
if (firstWord === "UNIQUE") {
|
|
3117
3261
|
pIdx += 1;
|
|
3118
3262
|
const uCols = [];
|
|
3263
|
+
const order = [];
|
|
3119
3264
|
if (part[pIdx]?.value === "(") {
|
|
3120
|
-
pIdx
|
|
3265
|
+
pIdx++;
|
|
3121
3266
|
while (pIdx < part.length && part[pIdx]?.value !== ")") {
|
|
3122
3267
|
yield;
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3268
|
+
if (part[pIdx].value === ",") {
|
|
3269
|
+
pIdx++;
|
|
3270
|
+
continue;
|
|
3126
3271
|
}
|
|
3127
|
-
pIdx
|
|
3272
|
+
uCols.push(part[pIdx++].value);
|
|
3273
|
+
let collation;
|
|
3274
|
+
if (part[pIdx]?.value.toUpperCase() === "COLLATE") {
|
|
3275
|
+
collation = part[pIdx + 1]?.value;
|
|
3276
|
+
pIdx += 2;
|
|
3277
|
+
}
|
|
3278
|
+
const direction = part[pIdx]?.value.toUpperCase();
|
|
3279
|
+
order.push({ desc: direction === "DESC", collation });
|
|
3280
|
+
if (direction === "ASC" || direction === "DESC") pIdx++;
|
|
3128
3281
|
}
|
|
3129
3282
|
}
|
|
3130
3283
|
if (uCols.length > 0) {
|
|
3131
3284
|
uniqueColSets.push(uCols);
|
|
3285
|
+
implicitIndexes.push({ columns: uCols, order, primary: false });
|
|
3132
3286
|
}
|
|
3133
3287
|
continue;
|
|
3134
3288
|
}
|
|
@@ -3145,6 +3299,17 @@ var SqliteDatabase = class {
|
|
|
3145
3299
|
if (colDef.unique) {
|
|
3146
3300
|
uniqueColSets.push([colDef.name]);
|
|
3147
3301
|
}
|
|
3302
|
+
for (let i = 1; i < part.length; i++) {
|
|
3303
|
+
if (part[i]?.type !== "word") continue;
|
|
3304
|
+
const keyword = part[i].value.toUpperCase();
|
|
3305
|
+
if (keyword === "UNIQUE" || keyword === "PRIMARY" && part[i + 1]?.value.toUpperCase() === "KEY") {
|
|
3306
|
+
implicitIndexes.push({
|
|
3307
|
+
columns: [colDef.name],
|
|
3308
|
+
primary: keyword === "PRIMARY",
|
|
3309
|
+
order: [{ desc: keyword === "PRIMARY" && part[i + 2]?.value.toUpperCase() === "DESC", collation: colDef.collate }]
|
|
3310
|
+
});
|
|
3311
|
+
}
|
|
3312
|
+
}
|
|
3148
3313
|
}
|
|
3149
3314
|
if (primaryKeyCols.length === 1) {
|
|
3150
3315
|
const pkCol = columns.find((c) => {
|
|
@@ -3166,6 +3331,7 @@ var SqliteDatabase = class {
|
|
|
3166
3331
|
primaryKeyCols,
|
|
3167
3332
|
primaryKeyOrder,
|
|
3168
3333
|
uniqueColSets,
|
|
3334
|
+
implicitIndexes,
|
|
3169
3335
|
foreignKeys
|
|
3170
3336
|
});
|
|
3171
3337
|
return;
|
|
@@ -3226,7 +3392,7 @@ var SqliteDatabase = class {
|
|
|
3226
3392
|
}
|
|
3227
3393
|
yield* stepSort(keys, compareKeys, this);
|
|
3228
3394
|
for (let i = 1; i < keys.length; i++) {
|
|
3229
|
-
if ((yield* compareKeys(keys[i - 1], keys[i])) === 0) throw new SqliteConstraintError(`UNIQUE constraint failed: ${tbl.name}`);
|
|
3395
|
+
if ((yield* compareKeys(keys[i - 1], keys[i])) === 0) throw new SqliteConstraintError(`UNIQUE constraint failed: ${cols.map((column) => `${tbl.name}.${column}`).join(", ")}`);
|
|
3230
3396
|
}
|
|
3231
3397
|
}
|
|
3232
3398
|
this.indexes.set(objName, { name: objName, tableName: tbl.name, unique, columns: cols, collations, sql });
|
|
@@ -3812,7 +3978,7 @@ var SqliteDatabase = class {
|
|
|
3812
3978
|
}
|
|
3813
3979
|
if (!previouslyValid) continue;
|
|
3814
3980
|
}
|
|
3815
|
-
throw new
|
|
3981
|
+
throw new SqliteConstraintError("FOREIGN KEY constraint failed");
|
|
3816
3982
|
}
|
|
3817
3983
|
}
|
|
3818
3984
|
}
|
|
@@ -3835,7 +4001,7 @@ var SqliteDatabase = class {
|
|
|
3835
4001
|
yield;
|
|
3836
4002
|
if (this.foreignKeyMatches(child, row, key, columns, oldData)) matches.push(row);
|
|
3837
4003
|
}
|
|
3838
|
-
if (action === "RESTRICT" && matches.length) throw new
|
|
4004
|
+
if (action === "RESTRICT" && matches.length) throw new SqliteConstraintError("FOREIGN KEY constraint failed");
|
|
3839
4005
|
for (const row of matches) {
|
|
3840
4006
|
yield;
|
|
3841
4007
|
const where = child.withoutRowId ? child.primaryKeyCols.map((name) => `${quote(name)} IS ${this.toSqlLiteral(row.data[name] ?? null)}`).join(" AND ") : `rowid = ${row.rowid}`;
|
|
@@ -3945,12 +4111,12 @@ var SqliteDatabase = class {
|
|
|
3945
4111
|
fastIdx.lastRow = added;
|
|
3946
4112
|
}
|
|
3947
4113
|
const byId = fastIdx.byRowid.get(candidate.rowid);
|
|
3948
|
-
if (byId) return byId;
|
|
4114
|
+
if (byId) return { row: byId, columns: [tbl.columns.find((col) => col.primaryKey && col.type.toUpperCase() === "INTEGER")?.name ?? "rowid"] };
|
|
3949
4115
|
for (let i = 0; i < resolvedKeySets.length; i += 1) {
|
|
3950
4116
|
const k = encodeKey(candidate, resolvedKeySets[i]);
|
|
3951
4117
|
if (k !== null) {
|
|
3952
4118
|
const hit = fastIdx.byKeySets[i].get(k);
|
|
3953
|
-
if (hit) return hit;
|
|
4119
|
+
if (hit) return { row: hit, columns: resolvedKeySets[i].map((key) => key.cKey) };
|
|
3954
4120
|
}
|
|
3955
4121
|
}
|
|
3956
4122
|
return null;
|
|
@@ -3961,7 +4127,7 @@ var SqliteDatabase = class {
|
|
|
3961
4127
|
continue;
|
|
3962
4128
|
}
|
|
3963
4129
|
if (existing.rowid === candidate.rowid) {
|
|
3964
|
-
return existing;
|
|
4130
|
+
return { row: existing, columns: [tbl.columns.find((col) => col.primaryKey && col.type.toUpperCase() === "INTEGER")?.name ?? "rowid"] };
|
|
3965
4131
|
}
|
|
3966
4132
|
for (const kSet of resolvedKeySets) {
|
|
3967
4133
|
yield;
|
|
@@ -3976,7 +4142,7 @@ var SqliteDatabase = class {
|
|
|
3976
4142
|
}
|
|
3977
4143
|
}
|
|
3978
4144
|
if (allEqual) {
|
|
3979
|
-
return existing;
|
|
4145
|
+
return { row: existing, columns: kSet.map((key) => key.cKey) };
|
|
3980
4146
|
}
|
|
3981
4147
|
}
|
|
3982
4148
|
}
|
|
@@ -4229,8 +4395,9 @@ var SqliteDatabase = class {
|
|
|
4229
4395
|
if (!(yield* this.fireTriggers(tbl.name, "BEFORE", "INSERT", void 0, candidate.data))) {
|
|
4230
4396
|
continue;
|
|
4231
4397
|
}
|
|
4232
|
-
const
|
|
4233
|
-
if (
|
|
4398
|
+
const conflict = yield* this.checkConstraintsAndConflicts(tbl, candidate);
|
|
4399
|
+
if (conflict) {
|
|
4400
|
+
const conflictRow = conflict.row;
|
|
4234
4401
|
if (upsertDoNothing || conflictAction === "IGNORE") {
|
|
4235
4402
|
continue;
|
|
4236
4403
|
}
|
|
@@ -4282,7 +4449,7 @@ var SqliteDatabase = class {
|
|
|
4282
4449
|
yield* this.applyForeignKeyActions(tbl, conflictRow.data);
|
|
4283
4450
|
}
|
|
4284
4451
|
} else {
|
|
4285
|
-
throw new
|
|
4452
|
+
throw new SqliteConstraintError(`UNIQUE constraint failed: ${conflict.columns.map((column) => `${tbl.name}.${column}`).join(", ")}`);
|
|
4286
4453
|
}
|
|
4287
4454
|
}
|
|
4288
4455
|
tbl.rows.push(candidate);
|
|
@@ -4315,7 +4482,7 @@ var SqliteDatabase = class {
|
|
|
4315
4482
|
let i = 0;
|
|
4316
4483
|
let whereExpr;
|
|
4317
4484
|
while (i < tokens.length) {
|
|
4318
|
-
if (tokens[i].value.toUpperCase() === "WHERE" || tokens
|
|
4485
|
+
if (tokens[i].value.toUpperCase() === "WHERE" || isFromClause(tokens, i)) {
|
|
4319
4486
|
if (tokens[i].value.toUpperCase() === "WHERE") {
|
|
4320
4487
|
whereExpr = new ExprParser(tokens.slice(i + 1)).parseExpression();
|
|
4321
4488
|
}
|
|
@@ -4374,7 +4541,7 @@ var SqliteDatabase = class {
|
|
|
4374
4541
|
d += 1;
|
|
4375
4542
|
} else if (t.value === ")") {
|
|
4376
4543
|
d -= 1;
|
|
4377
|
-
} else if (d === 0 && (t.value === "," || t.value.toUpperCase() === "WHERE" ||
|
|
4544
|
+
} else if (d === 0 && (t.value === "," || t.value.toUpperCase() === "WHERE" || isFromClause(tokens, i))) {
|
|
4378
4545
|
break;
|
|
4379
4546
|
}
|
|
4380
4547
|
exprToks.push(t);
|
|
@@ -4395,6 +4562,7 @@ var SqliteDatabase = class {
|
|
|
4395
4562
|
bindings[`${tbl.name}.${column}`] = value;
|
|
4396
4563
|
if (alias) bindings[`${alias}.${column}`] = value;
|
|
4397
4564
|
}
|
|
4565
|
+
this.rowTables.set(bindings, tbl);
|
|
4398
4566
|
return bindings;
|
|
4399
4567
|
}
|
|
4400
4568
|
*executeUpdate(tokens, positionalParams, _cteScope) {
|
|
@@ -4440,7 +4608,7 @@ var SqliteDatabase = class {
|
|
|
4440
4608
|
const token = tokens[i].value.toUpperCase();
|
|
4441
4609
|
if (token === "(") depth += 1;
|
|
4442
4610
|
else if (token === ")") depth -= 1;
|
|
4443
|
-
else if (depth === 0 &&
|
|
4611
|
+
else if (depth === 0 && isFromClause(tokens, i)) fromIdx = i;
|
|
4444
4612
|
else if (depth === 0 && token === "WHERE") whereIdx = i;
|
|
4445
4613
|
}
|
|
4446
4614
|
const setTokens = fromIdx === -1 ? tokens.slice(idx, sliceEnd) : [...tokens.slice(idx, fromIdx), ...tokens.slice(whereIdx, sliceEnd)];
|
|
@@ -4486,6 +4654,7 @@ var SqliteDatabase = class {
|
|
|
4486
4654
|
for (const other of source.rows) {
|
|
4487
4655
|
yield;
|
|
4488
4656
|
const ctx = { ...other, ...target };
|
|
4657
|
+
this.rowTables.set(ctx, tbl);
|
|
4489
4658
|
if (!whereExpr || isTruthy(yield* this.evalExprSteps(whereExpr, ctx, positionalParams, _cteScope)))
|
|
4490
4659
|
return [{ row, ctx }];
|
|
4491
4660
|
}
|
|
@@ -4533,10 +4702,10 @@ var SqliteDatabase = class {
|
|
|
4533
4702
|
}
|
|
4534
4703
|
if (conflict && conflictAction === "IGNORE") continue;
|
|
4535
4704
|
while (conflict) {
|
|
4536
|
-
if (conflictAction !== "REPLACE") throw new
|
|
4537
|
-
replacedRows.add(conflict);
|
|
4538
|
-
tbl.rows.splice(tbl.rows.indexOf(conflict), 1);
|
|
4539
|
-
yield* this.applyForeignKeyActions(tbl, conflict.data);
|
|
4705
|
+
if (conflictAction !== "REPLACE") throw new SqliteConstraintError(`UNIQUE constraint failed: ${conflict.columns.map((column) => `${tbl.name}.${column}`).join(", ")}`);
|
|
4706
|
+
replacedRows.add(conflict.row);
|
|
4707
|
+
tbl.rows.splice(tbl.rows.indexOf(conflict.row), 1);
|
|
4708
|
+
yield* this.applyForeignKeyActions(tbl, conflict.row.data);
|
|
4540
4709
|
conflict = yield* this.checkConstraintsAndConflicts(tbl, candidate, row.rowid);
|
|
4541
4710
|
}
|
|
4542
4711
|
row.data = newData;
|
|
@@ -5024,7 +5193,7 @@ var SqliteDatabase = class {
|
|
|
5024
5193
|
d -= 1;
|
|
5025
5194
|
} else if (d === 0 && t.type === "word") {
|
|
5026
5195
|
const u = t.value.toUpperCase();
|
|
5027
|
-
if (
|
|
5196
|
+
if (isFromClause(tokens, i) || u === "WHERE" || u === "HAVING" || u === "WINDOW" || u === "LIMIT") {
|
|
5028
5197
|
clausePositions.push({ name: u, pos: i });
|
|
5029
5198
|
} else if (u === "GROUP" && tokens[i + 1]?.value.toUpperCase() === "BY") {
|
|
5030
5199
|
clausePositions.push({ name: "GROUP BY", pos: i });
|
|
@@ -5308,7 +5477,7 @@ var SqliteDatabase = class {
|
|
|
5308
5477
|
const firstWindow = windowResults.keys().next().value;
|
|
5309
5478
|
if (!orderByTokens?.length && firstWindow?.kind === "func" && firstWindow.over) {
|
|
5310
5479
|
const sortSpecs = [
|
|
5311
|
-
...firstWindow.over.partitionBy.map((expr) => ({ expr, desc: false })),
|
|
5480
|
+
...firstWindow.over.partitionBy.map((expr) => ({ expr, desc: false, nulls: void 0 })),
|
|
5312
5481
|
...firstWindow.over.orderBy
|
|
5313
5482
|
];
|
|
5314
5483
|
if (sortSpecs.length > 0) {
|
|
@@ -5321,7 +5490,13 @@ var SqliteDatabase = class {
|
|
|
5321
5490
|
yield* stepSort(keyed, function* (a, b) {
|
|
5322
5491
|
for (let i = 0; i < sortSpecs.length; i++) {
|
|
5323
5492
|
yield;
|
|
5324
|
-
const
|
|
5493
|
+
const vA = a.keys[i];
|
|
5494
|
+
const vB = b.keys[i];
|
|
5495
|
+
const nulls = sortSpecs[i].nulls;
|
|
5496
|
+
if (nulls && vA === null !== (vB === null)) {
|
|
5497
|
+
return vA === null === (nulls === "FIRST") ? -1 : 1;
|
|
5498
|
+
}
|
|
5499
|
+
const cmp = compareSqlValues(vA, vB);
|
|
5325
5500
|
if (cmp !== 0) return sortSpecs[i].desc ? -cmp : cmp;
|
|
5326
5501
|
}
|
|
5327
5502
|
return 0;
|
|
@@ -6194,6 +6369,7 @@ var SqliteDatabase = class {
|
|
|
6194
6369
|
const sameAliasAndName = alias.toLowerCase() === name.toLowerCase();
|
|
6195
6370
|
const rows = yield* stepMap(this.preparing ? [] : tbl.rows, function* (r) {
|
|
6196
6371
|
yield;
|
|
6372
|
+
this.rowTables.set(r.data, tbl);
|
|
6197
6373
|
const tablesMap = sameAliasAndName ? { [alias]: r.data } : { [alias]: r.data, [name]: r.data };
|
|
6198
6374
|
const rowidsMap = sameAliasAndName ? { [alias]: r.rowid } : { [alias]: r.rowid, [name]: r.rowid };
|
|
6199
6375
|
return {
|
|
@@ -6398,6 +6574,9 @@ var SqliteDatabase = class {
|
|
|
6398
6574
|
yield;
|
|
6399
6575
|
const vA = yield* this.evalExprSteps(ob.expr, gA.representative, positionalParams, cteScope, { group: gA.group });
|
|
6400
6576
|
const vB = yield* this.evalExprSteps(ob.expr, gB.representative, positionalParams, cteScope, { group: gB.group });
|
|
6577
|
+
if (ob.nulls && vA === null !== (vB === null)) {
|
|
6578
|
+
return vA === null === (ob.nulls === "FIRST") ? -1 : 1;
|
|
6579
|
+
}
|
|
6401
6580
|
const cmp = compareSqlValues(vA, vB);
|
|
6402
6581
|
if (cmp !== 0) {
|
|
6403
6582
|
return ob.desc ? -cmp : cmp;
|
|
@@ -6994,7 +7173,16 @@ var SqliteDatabase = class {
|
|
|
6994
7173
|
return 0;
|
|
6995
7174
|
}
|
|
6996
7175
|
const collation = expr.left.kind === "collate" ? expr.left.collation : expr.right.kind === "collate" ? expr.right.collation : "BINARY";
|
|
6997
|
-
|
|
7176
|
+
let l = yield* this.evalExprSteps(expr.left, row, positionalParams, cteScope, evaluation);
|
|
7177
|
+
if (expr.op === "IS" || expr.op === "IS NOT") {
|
|
7178
|
+
let right = expr.right;
|
|
7179
|
+
while (right.kind === "collate") right = right.expr;
|
|
7180
|
+
if (right.kind === "literal" && right.booleanLiteral) {
|
|
7181
|
+
const truth = isTruthy(l instanceof Uint8Array ? toSqlString(l) : l);
|
|
7182
|
+
const matches = l !== null && truth === (right.value === 1);
|
|
7183
|
+
return matches !== (expr.op === "IS NOT") ? 1 : 0;
|
|
7184
|
+
}
|
|
7185
|
+
}
|
|
6998
7186
|
if ((expr.op === "LIKE" || expr.op === "GLOB") && expr.right.kind === "func" && expr.right.name === "__like_escape__") {
|
|
6999
7187
|
const pat = yield* this.evalExprSteps(
|
|
7000
7188
|
expr.right.args[0],
|
|
@@ -7015,7 +7203,15 @@ var SqliteDatabase = class {
|
|
|
7015
7203
|
}
|
|
7016
7204
|
return matchLike(toSqlString(l), toSqlString(pat), expr.op === "LIKE", toSqlString(esc)) ? 1 : 0;
|
|
7017
7205
|
}
|
|
7018
|
-
|
|
7206
|
+
let r = yield* this.evalExprSteps(expr.right, row, positionalParams, cteScope, evaluation);
|
|
7207
|
+
if (["=", "==", "!=", "<>", "<", "<=", ">", ">=", "IS", "IS NOT"].includes(expr.op)) {
|
|
7208
|
+
const leftAffinity = this.expressionAffinity(expr.left, row);
|
|
7209
|
+
const rightAffinity = this.expressionAffinity(expr.right, row);
|
|
7210
|
+
if (leftAffinity === "NUMERIC" && rightAffinity !== "NUMERIC") r = applyColumnAffinity(r, "NUMERIC", false);
|
|
7211
|
+
else if (rightAffinity === "NUMERIC" && leftAffinity !== "NUMERIC") l = applyColumnAffinity(l, "NUMERIC", false);
|
|
7212
|
+
else if (leftAffinity === "TEXT" && rightAffinity === void 0) r = applyColumnAffinity(r, "TEXT", false);
|
|
7213
|
+
else if (rightAffinity === "TEXT" && leftAffinity === void 0) l = applyColumnAffinity(l, "TEXT", false);
|
|
7214
|
+
}
|
|
7019
7215
|
return this.applyBinary(expr.op, l, r, collation);
|
|
7020
7216
|
}
|
|
7021
7217
|
case "between": {
|
|
@@ -7138,10 +7334,10 @@ var SqliteDatabase = class {
|
|
|
7138
7334
|
yield* this.evalExprSteps(expr.args[1], row, positionalParams, cteScope, evaluation)
|
|
7139
7335
|
) : mode;
|
|
7140
7336
|
if (mode === "ROLLBACK" && this.inTransaction) {
|
|
7141
|
-
|
|
7142
|
-
|
|
7337
|
+
const snapshot = this.txSnapshot ?? this.savepoints.values().next().value;
|
|
7338
|
+
if (snapshot) {
|
|
7339
|
+
yield* this.restoreSnapshot(snapshot);
|
|
7143
7340
|
}
|
|
7144
|
-
this.inTransaction = false;
|
|
7145
7341
|
this.txSnapshot = null;
|
|
7146
7342
|
this.savepoints.clear();
|
|
7147
7343
|
}
|
|
@@ -7174,6 +7370,31 @@ var SqliteDatabase = class {
|
|
|
7174
7370
|
}
|
|
7175
7371
|
}
|
|
7176
7372
|
}
|
|
7373
|
+
expressionAffinity(expr, row) {
|
|
7374
|
+
if (expr.kind === "collate") return this.expressionAffinity(expr.expr, row);
|
|
7375
|
+
let type;
|
|
7376
|
+
if (expr.kind === "cast") {
|
|
7377
|
+
type = expr.targetType;
|
|
7378
|
+
} else if (expr.kind === "column") {
|
|
7379
|
+
for (const scope of [row, ...this.outerRows.slice().reverse()]) {
|
|
7380
|
+
const tables = scope.__tables;
|
|
7381
|
+
const sources = expr.table ? Object.entries(tables ?? {}).filter(([name]) => name.toLowerCase() === expr.table.toLowerCase()).map(([, data]) => data) : scope.__sources ?? [];
|
|
7382
|
+
for (const source of this.rowTables.has(scope) || sources.length === 0 ? [scope, ...sources] : sources) {
|
|
7383
|
+
const key = expr.table && source === scope ? `${expr.table}.${expr.name}` : expr.name;
|
|
7384
|
+
if (!Object.keys(source).some((name) => name.toLowerCase() === key.toLowerCase())) continue;
|
|
7385
|
+
const table = this.rowTables.get(source);
|
|
7386
|
+
const column = table?.columns.find((column2) => column2.name.toLowerCase() === expr.name.toLowerCase());
|
|
7387
|
+
type = column?.type;
|
|
7388
|
+
if (!column && table && ["rowid", "_rowid_", "oid"].includes(expr.name.toLowerCase())) type = "INTEGER";
|
|
7389
|
+
break;
|
|
7390
|
+
}
|
|
7391
|
+
if (type !== void 0) break;
|
|
7392
|
+
}
|
|
7393
|
+
}
|
|
7394
|
+
if (type === void 0) return void 0;
|
|
7395
|
+
const affinity = columnAffinity(type);
|
|
7396
|
+
return affinity === "BLOB" ? void 0 : affinity === "TEXT" ? "TEXT" : "NUMERIC";
|
|
7397
|
+
}
|
|
7177
7398
|
applyUnary(op, v) {
|
|
7178
7399
|
if (op === "NOT") {
|
|
7179
7400
|
if (v === null) {
|
|
@@ -7260,10 +7481,10 @@ var SqliteDatabase = class {
|
|
|
7260
7481
|
return integerResult(BigInt.asIntN(64, integerPrefix(l) | integerPrefix(r)));
|
|
7261
7482
|
case "=":
|
|
7262
7483
|
case "==":
|
|
7263
|
-
return
|
|
7484
|
+
return compareSqlValues(l, r, collation) === 0 ? 1 : 0;
|
|
7264
7485
|
case "!=":
|
|
7265
7486
|
case "<>":
|
|
7266
|
-
return
|
|
7487
|
+
return compareSqlValues(l, r, collation) !== 0 ? 1 : 0;
|
|
7267
7488
|
case "<":
|
|
7268
7489
|
return compareSqlValues(l, r, collation) < 0 ? 1 : 0;
|
|
7269
7490
|
case "<=":
|
|
@@ -8024,8 +8245,10 @@ function* jsonString(parts) {
|
|
|
8024
8245
|
function* jsonValue(value) {
|
|
8025
8246
|
if (value instanceof JsonText) yield* textParts(value.valueOf());
|
|
8026
8247
|
else if (typeof value === "string" || value instanceof String || value instanceof Uint8Array) yield* jsonString(cellParts(value, ""));
|
|
8027
|
-
else if (value instanceof Number
|
|
8028
|
-
|
|
8248
|
+
else if (value instanceof Number || typeof value === "number" && !Number.isInteger(value)) {
|
|
8249
|
+
const number = value.valueOf();
|
|
8250
|
+
yield Number.isFinite(number) ? formatReal(number, 20) : "null";
|
|
8251
|
+
} else if (typeof value === "bigint") yield value.toString();
|
|
8029
8252
|
else yield JSON.stringify(value ?? null);
|
|
8030
8253
|
}
|
|
8031
8254
|
function* formatQueryParts({ columns, rows }, state) {
|
|
@@ -9341,13 +9564,14 @@ Options:
|
|
|
9341
9564
|
} catch (err) {
|
|
9342
9565
|
context.signal.throwIfAborted();
|
|
9343
9566
|
const msg = err instanceof Error ? err.message : String(err);
|
|
9344
|
-
|
|
9567
|
+
const constraint = err instanceof SqliteConstraintError;
|
|
9568
|
+
await writeText(context.stderr, constraint ? `Error: stepping, ${msg} (${err.code})
|
|
9569
|
+
` : `Error: ${msg}
|
|
9345
9570
|
`);
|
|
9571
|
+
state.exitCode = constraint ? err.code : 1;
|
|
9346
9572
|
if (state.bail || positional.length >= 2) {
|
|
9347
|
-
state.exitCode = 1;
|
|
9348
9573
|
return false;
|
|
9349
9574
|
}
|
|
9350
|
-
state.exitCode = 1;
|
|
9351
9575
|
}
|
|
9352
9576
|
if (state.exitRequested) {
|
|
9353
9577
|
return false;
|
|
@@ -9415,6 +9639,7 @@ Options:
|
|
|
9415
9639
|
}
|
|
9416
9640
|
}
|
|
9417
9641
|
if (!limitExceeded && state.dirty && state.dbPath !== ":memory:" && !state.readonly) {
|
|
9642
|
+
if (db.inTransaction) await execSingleStmt("ROLLBACK");
|
|
9418
9643
|
await saveDbToDisk(state.dbPath);
|
|
9419
9644
|
}
|
|
9420
9645
|
return { exitCode: limitExceeded ? 1 : state.exitCode };
|
|
@@ -9922,6 +10147,7 @@ Options:
|
|
|
9922
10147
|
if (!writeFileSync || !writeFileSync(save.file, save.bytes)) return void 0;
|
|
9923
10148
|
}
|
|
9924
10149
|
if (state.dirty && state.dbPath !== ":memory:") {
|
|
10150
|
+
if (db.inTransaction) db.executeStatement("ROLLBACK");
|
|
9925
10151
|
if (!writeFileSync || !writeFileSync(state.dbPath, db.serializeToBytes())) return void 0;
|
|
9926
10152
|
}
|
|
9927
10153
|
return out;
|