@voltro/database 0.84.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 +1215 -0
- package/THIRD-PARTY-NOTICES.md +5 -89
- 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 +122 -64
- package/dist/index.js +81 -2080
- 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-B28cPjEp.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 +58 -29
- package/dist/sql.js +41 -6661
- 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.d.ts +9 -10
- package/dist/wire.js +6 -2
- package/dist/writeAttribution.js +16 -0
- package/dist/writeRecorder.js +37 -0
- package/package.json +4 -6
- package/dist/replaceInProgress-DUHl5JEz.js +0 -3557
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
//#region src/migrations/ledgerRows.ts
|
|
2
|
+
var e = (e) => e.literal("(source = 'file' AND id NOT LIKE 'plan!_%' ESCAPE '!')"), t = (e) => e.literal("(source IS NULL OR source <> 'file' OR id LIKE 'plan!_%' ESCAPE '!')");
|
|
3
|
+
//#endregion
|
|
4
|
+
export { t as describesSchema, e as isFileMigrationRow };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { sqlPoolCapacity as e } from "../sqlPoolCapacity.js";
|
|
2
|
+
import { Effect as t, Exit as n, Fiber as r, Scope as i } from "effect";
|
|
3
|
+
//#region src/migrations/lock.ts
|
|
4
|
+
var a = (e, t) => e.executeUnprepared(t, [], void 0), o = 6322741009312437n, s = (e) => {
|
|
5
|
+
let t = e?.trim();
|
|
6
|
+
return t === void 0 || t === "" || t === "public" ? void 0 : t;
|
|
7
|
+
}, c = (e) => e?.schema === void 0 ? s(process.env.DB_SCHEMA) : s(e.schema), l = 14695981039346656037n, u = 1099511628211n, d = 18446744073709551615n, f = (e) => {
|
|
8
|
+
let t = l;
|
|
9
|
+
for (let n of new TextEncoder().encode(e)) t ^= BigInt(n), t = t * u & d;
|
|
10
|
+
return t;
|
|
11
|
+
}, p = (e) => {
|
|
12
|
+
let t = s(e);
|
|
13
|
+
return t === void 0 ? o : f(`voltro_migration_lock:${t}`) & 9223372036854775807n;
|
|
14
|
+
}, m = (e) => {
|
|
15
|
+
let t = `voltro_migration_${o.toString(36)}`, n = s(e);
|
|
16
|
+
if (n === void 0) return t;
|
|
17
|
+
let r = `${t}_${n}`;
|
|
18
|
+
return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(f(`voltro_migration_lock:${n}`) & d).toString(16)}`;
|
|
19
|
+
}, h = 250, g = () => {
|
|
20
|
+
let e = Number(process.env.VOLTRO_MIGRATION_LOCK_TIMEOUT_MS);
|
|
21
|
+
return Number.isFinite(e) && e > 0 ? e : 3e4;
|
|
22
|
+
}, _ = (e, n) => t.map(a(e, `SELECT (EXTRACT(EPOCH FROM (clock_timestamp() - a.state_change)) * 1000)::float8 AS silent
|
|
23
|
+
FROM pg_catalog.pg_locks l JOIN pg_catalog.pg_stat_activity a ON a.pid = l.pid
|
|
24
|
+
WHERE l.locktype = 'advisory' AND l.granted AND l.objsubid = 1
|
|
25
|
+
AND l.classid::bigint = ((${n.toString()}::bigint >> 32) & 4294967295)
|
|
26
|
+
AND l.objid::bigint = (${n.toString()}::bigint & 4294967295)
|
|
27
|
+
LIMIT 1`), (e) => {
|
|
28
|
+
let t = e[0]?.silent;
|
|
29
|
+
return t == null ? void 0 : Number(t);
|
|
30
|
+
}), v = () => Math.max(250, Math.min(5e3, Math.floor(g() / 4))), y = (e, n) => t.gen(function* () {
|
|
31
|
+
let r = g(), i = Date.now(), o = 0;
|
|
32
|
+
for (;;) {
|
|
33
|
+
if ((yield* a(e, `SELECT pg_try_advisory_lock(${n.toString()}::bigint) AS got`))[0]?.got) return;
|
|
34
|
+
let s = yield* _(e, n), c = s !== void 0 && s < r, l = Date.now() - i;
|
|
35
|
+
c && l - o >= r && (o = l, yield* t.logInfo(`migration lock: waiting for another migration in progress (${Math.round(l / 1e3)}s so far; its session was active ${Math.round(s / 1e3)}s ago)`).pipe(t.annotateLogs({ scope: "voltro:migrate" }))), !c && l >= r && (yield* t.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock: its holder has been silent for ${Math.round(r / 1e3)}s. A migration still running would have kept its lock session active, so this is most likely a prior boot that crashed while holding it. (A crashed process's session-level advisory lock is released once its DB connection closes; if this persists, find + terminate the holder via pg_stat_activity, or raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS.)`))), yield* t.sleep(`${h} millis`);
|
|
36
|
+
}
|
|
37
|
+
}), b = (e, n) => t.asVoid(a(e, `SELECT pg_advisory_unlock(${n.toString()}::bigint)`)), x = (e, n) => t.map(a(e, `SELECT p.TIME AS silent FROM information_schema.PROCESSLIST p WHERE p.ID = IS_USED_LOCK('${n}')`), (e) => {
|
|
38
|
+
let t = e[0]?.silent;
|
|
39
|
+
return t == null ? void 0 : Number(t) * 1e3;
|
|
40
|
+
}), S = (e, n) => t.gen(function* () {
|
|
41
|
+
let r = g(), i = Date.now(), o = 0;
|
|
42
|
+
for (;;) {
|
|
43
|
+
if ((yield* a(e, `SELECT GET_LOCK('${n}', 1) AS got`))[0]?.got === 1) return;
|
|
44
|
+
let s = yield* x(e, n), c = s !== void 0 && s - 1e3 < r, l = Date.now() - i;
|
|
45
|
+
c && l - o >= r && (o = l, yield* t.logInfo(`migration lock: waiting for another migration in progress (${Math.round(l / 1e3)}s so far)`).pipe(t.annotateLogs({ scope: "voltro:migrate" }))), !c && l >= r && (yield* t.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${n}' within ${Math.round(r / 1e3)}s (another migration is in progress and has been silent that long, or a prior one left it held). Raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS if a migration legitimately goes quiet for longer.`)));
|
|
46
|
+
}
|
|
47
|
+
}), C = (e, n) => t.asVoid(a(e, `SELECT RELEASE_LOCK('${n}')`)), w = 3e4, T = (e, n) => t.gen(function* () {
|
|
48
|
+
let r = yield* a(e, `
|
|
49
|
+
DECLARE @res int;
|
|
50
|
+
EXEC @res = sp_getapplock @Resource = '${n}', @LockMode = 'Exclusive',
|
|
51
|
+
@LockOwner = 'Session', @LockTimeout = ${String(w)};
|
|
52
|
+
SELECT @res AS res`);
|
|
53
|
+
(r[0]?.res ?? -999) < 0 && (yield* t.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${n}' (sp_getapplock returned ${r[0]?.res ?? "no row"}; another migration is in progress).`)));
|
|
54
|
+
}), E = (e, n) => t.asVoid(a(e, `EXEC sp_releaseapplock @Resource = '${n}', @LockOwner = 'Session'`)), D = t.void, O = (o, s) => t.gen(function* () {
|
|
55
|
+
let l = c(s), u = m(l), d = p(l);
|
|
56
|
+
if (!o.onDialectOrElse({
|
|
57
|
+
mysql: () => !0,
|
|
58
|
+
mssql: () => !0,
|
|
59
|
+
sqlite: () => !1,
|
|
60
|
+
orElse: () => !0
|
|
61
|
+
})) return {
|
|
62
|
+
release: D,
|
|
63
|
+
connection: void 0
|
|
64
|
+
};
|
|
65
|
+
let f = e(o);
|
|
66
|
+
if (f !== void 0 && f < 2) return yield* t.die(/* @__PURE__ */ Error(`migrate needs at least 2 connections, pool has ${f}: one holds the migration lock and another runs the statements. Configure maxConnections >= 2 for the migrating process.`));
|
|
67
|
+
let h = yield* i.make(), g = yield* t.provideService(o.reserve, i.Scope, h), _ = i.close(h, n.void);
|
|
68
|
+
yield* o.onDialectOrElse({
|
|
69
|
+
mysql: () => S(g, u),
|
|
70
|
+
mssql: () => T(g, u),
|
|
71
|
+
sqlite: () => D,
|
|
72
|
+
orElse: () => y(g, d)
|
|
73
|
+
}).pipe(t.onExit((e) => n.isSuccess(e) ? t.void : _));
|
|
74
|
+
let x = t.uninterruptible(t.ignore(a(g, "SELECT 1"))).pipe(t.delay(`${v()} millis`), t.forever, t.interruptible, t.forkIn(h)), w = yield* o.onDialectOrElse({
|
|
75
|
+
mysql: () => x,
|
|
76
|
+
mssql: () => t.succeed(void 0),
|
|
77
|
+
sqlite: () => t.succeed(void 0),
|
|
78
|
+
orElse: () => x
|
|
79
|
+
}), O = w === void 0 ? t.void : r.interrupt(w);
|
|
80
|
+
return {
|
|
81
|
+
release: o.onDialectOrElse({
|
|
82
|
+
mysql: () => C(g, u),
|
|
83
|
+
mssql: () => E(g, u),
|
|
84
|
+
sqlite: () => D,
|
|
85
|
+
orElse: () => b(g, d)
|
|
86
|
+
}).pipe((e) => t.andThen(O, e), t.ensuring(_)),
|
|
87
|
+
connection: g
|
|
88
|
+
};
|
|
89
|
+
}), k = "a migration needs 2 connections: one holds the migration lock for the whole apply, the other runs the statements. The pool could not hand out the second one — raise its size (DB_MAX_CONNECTIONS / PG_MAX_CONNECTIONS, or the driver's own `maxConnections`) to at least 2 for the migrating process; behind a pooler (PgBouncer, Supavisor) point the migration at the database directly (DB_DIRECT_URL / DB_MIGRATE_URL).", A = (e) => /acquire connection/i.test(String(e?.message ?? e)), j = (e, n, r) => t.acquireUseRelease(O(e, r), () => n.pipe(t.tapError((e) => A(e) ? t.logError(`migrate: ${k}`).pipe(t.annotateLogs({ scope: "voltro:migrate" })) : t.void)), (e) => e.release.pipe(t.orDie));
|
|
90
|
+
//#endregion
|
|
91
|
+
export { k as MIGRATION_NEEDS_TWO_CONNECTIONS, o as VOLTRO_MIGRATION_LOCK_KEY, O as acquireMigrationLock, f as fnv1a64, p as migrationLockKeyForSchema, m as migrationLockNameForSchema, c as resolveMigrationLockSchema, j as withMigrationLock };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { dialectOf as e } from "./resumeLedger.js";
|
|
2
|
+
import { Effect as t } from "effect";
|
|
3
|
+
//#region src/migrations/migrationTableExists.ts
|
|
4
|
+
var n = (n, r) => {
|
|
5
|
+
let i = e(n);
|
|
6
|
+
return (i === "sqlite" ? n`SELECT COUNT(*) AS n FROM sqlite_master WHERE type = 'table' AND name = ${r}` : i === "mysql" ? n`SELECT COUNT(*) AS n FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = ${r}` : i === "mssql" ? n`SELECT COUNT(*) AS n FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = ${r}` : n`SELECT COUNT(*) AS n FROM information_schema.tables WHERE table_schema = current_schema() AND table_name = ${r}`).pipe(t.map((e) => Number(e[0]?.n ?? 0) > 0));
|
|
7
|
+
};
|
|
8
|
+
//#endregion
|
|
9
|
+
export { n as migrationTableExists };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { quoteIdent as e } from "../dialect.js";
|
|
2
|
+
import { sqlError as t } from "../sqlError.js";
|
|
3
|
+
import { Effect as n } from "effect";
|
|
4
|
+
//#region src/migrations/mssqlColumnDependencies.ts
|
|
5
|
+
var r = (t) => e(t, "mssql"), i = (e, i, a, o) => n.gen(function* () {
|
|
6
|
+
let s = yield* e`
|
|
7
|
+
SELECT 'foreign key' AS kind FROM sys.foreign_key_columns f
|
|
8
|
+
JOIN sys.columns c ON c.object_id = f.parent_object_id AND c.column_id = f.parent_column_id
|
|
9
|
+
WHERE c.object_id = OBJECT_ID(${i}) AND c.name = ${a}
|
|
10
|
+
UNION ALL
|
|
11
|
+
SELECT 'referencing foreign key' FROM sys.foreign_key_columns f
|
|
12
|
+
JOIN sys.columns c ON c.object_id = f.referenced_object_id AND c.column_id = f.referenced_column_id
|
|
13
|
+
WHERE c.object_id = OBJECT_ID(${i}) AND c.name = ${a}
|
|
14
|
+
UNION ALL
|
|
15
|
+
SELECT 'schema-bound expression' FROM sys.sql_expression_dependencies dep
|
|
16
|
+
JOIN sys.columns c ON c.object_id = dep.referenced_id AND c.column_id = dep.referenced_minor_id
|
|
17
|
+
WHERE c.object_id = OBJECT_ID(${i}) AND c.name = ${a} AND dep.is_schema_bound_reference = 1
|
|
18
|
+
AND dep.referencing_class <> 7
|
|
19
|
+
AND NOT EXISTS (SELECT 1 FROM sys.check_constraints ck WHERE ck.object_id = dep.referencing_id)
|
|
20
|
+
UNION ALL
|
|
21
|
+
SELECT 'user-created statistics' FROM sys.stats s
|
|
22
|
+
JOIN sys.stats_columns sc ON sc.object_id = s.object_id AND sc.stats_id = s.stats_id
|
|
23
|
+
JOIN sys.columns c ON c.object_id = sc.object_id AND c.column_id = sc.column_id
|
|
24
|
+
WHERE c.object_id = OBJECT_ID(${i}) AND c.name = ${a} AND s.user_created = 1
|
|
25
|
+
AND NOT EXISTS (SELECT 1 FROM sys.indexes i WHERE i.object_id = s.object_id AND i.index_id = s.stats_id)
|
|
26
|
+
`, c = yield* e`
|
|
27
|
+
SELECT dc.name, dc.definition FROM sys.default_constraints dc
|
|
28
|
+
JOIN sys.columns c ON c.object_id = dc.parent_object_id AND c.column_id = dc.parent_column_id
|
|
29
|
+
WHERE c.object_id = OBJECT_ID(${i}) AND c.name = ${a}
|
|
30
|
+
`, l = yield* e`
|
|
31
|
+
SELECT ck.name, ck.definition, ck.is_disabled AS disabled, ck.is_not_trusted AS untrusted,
|
|
32
|
+
ck.is_not_for_replication AS notForReplication
|
|
33
|
+
FROM sys.check_constraints ck WHERE ck.parent_object_id = OBJECT_ID(${i}) AND (
|
|
34
|
+
ck.parent_column_id = (SELECT c.column_id FROM sys.columns c WHERE c.object_id = ck.parent_object_id AND c.name = ${a})
|
|
35
|
+
OR EXISTS (SELECT 1 FROM sys.sql_expression_dependencies dep
|
|
36
|
+
JOIN sys.columns c ON c.object_id = dep.referenced_id AND c.column_id = dep.referenced_minor_id
|
|
37
|
+
WHERE dep.referencing_id = ck.object_id AND c.object_id = ck.parent_object_id AND c.name = ${a})
|
|
38
|
+
) ORDER BY ck.name
|
|
39
|
+
`, u = yield* e`SELECT CASE WHEN COL_LENGTH('sys.indexes', 'optimize_for_sequential_key') IS NULL THEN 0 ELSE 1 END AS present`, d = yield* e`
|
|
40
|
+
SELECT i.index_id AS id, i.name, i.type, i.is_unique AS [unique], i.is_primary_key AS [primary],
|
|
41
|
+
i.is_unique_constraint AS [constraint], i.is_disabled AS disabled, i.filter_definition AS [filter],
|
|
42
|
+
i.fill_factor AS [fillFactor], i.is_padded AS padded, i.ignore_dup_key AS ignoreDuplicate,
|
|
43
|
+
i.allow_row_locks AS rowLocks, i.allow_page_locks AS pageLocks, s.no_recompute AS noRecompute,
|
|
44
|
+
ds.name AS dataSpace, ds.type AS dataSpaceType, ${e.literal(u[0].present ? "i.optimize_for_sequential_key" : "CAST(0 AS bit)")} AS sequential
|
|
45
|
+
FROM sys.indexes i JOIN sys.data_spaces ds ON ds.data_space_id = i.data_space_id
|
|
46
|
+
JOIN sys.stats s ON s.object_id = i.object_id AND s.stats_id = i.index_id
|
|
47
|
+
WHERE i.object_id = OBJECT_ID(${i}) AND (i.has_filter = 1 OR EXISTS (
|
|
48
|
+
SELECT 1 FROM sys.index_columns ic JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
|
|
49
|
+
WHERE ic.object_id = i.object_id AND ic.index_id = i.index_id AND c.name = ${a}
|
|
50
|
+
)) ORDER BY i.type, i.index_id
|
|
51
|
+
`, f = yield* e`
|
|
52
|
+
SELECT ic.index_id AS indexId, c.name, ic.key_ordinal AS ordinal,
|
|
53
|
+
ic.is_included_column AS included, ic.is_descending_key AS descending
|
|
54
|
+
FROM sys.index_columns ic JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
|
|
55
|
+
WHERE ic.object_id = OBJECT_ID(${i}) ORDER BY ic.index_id, ic.key_ordinal, ic.index_column_id
|
|
56
|
+
`, p = yield* e`
|
|
57
|
+
SELECT DISTINCT p.index_id AS indexId FROM sys.partitions p
|
|
58
|
+
WHERE p.object_id = OBJECT_ID(${i}) AND p.data_compression <> 0
|
|
59
|
+
`, m = d.find((e) => ![1, 2].includes(e.type) || e.dataSpaceType !== "FG" || p.some((t) => t.indexId === e.id) || e.type === 1 && e.disabled);
|
|
60
|
+
if (s.length > 0 || m !== void 0) return yield* n.fail(t(`Cannot retype ${i}.${a} while ${s[0]?.kind ?? `unsupported index ${m.name}`} depends on it. No dependencies were removed; use a reviewed file migration that restores the dependent definitions.`));
|
|
61
|
+
let h = d.flatMap((e) => {
|
|
62
|
+
let t = f.filter((t) => t.indexId === e.id), n = t.filter((e) => e.ordinal > 0).sort((e, t) => e.ordinal - t.ordinal).map((e) => `${r(e.name)} ${e.descending ? "DESC" : "ASC"}`).join(", "), a = t.filter((e) => e.included).map((e) => r(e.name)).join(", "), o = e.type === 1 ? "CLUSTERED" : "NONCLUSTERED", s = `PAD_INDEX = ${e.padded ? "ON" : "OFF"}, ` + (e.fillFactor > 0 ? `FILLFACTOR = ${e.fillFactor}, ` : "") + `IGNORE_DUP_KEY = ${e.ignoreDuplicate ? "ON" : "OFF"}, STATISTICS_NORECOMPUTE = ${e.noRecompute ? "ON" : "OFF"}, ALLOW_ROW_LOCKS = ${e.rowLocks ? "ON" : "OFF"}, ALLOW_PAGE_LOCKS = ${e.pageLocks ? "ON" : "OFF"}` + (u[0].present ? `, OPTIMIZE_FOR_SEQUENTIAL_KEY = ${e.sequential ? "ON" : "OFF"}` : "");
|
|
63
|
+
return [e.primary || e.constraint ? `ALTER TABLE ${r(i)} ADD CONSTRAINT ${r(e.name)} ${e.primary ? "PRIMARY KEY" : "UNIQUE"} ${o} (${n}) WITH (${s}) ON ${r(e.dataSpace)}` : `CREATE ${e.unique ? "UNIQUE " : ""}${o} INDEX ${r(e.name)} ON ${r(i)} (${n})` + (a ? ` INCLUDE (${a})` : "") + (e.filter ? ` WHERE ${e.filter}` : "") + ` WITH (${s}) ON ${r(e.dataSpace)}`, ...e.disabled ? [`ALTER INDEX ${r(e.name)} ON ${r(i)} DISABLE`] : []];
|
|
64
|
+
}), g = [
|
|
65
|
+
...c.map((e) => `ALTER TABLE ${r(i)} DROP CONSTRAINT ${r(e.name)}`),
|
|
66
|
+
...l.map((e) => `ALTER TABLE ${r(i)} DROP CONSTRAINT ${r(e.name)}`),
|
|
67
|
+
...[...d].reverse().map((e) => e.primary || e.constraint ? `ALTER TABLE ${r(i)} DROP CONSTRAINT ${r(e.name)}` : `DROP INDEX ${r(e.name)} ON ${r(i)}`),
|
|
68
|
+
o,
|
|
69
|
+
...c.map((e) => `ALTER TABLE ${r(i)} ADD CONSTRAINT ${r(e.name)} DEFAULT ${e.definition} FOR ${r(a)}`),
|
|
70
|
+
...l.flatMap((e) => [`ALTER TABLE ${r(i)} WITH ${e.untrusted ? "NOCHECK" : "CHECK"} ADD CONSTRAINT ${r(e.name)} CHECK ${e.notForReplication ? "NOT FOR REPLICATION " : ""}${e.definition}`, ...e.disabled ? [`ALTER TABLE ${r(i)} NOCHECK CONSTRAINT ${r(e.name)}`] : []]),
|
|
71
|
+
...h
|
|
72
|
+
];
|
|
73
|
+
yield* n.forEach(g, (t) => e.unsafe(t), { discard: !0 });
|
|
74
|
+
});
|
|
75
|
+
//#endregion
|
|
76
|
+
export { i as alterColumnWithDependenciesMssql };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Effect as e } from "effect";
|
|
2
|
+
//#region src/migrations/mysqlEngine.ts
|
|
3
|
+
var t = (e) => /mariadb/i.test(e) ? "mariadb" : "mysql", n = /* @__PURE__ */ new WeakMap(), r = (t) => e.suspend(() => {
|
|
4
|
+
let r = n.get(t);
|
|
5
|
+
return r === void 0 ? i(t).pipe(e.tap((r) => e.sync(() => n.set(t, r)))) : e.succeed(r);
|
|
6
|
+
}), i = (n) => n.unsafe("SELECT VERSION() AS v").pipe(e.map((e) => {
|
|
7
|
+
let n = e[0]?.v;
|
|
8
|
+
return typeof n == "string" ? t(n) : "mysql";
|
|
9
|
+
}), e.catch(() => e.succeed("mysql")));
|
|
10
|
+
//#endregion
|
|
11
|
+
export { t as engineFromVersion, r as resolveMysqlEngine };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { storeCharsetFindings as e } from "./storeCharset.js";
|
|
2
|
+
import { Effect as t } from "effect";
|
|
3
|
+
import { SqlClient as n } from "effect/sql";
|
|
4
|
+
//#region src/migrations/namespaceCharset.ts
|
|
5
|
+
var r = "tenant_", i = (e) => e.map((e) => Object.fromEntries(Object.entries(e).map(([e, t]) => [e.toLowerCase(), t]))), a = async (a, o) => a(t.gen(function* () {
|
|
6
|
+
let a = yield* n.SqlClient, s = i(yield* a`
|
|
7
|
+
SELECT schema_name FROM information_schema.schemata
|
|
8
|
+
WHERE schema_name LIKE ${`${r}%`} ORDER BY schema_name`), c = [];
|
|
9
|
+
for (let { schema_name: n } of s) {
|
|
10
|
+
let r = i(yield* a`
|
|
11
|
+
SELECT table_name, column_name, data_type, character_set_name
|
|
12
|
+
FROM information_schema.columns
|
|
13
|
+
WHERE table_schema = ${n}
|
|
14
|
+
ORDER BY table_name, ordinal_position`), s = i(yield* a`
|
|
15
|
+
SELECT cc.table_name AS table_name, cc.check_clause AS check_clause
|
|
16
|
+
FROM information_schema.check_constraints cc
|
|
17
|
+
WHERE cc.constraint_schema = ${n}`.pipe(t.orElseSucceed(() => []))), l = /* @__PURE__ */ new Set();
|
|
18
|
+
for (let e of s) {
|
|
19
|
+
let t = /json_valid\(`?([^`)]+)`?\)/i.exec(e.check_clause);
|
|
20
|
+
t && l.add(`${e.table_name}.${t[1]}`);
|
|
21
|
+
}
|
|
22
|
+
let u = /* @__PURE__ */ new Map();
|
|
23
|
+
for (let e of r) {
|
|
24
|
+
let t = e.data_type.toLowerCase() === "json" || l.has(`${e.table_name}.${e.column_name}`), n = {
|
|
25
|
+
name: e.column_name,
|
|
26
|
+
type: t ? "json" : e.character_set_name === null ? "integer" : "text",
|
|
27
|
+
nullable: !0,
|
|
28
|
+
unique: !1,
|
|
29
|
+
hasDefault: !1,
|
|
30
|
+
...!t && e.character_set_name !== null ? { charset: e.character_set_name } : {}
|
|
31
|
+
}, r = u.get(e.table_name) ?? [];
|
|
32
|
+
r.push(n), u.set(e.table_name, r);
|
|
33
|
+
}
|
|
34
|
+
let d = { tables: [...u].map(([e, t]) => ({
|
|
35
|
+
name: e,
|
|
36
|
+
columns: t,
|
|
37
|
+
indexes: []
|
|
38
|
+
})) }, f = e({
|
|
39
|
+
live: d,
|
|
40
|
+
dialect: o.dialect ?? "mysql",
|
|
41
|
+
charset: o.charset
|
|
42
|
+
});
|
|
43
|
+
f.length > 0 && c.push({
|
|
44
|
+
namespace: n,
|
|
45
|
+
findings: f
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return c;
|
|
49
|
+
}));
|
|
50
|
+
//#endregion
|
|
51
|
+
export { a as tenantNamespaceCharsetFindings };
|