@voltro/database 0.85.0 → 0.86.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +666 -0
- package/THIRD-PARTY-NOTICES.md +5 -33
- package/dist/actorSnapshot.js +24 -0
- package/dist/arrayCodec.js +32 -0
- package/dist/branchExecute.js +92 -0
- package/dist/branching.js +106 -0
- package/dist/bulkInsertLimits.js +25 -0
- package/dist/cdcOffsetsTables.js +19 -0
- package/dist/changeEvent.js +41 -0
- package/dist/changeIdentity.js +65 -0
- package/dist/changeListenerCeiling.js +6 -0
- package/dist/columnReference.js +17 -0
- package/dist/columns.js +326 -0
- package/dist/committedChanges.js +12 -0
- package/dist/connectionIdentity.js +36 -0
- package/dist/coreTables.js +16 -0
- package/dist/coreTablesRegistry.js +10 -0
- package/dist/dataTransfers.js +22 -0
- package/dist/dbCause.js +222 -0
- package/dist/dbMetrics.js +65 -0
- package/dist/decimalComparison.js +27 -0
- package/dist/derivedRowId.js +5 -0
- package/dist/dialect.js +13 -0
- package/dist/enumRenames.js +14 -0
- package/dist/expiresMixin.js +10 -0
- package/dist/fieldEncryption.js +98 -0
- package/dist/frameworkTables.js +130 -0
- package/dist/ginIndex.js +10 -0
- package/dist/hybridSearch.js +32 -0
- package/dist/idGenerator.js +57 -0
- package/dist/identifierLimits.js +32 -0
- package/dist/index.d.ts +18 -7
- package/dist/index.js +81 -2183
- package/dist/indexAudit.js +61 -0
- package/dist/indexStorage.js +58 -0
- package/dist/joinCompiler.js +160 -0
- package/dist/jsonEagerCompiler.js +436 -0
- package/dist/jsonPatch.js +78 -0
- package/dist/jsonPatchAssignments.js +13 -0
- package/dist/jsonPath.js +31 -0
- package/dist/localFirstMixin.js +12 -0
- package/dist/migrate.js +624 -0
- package/dist/migration.js +18 -0
- package/dist/migrations/appliedAtValue.js +8 -0
- package/dist/migrations/applier.js +1085 -0
- package/dist/migrations/boot.js +196 -0
- package/dist/migrations/branchRehearsal.js +122 -0
- package/dist/migrations/columnEquivalence.js +85 -0
- package/dist/migrations/ddlError.js +63 -0
- package/dist/migrations/declaredSchema.js +162 -0
- package/dist/migrations/deployLedger.js +19 -0
- package/dist/migrations/fileBased.js +57 -0
- package/dist/migrations/fileContext.js +482 -0
- package/dist/migrations/fileDiscovery.js +318 -0
- package/dist/migrations/fileSkipProbes.js +117 -0
- package/dist/migrations/fingerprint.js +46 -0
- package/dist/migrations/fkCycles.js +13 -0
- package/dist/migrations/frameworkLiveTables.js +25 -0
- package/dist/migrations/idempotentDdl.js +37 -0
- package/dist/migrations/indexPredicate.js +50 -0
- package/dist/migrations/introspect.js +799 -0
- package/dist/migrations/ledgerRows.js +4 -0
- package/dist/migrations/lock.js +91 -0
- package/dist/migrations/migrationTableExists.js +9 -0
- package/dist/migrations/mssqlColumnDependencies.js +76 -0
- package/dist/migrations/mysqlEngine.js +11 -0
- package/dist/migrations/namespaceCharset.js +51 -0
- package/dist/migrations/planner.js +775 -0
- package/dist/migrations/postgresEnumCheck.js +19 -0
- package/dist/migrations/reactiveTriggerDrift.js +58 -0
- package/dist/migrations/reactiveTriggerName.js +7 -0
- package/dist/migrations/renameMssqlCheck.js +21 -0
- package/dist/migrations/restoreSnapshots.js +206 -0
- package/dist/migrations/resumeLedger.js +86 -0
- package/dist/migrations/rollingDeploy.js +106 -0
- package/dist/migrations/schemaOwner.js +46 -0
- package/dist/migrations/schemaOwnerTable.js +4 -0
- package/dist/migrations/softDropSnapshot.js +20 -0
- package/dist/migrations/sqlLimit.js +8 -0
- package/dist/migrations/sqliteConstraintIdentity.js +97 -0
- package/dist/migrations/sqliteDecimalBoot.js +22 -0
- package/dist/migrations/sqliteDecimalPublication.js +257 -0
- package/dist/migrations/sqliteDecimalReview.js +30 -0
- package/dist/migrations/sqliteDecimalReviewStore.js +188 -0
- package/dist/migrations/sqliteDecimalReviewWitness.js +38 -0
- package/dist/migrations/sqliteDecimalSource.js +69 -0
- package/dist/migrations/sqliteDecimalStage.js +135 -0
- package/dist/migrations/sqliteForeignKeys.js +38 -0
- package/dist/migrations/sqliteMigrationBatch.js +37 -0
- package/dist/migrations/sqliteRetainedSource.js +106 -0
- package/dist/migrations/sqliteRowIdentity.js +63 -0
- package/dist/migrations/sqliteSchemaEpoch.js +12 -0
- package/dist/migrations/sqliteSnapshotGuard.js +10 -0
- package/dist/migrations/sqliteTableContents.js +34 -0
- package/dist/migrations/sqliteTableCopy.js +25 -0
- package/dist/migrations/sqliteTableSchema.js +19 -0
- package/dist/migrations/sqliteWitnessProtection.js +8 -0
- package/dist/migrations/squash.js +81 -0
- package/dist/migrations/storeCharset.js +66 -0
- package/dist/migrations/transactionCause.js +10 -0
- package/dist/migrations/undeclaredCharset.js +40 -0
- package/dist/migrations/uniqueActiveLowering.js +39 -0
- package/dist/mixins.js +22 -0
- package/dist/mssqlDecimalDistinct.js +51 -0
- package/dist/mssqlJsonValueCheck.js +42 -0
- package/dist/mssqlTextStorage.js +9 -0
- package/dist/namespace.js +21 -0
- package/dist/{wire-CG2j7J3f.js → optimisticVersion.js} +2 -2
- package/dist/pendingAttribution.js +79 -0
- package/dist/pluginRef.js +17 -0
- package/dist/predicate.js +266 -0
- package/dist/predicateCoercion.js +13 -0
- package/dist/projectedColumn.js +37 -0
- package/dist/queryBuilder.js +382 -0
- package/dist/rawSql.js +8 -0
- package/dist/relations.js +69 -0
- package/dist/relationsRegistry.js +38 -0
- package/dist/replaceInProgress.js +53 -0
- package/dist/requiredColumns.js +26 -0
- package/dist/residency.js +52 -0
- package/dist/retention.js +62 -0
- package/dist/rowDecoder.js +123 -0
- package/dist/rowKey.js +8 -0
- package/dist/rowSchema.js +31 -0
- package/dist/scopeKey.js +8 -0
- package/dist/seed.js +33 -0
- package/dist/snowflake.js +26 -0
- package/dist/sql.d.ts +27 -6
- package/dist/sql.js +41 -6905
- package/dist/sqlCompiler.js +343 -0
- package/dist/sqlError.js +8 -0
- package/dist/sqlPoolCapacity.js +12 -0
- package/dist/sqliteDecimal.js +22 -0
- package/dist/sqliteDecimalAggregateSql.js +61 -0
- package/dist/sqliteDecimalColumnSql.js +108 -0
- package/dist/sqliteDecimalConversion.js +15 -0
- package/dist/sqliteDecimalCte.js +154 -0
- package/dist/sqliteDecimalEncodeSql.js +32 -0
- package/dist/sqliteDecimalOutputs.js +74 -0
- package/dist/sqliteDecimalPredicate.js +66 -0
- package/dist/sqliteDecimalQuery.js +183 -0
- package/dist/sqliteDecimalQueryPlan.js +37 -0
- package/dist/sqliteDecimalResultSql.js +44 -0
- package/dist/sqliteDecimalRowQuery.js +63 -0
- package/dist/sqliteDecimalSetQuery.js +50 -0
- package/dist/sqliteDecimalSource.js +63 -0
- package/dist/sqliteDecimalStorage.js +29 -0
- package/dist/sqliteDecimalSubquery.js +19 -0
- package/dist/sqliteDecimalWindowQuery.js +196 -0
- package/dist/sqliteValueCoercion.js +4 -0
- package/dist/stampId.js +21 -0
- package/dist/storeErrors.js +9 -0
- package/dist/storeRefusal.js +20 -0
- package/dist/stream.js +36 -0
- package/dist/subjectGraph.js +175 -0
- package/dist/table.js +394 -0
- package/dist/tableRegistry.js +16 -0
- package/dist/tenantSelection.js +27 -0
- package/dist/transactionOutcome.js +97 -0
- package/dist/transientContention.js +36 -0
- package/dist/typedStore.js +16 -0
- package/dist/upsertUpdate.js +20 -0
- package/dist/vectorEmbedding.js +31 -0
- package/dist/view.js +39 -0
- package/dist/wire.js +6 -2
- package/dist/writeAttribution.js +16 -0
- package/dist/writeRecorder.js +37 -0
- package/package.json +3 -3
- package/dist/replaceInProgress-DC88Pdiy.js +0 -3735
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { sqliteDecimalOutputs as e } from "./sqliteDecimalOutputs.js";
|
|
2
|
+
//#region src/sqliteDecimalSetQuery.ts
|
|
3
|
+
var t = (t, n, r, i) => {
|
|
4
|
+
let a = (e) => [
|
|
5
|
+
e.table,
|
|
6
|
+
...(e.joins ?? []).map((e) => e.table),
|
|
7
|
+
...e.setOp?.queries.flatMap(a) ?? []
|
|
8
|
+
], o = "__voltro_decimal_set_";
|
|
9
|
+
for (; a(t).some((e) => e.toLowerCase().startsWith(o));) o += "_";
|
|
10
|
+
let s = [], c = (e) => {
|
|
11
|
+
let t = `${o}${s.length}`;
|
|
12
|
+
return s.push(n`${n(t)} AS (${e})`), t;
|
|
13
|
+
}, l = (t) => {
|
|
14
|
+
if (!t.setOp) throw Error("Missing exact set operation");
|
|
15
|
+
if (t.ctes || t.distinctOn || t.annClause || t.spatialClause || t.fullTextSearch) throw Error("Unsupported exact set query clause");
|
|
16
|
+
let a = e(t, r.resultScale);
|
|
17
|
+
if (new Set(a.map((e) => e.name)).size !== a.length) throw Error("Duplicate exact set output name");
|
|
18
|
+
let o = {
|
|
19
|
+
union: "UNION",
|
|
20
|
+
"union-all": "UNION ALL",
|
|
21
|
+
intersect: "INTERSECT",
|
|
22
|
+
except: "EXCEPT"
|
|
23
|
+
}[t.setOp.kind], s = t.setOp.queries.map((t) => {
|
|
24
|
+
let o = e(t, r.resultScale), s = a.map((e, t) => {
|
|
25
|
+
let r = n`${n(o[t].name)}`, i = (e.decimal?.scale ?? 0) - (o[t].decimal?.scale ?? 0), a = i > 0 ? (o[t].decimal.scale === 0 ? "." : "") + "0".repeat(i) : "";
|
|
26
|
+
return n`${a ? n`${r} || ${a}` : r} AS ${n(`v${t}`)}`;
|
|
27
|
+
}), u = c(t.setOp ? l(t) : i(t));
|
|
28
|
+
return n`SELECT ${n.join(", ", !1)(s)} FROM ${n(u)}`;
|
|
29
|
+
}).reduce((e, t) => n`${e} ${n.unsafe(o)} ${t}`), u = c(s), d = t.order.length ? n` ORDER BY ${n.join(", ", !1)(t.order.flatMap((e) => {
|
|
30
|
+
let t = a.findIndex((t) => t.name === e.column);
|
|
31
|
+
if (t < 0) throw Error("Exact set ordering references an unknown output");
|
|
32
|
+
let r = n`${n(`v${t}`)}`, i = e.direction !== "desc", o = (e, t) => t ? n`${e} ASC` : n`${e} DESC`;
|
|
33
|
+
if (!a[t].decimal) return [o(r, i)];
|
|
34
|
+
let s = n`substr(${r}, 1, 1) = '-'`;
|
|
35
|
+
return [
|
|
36
|
+
o(n`CASE WHEN ${r} IS NULL THEN NULL WHEN ${s} THEN 0 ELSE 1 END`, i),
|
|
37
|
+
o(n`CASE WHEN ${s} THEN length(${r}) END`, !i),
|
|
38
|
+
o(n`CASE WHEN NOT (${s}) THEN length(${r}) END`, i),
|
|
39
|
+
o(n`CASE WHEN ${s} THEN ${r} END COLLATE BINARY`, !i),
|
|
40
|
+
o(n`CASE WHEN NOT (${s}) THEN ${r} END COLLATE BINARY`, i)
|
|
41
|
+
];
|
|
42
|
+
}))}` : n``;
|
|
43
|
+
for (let e of [t.take, t.skip]) if (e !== void 0 && (!Number.isSafeInteger(e) || e < 0)) throw Error("Invalid exact set pagination");
|
|
44
|
+
let f = t.take === void 0 ? t.skip === void 0 ? n`` : n` LIMIT -1` : n` LIMIT ${t.take}`, p = t.skip === void 0 ? n`` : n` OFFSET ${t.skip}`;
|
|
45
|
+
return n`SELECT ${n.join(", ", !1)(a.map((e, t) => n`${n(`v${t}`)} AS ${n(e.name)}`))} FROM ${n(u)}${d}${f}${p}`;
|
|
46
|
+
}, u = l(t);
|
|
47
|
+
return n`WITH ${n.join(", ", !1)(s)} ${u}`;
|
|
48
|
+
};
|
|
49
|
+
//#endregion
|
|
50
|
+
export { t as compileSqliteDecimalSetQuery };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { columnComparisonOperators as e, isColumnReference as t } from "./columnReference.js";
|
|
2
|
+
import { isSqliteDecimalEncodedColumn as n } from "./sqliteDecimalStorage.js";
|
|
3
|
+
import { projectedColumn as r } from "./projectedColumn.js";
|
|
4
|
+
import { compileSqliteDecimalSubquery as i } from "./sqliteDecimalSubquery.js";
|
|
5
|
+
import { compileSqliteDecimalColumnComparison as a, compileSqliteDecimalColumnValue as o } from "./sqliteDecimalColumnSql.js";
|
|
6
|
+
import { lowerSqliteDecimalPredicate as s } from "./sqliteDecimalPredicate.js";
|
|
7
|
+
import { compileStoragePredicate as c } from "./sqlCompiler.js";
|
|
8
|
+
//#region src/sqliteDecimalSource.ts
|
|
9
|
+
var l = (l, u, d, f) => {
|
|
10
|
+
let p = (f) => {
|
|
11
|
+
if ("not" in f) return u`NOT (${p(f.not)})`;
|
|
12
|
+
if ("and" in f) return f.and.length ? u.and(f.and.map(p)) : u`TRUE`;
|
|
13
|
+
if ("or" in f) return f.or.length ? u.or(f.or.map(p)) : u`FALSE`;
|
|
14
|
+
if ("subquery" in f) return i(f, u, d, (e) => {
|
|
15
|
+
let t = r(e, l);
|
|
16
|
+
if (!t) throw Error("Exact IN subquery requires a declared outer column");
|
|
17
|
+
let i = u`${u(e)}`;
|
|
18
|
+
return n(t) ? {
|
|
19
|
+
value: u.unsafe(o({
|
|
20
|
+
expression: i.compile()[0],
|
|
21
|
+
shape: {
|
|
22
|
+
precision: t.precision,
|
|
23
|
+
scale: t.scale
|
|
24
|
+
}
|
|
25
|
+
})),
|
|
26
|
+
scale: t.scale
|
|
27
|
+
} : { value: i };
|
|
28
|
+
});
|
|
29
|
+
if (!("value" in f) || !t(f.value)) {
|
|
30
|
+
if (!("column" in f)) throw Error("Decimal subquery predicates are not integrated yet");
|
|
31
|
+
let e = r(f.column, l), t = n(e) ? s(f, {
|
|
32
|
+
precision: e.precision,
|
|
33
|
+
scale: e.scale
|
|
34
|
+
}, "column") : f;
|
|
35
|
+
return c(t, u, null, l.table);
|
|
36
|
+
}
|
|
37
|
+
let m = r(f.column, l), h = r(f.value.column, l);
|
|
38
|
+
if (!m || !h) throw Error("Column comparisons require declared source columns");
|
|
39
|
+
if (!n(m) && !n(h)) return c(f, u);
|
|
40
|
+
if (!n(m) || !n(h)) throw Error("Encoded decimal comparisons require two decimal columns");
|
|
41
|
+
if (!e.includes(f.op) || f.path?.length) throw Error("Unsupported exact decimal column comparison");
|
|
42
|
+
let g = (e, t) => {
|
|
43
|
+
if (t.precision === void 0 || t.scale === void 0) throw Error("Decimal comparison requires declared precision and scale");
|
|
44
|
+
return {
|
|
45
|
+
expression: u`${u(e)}`.compile()[0],
|
|
46
|
+
shape: {
|
|
47
|
+
precision: t.precision,
|
|
48
|
+
scale: t.scale
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
return u.unsafe(a(g(f.column, m), f.op, g(f.value.column, h)));
|
|
53
|
+
};
|
|
54
|
+
return p(f);
|
|
55
|
+
}, u = (e, t, n) => {
|
|
56
|
+
let r = (r) => l(e, t, n, r), i = n.sourceTable ?? ((e) => e), a = e.alias === void 0 ? t`${t(i(e.table))}` : t`${t(i(e.table))} AS ${t(e.alias)}`;
|
|
57
|
+
return {
|
|
58
|
+
from: (e.joins ?? []).reduce((e, n) => t`${e} ${n.kind === "inner" ? t`INNER` : t`LEFT`} JOIN ${t(i(n.table))} AS ${t(n.alias)} ON ${r(n.on)}`, a),
|
|
59
|
+
where: e.predicate === void 0 ? t`` : t` WHERE ${r(e.predicate)}`
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
//#endregion
|
|
63
|
+
export { u as compileSqliteDecimalSource, l as compileSqliteDecimalSourcePredicate };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { encodeSqliteDecimal as e } from "./sqliteDecimal.js";
|
|
2
|
+
//#region src/sqliteDecimalStorage.ts
|
|
3
|
+
var t = (e) => e?.type === "decimal" && n(e) !== void 0, n = (t) => {
|
|
4
|
+
if (t.sqliteDecimalEncoding === void 0) return;
|
|
5
|
+
if (t.precision === void 0 || t.scale === void 0) throw Error("Encoded SQLite decimal metadata requires precision and scale");
|
|
6
|
+
let n = {
|
|
7
|
+
precision: t.precision,
|
|
8
|
+
scale: t.scale
|
|
9
|
+
};
|
|
10
|
+
return e("0", n), n;
|
|
11
|
+
}, r = (t) => (e("0", t), `VOLTRO_DECIMAL_V1_P${t.precision}_S${t.scale}_TEXT`), i = (t) => {
|
|
12
|
+
let n = /^\s*VOLTRO_DECIMAL_V1_P(\d+)_S(\d+)_TEXT\s*$/i.exec(t);
|
|
13
|
+
if (!n) return;
|
|
14
|
+
let r = {
|
|
15
|
+
precision: Number(n[1]),
|
|
16
|
+
scale: Number(n[2])
|
|
17
|
+
};
|
|
18
|
+
return e("0", r), r;
|
|
19
|
+
}, a = (t, n) => {
|
|
20
|
+
e("0", n);
|
|
21
|
+
let r = "D" + "0".repeat(n.precision + 1), i = "D2" + "0".repeat(n.precision);
|
|
22
|
+
return `(${t} IS NULL OR (typeof(${t}) = 'text' AND length(${t}) = ${n.precision + 2} AND substr(${t}, 1, 1) = 'D' AND substr(${t}, 2) NOT GLOB '*[^0-9]*' AND instr(${t}, char(0)) = 0 AND ${t} COLLATE BINARY > '${r}' AND ${t} COLLATE BINARY < '${i}'))`;
|
|
23
|
+
}, o = (t, n) => {
|
|
24
|
+
if (t == null) return t;
|
|
25
|
+
if (typeof t != "string") throw TypeError("SQLite decimal defaults require exact strings");
|
|
26
|
+
return e(t, n);
|
|
27
|
+
};
|
|
28
|
+
//#endregion
|
|
29
|
+
export { o as encodeSqliteDecimalDefault, t as isSqliteDecimalEncodedColumn, i as parseSqliteDecimalStorageType, a as sqliteDecimalStorageCheck, n as sqliteDecimalStorageShape, r as sqliteDecimalStorageType };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { sqliteDecimalOutputs as e } from "./sqliteDecimalOutputs.js";
|
|
2
|
+
//#region src/sqliteDecimalSubquery.ts
|
|
3
|
+
var t = (t, n, r, i) => {
|
|
4
|
+
let a = r.compile(t.subquery);
|
|
5
|
+
if (t.op === "exists") return n`EXISTS (${a})`;
|
|
6
|
+
if (t.op === "not-exists") return n`NOT EXISTS (${a})`;
|
|
7
|
+
let o = e(t.subquery, r.resultScale);
|
|
8
|
+
if (o.length !== 1) throw Error("Exact IN subquery must project exactly one column");
|
|
9
|
+
if (!("column" in t)) throw Error("Unsupported exact subquery predicate");
|
|
10
|
+
let s = i(t.column), c = o[0];
|
|
11
|
+
if (s.scale === void 0 != (c.decimal === void 0)) throw Error("Exact IN subquery cannot mix decimal and nondecimal values");
|
|
12
|
+
let l = Math.max(s.scale ?? 0, c.decimal?.scale ?? 0), u = (e, t) => {
|
|
13
|
+
let r = l - t;
|
|
14
|
+
return r ? n`${e} || ${(t === 0 ? "." : "") + "0".repeat(r)}` : e;
|
|
15
|
+
}, d = u(s.value, s.scale ?? 0), f = n`SELECT ${u(n`${n(c.name)}`, c.decimal?.scale ?? 0)} FROM (${a})`;
|
|
16
|
+
return t.op === "subquery-in" ? n`${d} IN (${f})` : n`${d} NOT IN (${f})`;
|
|
17
|
+
};
|
|
18
|
+
//#endregion
|
|
19
|
+
export { t as compileSqliteDecimalSubquery };
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { isSqliteDecimalEncodedColumn as e } from "./sqliteDecimalStorage.js";
|
|
2
|
+
import { prepareProjectedColumn as t } from "./projectedColumn.js";
|
|
3
|
+
import { compileSqliteDecimalEncodedSource as n } from "./sqliteDecimalEncodeSql.js";
|
|
4
|
+
import { compileSqliteDecimalDecodedRows as r } from "./sqliteDecimalColumnSql.js";
|
|
5
|
+
import { compileSqliteDecimalResult as i } from "./sqliteDecimalResultSql.js";
|
|
6
|
+
import { compileSqliteDecimalSource as a } from "./sqliteDecimalSource.js";
|
|
7
|
+
import { compileSqliteDecimalAvg as o, compileSqliteDecimalSum as s } from "./sqliteDecimalAggregateSql.js";
|
|
8
|
+
//#region src/sqliteDecimalWindowQuery.ts
|
|
9
|
+
var c = (c, l, u, d, f, p) => {
|
|
10
|
+
let m = t(c), h = c.aggregations ?? [], g = {
|
|
11
|
+
"window-row-number": "ROW_NUMBER",
|
|
12
|
+
"window-rank": "RANK",
|
|
13
|
+
"window-dense-rank": "DENSE_RANK",
|
|
14
|
+
"window-lag": "LAG",
|
|
15
|
+
"window-lead": "LEAD",
|
|
16
|
+
"window-sum-over": "SUM",
|
|
17
|
+
"window-avg-over": "AVG"
|
|
18
|
+
};
|
|
19
|
+
if (c.groupBy?.length || c.having || c.setOp || c.ctes || c.distinctOn || c.annClause || c.spatialClause || c.fullTextSearch || h.some((e) => e.op !== "column" && !(e.op in g))) throw Error("Exact window queries require supported ungrouped window projections");
|
|
20
|
+
if (new Set(h.map((e) => e.alias)).size !== h.length) throw Error("Duplicate decimal result alias");
|
|
21
|
+
let _ = [...new Set(h.flatMap((e) => [
|
|
22
|
+
...e.column === void 0 ? [] : [e.column],
|
|
23
|
+
...e.window?.partitionBy ?? [],
|
|
24
|
+
...(e.window?.orderBy ?? []).map((e) => e.column)
|
|
25
|
+
]))].map((e, t) => {
|
|
26
|
+
let n = m(e);
|
|
27
|
+
if (!n) throw Error("Exact window requires declared source columns");
|
|
28
|
+
return {
|
|
29
|
+
source: e,
|
|
30
|
+
name: `c${t}`,
|
|
31
|
+
field: n
|
|
32
|
+
};
|
|
33
|
+
}), v = new Map(_.map((e) => [e.source, e])), y = (e) => {
|
|
34
|
+
let t = v.get(e);
|
|
35
|
+
if (!t) throw Error("Unknown exact window source column");
|
|
36
|
+
return t.name;
|
|
37
|
+
}, b = (e) => "\"" + e.replace(/"/g, "\"\"") + "\"", { from: x, where: S } = a(c, l, d), [C, w] = l`SELECT ${l.join(", ", !1)([l`ROW_NUMBER() OVER () AS identity`, ..._.map((e) => l`${l(e.source)} AS ${l(e.name)}`)])} FROM ${x}${S}`.compile(), T = f ?? p, E = T?.prefix ?? "__voltro_decimal_window_", D = [c.table, ...(c.joins ?? []).map((e) => e.table)];
|
|
38
|
+
for (; D.some((e) => e.toLowerCase().startsWith(E));) E += "_";
|
|
39
|
+
let O = [], k = (e, t, n) => {
|
|
40
|
+
T ? T.append(e, t) : O.push(`${e} AS MATERIALIZED (${t})`);
|
|
41
|
+
};
|
|
42
|
+
k(E + "source", C, u.materialized);
|
|
43
|
+
let A = [], j = /* @__PURE__ */ new Map(), M, N = !1, P = (e) => {
|
|
44
|
+
if (!N) {
|
|
45
|
+
N = !0;
|
|
46
|
+
let e = c.order;
|
|
47
|
+
if (e.length >= 32 && Object.getPrototypeOf(e) === Array.prototype && !Object.hasOwn(e, "some") && !Object.hasOwn(e, Symbol.iterator)) {
|
|
48
|
+
let t = [];
|
|
49
|
+
for (let n = 0; n < e.length; n++) {
|
|
50
|
+
let r = Object.getOwnPropertyDescriptor(e, String(n)), i = r && "value" in r ? Object.getOwnPropertyDescriptor(r.value, "column") : void 0;
|
|
51
|
+
if (!i || !("value" in i) || typeof i.value != "string") break;
|
|
52
|
+
t.push(i.value);
|
|
53
|
+
}
|
|
54
|
+
t.length === e.length && (M = new Set(t));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return M?.has(e) ?? c.order.some((t) => t.column === e);
|
|
58
|
+
};
|
|
59
|
+
for (let [t, r] of h.entries()) {
|
|
60
|
+
let a = `SELECT * FROM ${E}source`, c = r.column === void 0 ? void 0 : v.get(r.column);
|
|
61
|
+
if (r.op === "column") {
|
|
62
|
+
if (!c) throw Error("Window column projection requires a source column");
|
|
63
|
+
j.set(r.alias, {
|
|
64
|
+
value: c.name,
|
|
65
|
+
key: c.name,
|
|
66
|
+
encoded: c.field
|
|
67
|
+
});
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
let l = [
|
|
71
|
+
"window-lag",
|
|
72
|
+
"window-lead",
|
|
73
|
+
"window-sum-over",
|
|
74
|
+
"window-avg-over"
|
|
75
|
+
].includes(r.op);
|
|
76
|
+
if (l && !c) throw Error("Window operation requires a source column");
|
|
77
|
+
let d = r.window?.partitionBy?.map(y), p = r.window?.orderBy?.map((e) => ({
|
|
78
|
+
...e,
|
|
79
|
+
column: y(e.column)
|
|
80
|
+
})), m = `w${t}`, h = e(c?.field) && ["window-sum-over", "window-avg-over"].includes(r.op);
|
|
81
|
+
if (h) {
|
|
82
|
+
let e = c.field.precision, l = c.field.scale, h = r.op === "window-avg-over" ? u.resultScale ?? l : l, g = e + 20 + Math.max(0, h - l), _ = {
|
|
83
|
+
kind: "window",
|
|
84
|
+
identity: "identity",
|
|
85
|
+
partitionBy: d ?? [],
|
|
86
|
+
orderBy: p ?? []
|
|
87
|
+
}, v = /* @__PURE__ */ new Map(), y = 0, x = {
|
|
88
|
+
prefix: `${E}${t}_`,
|
|
89
|
+
reference: (e) => {
|
|
90
|
+
let t = v.get(e);
|
|
91
|
+
return t === void 0 ? e : `(${t}${t.endsWith("LIMIT -1 OFFSET 0") ? "" : " LIMIT -1 OFFSET 0"}) AS ${e}`;
|
|
92
|
+
},
|
|
93
|
+
append: (e, t, n) => {
|
|
94
|
+
u.materialized || ++y % 4 == 0 ? k(e, t, n) : v.set(e, t);
|
|
95
|
+
}
|
|
96
|
+
}, S = {
|
|
97
|
+
stages: x,
|
|
98
|
+
sourceSql: `SELECT *,${b(c.name)} AS value FROM (${a})`,
|
|
99
|
+
precision: e,
|
|
100
|
+
scope: _,
|
|
101
|
+
materialized: u.materialized
|
|
102
|
+
}, C = r.op === "window-avg-over" ? o({
|
|
103
|
+
...S,
|
|
104
|
+
inputScale: l,
|
|
105
|
+
resultScale: h,
|
|
106
|
+
rounding: u.rounding ?? "half-even"
|
|
107
|
+
}) : s(S);
|
|
108
|
+
if (f) {
|
|
109
|
+
let e = n(`SELECT identity,units AS value FROM (${C})`, {
|
|
110
|
+
precision: g,
|
|
111
|
+
scale: 0
|
|
112
|
+
}, ["identity"], {
|
|
113
|
+
prefix: x.prefix,
|
|
114
|
+
reference: x.reference,
|
|
115
|
+
append: (e, t) => x.append(e, t, u.materialized)
|
|
116
|
+
});
|
|
117
|
+
a = `SELECT identity,value AS ${b(m)} FROM ${e}`, j.set(r.alias, {
|
|
118
|
+
value: m,
|
|
119
|
+
key: m,
|
|
120
|
+
encoded: {
|
|
121
|
+
...c.field,
|
|
122
|
+
precision: g,
|
|
123
|
+
scale: h
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
} else {
|
|
127
|
+
let e = i({
|
|
128
|
+
sourceSql: C,
|
|
129
|
+
digits: g,
|
|
130
|
+
scale: h,
|
|
131
|
+
materialized: u.materialized,
|
|
132
|
+
stages: x
|
|
133
|
+
}), t = P(r.alias);
|
|
134
|
+
a = `SELECT identity,decimal_value AS ${b(m)}${t ? `,decimal_key AS ${b(m + "_key")}` : ""} FROM (${e})`, j.set(r.alias, {
|
|
135
|
+
value: m,
|
|
136
|
+
key: t ? m + "_key" : m
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
} else {
|
|
140
|
+
let e = [...d?.length ? [`PARTITION BY ${d.map(b).join(",")}`] : [], ...p?.length ? [`ORDER BY ${p.map((e) => `${b(e.column)} ${e.direction === "desc" ? "DESC" : "ASC"}`).join(",")}`] : []].join(" "), n = r.op === "window-lag" || r.op === "window-lead", i = r.offset ?? 1;
|
|
141
|
+
if (n && (!Number.isSafeInteger(i) || i < 0)) throw Error("Invalid exact window offset");
|
|
142
|
+
let o = l ? b(c.name) + (n ? `,${i}` : "") : "";
|
|
143
|
+
if (r.op === "window-rank" || r.op === "window-dense-rank") {
|
|
144
|
+
let n = [.../* @__PURE__ */ new Set([...d ?? [], ...(p ?? []).map((e) => e.column)])], i = n.length ? `PARTITION BY ${n.map(b).join(",")}` : "";
|
|
145
|
+
if (r.op === "window-rank") a = `SELECT *,COUNT(*) OVER (${e})-COUNT(*) OVER (${i})+1 AS ${b(m)} FROM (${a})`;
|
|
146
|
+
else {
|
|
147
|
+
let n = `${m}_peer`, r = `${E}peer${t}`;
|
|
148
|
+
k(r, `SELECT *,CASE WHEN ROW_NUMBER() OVER (${i})=1 THEN 1 ELSE 0 END AS ${b(n)} FROM (${a})`, u.materialized), a = `SELECT *,SUM(${b(n)}) OVER (${e}) AS ${b(m)} FROM ${r}`;
|
|
149
|
+
}
|
|
150
|
+
} else if (n) {
|
|
151
|
+
let e = `${m}_position`, n = `${E}shift${t}`;
|
|
152
|
+
k(n, `SELECT *,ROW_NUMBER() OVER (${[...d?.length ? [`PARTITION BY ${d.map(b).join(",")}`] : [], `ORDER BY ${[...(p ?? []).map((e) => `${b(e.column)} ${e.direction === "desc" ? "DESC" : "ASC"}`), "identity ASC"].join(",")}`].join(" ")}) AS ${b(e)} FROM (${a})`, u.materialized);
|
|
153
|
+
let o = [...(d ?? []).map((e) => `shifted.${b(e)} IS current.${b(e)}`), `shifted.${b(e)}=current.${b(e)}${r.op === "window-lag" ? "-" : "+"}${i}`].join(" AND ");
|
|
154
|
+
a = `SELECT current.*,(SELECT shifted.${b(c.name)} FROM ${n} AS shifted WHERE ${o}) AS ${b(m)} FROM ${n} AS current`;
|
|
155
|
+
} else a = `SELECT *,${g[r.op]}(${o}) OVER (${e}) AS ${b(m)} FROM (${a}) LIMIT -1 OFFSET 0`;
|
|
156
|
+
j.set(r.alias, {
|
|
157
|
+
value: m,
|
|
158
|
+
key: m,
|
|
159
|
+
...n ? { encoded: c.field } : {}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
let _ = `${E}stage${t}`, x = h && j.get(r.alias).key !== m ? [m, m + "_key"] : [m];
|
|
163
|
+
k(_, h ? a : `SELECT identity,${x.map(b).join(",")} FROM (${a})`, u.materialized), A.push({
|
|
164
|
+
stage: _,
|
|
165
|
+
values: x
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
let F = `${E}output`;
|
|
169
|
+
k(F, `SELECT ${["input.*", ...A.flatMap((e) => e.values.map((t) => `(SELECT result.${b(t)} FROM ${e.stage} AS result WHERE result.identity=input.identity) AS ${b(t)}`))].join(",")} FROM ${E}source AS input`, u.materialized);
|
|
170
|
+
let I = new Map([...j.values()].flatMap((t) => e(t.encoded) ? [[t.value, {
|
|
171
|
+
name: t.value,
|
|
172
|
+
shape: {
|
|
173
|
+
precision: t.encoded.precision,
|
|
174
|
+
scale: t.encoded.scale
|
|
175
|
+
}
|
|
176
|
+
}]] : [])), L = r(F, f ? [] : [...I.values()], [
|
|
177
|
+
"identity",
|
|
178
|
+
..._.map((e) => e.name),
|
|
179
|
+
...A.flatMap((e) => e.values)
|
|
180
|
+
], {
|
|
181
|
+
prefix: `${E}result_`,
|
|
182
|
+
append: (e, t) => k(e, t, u.materialized)
|
|
183
|
+
}), R = h.map((t) => {
|
|
184
|
+
let n = j.get(t.alias), r = `window_output.${b(n.value)}`;
|
|
185
|
+
return f && e(n.encoded) ? (f.encodedOutput(t.alias), `${r} AS ${b(t.alias)}`) : `${L.values.get(n.value) ?? (n.encoded?.type === "bigint" ? `CAST(${r} AS TEXT)` : r)} AS ${b(t.alias)}`;
|
|
186
|
+
}), z = c.order.length ? " ORDER BY " + c.order.map((e) => {
|
|
187
|
+
let t = j.get(e.column);
|
|
188
|
+
if (!t) throw Error("Ordering references an unknown window result");
|
|
189
|
+
return `window_output.${b(t.key)} ${e.direction === "desc" ? "DESC" : "ASC"}`;
|
|
190
|
+
}).join(",") : "";
|
|
191
|
+
for (let e of [c.take, c.skip]) if (e !== void 0 && (!Number.isSafeInteger(e) || e < 0)) throw Error("Invalid exact decimal pagination");
|
|
192
|
+
let B = c.take === void 0 ? c.skip === void 0 ? "" : " LIMIT -1" : ` LIMIT ${c.take}`, V = c.skip === void 0 ? "" : ` OFFSET ${c.skip}`;
|
|
193
|
+
return l.unsafe(`${T ? "" : `WITH ${O.join(",")} `}SELECT ${c.distinct ? "DISTINCT " : ""}${R.join(",")} FROM ${L.source} AS window_output${z}${B}${V}`, w);
|
|
194
|
+
};
|
|
195
|
+
//#endregion
|
|
196
|
+
export { c as compileSqliteDecimalWindowQuery };
|
package/dist/stampId.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { generateId as e } from "./idGenerator.js";
|
|
2
|
+
import { getTable as t } from "./tableRegistry.js";
|
|
3
|
+
//#region src/stampId.ts
|
|
4
|
+
var n = "id", r = (r, i) => {
|
|
5
|
+
let a = t(r);
|
|
6
|
+
if (a === void 0) return i;
|
|
7
|
+
let o = a.fields[n]?.idScheme;
|
|
8
|
+
if (o === void 0 || i[n] != null) return i;
|
|
9
|
+
if (o.kind === "numeric") {
|
|
10
|
+
if (!(n in i)) return i;
|
|
11
|
+
let e = { ...i };
|
|
12
|
+
return delete e[n], e;
|
|
13
|
+
}
|
|
14
|
+
let s = e(o, r);
|
|
15
|
+
return s === null ? i : {
|
|
16
|
+
...i,
|
|
17
|
+
[n]: s
|
|
18
|
+
};
|
|
19
|
+
}, i = (e, t) => t.map((t) => r(e, t));
|
|
20
|
+
//#endregion
|
|
21
|
+
export { r as stampGeneratedId, i as stampGeneratedIds };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/storeErrors.ts
|
|
2
|
+
var e = (e, t, n) => ({
|
|
3
|
+
_tag: "PrimaryKeyConflictError",
|
|
4
|
+
table: e,
|
|
5
|
+
key: t,
|
|
6
|
+
cause: n
|
|
7
|
+
}), t = (e) => typeof e == "object" && !!e && e._tag === "PrimaryKeyConflictError";
|
|
8
|
+
//#endregion
|
|
9
|
+
export { t as isPrimaryKeyConflictError, e as primaryKeyConflictError };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { authoredError as e, causeBranches as t } from "./dbCause.js";
|
|
2
|
+
//#region src/storeRefusal.ts
|
|
3
|
+
var n = Symbol.for("@voltro/database/storeRefusal"), r = (t) => {
|
|
4
|
+
let r = e(t.detail);
|
|
5
|
+
return Object.defineProperty(r, n, {
|
|
6
|
+
value: t,
|
|
7
|
+
enumerable: !1
|
|
8
|
+
}), r;
|
|
9
|
+
}, i = (e) => {
|
|
10
|
+
for (let r of t(e)) {
|
|
11
|
+
let e = r;
|
|
12
|
+
for (let t = 0; e != null && t < 8; t += 1) {
|
|
13
|
+
let t = e[n];
|
|
14
|
+
if (t !== void 0) return t;
|
|
15
|
+
e = e.cause;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
//#endregion
|
|
20
|
+
export { r as refuseWrite, i as storeRefusalOf };
|
package/dist/stream.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { and as e, gt as t } from "./predicate.js";
|
|
2
|
+
import { Data as n, Effect as r, Option as i, Stream as a } from "effect";
|
|
3
|
+
//#region src/stream.ts
|
|
4
|
+
var o = class extends n.TaggedError("TableStreamError") {}, s = 1e3, c = (n, r, a, o) => {
|
|
5
|
+
let s = i.match(o, {
|
|
6
|
+
onNone: () => n.where,
|
|
7
|
+
onSome: (i) => n.where ? e(n.where, t(r, i)) : t(r, i)
|
|
8
|
+
});
|
|
9
|
+
return {
|
|
10
|
+
table: n.table,
|
|
11
|
+
predicate: s,
|
|
12
|
+
order: [{
|
|
13
|
+
column: r,
|
|
14
|
+
direction: "asc"
|
|
15
|
+
}],
|
|
16
|
+
take: a,
|
|
17
|
+
skip: void 0,
|
|
18
|
+
projection: n.projection,
|
|
19
|
+
...n.includeDeleted === void 0 ? {} : { includeDeleted: n.includeDeleted },
|
|
20
|
+
...n.crossTenant === void 0 ? {} : { crossTenant: n.crossTenant }
|
|
21
|
+
};
|
|
22
|
+
}, l = (e, t) => {
|
|
23
|
+
let n = t.pk ?? "id", l = t.chunkSize ?? s;
|
|
24
|
+
return a.paginate(i.none(), (a) => {
|
|
25
|
+
let s = r.tryPromise({
|
|
26
|
+
try: () => e.query(c(t, n, l, a)),
|
|
27
|
+
catch: (e) => new o({
|
|
28
|
+
table: t.table,
|
|
29
|
+
cause: e
|
|
30
|
+
})
|
|
31
|
+
});
|
|
32
|
+
return (t.retry ? s.pipe(r.retry(t.retry)) : s).pipe(r.map((e) => [e, e.length === l && e.length > 0 ? i.some(i.some(e[e.length - 1][n])) : i.none()]));
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
//#endregion
|
|
36
|
+
export { o as TableStreamError, l as streamTable };
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { allRegisteredTables as e } from "./tableRegistry.js";
|
|
2
|
+
import { allRegisteredRelations as t } from "./relationsRegistry.js";
|
|
3
|
+
import { types as n } from "node:util";
|
|
4
|
+
//#region src/subjectGraph.ts
|
|
5
|
+
var r = 4, i = (e) => Object.keys(e.fields), a = (e, t) => Object.prototype.hasOwnProperty.call(e.fields, t), o = (e, t) => {
|
|
6
|
+
let n = [];
|
|
7
|
+
for (let [r, i] of Object.entries(e.fields)) i.type === "reference" && i.references?.()?.tableName === t && n.push(r);
|
|
8
|
+
return n;
|
|
9
|
+
}, s = (e, t) => {
|
|
10
|
+
let n = [];
|
|
11
|
+
for (let r of t) {
|
|
12
|
+
if (r.source !== e) continue;
|
|
13
|
+
let t = r.relation, i;
|
|
14
|
+
try {
|
|
15
|
+
i = t.target();
|
|
16
|
+
} catch {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
if (t.kind === "manyToMany") {
|
|
20
|
+
let e;
|
|
21
|
+
try {
|
|
22
|
+
e = t.through();
|
|
23
|
+
} catch {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (!a(e, t.sourceKey)) continue;
|
|
27
|
+
n.push({
|
|
28
|
+
table: e.tableName,
|
|
29
|
+
foreignKey: t.sourceKey,
|
|
30
|
+
parentKey: "id"
|
|
31
|
+
});
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (t.sourceKey !== void 0) continue;
|
|
35
|
+
let s = o(i, e), c = t.foreignKey ?? (s.length === 1 ? s[0] : void 0);
|
|
36
|
+
if (c === void 0 || !a(i, c)) continue;
|
|
37
|
+
let l = i.fields[c];
|
|
38
|
+
n.push({
|
|
39
|
+
table: i.tableName,
|
|
40
|
+
foreignKey: c,
|
|
41
|
+
parentKey: l?.referenceColumn ?? "id"
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return n;
|
|
45
|
+
}, c = (e, t) => {
|
|
46
|
+
let n = [];
|
|
47
|
+
for (let r of t) if (r.tableName !== e) for (let t of o(r, e)) {
|
|
48
|
+
let e = r.fields[t];
|
|
49
|
+
n.push({
|
|
50
|
+
table: r.tableName,
|
|
51
|
+
foreignKey: t,
|
|
52
|
+
parentKey: e?.referenceColumn ?? "id"
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return n;
|
|
56
|
+
}, l = (e) => {
|
|
57
|
+
if (n.isProxy(e)) return !1;
|
|
58
|
+
let t = Object.getPrototypeOf(e);
|
|
59
|
+
return (t === Object.prototype || t === null) && Reflect.ownKeys(e).every((t) => "value" in Object.getOwnPropertyDescriptor(e, t));
|
|
60
|
+
}, u = (e) => !n.isProxy(e) && Object.getPrototypeOf(e) === Array.prototype && Reflect.ownKeys(e).every((t) => typeof t == "string" && (t === "length" || /^(0|[1-9][0-9]*)$/.test(t)) && "value" in Object.getOwnPropertyDescriptor(e, t)), d = (e) => {
|
|
61
|
+
if (e.length < 32 || !u(e) || !e.every((e) => l(e) && l(e.fields) && Object.values(e.fields).every(l))) return (t) => c(t, e);
|
|
62
|
+
let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
|
|
63
|
+
e.forEach((e, t) => {
|
|
64
|
+
n.has(e) || n.set(e, t);
|
|
65
|
+
});
|
|
66
|
+
let r, i = !1, a = (e) => {
|
|
67
|
+
for (let r of e) {
|
|
68
|
+
let e = n.get(r);
|
|
69
|
+
for (let [n, i] of Object.entries(r.fields)) {
|
|
70
|
+
if (i.type !== "reference") continue;
|
|
71
|
+
let a = i.references?.()?.tableName;
|
|
72
|
+
if (a === void 0) continue;
|
|
73
|
+
let o = {
|
|
74
|
+
order: e,
|
|
75
|
+
hop: {
|
|
76
|
+
table: r.tableName,
|
|
77
|
+
foreignKey: n,
|
|
78
|
+
parentKey: i.referenceColumn ?? "id"
|
|
79
|
+
}
|
|
80
|
+
}, s = t.get(a);
|
|
81
|
+
s ? s.push(o) : t.set(a, [o]);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
return (n) => {
|
|
86
|
+
if (!i) r = e.filter((e) => e.tableName === n), a(e.filter((e) => e.tableName !== n)), i = !0;
|
|
87
|
+
else if (r?.some((e) => e.tableName !== n)) {
|
|
88
|
+
a(r), r = void 0;
|
|
89
|
+
for (let e of t.values()) e.sort((e, t) => e.order - t.order);
|
|
90
|
+
}
|
|
91
|
+
return (t.get(n) ?? []).filter((e) => e.hop.table !== n).map((e) => e.hop);
|
|
92
|
+
};
|
|
93
|
+
}, f = (e) => {
|
|
94
|
+
if (e.length < 32 || !u(e) || !e.every(l)) return (t) => s(t, e);
|
|
95
|
+
let t = /* @__PURE__ */ new Map();
|
|
96
|
+
for (let n of e) {
|
|
97
|
+
let e = t.get(n.source);
|
|
98
|
+
e ? e.push(n) : t.set(n.source, [n]);
|
|
99
|
+
}
|
|
100
|
+
return (e) => s(e, t.get(e) ?? []);
|
|
101
|
+
}, p = (e) => `${e.table}\u0000${e.hops.map((e) => `${e.table}.${e.foreignKey}<-${e.parentKey}`).join("|")}`, m = (n) => {
|
|
102
|
+
let r = n.tables ?? e(), a = n.relations ?? t(), o = n.maxDepth ?? 4, s = new Set(n.exclude ?? []), c = new Map(r.map((e) => [e.tableName, e])), l = [];
|
|
103
|
+
if (!c.has(n.subjectTable)) return {
|
|
104
|
+
subjectTable: n.subjectTable,
|
|
105
|
+
paths: [],
|
|
106
|
+
limitations: [{
|
|
107
|
+
kind: "unreachable",
|
|
108
|
+
table: n.subjectTable,
|
|
109
|
+
detail: `the subject table '${n.subjectTable}' is not registered — no schema was loaded, or the name is wrong. Registered: ${r.length === 0 ? "<none>" : r.map((e) => e.tableName).join(", ")}`
|
|
110
|
+
}]
|
|
111
|
+
};
|
|
112
|
+
let u = {
|
|
113
|
+
table: n.subjectTable,
|
|
114
|
+
hops: [],
|
|
115
|
+
depth: 0,
|
|
116
|
+
via: "relation"
|
|
117
|
+
}, m = d(r), h = f(a), g = [u], _ = /* @__PURE__ */ new Set([p(u)]), v = /* @__PURE__ */ new Set(), y = [u];
|
|
118
|
+
for (let e = 1; e <= o; e++) {
|
|
119
|
+
let t = [];
|
|
120
|
+
for (let n of y) {
|
|
121
|
+
let r = h(n.table), i = m(n.table), a = [...r.map((e) => [e, "relation"]), ...i.map((e) => [e, "reference"])];
|
|
122
|
+
for (let [r, i] of a) {
|
|
123
|
+
if (s.has(r.table)) {
|
|
124
|
+
l.push({
|
|
125
|
+
kind: "excluded",
|
|
126
|
+
table: r.table,
|
|
127
|
+
detail: `excluded by configuration (reached from '${n.table}')`
|
|
128
|
+
});
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
let a = `${r.table}\u0000${r.foreignKey}`;
|
|
132
|
+
if (v.has(a)) continue;
|
|
133
|
+
v.add(a);
|
|
134
|
+
let o = {
|
|
135
|
+
table: r.table,
|
|
136
|
+
hops: [...n.hops, r],
|
|
137
|
+
depth: e,
|
|
138
|
+
via: i
|
|
139
|
+
}, c = p(o);
|
|
140
|
+
_.has(c) || (_.add(c), g.push(o), t.push(o));
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (t.length === 0) {
|
|
144
|
+
y = [];
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
y = t;
|
|
148
|
+
}
|
|
149
|
+
for (let e of y) (h(e.table).length > 0 || m(e.table).length > 0) && l.push({
|
|
150
|
+
kind: "depth-truncated",
|
|
151
|
+
table: e.table,
|
|
152
|
+
detail: `stopped at maxDepth ${o}; tables linked FROM '${e.table}' were not explored`
|
|
153
|
+
});
|
|
154
|
+
let b = new Set(g.map((e) => e.table));
|
|
155
|
+
for (let e of r) b.has(e.tableName) || s.has(e.tableName) || l.push({
|
|
156
|
+
kind: "unreachable",
|
|
157
|
+
table: e.tableName,
|
|
158
|
+
detail: `no relation() and no reference() column links '${e.tableName}' to '${n.subjectTable}'. If it holds subject data through a plain column, a polymorphic (type,id) pair, JSON or free text, add an explicit subjectScopes entry — this derivation cannot see it. Columns: ${i(e).join(", ")}`
|
|
159
|
+
});
|
|
160
|
+
return {
|
|
161
|
+
subjectTable: n.subjectTable,
|
|
162
|
+
paths: g,
|
|
163
|
+
limitations: l
|
|
164
|
+
};
|
|
165
|
+
}, h = (e) => {
|
|
166
|
+
let t = [`subject graph · ${e.subjectTable} · ${e.paths.length} table(s) reachable`];
|
|
167
|
+
for (let n of e.paths) {
|
|
168
|
+
let r = n.hops.length === 0 ? `${e.subjectTable} (the subject row itself)` : [e.subjectTable, ...n.hops.map((e) => `${e.table}.${e.foreignKey}`)].join(" → ");
|
|
169
|
+
t.push(` • ${n.table} [depth ${n.depth}, via ${n.via}]`), t.push(` ${r}`);
|
|
170
|
+
}
|
|
171
|
+
let n = e.limitations.filter((e) => e.kind === "depth-truncated"), r = e.limitations.filter((e) => e.kind === "unreachable"), i = e.limitations.filter((e) => e.kind === "excluded");
|
|
172
|
+
return t.push(""), t.push(" WHAT THIS CANNOT SEE — a DSAR is only as complete as this list is short:"), n.length > 0 && t.push(` depth-truncated (${n.length}): ${n.map((e) => e.table).join(", ")}`), i.length > 0 && t.push(` excluded (${i.length}): ${[...new Set(i.map((e) => e.table))].join(", ")}`), t.push(r.length === 0 ? " unreachable: none — every registered table is linked to the subject." : ` unreachable (${r.length}): ${r.map((e) => e.table).join(", ")}`), t.push(" Always outside this graph: object storage / uploaded files, external processors,"), t.push(" log and metric sinks, backups, and any subject id embedded in JSON or free text."), t.join("\n");
|
|
173
|
+
};
|
|
174
|
+
//#endregion
|
|
175
|
+
export { r as DEFAULT_SUBJECT_GRAPH_DEPTH, m as deriveSubjectGraph, h as formatSubjectGraph };
|