@vibeorm/sql 2.2.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dialects/migration-objects.d.ts +9 -0
- package/dist/dialects/migration-objects.d.ts.map +1 -1
- package/dist/dialects/migration-replay-coverage.d.ts +9 -0
- package/dist/dialects/migration-replay-coverage.d.ts.map +1 -0
- package/dist/dialects/migration-shadow.d.ts +44 -0
- package/dist/dialects/migration-shadow.d.ts.map +1 -0
- package/dist/dialects/module-dependency.d.ts +16 -0
- package/dist/dialects/module-dependency.d.ts.map +1 -0
- package/dist/dialects/mysql.d.ts.map +1 -1
- package/dist/dialects/postgres-type-identity.d.ts +32 -0
- package/dist/dialects/postgres-type-identity.d.ts.map +1 -0
- package/dist/dialects/postgres.d.ts.map +1 -1
- package/dist/dialects/sqlite.d.ts.map +1 -1
- package/dist/identifiers.d.ts +14 -0
- package/dist/identifiers.d.ts.map +1 -0
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +450 -218
- package/dist/index.js.map +13 -8
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -16,6 +16,130 @@ class ParamCollector {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
// packages/sql/src/dialects/module-dependency.ts
|
|
20
|
+
function renderModuleDependencyQuery(params) {
|
|
21
|
+
const { dialect, operation } = params;
|
|
22
|
+
if (operation.kind === "visibility")
|
|
23
|
+
return dialect.name === "mysql" ? { text: "SHOW GRANTS FOR CURRENT_USER", values: [], returning: "none" } : undefined;
|
|
24
|
+
if (dialect.name === "sqlite" || operation.tables.length === 0)
|
|
25
|
+
return;
|
|
26
|
+
const collector = new ParamCollector(dialect);
|
|
27
|
+
const owned = operation.tables.map((table, index) => `SELECT ${collector.add(operation.namespace)}${index === 0 ? " AS namespace" : ""}, ${collector.add(table)}${index === 0 ? " AS table_name" : ""}`).join(" UNION ALL ");
|
|
28
|
+
const pg = dialect.name === "postgres";
|
|
29
|
+
const nameKey = ({ column }) => pg ? column : `CAST(IF(@@lower_case_table_names = 0, ${column}, LOWER(${column})) AS BINARY)`;
|
|
30
|
+
const isOwned = ({ namespace, table }) => `EXISTS (SELECT 1 FROM owned_tables o WHERE ${nameKey({ column: namespace })} = ${nameKey({ column: "o.namespace" })} AND ${nameKey({ column: table })} = ${nameKey({ column: "o.table_name" })})`;
|
|
31
|
+
const sourceNamespace = pg ? "sn.nspname" : "fk.CONSTRAINT_SCHEMA";
|
|
32
|
+
const sourceTable = pg ? "s.relname" : "fk.TABLE_NAME";
|
|
33
|
+
const targetNamespace = pg ? "tn.nspname" : "fk.UNIQUE_CONSTRAINT_SCHEMA";
|
|
34
|
+
const targetTable = pg ? "t.relname" : "fk.REFERENCED_TABLE_NAME";
|
|
35
|
+
const from = pg ? "pg_catalog.pg_constraint fk JOIN pg_catalog.pg_class s ON s.oid = fk.conrelid JOIN pg_catalog.pg_namespace sn ON sn.oid = s.relnamespace JOIN pg_catalog.pg_class t ON t.oid = fk.confrelid JOIN pg_catalog.pg_namespace tn ON tn.oid = t.relnamespace WHERE fk.contype = 'f'" : "information_schema.REFERENTIAL_CONSTRAINTS fk";
|
|
36
|
+
return {
|
|
37
|
+
text: `WITH owned_tables AS (${owned})
|
|
38
|
+
SELECT * FROM (SELECT ${pg ? "fk.conname" : "fk.CONSTRAINT_NAME"} AS constraint_name, ${sourceNamespace} AS source_namespace, ${sourceTable} AS source_table, ${targetNamespace} AS target_namespace, ${targetTable} AS target_table, ${isOwned({ namespace: sourceNamespace, table: sourceTable })} AS source_owned, ${isOwned({ namespace: targetNamespace, table: targetTable })} AS target_owned FROM ${from}) dependencies
|
|
39
|
+
WHERE source_owned OR target_owned
|
|
40
|
+
ORDER BY source_namespace, source_table, constraint_name`,
|
|
41
|
+
values: collector.values,
|
|
42
|
+
returning: "none"
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
// packages/sql/src/dialects/migration-replay-coverage.ts
|
|
46
|
+
function renderReplayCoverageGaps(params) {
|
|
47
|
+
const { dialect } = params;
|
|
48
|
+
const collector = new ParamCollector(dialect);
|
|
49
|
+
const namespace = collector.add(params.namespace);
|
|
50
|
+
if (dialect.name === "postgres")
|
|
51
|
+
return { text: `SELECT 'type' AS kind, t.typname::text AS name FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace WHERE n.nspname = ${namespace} AND (t.typtype IN ('b', 'd', 'r', 'm') AND t.typelem = 0 OR t.typtype = 'c' AND EXISTS (SELECT 1 FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid AND c.relkind = 'c')) AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend d WHERE d.classid = 'pg_type'::regclass AND d.objid = t.oid AND d.deptype = 'e')
|
|
52
|
+
UNION ALL SELECT 'routine', p.proname::text FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace WHERE n.nspname = ${namespace} AND p.prokind <> 'f' AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend d WHERE d.classid = 'pg_proc'::regclass AND d.objid = p.oid AND d.deptype = 'e')
|
|
53
|
+
UNION ALL SELECT 'relation-layout', c.relname::text FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname = ${namespace} AND (c.relkind IN ('p', 'f') OR c.relispartition OR EXISTS (SELECT 1 FROM pg_catalog.pg_inherits i WHERE i.inhrelid = c.oid)) AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend d WHERE d.classid = 'pg_class'::regclass AND d.objid = c.oid AND d.deptype = 'e')
|
|
54
|
+
UNION ALL SELECT 'rule', r.rulename::text FROM pg_catalog.pg_rewrite r JOIN pg_catalog.pg_class c ON c.oid = r.ev_class JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname = ${namespace} AND r.rulename <> '_RETURN'
|
|
55
|
+
UNION ALL SELECT 'namespace', n.nspname::text FROM pg_catalog.pg_namespace n WHERE n.nspname <> ${namespace} AND n.nspname <> 'information_schema' AND n.nspname NOT LIKE 'pg\\_%' ESCAPE '\\'${params.privateNamespace === undefined ? "" : ` AND n.nspname <> ${collector.add(params.privateNamespace)}`}`, values: collector.values, returning: "none" };
|
|
56
|
+
if (dialect.name === "mysql")
|
|
57
|
+
return { text: `SELECT 'procedure' AS kind, ROUTINE_NAME AS name FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = ${namespace} AND ROUTINE_TYPE = 'PROCEDURE'
|
|
58
|
+
UNION ALL SELECT 'event', EVENT_NAME FROM information_schema.EVENTS WHERE EVENT_SCHEMA = ${collector.add(params.namespace)}
|
|
59
|
+
UNION ALL SELECT DISTINCT 'partition', TABLE_NAME FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = ${collector.add(params.namespace)} AND PARTITION_NAME IS NOT NULL`, values: collector.values, returning: "none" };
|
|
60
|
+
return { text: `SELECT 'table-options' AS kind, name FROM pragma_table_list WHERE schema = ${namespace} AND name NOT LIKE 'sqlite\\_%' ESCAPE '\\' AND (type = 'virtual' OR wr <> 0 OR strict <> 0)`, values: collector.values, returning: "none" };
|
|
61
|
+
}
|
|
62
|
+
// packages/sql/src/dialects/migration-shadow.ts
|
|
63
|
+
import { unsupportedCapability } from "@vibeorm/schema";
|
|
64
|
+
var SHADOW_DATABASE = Object.freeze({ schema: "_vibeorm_shadow", table: "_vibe_shadow", lock: 1447645267, timeoutSeconds: 60 });
|
|
65
|
+
var SHADOW_CAPABILITIES = Object.freeze({
|
|
66
|
+
postgres: Object.freeze({ serverProvisioning: true, dedicated: true }),
|
|
67
|
+
mysql: Object.freeze({ serverProvisioning: true, dedicated: true }),
|
|
68
|
+
sqlite: Object.freeze({ serverProvisioning: false, dedicated: false })
|
|
69
|
+
});
|
|
70
|
+
function renderShadowOperation(params) {
|
|
71
|
+
const { dialect, operation } = params;
|
|
72
|
+
if (!SHADOW_CAPABILITIES[dialect.name].serverProvisioning)
|
|
73
|
+
throw unsupportedCapability({ dialect: dialect.name, feature: "shadowDatabaseProvisioning" });
|
|
74
|
+
const pg = dialect.name === "postgres";
|
|
75
|
+
const collector = new ParamCollector(dialect);
|
|
76
|
+
const marker = pg ? `${dialect.quoteIdent({ name: SHADOW_DATABASE.schema })}.${dialect.quoteIdent({ name: SHADOW_DATABASE.table })}` : dialect.quoteIdent({ name: SHADOW_DATABASE.table });
|
|
77
|
+
const result = (text) => [{ text, values: collector.values, returning: "none" }];
|
|
78
|
+
switch (operation.kind) {
|
|
79
|
+
case "createDatabase":
|
|
80
|
+
return result(`CREATE DATABASE ${dialect.quoteIdent({ name: operation.name })}`);
|
|
81
|
+
case "dropDatabase":
|
|
82
|
+
return result(`DROP DATABASE ${dialect.quoteIdent({ name: operation.name })}`);
|
|
83
|
+
case "identity":
|
|
84
|
+
return result(pg ? `SELECT current_database()::text AS database, (SELECT oid::text FROM pg_catalog.pg_database WHERE datname = current_database()) AS database_id, current_schema()::text AS namespace` : `SELECT DATABASE() AS \`database\`, @@lower_case_table_names AS name_folding, @@server_uuid AS server_id`);
|
|
85
|
+
case "lock":
|
|
86
|
+
return result(pg ? `SELECT pg_catalog.pg_advisory_lock(${collector.add(SHADOW_DATABASE.lock)})` : `SELECT GET_LOCK(${collector.add(`vibeorm_shadow:${operation.database}`)}, ${collector.add(SHADOW_DATABASE.timeoutSeconds)}) AS acquired`);
|
|
87
|
+
case "unlock":
|
|
88
|
+
return result(pg ? `SELECT pg_catalog.pg_advisory_unlock(${collector.add(SHADOW_DATABASE.lock)}) AS released` : `SELECT RELEASE_LOCK(${collector.add(`vibeorm_shadow:${operation.database}`)}) AS released`);
|
|
89
|
+
case "markerExists":
|
|
90
|
+
return result(pg ? `SELECT c.relname AS name FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname = ${collector.add(SHADOW_DATABASE.schema)} AND c.relname = ${collector.add(SHADOW_DATABASE.table)}` : `SELECT TABLE_NAME AS name FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ${collector.add(SHADOW_DATABASE.table)}`);
|
|
91
|
+
case "markerRead":
|
|
92
|
+
return result(`SELECT payload FROM ${marker}`);
|
|
93
|
+
case "markerColumns":
|
|
94
|
+
return result(`SELECT column_name AS name, data_type AS type, is_nullable AS nullable FROM information_schema.columns AS marker_column WHERE table_schema = ${pg ? collector.add(SHADOW_DATABASE.schema) : "DATABASE()"} AND table_name = ${collector.add(SHADOW_DATABASE.table)} AND ${pg ? `EXISTS (SELECT 1 FROM pg_catalog.pg_class r JOIN pg_catalog.pg_namespace n ON n.oid = r.relnamespace WHERE n.nspname = marker_column.table_schema AND r.relname = marker_column.table_name AND r.relkind = 'r' AND r.relpersistence = 'p' AND NOT r.relrowsecurity AND NOT r.relforcerowsecurity AND NOT r.relhasrules AND NOT r.relhastriggers AND NOT r.relispartition AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_attrdef a WHERE a.adrelid = r.oid) AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_constraint c WHERE c.conrelid = r.oid AND c.contype <> 'n') AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_index i WHERE i.indrelid = r.oid) AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_inherits i WHERE i.inhrelid = r.oid OR i.inhparent = r.oid) AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_attribute a WHERE a.attrelid = r.oid AND (a.attisdropped OR a.attidentity <> '' OR a.attgenerated <> '')))` : `EXISTS (SELECT 1 FROM information_schema.TABLES t WHERE t.TABLE_SCHEMA = marker_column.table_schema AND t.TABLE_NAME = marker_column.table_name AND t.TABLE_TYPE = 'BASE TABLE' AND t.ENGINE = 'InnoDB') AND NOT EXISTS (SELECT 1 FROM information_schema.COLUMNS c WHERE c.TABLE_SCHEMA = marker_column.table_schema AND c.TABLE_NAME = marker_column.table_name AND (c.COLUMN_DEFAULT IS NOT NULL OR c.EXTRA <> '')) AND NOT EXISTS (SELECT 1 FROM information_schema.TRIGGERS t WHERE t.EVENT_OBJECT_SCHEMA = DATABASE() AND t.EVENT_OBJECT_TABLE = ${collector.add(SHADOW_DATABASE.table)}) AND NOT EXISTS (SELECT 1 FROM information_schema.TABLE_CONSTRAINTS c WHERE c.TABLE_SCHEMA = DATABASE() AND c.TABLE_NAME = ${collector.add(SHADOW_DATABASE.table)})`}
|
|
95
|
+
ORDER BY ordinal_position`);
|
|
96
|
+
case "grants": {
|
|
97
|
+
if (pg)
|
|
98
|
+
throw unsupportedCapability({ dialect: dialect.name, feature: "mysqlShadowPrivileges" });
|
|
99
|
+
return result("SHOW GRANTS FOR CURRENT_USER");
|
|
100
|
+
}
|
|
101
|
+
case "markerCreate":
|
|
102
|
+
return pg ? [{ text: `CREATE SCHEMA ${dialect.quoteIdent({ name: SHADOW_DATABASE.schema })}`, values: [], returning: "none" }, { text: `CREATE TABLE ${marker} (payload text NOT NULL)`, values: [], returning: "none" }] : result(`CREATE TABLE ${marker} (payload LONGTEXT NOT NULL) ENGINE=InnoDB`);
|
|
103
|
+
case "markerWrite":
|
|
104
|
+
return result(operation.insert ? `INSERT INTO ${marker} (payload) VALUES (${collector.add(operation.value)})` : `UPDATE ${marker} SET payload = ${collector.add(operation.value)}`);
|
|
105
|
+
case "journal":
|
|
106
|
+
return result(`SELECT name, checksum, statement_index, error FROM ${dialect.quoteIdent({ name: "_vibe_migrations" })} ORDER BY name`);
|
|
107
|
+
case "inventory":
|
|
108
|
+
return result(pg ? `SELECT 'namespace' AS kind, nspname::text AS name, nspname::text AS namespace FROM pg_catalog.pg_namespace WHERE nspname NOT IN ('public', 'information_schema') AND nspname NOT LIKE 'pg\\_%' ESCAPE '\\'
|
|
109
|
+
UNION ALL SELECT 'relation', c.relname::text, n.nspname::text FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname <> 'information_schema' AND n.nspname NOT LIKE 'pg\\_%' ESCAPE '\\'
|
|
110
|
+
UNION ALL SELECT 'routine', p.proname::text, n.nspname::text FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace WHERE n.nspname <> 'information_schema' AND n.nspname NOT LIKE 'pg\\_%' ESCAPE '\\'
|
|
111
|
+
UNION ALL SELECT 'type', t.typname::text, n.nspname::text FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace WHERE n.nspname <> 'information_schema' AND n.nspname NOT LIKE 'pg\\_%' ESCAPE '\\' AND t.typrelid = 0 AND t.typelem = 0
|
|
112
|
+
UNION ALL SELECT 'extension', e.extname::text, n.nspname::text FROM pg_catalog.pg_extension e JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace WHERE e.extname <> 'plpgsql'
|
|
113
|
+
UNION ALL SELECT 'marker-dependency', d.objid::text, '${SHADOW_DATABASE.schema}' FROM pg_catalog.pg_depend d JOIN pg_catalog.pg_class c ON d.classid = 'pg_class'::regclass AND d.objid = c.oid JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname = '${SHADOW_DATABASE.schema}' AND d.deptype NOT IN ('i', 'a') AND d.refclassid <> 'pg_namespace'::regclass
|
|
114
|
+
UNION ALL SELECT 'marker-trigger', t.tgname::text, n.nspname::text FROM pg_catalog.pg_trigger t JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname = '${SHADOW_DATABASE.schema}'
|
|
115
|
+
UNION ALL SELECT 'namespace-object', o.name::text, n.nspname::text FROM pg_catalog.pg_depend d JOIN pg_catalog.pg_namespace n ON d.refclassid = 'pg_namespace'::regclass AND d.refobjid = n.oid CROSS JOIN LATERAL pg_catalog.pg_identify_object(d.classid, d.objid, d.objsubid) o WHERE n.nspname <> 'information_schema' AND n.nspname NOT LIKE 'pg\\_%' ESCAPE '\\' AND d.classid NOT IN ('pg_class'::regclass, 'pg_proc'::regclass, 'pg_type'::regclass, 'pg_extension'::regclass)
|
|
116
|
+
UNION ALL SELECT 'database-object', evtname::text, '' FROM pg_catalog.pg_event_trigger
|
|
117
|
+
UNION ALL SELECT 'database-object', pubname::text, '' FROM pg_catalog.pg_publication
|
|
118
|
+
UNION ALL SELECT 'database-object', subname::text, '' FROM pg_catalog.pg_subscription WHERE subdbid = (SELECT oid FROM pg_catalog.pg_database WHERE datname = current_database())
|
|
119
|
+
UNION ALL SELECT 'database-object', srvname::text, '' FROM pg_catalog.pg_foreign_server
|
|
120
|
+
UNION ALL SELECT 'database-object', fdwname::text, '' FROM pg_catalog.pg_foreign_data_wrapper
|
|
121
|
+
UNION ALL SELECT 'database-object', c.oid::text, '' FROM pg_catalog.pg_cast c JOIN pg_catalog.pg_type s ON s.oid = c.castsource JOIN pg_catalog.pg_type t ON t.oid = c.casttarget LEFT JOIN pg_catalog.pg_proc p ON p.oid = c.castfunc WHERE s.typnamespace <> 'pg_catalog'::regnamespace OR t.typnamespace <> 'pg_catalog'::regnamespace OR p.pronamespace <> 'pg_catalog'::regnamespace` : `SELECT TABLE_TYPE AS kind, TABLE_NAME AS name, TABLE_SCHEMA AS namespace FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE()
|
|
122
|
+
UNION ALL SELECT ROUTINE_TYPE, ROUTINE_NAME, ROUTINE_SCHEMA FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = DATABASE()
|
|
123
|
+
UNION ALL SELECT 'EVENT', EVENT_NAME, EVENT_SCHEMA FROM information_schema.EVENTS WHERE EVENT_SCHEMA = DATABASE()
|
|
124
|
+
UNION ALL SELECT 'TRIGGER', TRIGGER_NAME, TRIGGER_SCHEMA FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = DATABASE()
|
|
125
|
+
UNION ALL SELECT 'EXTERNAL FOREIGN KEY', CONCAT(TABLE_NAME, '.', CONSTRAINT_NAME), CONSTRAINT_SCHEMA FROM information_schema.REFERENTIAL_CONSTRAINTS WHERE UNIQUE_CONSTRAINT_SCHEMA = DATABASE() AND CAST(CONSTRAINT_SCHEMA AS BINARY) <> CAST(DATABASE() AS BINARY)`);
|
|
126
|
+
case "resetPostgres": {
|
|
127
|
+
if (!pg)
|
|
128
|
+
throw unsupportedCapability({ dialect: dialect.name, feature: "postgresShadowReset" });
|
|
129
|
+
return [{ text: 'DROP SCHEMA "public" CASCADE', values: [], returning: "none" }, { text: 'CREATE SCHEMA "public"', values: [], returning: "none" }];
|
|
130
|
+
}
|
|
131
|
+
case "mysqlForeignKeys": {
|
|
132
|
+
if (pg)
|
|
133
|
+
throw unsupportedCapability({ dialect: dialect.name, feature: "mysqlShadowReset" });
|
|
134
|
+
return result(`SET FOREIGN_KEY_CHECKS = ${operation.enabled ? "1" : "0"}`);
|
|
135
|
+
}
|
|
136
|
+
case "dropMysqlObject": {
|
|
137
|
+
if (pg)
|
|
138
|
+
throw unsupportedCapability({ dialect: dialect.name, feature: "mysqlShadowReset" });
|
|
139
|
+
return result(`DROP ${operation.object} ${dialect.quoteIdent({ name: operation.name })}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
19
143
|
// packages/sql/src/module-journal.ts
|
|
20
144
|
var MODULE_JOURNAL_COLUMN = "module_origin";
|
|
21
145
|
function renderModuleJournal(params) {
|
|
@@ -525,15 +649,15 @@ var decode = Object.freeze({
|
|
|
525
649
|
}
|
|
526
650
|
});
|
|
527
651
|
// packages/sql/src/exclusion.ts
|
|
528
|
-
import { VibeError as VibeError5, fieldTypeIdentity as fieldTypeIdentity2, unsupportedCapability as
|
|
652
|
+
import { VibeError as VibeError5, fieldTypeIdentity as fieldTypeIdentity2, unsupportedCapability as unsupportedCapability3 } from "@vibeorm/schema";
|
|
529
653
|
|
|
530
654
|
// packages/sql/src/predicate.ts
|
|
531
|
-
import { VibeError as VibeError4, fieldTypeIdentity, isEnumType, unsupportedCapability } from "@vibeorm/schema";
|
|
655
|
+
import { VibeError as VibeError4, fieldTypeIdentity, isEnumType, unsupportedCapability as unsupportedCapability2 } from "@vibeorm/schema";
|
|
532
656
|
function renderPredicate(params) {
|
|
533
657
|
if (params.usage === "exclusionPredicate" && !params.dialect.capabilities.exclusionConstraints)
|
|
534
|
-
throw
|
|
658
|
+
throw unsupportedCapability2({ dialect: params.dialect.name, feature: "exclusionConstraints" });
|
|
535
659
|
if (params.usage === "indexPredicate" && !params.dialect.capabilities.partialIndexes) {
|
|
536
|
-
throw
|
|
660
|
+
throw unsupportedCapability2({ dialect: params.dialect.name, feature: "partialIndexes" });
|
|
537
661
|
}
|
|
538
662
|
const context = {
|
|
539
663
|
model: params.model,
|
|
@@ -661,7 +785,7 @@ function resolveField(params) {
|
|
|
661
785
|
});
|
|
662
786
|
}
|
|
663
787
|
if (context.usage === "check" && context.dialect.name === "mysql" && field.default?.kind === "autoincrement") {
|
|
664
|
-
throw
|
|
788
|
+
throw unsupportedCapability2({
|
|
665
789
|
dialect: "mysql",
|
|
666
790
|
feature: `CHECK constraint referencing auto-increment column "${context.model.name}.${name}"`,
|
|
667
791
|
hint: "mysql refuses this with error 3818 \u2014 enforce the rule in application code or on a non-generated column"
|
|
@@ -837,7 +961,7 @@ function invalid2(rule) {
|
|
|
837
961
|
function compileExclusion(params) {
|
|
838
962
|
const { exclusion: spec, model, dialect } = params;
|
|
839
963
|
if (!dialect.capabilities.exclusionConstraints)
|
|
840
|
-
throw
|
|
964
|
+
throw unsupportedCapability3({ dialect: dialect.name, feature: "exclusionConstraints" });
|
|
841
965
|
if (!spec.name || spec.name.includes("\x00"))
|
|
842
966
|
invalid2("name");
|
|
843
967
|
if (!["int8range", "tsrange", "tstzrange"].includes(spec.range.type))
|
|
@@ -867,8 +991,8 @@ function compileExclusion(params) {
|
|
|
867
991
|
if (timezone !== (spec.range.type === "tstzrange"))
|
|
868
992
|
invalid2("range-timezone");
|
|
869
993
|
}
|
|
870
|
-
const
|
|
871
|
-
return literal === undefined ?
|
|
994
|
+
const sql = dialect.quoteIdent({ name: column.dbName ?? column.name });
|
|
995
|
+
return literal === undefined ? sql : `COALESCE(${sql}, ${literal})`;
|
|
872
996
|
};
|
|
873
997
|
const keys = spec.keys.map((key) => {
|
|
874
998
|
if ("expression" in key) {
|
|
@@ -890,13 +1014,13 @@ function compileExclusion(params) {
|
|
|
890
1014
|
}
|
|
891
1015
|
function renderExclusionSetup(params) {
|
|
892
1016
|
if (!params.dialect.capabilities.exclusionConstraints)
|
|
893
|
-
throw
|
|
1017
|
+
throw unsupportedCapability3({ dialect: params.dialect.name, feature: "exclusionConstraints" });
|
|
894
1018
|
return params.exclusion.requiredExtensions.map((name) => `CREATE EXTENSION IF NOT EXISTS ${params.dialect.quoteIdent({ name })};`);
|
|
895
1019
|
}
|
|
896
1020
|
function renderExclusionDdl(params) {
|
|
897
1021
|
const { dialect, table, exclusion, operation } = params;
|
|
898
1022
|
if (!dialect.capabilities.exclusionConstraints)
|
|
899
|
-
throw
|
|
1023
|
+
throw unsupportedCapability3({ dialect: dialect.name, feature: "exclusionConstraints" });
|
|
900
1024
|
const target = `ALTER TABLE ${dialect.quoteIdent({ name: table })}`;
|
|
901
1025
|
if (operation === "drop")
|
|
902
1026
|
return [`${target} DROP CONSTRAINT ${dialect.quoteIdent({ name: exclusion.name })};`];
|
|
@@ -905,14 +1029,14 @@ function renderExclusionDdl(params) {
|
|
|
905
1029
|
function renderExclusionCatalog(params) {
|
|
906
1030
|
const { dialect, probe } = params;
|
|
907
1031
|
if (!dialect.capabilities.exclusionConstraints)
|
|
908
|
-
throw
|
|
1032
|
+
throw unsupportedCapability3({ dialect: dialect.name, feature: "exclusionConstraints" });
|
|
909
1033
|
const scope = probe === undefined ? "n.nspname = 'public'" : `t.oid = ${dialect.quoteStringLiteral({ value: probe })}::regclass`;
|
|
910
1034
|
return `SELECT t.relname AS table_name, c.conname AS constraint_name, pg_catalog.pg_get_constraintdef(c.oid, true) AS definition, c.convalidated AS validated, i.indisvalid AS valid, i.indisready AS ready FROM pg_catalog.pg_constraint c JOIN pg_catalog.pg_class t ON t.oid = c.conrelid JOIN pg_catalog.pg_namespace n ON n.oid = t.relnamespace JOIN pg_catalog.pg_index i ON i.indexrelid = c.conindid WHERE c.contype = 'x' AND ${scope} ORDER BY t.relname, c.conname`;
|
|
911
1035
|
}
|
|
912
1036
|
function renderExclusionProbe(params) {
|
|
913
1037
|
const { dialect, table, probe, definition } = params;
|
|
914
1038
|
if (!dialect.capabilities.exclusionConstraints)
|
|
915
|
-
throw
|
|
1039
|
+
throw unsupportedCapability3({ dialect: dialect.name, feature: "exclusionConstraints" });
|
|
916
1040
|
return [`CREATE TEMP TABLE ${dialect.quoteIdent({ name: probe })} (LIKE ${dialect.quoteIdent({ name: "public" })}.${dialect.quoteIdent({ name: table })})`, `ALTER TABLE ${dialect.quoteIdent({ name: probe })} ADD CONSTRAINT ${dialect.quoteIdent({ name: `${probe}_x` })} ${definition}`];
|
|
917
1041
|
}
|
|
918
1042
|
// packages/sql/src/ast.ts
|
|
@@ -968,7 +1092,7 @@ function isExcludedRef(value) {
|
|
|
968
1092
|
}
|
|
969
1093
|
var ADVISORY_LOCK_RESULT_COLUMN = "acquired";
|
|
970
1094
|
// packages/sql/src/locks.ts
|
|
971
|
-
import { internalError, unsupportedCapability as
|
|
1095
|
+
import { internalError, unsupportedCapability as unsupportedCapability4 } from "@vibeorm/schema";
|
|
972
1096
|
var ROW_LOCK_PROSE = Object.freeze({
|
|
973
1097
|
strengths: Object.freeze({
|
|
974
1098
|
update: "FOR UPDATE",
|
|
@@ -988,7 +1112,7 @@ function renderRowLockClause(params) {
|
|
|
988
1112
|
if (syntax === null) {
|
|
989
1113
|
if (lock.strength === "update" && lock.wait === "wait")
|
|
990
1114
|
return null;
|
|
991
|
-
throw
|
|
1115
|
+
throw unsupportedCapability4({
|
|
992
1116
|
dialect: dialect.name,
|
|
993
1117
|
feature: `a ${describeRowLock({ lock })} locking read`,
|
|
994
1118
|
hint: `${dialect.name} has no locking-read clause at all`
|
|
@@ -996,7 +1120,7 @@ function renderRowLockClause(params) {
|
|
|
996
1120
|
}
|
|
997
1121
|
const strengthText = syntax.strengths[lock.strength];
|
|
998
1122
|
if (strengthText === undefined) {
|
|
999
|
-
throw
|
|
1123
|
+
throw unsupportedCapability4({
|
|
1000
1124
|
dialect: dialect.name,
|
|
1001
1125
|
feature: `the ${describeRowLock({ lock: { ...lock, wait: "wait" } })} row-lock strength`,
|
|
1002
1126
|
hint: `${dialect.name} can express: ${Object.keys(syntax.strengths).join(", ")}`
|
|
@@ -1004,7 +1128,7 @@ function renderRowLockClause(params) {
|
|
|
1004
1128
|
}
|
|
1005
1129
|
const waitText = syntax.wait[lock.wait];
|
|
1006
1130
|
if (waitText === undefined) {
|
|
1007
|
-
throw
|
|
1131
|
+
throw unsupportedCapability4({
|
|
1008
1132
|
dialect: dialect.name,
|
|
1009
1133
|
feature: `the "${lock.wait}" lock wait policy`,
|
|
1010
1134
|
hint: `${dialect.name} can express: ${Object.keys(syntax.wait).join(", ")}`
|
|
@@ -1023,7 +1147,7 @@ function renderAdvisoryLock(params) {
|
|
|
1023
1147
|
const { dialect, statement, collector } = params;
|
|
1024
1148
|
const functions = dialect.advisoryLockFunctions;
|
|
1025
1149
|
if (functions === null) {
|
|
1026
|
-
throw
|
|
1150
|
+
throw unsupportedCapability4({
|
|
1027
1151
|
dialect: dialect.name,
|
|
1028
1152
|
feature: "advisory locks",
|
|
1029
1153
|
hint: dialect.name === "mysql" ? "mysql's GET_LOCK is SESSION-scoped \u2014 it survives a rollback, so it cannot be released with the transaction" : `${dialect.name} has no advisory-lock functions`
|
|
@@ -1064,6 +1188,19 @@ import {
|
|
|
1064
1188
|
MYSQL_CAPABILITIES
|
|
1065
1189
|
} from "@vibeorm/schema";
|
|
1066
1190
|
|
|
1191
|
+
// packages/sql/src/identifiers.ts
|
|
1192
|
+
import { VibeError as VibeError6 } from "@vibeorm/schema";
|
|
1193
|
+
function assertNoNul(params) {
|
|
1194
|
+
if (params.name.includes("\x00")) {
|
|
1195
|
+
throw new VibeError6({
|
|
1196
|
+
code: "VIBE_VALIDATION",
|
|
1197
|
+
message: "an SQL identifier cannot contain a NUL character \u2014 the server would stop reading it there and address a different object",
|
|
1198
|
+
meta: { name: params.name.replaceAll("\x00", "\\0") }
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
1201
|
+
return params.name;
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1067
1204
|
// packages/sql/src/dialects/postgres.ts
|
|
1068
1205
|
var postgresDialect = {
|
|
1069
1206
|
name: "postgres",
|
|
@@ -1119,7 +1256,7 @@ var postgresDialect = {
|
|
|
1119
1256
|
paramBudget: 30000,
|
|
1120
1257
|
booleanLiteral: { true: "true", false: "false" },
|
|
1121
1258
|
quoteIdent({ name }) {
|
|
1122
|
-
return `"${name.replaceAll('"', '""')}"`;
|
|
1259
|
+
return `"${assertNoNul({ name }).replaceAll('"', '""')}"`;
|
|
1123
1260
|
},
|
|
1124
1261
|
quoteStringLiteral({ value }) {
|
|
1125
1262
|
return `'${value.replaceAll("'", "''")}'`;
|
|
@@ -1170,7 +1307,7 @@ var sqliteDialect = {
|
|
|
1170
1307
|
paramBudget: 900,
|
|
1171
1308
|
booleanLiteral: { true: "1", false: "0" },
|
|
1172
1309
|
quoteIdent({ name }) {
|
|
1173
|
-
return `"${name.replaceAll('"', '""')}"`;
|
|
1310
|
+
return `"${assertNoNul({ name }).replaceAll('"', '""')}"`;
|
|
1174
1311
|
},
|
|
1175
1312
|
quoteStringLiteral({ value }) {
|
|
1176
1313
|
return `'${value.replaceAll("'", "''")}'`;
|
|
@@ -1225,7 +1362,7 @@ var mysqlDialect = {
|
|
|
1225
1362
|
paramBudget: 1e4,
|
|
1226
1363
|
booleanLiteral: { true: "1", false: "0" },
|
|
1227
1364
|
quoteIdent({ name }) {
|
|
1228
|
-
return `\`${name.replaceAll("`", "``")}\``;
|
|
1365
|
+
return `\`${assertNoNul({ name }).replaceAll("`", "``")}\``;
|
|
1229
1366
|
},
|
|
1230
1367
|
quoteStringLiteral({ value }) {
|
|
1231
1368
|
return `'${value.replaceAll("\\", "\\\\").replaceAll("'", "''")}'`;
|
|
@@ -1249,7 +1386,7 @@ function getSqlDialect(params) {
|
|
|
1249
1386
|
return SQL_DIALECTS[params.dialect];
|
|
1250
1387
|
}
|
|
1251
1388
|
// packages/sql/src/dialects/diagnostics.ts
|
|
1252
|
-
import { unsupportedCapability as
|
|
1389
|
+
import { unsupportedCapability as unsupportedCapability5 } from "@vibeorm/schema";
|
|
1253
1390
|
var QUERIES = Object.freeze({
|
|
1254
1391
|
postgresJsonWire: { dialect: "postgres", text: `SELECT '{"__vibeorm":1}'::jsonb AS "probe"` },
|
|
1255
1392
|
sqliteTriggers: { dialect: "sqlite", text: "SELECT name, tbl_name, sql FROM sqlite_master WHERE type = 'trigger'" }
|
|
@@ -1257,7 +1394,7 @@ var QUERIES = Object.freeze({
|
|
|
1257
1394
|
function renderDiagnostic(params) {
|
|
1258
1395
|
const query = QUERIES[params.query];
|
|
1259
1396
|
if (params.dialect.name !== query.dialect) {
|
|
1260
|
-
throw
|
|
1397
|
+
throw unsupportedCapability5({ dialect: params.dialect.name, feature: params.query, hint: `this diagnostic requires ${query.dialect}` });
|
|
1261
1398
|
}
|
|
1262
1399
|
return { text: query.text, values: [], returning: "none" };
|
|
1263
1400
|
}
|
|
@@ -1266,7 +1403,7 @@ function isFixedDiagnostic(params) {
|
|
|
1266
1403
|
}
|
|
1267
1404
|
|
|
1268
1405
|
// packages/sql/src/dialects/postgres-diagnostics.ts
|
|
1269
|
-
import { VibeError as
|
|
1406
|
+
import { VibeError as VibeError7, unsupportedCapability as unsupportedCapability6 } from "@vibeorm/schema";
|
|
1270
1407
|
function renderPostgresExplain(params) {
|
|
1271
1408
|
const { dialect, query, options } = params;
|
|
1272
1409
|
requirePostgres({ dialect, feature: "query plan inspection (EXPLAIN)" });
|
|
@@ -1301,7 +1438,7 @@ var POSTGRES_WORKLOAD_LIMITS = Object.freeze({
|
|
|
1301
1438
|
});
|
|
1302
1439
|
function requirePostgres(params) {
|
|
1303
1440
|
if (params.dialect.name !== "postgres") {
|
|
1304
|
-
throw
|
|
1441
|
+
throw unsupportedCapability6({
|
|
1305
1442
|
dialect: params.dialect.name,
|
|
1306
1443
|
feature: params.feature,
|
|
1307
1444
|
hint: "plan inspection and workload statistics are PostgreSQL-shaped; portable operation tracing works on every dialect"
|
|
@@ -1319,7 +1456,7 @@ function renderPostgresWorkload(params) {
|
|
|
1319
1456
|
if (query === "statementSnapshot") {
|
|
1320
1457
|
const bounded = limit ?? 20;
|
|
1321
1458
|
if (!Number.isInteger(bounded) || bounded < POSTGRES_WORKLOAD_LIMITS.minLimit || bounded > POSTGRES_WORKLOAD_LIMITS.maxLimit) {
|
|
1322
|
-
throw new
|
|
1459
|
+
throw new VibeError7({
|
|
1323
1460
|
code: "VIBE_CONFIG",
|
|
1324
1461
|
message: `workload snapshot limit must be an integer between ${POSTGRES_WORKLOAD_LIMITS.minLimit} and ${POSTGRES_WORKLOAD_LIMITS.maxLimit}, got ${String(limit)}`,
|
|
1325
1462
|
meta: { limit }
|
|
@@ -1338,7 +1475,7 @@ function renderPostgresWorkload(params) {
|
|
|
1338
1475
|
function requireArg(params) {
|
|
1339
1476
|
const { value, name, query } = params;
|
|
1340
1477
|
if (value === undefined || value.length === 0) {
|
|
1341
|
-
throw new
|
|
1478
|
+
throw new VibeError7({
|
|
1342
1479
|
code: "VIBE_CONFIG",
|
|
1343
1480
|
message: `the "${query}" diagnostic read requires a ${name}`,
|
|
1344
1481
|
meta: { query, argument: name }
|
|
@@ -1348,10 +1485,10 @@ function requireArg(params) {
|
|
|
1348
1485
|
}
|
|
1349
1486
|
|
|
1350
1487
|
// packages/sql/src/dialects/postgres-rls-readiness.ts
|
|
1351
|
-
import { unsupportedCapability as
|
|
1488
|
+
import { unsupportedCapability as unsupportedCapability8 } from "@vibeorm/schema";
|
|
1352
1489
|
|
|
1353
1490
|
// packages/sql/src/dialects/postgres-rls.ts
|
|
1354
|
-
import { RlsContextError, VibeError as
|
|
1491
|
+
import { RlsContextError, VibeError as VibeError8, assertValidSchemaIR, unsupportedCapability as unsupportedCapability7, validateRlsContextIR } from "@vibeorm/schema";
|
|
1355
1492
|
var NATIVE_RLS = Object.freeze({ policyName: "vibeorm_managed", tableSchema: "public", settingPrefix: "vibeorm.", parentAlias: "parent" });
|
|
1356
1493
|
var COLUMN_TYPES = {
|
|
1357
1494
|
String: { default: "text", native: { text: "text", varchar: "varchar", charactervarying: "varchar", uuid: "uuid" } },
|
|
@@ -1364,18 +1501,18 @@ var COLUMN_TYPES = {
|
|
|
1364
1501
|
};
|
|
1365
1502
|
function requireRls(params) {
|
|
1366
1503
|
if (!params.dialect.capabilities.nativeRowLevelSecurity) {
|
|
1367
|
-
throw
|
|
1504
|
+
throw unsupportedCapability7({ dialect: params.dialect.name, feature: "nativeRowLevelSecurity" });
|
|
1368
1505
|
}
|
|
1369
1506
|
}
|
|
1370
1507
|
function identifier2(params) {
|
|
1371
1508
|
if (typeof params.name !== "string" || params.name.length === 0 || params.name.includes("\x00") || new TextEncoder().encode(params.name).length > 63) {
|
|
1372
|
-
throw new
|
|
1509
|
+
throw new VibeError8({ code: "VIBE_SCHEMA_INVALID", message: "Native RLS identifiers must be nonempty PostgreSQL identifiers of at most 63 bytes" });
|
|
1373
1510
|
}
|
|
1374
1511
|
return params.dialect.quoteIdent({ name: params.name });
|
|
1375
1512
|
}
|
|
1376
1513
|
function tableRef(params) {
|
|
1377
1514
|
if (params.schema !== undefined && params.schema !== "public" && params.schema !== "pg_temp") {
|
|
1378
|
-
throw
|
|
1515
|
+
throw unsupportedCapability7({ dialect: params.dialect.name, feature: "nativeRowLevelSecurity", hint: "Only public tables and temporary policy probes are supported" });
|
|
1379
1516
|
}
|
|
1380
1517
|
return `${identifier2({ dialect: params.dialect, name: params.schema ?? NATIVE_RLS.tableSchema })}.${identifier2({ dialect: params.dialect, name: params.table })}`;
|
|
1381
1518
|
}
|
|
@@ -1416,14 +1553,14 @@ function renderRlsColumnType(params) {
|
|
|
1416
1553
|
if (native !== undefined)
|
|
1417
1554
|
return native;
|
|
1418
1555
|
}
|
|
1419
|
-
throw
|
|
1556
|
+
throw unsupportedCapability7({ dialect: params.dialect.name, feature: "nativeRowLevelSecurity", hint: `Unsupported physical ownership type on field ${field.name}` });
|
|
1420
1557
|
}
|
|
1421
1558
|
function protectedModel(params) {
|
|
1422
1559
|
requireRls(params);
|
|
1423
1560
|
assertValidSchemaIR({ schema: params.schema });
|
|
1424
1561
|
const model = params.schema.models.find((entry) => entry.name === params.model);
|
|
1425
1562
|
if (model === undefined || model.rls === undefined || model.rls === "unprotected") {
|
|
1426
|
-
throw new
|
|
1563
|
+
throw new VibeError8({ code: "VIBE_SCHEMA_INVALID", message: "Native RLS policy rendering requires a protected model", meta: { model: params.model } });
|
|
1427
1564
|
}
|
|
1428
1565
|
return model;
|
|
1429
1566
|
}
|
|
@@ -1456,7 +1593,7 @@ function predicate(params) {
|
|
|
1456
1593
|
}).join(" AND ");
|
|
1457
1594
|
return `EXISTS (SELECT 1 FROM ${tableRef({ dialect, table: parent.dbName ?? parent.name })} AS ${alias} WHERE ${join})`;
|
|
1458
1595
|
}
|
|
1459
|
-
throw new
|
|
1596
|
+
throw new VibeError8({ code: "VIBE_SCHEMA_INVALID", message: "Native RLS requires a protected policy rule" });
|
|
1460
1597
|
}
|
|
1461
1598
|
function renderRlsPolicy(params) {
|
|
1462
1599
|
const model = protectedModel(params);
|
|
@@ -1490,7 +1627,7 @@ function renderRlsContext(params) {
|
|
|
1490
1627
|
function renderRlsRole(params) {
|
|
1491
1628
|
requireRls(params);
|
|
1492
1629
|
if (typeof params.role !== "string" || params.role.trim().length === 0 || params.role.includes("\x00")) {
|
|
1493
|
-
throw new
|
|
1630
|
+
throw new VibeError8({ code: "VIBE_CONFIG", message: "PGlite native RLS requires a trusted nonempty runtime role name" });
|
|
1494
1631
|
}
|
|
1495
1632
|
const collector = new ParamCollector(params.dialect);
|
|
1496
1633
|
return query({ text: `SELECT set_config('role', ${collector.add(params.role)}, true)`, values: collector.values });
|
|
@@ -1642,7 +1779,7 @@ ORDER BY c.relname, p.polname`,
|
|
|
1642
1779
|
});
|
|
1643
1780
|
function requireRls2(params) {
|
|
1644
1781
|
if (!params.dialect.capabilities.nativeRowLevelSecurity) {
|
|
1645
|
-
throw
|
|
1782
|
+
throw unsupportedCapability8({ dialect: params.dialect.name, feature: "nativeRowLevelSecurity" });
|
|
1646
1783
|
}
|
|
1647
1784
|
}
|
|
1648
1785
|
function renderRlsReadinessQuery(params) {
|
|
@@ -1674,7 +1811,7 @@ function renderRlsPolicyPath(params) {
|
|
|
1674
1811
|
}
|
|
1675
1812
|
|
|
1676
1813
|
// packages/sql/src/render.ts
|
|
1677
|
-
import { internalError as internalError2, unsupportedCapability as
|
|
1814
|
+
import { internalError as internalError2, unsupportedCapability as unsupportedCapability9 } from "@vibeorm/schema";
|
|
1678
1815
|
|
|
1679
1816
|
// packages/sql/src/like.ts
|
|
1680
1817
|
function escapeLikePattern(params) {
|
|
@@ -1819,7 +1956,7 @@ function renderAggRef(dialect, agg) {
|
|
|
1819
1956
|
function assertScalarArrays(dialect, feature) {
|
|
1820
1957
|
if (dialect.capabilities.scalarArrays)
|
|
1821
1958
|
return;
|
|
1822
|
-
throw
|
|
1959
|
+
throw unsupportedCapability9({
|
|
1823
1960
|
dialect: dialect.name,
|
|
1824
1961
|
feature,
|
|
1825
1962
|
hint: "only postgres has native array columns \u2014 model the list as a related table instead"
|
|
@@ -1876,8 +2013,8 @@ function renderExpr(params) {
|
|
|
1876
2013
|
const columns = expr.columns.map((column) => quoteCol(dialect, column));
|
|
1877
2014
|
if (dialect.tupleInStrategy === "rowValue") {
|
|
1878
2015
|
const tuples = expr.rows.map((row) => `(${collector.addMany(row).join(", ")})`);
|
|
1879
|
-
const
|
|
1880
|
-
return expr.negate === true ? `NOT (${
|
|
2016
|
+
const base = `(${columns.join(", ")}) IN (${tuples.join(", ")})`;
|
|
2017
|
+
return expr.negate === true ? `NOT (${base})` : base;
|
|
1881
2018
|
}
|
|
1882
2019
|
const conjunctions = expr.rows.map((row) => {
|
|
1883
2020
|
const terms = row.map((value, index) => `${columns[index]} = ${collector.add(value)}`);
|
|
@@ -1997,7 +2134,7 @@ function jsonPathString(path) {
|
|
|
1997
2134
|
} else if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(segment)) {
|
|
1998
2135
|
out += `.${segment}`;
|
|
1999
2136
|
} else {
|
|
2000
|
-
out += `."${segment.replaceAll('"', "\\\"")}"`;
|
|
2137
|
+
out += `."${segment.replaceAll("\\", "\\\\").replaceAll('"', "\\\"")}"`;
|
|
2001
2138
|
}
|
|
2002
2139
|
}
|
|
2003
2140
|
return out;
|
|
@@ -2029,7 +2166,7 @@ function renderJsonLike(params) {
|
|
|
2029
2166
|
function renderJsonFilter(params) {
|
|
2030
2167
|
const { dialect, expr, collector } = params;
|
|
2031
2168
|
if (!dialect.supportedJsonOps.includes(expr.op)) {
|
|
2032
|
-
throw
|
|
2169
|
+
throw unsupportedCapability9({
|
|
2033
2170
|
dialect: dialect.name,
|
|
2034
2171
|
feature: `the json filter "${expr.op}"`,
|
|
2035
2172
|
hint: `this dialect can express: ${dialect.supportedJsonOps.join(", ")}`
|
|
@@ -2037,25 +2174,25 @@ function renderJsonFilter(params) {
|
|
|
2037
2174
|
}
|
|
2038
2175
|
const cmp = expr.negate === true ? "<>" : "=";
|
|
2039
2176
|
if (dialect.jsonPathMode === "operators") {
|
|
2040
|
-
const
|
|
2177
|
+
const column = quoteCol(dialect, expr.column);
|
|
2041
2178
|
const pathParam = `${collector.add(expr.path.map(String))}::text[]`;
|
|
2042
2179
|
switch (expr.op) {
|
|
2043
2180
|
case "equals":
|
|
2044
|
-
return `(${
|
|
2181
|
+
return `(${column} #> ${pathParam}) ${cmp} ${collector.add(JSON.stringify(expr.value))}${dialect.jsonParamCast}`;
|
|
2045
2182
|
case "string_contains":
|
|
2046
2183
|
case "string_starts_with":
|
|
2047
2184
|
case "string_ends_with":
|
|
2048
|
-
return renderJsonLike({ dialect, target: `(${
|
|
2185
|
+
return renderJsonLike({ dialect, target: `(${column} #>> ${pathParam})`, expr, collector });
|
|
2049
2186
|
case "array_contains":
|
|
2050
|
-
return `(${
|
|
2187
|
+
return `(${column} #> ${pathParam}) @> ${collector.add(JSON.stringify(expr.value))}${dialect.jsonParamCast}`;
|
|
2051
2188
|
case "array_starts_with":
|
|
2052
|
-
return `(${
|
|
2189
|
+
return `(${column} #> ${pathParam}) -> 0 = ${collector.add(JSON.stringify(expr.value))}${dialect.jsonParamCast}`;
|
|
2053
2190
|
case "array_ends_with":
|
|
2054
|
-
return `(${
|
|
2191
|
+
return `(${column} #> ${pathParam}) -> -1 = ${collector.add(JSON.stringify(expr.value))}${dialect.jsonParamCast}`;
|
|
2055
2192
|
}
|
|
2056
2193
|
}
|
|
2057
2194
|
if (dialect.jsonPathMode === "sqliteExtract") {
|
|
2058
|
-
const
|
|
2195
|
+
const column = quoteCol(dialect, expr.column);
|
|
2059
2196
|
const typeMatches = (type, value) => {
|
|
2060
2197
|
if (typeof value === "number")
|
|
2061
2198
|
return `${type} IN ('integer', 'real')`;
|
|
@@ -2063,11 +2200,11 @@ function renderJsonFilter(params) {
|
|
|
2063
2200
|
return `${type} = '${tag}'`;
|
|
2064
2201
|
};
|
|
2065
2202
|
const compareExtracted = (path, value) => {
|
|
2066
|
-
const type = `json_type(${
|
|
2203
|
+
const type = `json_type(${column}, ${collector.add(path)})`;
|
|
2067
2204
|
const guard = typeMatches(type, value);
|
|
2068
2205
|
let base = guard;
|
|
2069
2206
|
if (value !== null) {
|
|
2070
|
-
const target = `json_extract(${
|
|
2207
|
+
const target = `json_extract(${column}, ${collector.add(path)})`;
|
|
2071
2208
|
const bound = typeof value === "boolean" ? value ? 1 : 0 : value;
|
|
2072
2209
|
const operand = typeof value === "object" ? `json(${collector.add(JSON.stringify(value))})` : collector.add(bound);
|
|
2073
2210
|
base = `(${guard} AND ${target} = ${operand})`;
|
|
@@ -2080,7 +2217,7 @@ function renderJsonFilter(params) {
|
|
|
2080
2217
|
case "string_contains":
|
|
2081
2218
|
case "string_starts_with":
|
|
2082
2219
|
case "string_ends_with": {
|
|
2083
|
-
const target = `json_extract(${
|
|
2220
|
+
const target = `json_extract(${column}, ${collector.add(jsonPathString(expr.path))})`;
|
|
2084
2221
|
return renderJsonLike({ dialect, target, expr, collector });
|
|
2085
2222
|
}
|
|
2086
2223
|
case "array_starts_with":
|
|
@@ -2089,11 +2226,11 @@ function renderJsonFilter(params) {
|
|
|
2089
2226
|
return compareExtracted(`${jsonPathString(expr.path)}${edge}`, expr.value);
|
|
2090
2227
|
}
|
|
2091
2228
|
case "array_contains": {
|
|
2092
|
-
const guard = `json_type(${
|
|
2229
|
+
const guard = `json_type(${column}, ${collector.add(jsonPathString(expr.path))}) = 'array'`;
|
|
2093
2230
|
const elements = Array.isArray(expr.value) ? expr.value : [expr.value];
|
|
2094
2231
|
const tests = elements.map((element) => {
|
|
2095
2232
|
if (element === null || typeof element === "object" && element !== null) {
|
|
2096
|
-
throw
|
|
2233
|
+
throw unsupportedCapability9({
|
|
2097
2234
|
dialect: dialect.name,
|
|
2098
2235
|
feature: "json array_contains with object/array/null elements",
|
|
2099
2236
|
hint: "sqlite expresses scalar-element containment only \u2014 deep structural containment needs postgres or mysql"
|
|
@@ -2102,7 +2239,7 @@ function renderJsonFilter(params) {
|
|
|
2102
2239
|
const bound = typeof element === "boolean" ? element ? 1 : 0 : element;
|
|
2103
2240
|
const path = collector.add(jsonPathString(expr.path));
|
|
2104
2241
|
const type = `${dialect.quoteIdent({ name: "json_each" })}.${dialect.quoteIdent({ name: "type" })}`;
|
|
2105
|
-
return `EXISTS (SELECT 1 FROM json_each(${
|
|
2242
|
+
return `EXISTS (SELECT 1 FROM json_each(${column}, ${path}) WHERE ${typeMatches(type, element)} AND ${dialect.quoteIdent({ name: "json_each" })}.${dialect.quoteIdent({ name: "value" })} = ${collector.add(bound)})`;
|
|
2106
2243
|
});
|
|
2107
2244
|
return tests.length === 0 ? guard : `(${[guard, ...tests].join(" AND ")})`;
|
|
2108
2245
|
}
|
|
@@ -2244,7 +2381,7 @@ function renderSelect(params) {
|
|
|
2244
2381
|
let distinctPrefix = "";
|
|
2245
2382
|
if (statement.distinctOn !== undefined && statement.distinctOn.length > 0) {
|
|
2246
2383
|
if (!dialect.capabilities.distinctOn) {
|
|
2247
|
-
throw
|
|
2384
|
+
throw unsupportedCapability9({
|
|
2248
2385
|
dialect: dialect.name,
|
|
2249
2386
|
feature: "SELECT DISTINCT ON",
|
|
2250
2387
|
hint: "postgres-only \u2014 the runtime emulates distinct client-side on this dialect"
|
|
@@ -2275,7 +2412,7 @@ function renderSelect(params) {
|
|
|
2275
2412
|
}
|
|
2276
2413
|
if (statement.lateralJoins !== undefined && statement.lateralJoins.length > 0) {
|
|
2277
2414
|
if (!dialect.capabilities.lateralJoin) {
|
|
2278
|
-
throw
|
|
2415
|
+
throw unsupportedCapability9({
|
|
2279
2416
|
dialect: dialect.name,
|
|
2280
2417
|
feature: "LATERAL JOIN relation loading",
|
|
2281
2418
|
hint: 'use the portable "query" relation strategy on this dialect'
|
|
@@ -2360,7 +2497,7 @@ function renderInsert(params) {
|
|
|
2360
2497
|
let target = "";
|
|
2361
2498
|
if (onConflict.constraint !== undefined) {
|
|
2362
2499
|
if (dialect.name !== "postgres") {
|
|
2363
|
-
throw
|
|
2500
|
+
throw unsupportedCapability9({
|
|
2364
2501
|
dialect: dialect.name,
|
|
2365
2502
|
feature: "a named-constraint conflict target (ON CONFLICT ON CONSTRAINT)",
|
|
2366
2503
|
hint: "only postgres names constraints in conflict targets \u2014 use a column-list target"
|
|
@@ -2375,7 +2512,7 @@ function renderInsert(params) {
|
|
|
2375
2512
|
}
|
|
2376
2513
|
text += ` ON CONFLICT${target} DO NOTHING`;
|
|
2377
2514
|
} else if (onConflict.constraint !== undefined || onConflict.conflictWhere !== undefined) {
|
|
2378
|
-
throw
|
|
2515
|
+
throw unsupportedCapability9({
|
|
2379
2516
|
dialect: dialect.name,
|
|
2380
2517
|
feature: "a refined conflict target (constraint / partial-index predicate) on INSERT IGNORE",
|
|
2381
2518
|
hint: "mysql skips on any duplicate key \u2014 drop the refinement or gate the call per dialect"
|
|
@@ -2393,7 +2530,7 @@ function renderInsert(params) {
|
|
|
2393
2530
|
throw internalError2({ message: "lastInsertIdColumn is a mysql (onDuplicateKey) construct" });
|
|
2394
2531
|
}
|
|
2395
2532
|
if (onConflict.constraint !== undefined && dialect.name !== "postgres") {
|
|
2396
|
-
throw
|
|
2533
|
+
throw unsupportedCapability9({
|
|
2397
2534
|
dialect: dialect.name,
|
|
2398
2535
|
feature: "a named-constraint conflict target (ON CONFLICT ON CONSTRAINT)",
|
|
2399
2536
|
hint: "sqlite conflict targets are column lists \u2014 name the indexed columns instead"
|
|
@@ -2409,14 +2546,14 @@ function renderInsert(params) {
|
|
|
2409
2546
|
text += ` ON CONFLICT${target} DO UPDATE SET ${assignments}`;
|
|
2410
2547
|
} else {
|
|
2411
2548
|
if (onConflict.constraint !== undefined) {
|
|
2412
|
-
throw
|
|
2549
|
+
throw unsupportedCapability9({
|
|
2413
2550
|
dialect: dialect.name,
|
|
2414
2551
|
feature: "a named-constraint conflict target on ON DUPLICATE KEY UPDATE",
|
|
2415
2552
|
hint: "mysql's ODKU fires on any duplicate key \u2014 no target can be named"
|
|
2416
2553
|
});
|
|
2417
2554
|
}
|
|
2418
2555
|
if (onConflict.conflictWhere !== undefined) {
|
|
2419
|
-
throw
|
|
2556
|
+
throw unsupportedCapability9({
|
|
2420
2557
|
dialect: dialect.name,
|
|
2421
2558
|
feature: "a partial-index conflict target on ON DUPLICATE KEY UPDATE",
|
|
2422
2559
|
hint: "mysql's ODKU fires on any duplicate key \u2014 a partial arbiter cannot be selected; gate the call per dialect"
|
|
@@ -2499,20 +2636,20 @@ function renderDelete(params) {
|
|
|
2499
2636
|
return { text: text + returning.suffix, values: collector.values, returning: returning.status };
|
|
2500
2637
|
}
|
|
2501
2638
|
// packages/sql/src/dialects/sqlite-table-definition.ts
|
|
2502
|
-
import { VibeError as
|
|
2639
|
+
import { VibeError as VibeError9 } from "@vibeorm/schema";
|
|
2503
2640
|
function tableDefinitionParts(params) {
|
|
2504
|
-
const
|
|
2505
|
-
if (!/^\s*CREATE\s+(?:TEMP(?:ORARY)?\s+)?TABLE\b/i.test(
|
|
2641
|
+
const sql = params.sql;
|
|
2642
|
+
if (!/^\s*CREATE\s+(?:TEMP(?:ORARY)?\s+)?TABLE\b/i.test(sql))
|
|
2506
2643
|
throw unavailable();
|
|
2507
2644
|
const parts = [];
|
|
2508
2645
|
let start = -1;
|
|
2509
2646
|
let depth = 0;
|
|
2510
2647
|
let quote;
|
|
2511
|
-
for (let index = 0;index <
|
|
2512
|
-
const char =
|
|
2648
|
+
for (let index = 0;index < sql.length; index++) {
|
|
2649
|
+
const char = sql[index];
|
|
2513
2650
|
if (quote !== undefined) {
|
|
2514
2651
|
if (char === quote) {
|
|
2515
|
-
if (quote !== "]" &&
|
|
2652
|
+
if (quote !== "]" && sql[index + 1] === quote)
|
|
2516
2653
|
index++;
|
|
2517
2654
|
else
|
|
2518
2655
|
quote = undefined;
|
|
@@ -2527,16 +2664,16 @@ function tableDefinitionParts(params) {
|
|
|
2527
2664
|
quote = "]";
|
|
2528
2665
|
continue;
|
|
2529
2666
|
}
|
|
2530
|
-
if (char === "-" &&
|
|
2531
|
-
const end =
|
|
2667
|
+
if (char === "-" && sql[index + 1] === "-") {
|
|
2668
|
+
const end = sql.indexOf(`
|
|
2532
2669
|
`, index + 2);
|
|
2533
2670
|
if (end < 0)
|
|
2534
2671
|
break;
|
|
2535
2672
|
index = end;
|
|
2536
2673
|
continue;
|
|
2537
2674
|
}
|
|
2538
|
-
if (char === "/" &&
|
|
2539
|
-
const end =
|
|
2675
|
+
if (char === "/" && sql[index + 1] === "*") {
|
|
2676
|
+
const end = sql.indexOf("*/", index + 2);
|
|
2540
2677
|
if (end < 0)
|
|
2541
2678
|
break;
|
|
2542
2679
|
index = end + 1;
|
|
@@ -2549,18 +2686,18 @@ function tableDefinitionParts(params) {
|
|
|
2549
2686
|
} else if (char === ")") {
|
|
2550
2687
|
depth--;
|
|
2551
2688
|
if (depth === 0 && start >= 0) {
|
|
2552
|
-
parts.push(
|
|
2553
|
-
return { clauses: parts, suffix:
|
|
2689
|
+
parts.push(sql.slice(start, index).trim());
|
|
2690
|
+
return { clauses: parts, suffix: sql.slice(index + 1) };
|
|
2554
2691
|
}
|
|
2555
2692
|
} else if (char === "," && depth === 1) {
|
|
2556
|
-
parts.push(
|
|
2693
|
+
parts.push(sql.slice(start, index).trim());
|
|
2557
2694
|
start = index + 1;
|
|
2558
2695
|
}
|
|
2559
2696
|
}
|
|
2560
2697
|
throw unavailable();
|
|
2561
2698
|
}
|
|
2562
2699
|
function unavailable() {
|
|
2563
|
-
return new
|
|
2700
|
+
return new VibeError9({ code: "VIBE_MIGRATION", message: "Cannot preserve table definition", meta: { reason: "table-definition-unavailable" } });
|
|
2564
2701
|
}
|
|
2565
2702
|
function sqliteColumnClauses(params) {
|
|
2566
2703
|
const columns = [];
|
|
@@ -2575,12 +2712,58 @@ function sqliteColumnClauses(params) {
|
|
|
2575
2712
|
}
|
|
2576
2713
|
return columns;
|
|
2577
2714
|
}
|
|
2715
|
+
// packages/sql/src/dialects/postgres-type-identity.ts
|
|
2716
|
+
import { unsupportedCapability as unsupportedCapability10 } from "@vibeorm/schema";
|
|
2717
|
+
var IDENTIFIER = '(?:"(?:[^"\\x00]|"")+"|[a-zA-Z_][a-zA-Z_0-9$]*)';
|
|
2718
|
+
var MODIFIER_VALUE = `(?:[+-]?\\d+|${IDENTIFIER}|'(?:[^'\\x00]|'')*')`;
|
|
2719
|
+
var TYPE_NAME = new RegExp(`^\\s*(${IDENTIFIER})(?:\\s*\\.\\s*(${IDENTIFIER}))?\\s*(\\(\\s*${MODIFIER_VALUE}(?:\\s*,\\s*${MODIFIER_VALUE})*\\s*\\))?\\s*((?:\\[\\s*\\]\\s*)*)$`);
|
|
2720
|
+
var MODIFIER_TOKEN = new RegExp(MODIFIER_VALUE, "g");
|
|
2721
|
+
function modifier(params) {
|
|
2722
|
+
if (params.raw === undefined)
|
|
2723
|
+
return "";
|
|
2724
|
+
const tokens = params.raw.slice(1, -1).match(MODIFIER_TOKEN) ?? [];
|
|
2725
|
+
return `(${tokens.map((token) => /^[+-]?\d+$/.test(token) ? BigInt(token).toString() : token.startsWith("'") || token.startsWith('"') ? token : token.toLowerCase()).join(",")})`;
|
|
2726
|
+
}
|
|
2727
|
+
function identifier3(params) {
|
|
2728
|
+
return params.value.startsWith('"') ? params.value.slice(1, -1).replaceAll('""', '"') : params.value.toLowerCase();
|
|
2729
|
+
}
|
|
2730
|
+
function parsePostgresTypeName(params) {
|
|
2731
|
+
const match = TYPE_NAME.exec(params.raw);
|
|
2732
|
+
if (match === null)
|
|
2733
|
+
return;
|
|
2734
|
+
return {
|
|
2735
|
+
...match[2] === undefined ? {} : { namespace: identifier3({ value: match[1] }) },
|
|
2736
|
+
name: identifier3({ value: match[2] ?? match[1] }),
|
|
2737
|
+
modifier: modifier({ ...match[3] === undefined ? {} : { raw: match[3] } }),
|
|
2738
|
+
array: (match[4]?.length ?? 0) > 0
|
|
2739
|
+
};
|
|
2740
|
+
}
|
|
2741
|
+
function renderPostgresTypeName(params) {
|
|
2742
|
+
if (params.dialect.name !== "postgres")
|
|
2743
|
+
throw unsupportedCapability10({ dialect: params.dialect.name, feature: "postgresTypeIdentity" });
|
|
2744
|
+
const { dialect, type } = params;
|
|
2745
|
+
return `${type.namespace === undefined ? "" : `${dialect.quoteIdent({ name: type.namespace })}.`}${dialect.quoteIdent({ name: type.name })}${type.modifier}${type.array ? "[]" : ""}`;
|
|
2746
|
+
}
|
|
2747
|
+
function renderPostgresTypeIdentity(params) {
|
|
2748
|
+
if (params.dialect.name !== "postgres")
|
|
2749
|
+
throw unsupportedCapability10({ dialect: params.dialect.name, feature: "postgresTypeIdentity" });
|
|
2750
|
+
const collector = new ParamCollector(params.dialect);
|
|
2751
|
+
const { source } = params;
|
|
2752
|
+
let text;
|
|
2753
|
+
if ("table" in source) {
|
|
2754
|
+
text = `SELECT tn.nspname::text AS "namespace", base.typname::text AS "name" FROM pg_catalog.pg_attribute a JOIN pg_catalog.pg_class c ON c.oid = a.attrelid JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace JOIN pg_catalog.pg_type t ON t.oid = a.atttypid JOIN pg_catalog.pg_type base ON base.oid = CASE WHEN t.typelem <> 0 AND t.typlen = -1 THEN t.typelem ELSE t.oid END JOIN pg_catalog.pg_namespace tn ON tn.oid = base.typnamespace WHERE n.nspname = ${collector.add(source.table.namespace)} AND c.relname = ${collector.add(source.table.name)} AND a.attname = ${collector.add(source.column)} AND a.attnum > 0 AND NOT a.attisdropped`;
|
|
2755
|
+
} else {
|
|
2756
|
+
const name = renderPostgresTypeName({ dialect: params.dialect, type: { ...source.type, modifier: "", array: false } });
|
|
2757
|
+
text = `SELECT n.nspname::text AS "namespace", t.typname::text AS "name" FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace WHERE t.oid = pg_catalog.to_regtype(${collector.add(name)})`;
|
|
2758
|
+
}
|
|
2759
|
+
return { text, values: collector.values, returning: "none" };
|
|
2760
|
+
}
|
|
2578
2761
|
// packages/sql/src/dialects/postgres-default-identity.ts
|
|
2579
|
-
import { unsupportedCapability as
|
|
2762
|
+
import { unsupportedCapability as unsupportedCapability11 } from "@vibeorm/schema";
|
|
2580
2763
|
function renderPostgresDefaultFunctionIdentity(params) {
|
|
2581
2764
|
const { dialect, table, column } = params;
|
|
2582
2765
|
if (dialect.name !== "postgres")
|
|
2583
|
-
throw
|
|
2766
|
+
throw unsupportedCapability11({ dialect: dialect.name, feature: "defaultFunctionIdentity" });
|
|
2584
2767
|
const collector = new ParamCollector(dialect);
|
|
2585
2768
|
const namespace = collector.add(table.namespace);
|
|
2586
2769
|
const name = collector.add(table.name);
|
|
@@ -2604,28 +2787,28 @@ WHERE n.nspname = ${namespace} AND c.relname = ${name} AND a.attname = ${field}
|
|
|
2604
2787
|
};
|
|
2605
2788
|
}
|
|
2606
2789
|
// packages/sql/src/dialects/constraint-owned-index.ts
|
|
2607
|
-
import { unsupportedCapability as
|
|
2790
|
+
import { unsupportedCapability as unsupportedCapability12 } from "@vibeorm/schema";
|
|
2608
2791
|
function renderConstraintOwnedIndexDrop(params) {
|
|
2609
2792
|
if (params.dialect.name !== "postgres")
|
|
2610
|
-
throw
|
|
2793
|
+
throw unsupportedCapability12({ dialect: params.dialect.name, feature: "constraintOwnedIndexDrop" });
|
|
2611
2794
|
const quote = (name) => params.dialect.quoteIdent({ name });
|
|
2612
2795
|
return { text: `ALTER TABLE ${quote(params.table)} DROP CONSTRAINT ${quote(params.constraint)};`, values: [], returning: "none" };
|
|
2613
2796
|
}
|
|
2614
2797
|
// packages/sql/src/dialects/mysql-check-probe.ts
|
|
2615
|
-
import { unsupportedCapability as
|
|
2798
|
+
import { unsupportedCapability as unsupportedCapability13 } from "@vibeorm/schema";
|
|
2616
2799
|
function renderMysqlCheckProbe(params) {
|
|
2617
2800
|
if (params.dialect.name !== "mysql")
|
|
2618
|
-
throw
|
|
2801
|
+
throw unsupportedCapability13({ dialect: params.dialect.name, feature: "temporaryCheckProbe" });
|
|
2619
2802
|
const q = (name) => params.dialect.quoteIdent({ name });
|
|
2620
2803
|
const probe = q(params.probe);
|
|
2621
2804
|
switch (params.operation) {
|
|
2622
2805
|
case "clone":
|
|
2623
2806
|
if (params.table === undefined)
|
|
2624
|
-
throw
|
|
2807
|
+
throw unsupportedCapability13({ dialect: "mysql", feature: "temporaryCheckProbe", hint: "A source table is required" });
|
|
2625
2808
|
return { text: `CREATE TEMPORARY TABLE ${probe} LIKE ${q(params.table.namespace)}.${q(params.table.name)}`, values: [], returning: "none" };
|
|
2626
2809
|
case "add": {
|
|
2627
2810
|
if (params.expression === undefined || params.definition === undefined)
|
|
2628
|
-
throw
|
|
2811
|
+
throw unsupportedCapability13({ dialect: "mysql", feature: "temporaryCheckProbe", hint: "An authored expression and temporary clone definition are required" });
|
|
2629
2812
|
const parts = tableDefinitionParts({ sql: params.definition });
|
|
2630
2813
|
return { text: `CREATE TEMPORARY TABLE ${probe} (
|
|
2631
2814
|
${[...parts.clauses, `CONSTRAINT ${probe} CHECK (${params.expression})`].join(`,
|
|
@@ -2644,8 +2827,8 @@ function renderMigrationHistoryQuery(params) {
|
|
|
2644
2827
|
return { text: `SELECT ${q("name")}, ${q("checksum")}, ${q("statement_index")}, ${q("error")} FROM ${q(params.namespace)}.${q("_vibe_migrations")} ORDER BY ${q("id")}`, values: [], returning: "none" };
|
|
2645
2828
|
}
|
|
2646
2829
|
// packages/sql/src/dialects/sqlite-constraints.ts
|
|
2647
|
-
var
|
|
2648
|
-
function
|
|
2830
|
+
var IDENTIFIER2 = '(?:"(?:[^" ]| |"")+"|`(?:[^`]|``)+`|\\[[^\\]]+\\]|[A-Za-z_][A-Za-z_0-9]*)';
|
|
2831
|
+
function identifier4(value) {
|
|
2649
2832
|
const text = value.trim();
|
|
2650
2833
|
if (text.startsWith('"'))
|
|
2651
2834
|
return text.slice(1, -1).replaceAll('""', '"');
|
|
@@ -2658,44 +2841,44 @@ function identifier3(value) {
|
|
|
2658
2841
|
function sqliteTableConstraints(params) {
|
|
2659
2842
|
const result = [];
|
|
2660
2843
|
for (const clause of tableDefinitionParts(params).clauses) {
|
|
2661
|
-
const named = new RegExp(`^CONSTRAINT\\s+(${
|
|
2844
|
+
const named = new RegExp(`^CONSTRAINT\\s+(${IDENTIFIER2})\\s+`, "i").exec(clause);
|
|
2662
2845
|
const body = named === null ? clause : clause.slice(named[0].length);
|
|
2663
2846
|
const kind = /^(CHECK|FOREIGN\s+KEY|UNIQUE|PRIMARY\s+KEY)\s*\(/i.exec(body);
|
|
2664
2847
|
if (kind === null)
|
|
2665
2848
|
continue;
|
|
2666
2849
|
const type = /^CHECK$/i.test(kind[1]) ? "check" : /^FOREIGN/i.test(kind[1]) ? "foreignKey" : /^PRIMARY/i.test(kind[1]) ? "primaryKey" : "unique";
|
|
2667
2850
|
const parts = tableDefinitionParts({ sql: `CREATE TABLE x ${body.slice(kind[0].indexOf("("))}` });
|
|
2668
|
-
const columns = type === "check" ? [] : parts.clauses.map(
|
|
2669
|
-
result.push({ name: named === null ? `@sqlite:${type}:${result.length}` :
|
|
2851
|
+
const columns = type === "check" ? [] : parts.clauses.map(identifier4);
|
|
2852
|
+
result.push({ name: named === null ? `@sqlite:${type}:${result.length}` : identifier4(named[1]), named: named !== null, type, sql: body, columns });
|
|
2670
2853
|
}
|
|
2671
2854
|
return result;
|
|
2672
2855
|
}
|
|
2673
2856
|
// packages/sql/src/dialects/migration-visibility.ts
|
|
2674
|
-
import { unsupportedCapability as
|
|
2857
|
+
import { unsupportedCapability as unsupportedCapability14 } from "@vibeorm/schema";
|
|
2675
2858
|
function renderMigrationVisibility(params) {
|
|
2676
2859
|
if (params.dialect.name !== "mysql")
|
|
2677
|
-
throw
|
|
2860
|
+
throw unsupportedCapability14({ dialect: params.dialect.name, feature: "mysqlCatalogVisibility" });
|
|
2678
2861
|
const collector = new ParamCollector(params.dialect);
|
|
2679
2862
|
const grantee = "CONCAT(QUOTE(SUBSTRING_INDEX(CURRENT_USER(), '@', 1)), '@', QUOTE(SUBSTRING_INDEX(CURRENT_USER(), '@', -1)))";
|
|
2680
2863
|
return { text: `SELECT PRIVILEGE_TYPE AS privilege FROM information_schema.USER_PRIVILEGES WHERE GRANTEE = ${grantee} UNION SELECT PRIVILEGE_TYPE AS privilege FROM information_schema.SCHEMA_PRIVILEGES WHERE GRANTEE = ${grantee} AND ${collector.add(params.namespace)} LIKE TABLE_SCHEMA`, values: collector.values, returning: "none" };
|
|
2681
2864
|
}
|
|
2682
2865
|
// packages/sql/src/dialects/migration-inventory.ts
|
|
2683
|
-
import { unsupportedCapability as
|
|
2866
|
+
import { unsupportedCapability as unsupportedCapability15 } from "@vibeorm/schema";
|
|
2684
2867
|
function renderSqliteColumnInventory(params) {
|
|
2685
2868
|
if (params.dialect.name !== "sqlite")
|
|
2686
|
-
throw
|
|
2869
|
+
throw unsupportedCapability15({ dialect: params.dialect.name, feature: "sqliteColumnInventory" });
|
|
2687
2870
|
const collector = new ParamCollector(params.dialect);
|
|
2688
2871
|
return { text: `SELECT name, hidden, pk, dflt_value AS definition FROM pragma_table_xinfo(${collector.add(params.table)}, ${collector.add(params.namespace)}) ORDER BY cid`, values: collector.values, returning: "none" };
|
|
2689
2872
|
}
|
|
2690
2873
|
function renderSqliteForeignKeyInventory(params) {
|
|
2691
2874
|
if (params.dialect.name !== "sqlite")
|
|
2692
|
-
throw
|
|
2875
|
+
throw unsupportedCapability15({ dialect: params.dialect.name, feature: "sqliteForeignKeyInventory" });
|
|
2693
2876
|
const collector = new ParamCollector(params.dialect);
|
|
2694
2877
|
return { text: `SELECT id, seq, "from", "to", "table", on_update, on_delete, match FROM pragma_foreign_key_list(${collector.add(params.table)}, ${collector.add(params.namespace)}) ORDER BY id, seq`, values: collector.values, returning: "none" };
|
|
2695
2878
|
}
|
|
2696
2879
|
function renderSqliteRebuildObjects(params) {
|
|
2697
2880
|
if (params.dialect.name !== "sqlite")
|
|
2698
|
-
throw
|
|
2881
|
+
throw unsupportedCapability15({ dialect: params.dialect.name, feature: "sqliteRebuildObjects" });
|
|
2699
2882
|
return { text: "SELECT name, tbl_name, type, sql FROM main.sqlite_schema WHERE type IN ('index', 'trigger') AND sql IS NOT NULL ORDER BY type, name", values: [], returning: "none" };
|
|
2700
2883
|
}
|
|
2701
2884
|
function renderMigrationInventory(params) {
|
|
@@ -2732,10 +2915,12 @@ ORDER BY kind, parent, name`, values: collector.values, returning: "none" };
|
|
|
2732
2915
|
return { text: `SELECT type AS kind, name, tbl_name AS parent, sql AS definition FROM ${schema}.sqlite_schema WHERE name NOT LIKE 'sqlite\\_%' ESCAPE '\\' AND name <> '_vibe_migrations' ORDER BY type, tbl_name, name`, values: [], returning: "none" };
|
|
2733
2916
|
}
|
|
2734
2917
|
// packages/sql/src/dialects/migration-objects.ts
|
|
2735
|
-
import { unsupportedCapability as
|
|
2918
|
+
import { internalError as internalError3, unsupportedCapability as unsupportedCapability16 } from "@vibeorm/schema";
|
|
2736
2919
|
function renderMigrationObjectQuery(params) {
|
|
2737
|
-
|
|
2738
|
-
|
|
2920
|
+
return objectQuery({ ...params, collector: new ParamCollector(params.dialect) });
|
|
2921
|
+
}
|
|
2922
|
+
function objectQuery(params) {
|
|
2923
|
+
const { dialect, identity: object, collector } = params;
|
|
2739
2924
|
const physical = "table" in object ? object.table : object.name;
|
|
2740
2925
|
const namespace = collector.add(physical.namespace);
|
|
2741
2926
|
const name = collector.add(physical.name);
|
|
@@ -2753,7 +2938,7 @@ function renderMigrationObjectQuery(params) {
|
|
|
2753
2938
|
text = `SELECT pg_catalog.pg_get_triggerdef(t.oid, false) AS "definition", t.tgenabled::text AS "enabled", pn.nspname::text AS "functionNamespace", p.proname::text AS "functionName", pg_catalog.pg_get_function_identity_arguments(p.oid) AS "functionArguments" ${relation} JOIN pg_catalog.pg_trigger t ON t.tgrelid = c.oid JOIN pg_catalog.pg_proc p ON p.oid = t.tgfoid JOIN pg_catalog.pg_namespace pn ON pn.oid = p.pronamespace WHERE ${where} AND t.tgname = ${collector.add(object.name)} AND NOT t.tgisinternal`;
|
|
2754
2939
|
break;
|
|
2755
2940
|
case "function":
|
|
2756
|
-
text = `SELECT pg_catalog.pg_get_functiondef(p.oid) AS "definition", p.provolatile::text AS "volatility", p.prosecdef AS "securityDefiner", p.proisstrict AS "strict", p.proconfig::text AS "config", pg_catalog.pg_get_function_result(p.oid) AS "result" FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace WHERE n.nspname = ${namespace} AND p.proname = ${name} AND p.prokind = 'f' AND ARRAY(SELECT tn.nspname || '.' || t.typname FROM unnest(p.proargtypes) WITH ORDINALITY a(oid, ord) JOIN pg_catalog.pg_type t ON t.oid = a.oid JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace ORDER BY a.ord) = ${collector.add(object.argumentTypes.map((type) => `${type.namespace}.${type.name}`))}::text[]`;
|
|
2941
|
+
text = `SELECT pg_catalog.pg_get_functiondef(p.oid) AS "definition", p.provolatile::text AS "volatility", p.prosecdef AS "securityDefiner", CASE WHEN p.prosecdef THEN pg_catalog.pg_get_userbyid(p.proowner)::text ELSE NULL END AS "definerOwner", p.proisstrict AS "strict", p.proconfig::text AS "config", pg_catalog.pg_get_function_result(p.oid) AS "result" FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace WHERE n.nspname = ${namespace} AND p.proname = ${name} AND p.prokind = 'f' AND ARRAY(SELECT tn.nspname || '.' || t.typname FROM unnest(p.proargtypes) WITH ORDINALITY a(oid, ord) JOIN pg_catalog.pg_type t ON t.oid = a.oid JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace ORDER BY a.ord) = ${collector.add(object.argumentTypes.map((type) => `${type.namespace}.${type.name}`))}::text[]`;
|
|
2757
2942
|
break;
|
|
2758
2943
|
case "view":
|
|
2759
2944
|
text = `SELECT pg_catalog.pg_get_viewdef(c.oid, false) AS "definition", c.relkind::text AS "type", c.reloptions::text AS "options" ${relation} WHERE ${where} AND c.relkind IN ('v', 'm')`;
|
|
@@ -2764,7 +2949,7 @@ function renderMigrationObjectQuery(params) {
|
|
|
2764
2949
|
case "column":
|
|
2765
2950
|
case "columnDefault":
|
|
2766
2951
|
case "generatedColumn":
|
|
2767
|
-
text = `SELECT pg_catalog.format_type(a.atttypid, a.atttypmod) AS "type", a.attnotnull AS "notNull", a.attgenerated::text AS "generated", a.attidentity::text AS "identity", pg_catalog.pg_get_expr(d.adbin, d.adrelid, false) AS "definition" ${relation} JOIN pg_catalog.pg_attribute a ON a.attrelid = c.oid LEFT JOIN pg_catalog.pg_attrdef d ON d.adrelid = c.oid AND d.adnum = a.attnum WHERE ${where} AND a.attname = ${collector.add(object.column)} AND a.attnum > 0 AND NOT a.attisdropped`;
|
|
2952
|
+
text = `SELECT pg_catalog.format_type(a.atttypid, a.atttypmod) AS "type", a.attnotnull AS "notNull", a.attgenerated::text AS "generated", a.attidentity::text AS "identity", cn.nspname::text AS "collationNamespace", coll.collname::text AS "collationName", pg_catalog.pg_get_expr(d.adbin, d.adrelid, false) AS "definition" ${relation} JOIN pg_catalog.pg_attribute a ON a.attrelid = c.oid LEFT JOIN pg_catalog.pg_collation coll ON coll.oid = a.attcollation LEFT JOIN pg_catalog.pg_namespace cn ON cn.oid = coll.collnamespace LEFT JOIN pg_catalog.pg_attrdef d ON d.adrelid = c.oid AND d.adnum = a.attnum WHERE ${where} AND a.attname = ${collector.add(object.column)} AND a.attnum > 0 AND NOT a.attisdropped`;
|
|
2768
2953
|
break;
|
|
2769
2954
|
case "index":
|
|
2770
2955
|
text = `SELECT pg_catalog.pg_get_indexdef(i.indexrelid, 0, false) AS "definition", i.indisunique AS "unique", i.indisvalid AS "valid", i.indisready AS "ready", con.conname::text AS "constraint", con.contype::text AS "constraintType" ${relation} JOIN pg_catalog.pg_index i ON i.indrelid = c.oid JOIN pg_catalog.pg_class ix ON ix.oid = i.indexrelid LEFT JOIN pg_catalog.pg_constraint con ON con.conindid = i.indexrelid AND con.contype IN ('p', 'u', 'x') WHERE ${where} AND ix.relname = ${collector.add(object.name)}`;
|
|
@@ -2793,11 +2978,11 @@ function renderMigrationObjectQuery(params) {
|
|
|
2793
2978
|
case "column":
|
|
2794
2979
|
case "columnDefault":
|
|
2795
2980
|
case "generatedColumn":
|
|
2796
|
-
text = `SELECT COLUMN_TYPE AS type, IS_NULLABLE AS nullable, COLUMN_DEFAULT AS definition, GENERATION_EXPRESSION AS generated, EXTRA AS extra, COLLATION_NAME AS collation FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ${namespace} AND TABLE_NAME = ${name} AND COLUMN_NAME = ${collector.add(object.column)}`;
|
|
2981
|
+
text = `SELECT COLUMN_TYPE AS type, IS_NULLABLE AS nullable, COLUMN_DEFAULT AS definition, GENERATION_EXPRESSION AS ${dialect.quoteIdent({ name: "generated" })}, EXTRA AS extra, COLLATION_NAME AS collation FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ${namespace} AND TABLE_NAME = ${name} AND COLUMN_NAME = ${collector.add(object.column)}`;
|
|
2797
2982
|
break;
|
|
2798
2983
|
case "constraint":
|
|
2799
2984
|
if (object.constraintType === "exclusion")
|
|
2800
|
-
throw
|
|
2985
|
+
throw unsupportedCapability16({ dialect: "mysql", feature: "exclusionConstraints" });
|
|
2801
2986
|
text = `SELECT tc.CONSTRAINT_TYPE AS type, tc.ENFORCED AS enforced, cc.CHECK_CLAUSE AS definition, rc.UPDATE_RULE AS onUpdate, rc.DELETE_RULE AS onDelete, rc.MATCH_OPTION AS matchOption FROM information_schema.TABLE_CONSTRAINTS tc LEFT JOIN information_schema.CHECK_CONSTRAINTS cc ON cc.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA AND cc.CONSTRAINT_NAME = tc.CONSTRAINT_NAME LEFT JOIN information_schema.REFERENTIAL_CONSTRAINTS rc ON rc.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA AND rc.TABLE_NAME = tc.TABLE_NAME AND rc.CONSTRAINT_NAME = tc.CONSTRAINT_NAME WHERE tc.TABLE_SCHEMA = ${namespace} AND tc.TABLE_NAME = ${name} AND tc.CONSTRAINT_NAME = ${collector.add(object.name)}`;
|
|
2802
2987
|
break;
|
|
2803
2988
|
case "index":
|
|
@@ -2807,15 +2992,15 @@ function renderMigrationObjectQuery(params) {
|
|
|
2807
2992
|
text = `SELECT TABLE_TYPE AS type, ENGINE AS engine, TABLE_COLLATION AS collation FROM information_schema.TABLES WHERE TABLE_SCHEMA = ${namespace} AND TABLE_NAME = ${name}`;
|
|
2808
2993
|
break;
|
|
2809
2994
|
default:
|
|
2810
|
-
throw
|
|
2995
|
+
throw unsupportedCapability16({ dialect: "mysql", feature: `inspect:${object.kind}` });
|
|
2811
2996
|
}
|
|
2812
2997
|
} else {
|
|
2813
2998
|
if (physical.namespace !== "main" && physical.namespace !== "temp")
|
|
2814
|
-
throw
|
|
2999
|
+
throw unsupportedCapability16({ dialect: "sqlite", feature: "attachedSchemaInspection" });
|
|
2815
3000
|
const catalog = `${dialect.quoteIdent({ name: physical.namespace })}.sqlite_schema`;
|
|
2816
3001
|
const kind = object.kind === "table" || object.kind === "view" ? object.kind : object.kind === "trigger" ? "trigger" : object.kind === "index" ? "index" : "table";
|
|
2817
3002
|
if (["function", "sequence", "postgresExtension", "enum"].includes(object.kind) || object.kind === "constraint" && object.constraintType === "exclusion")
|
|
2818
|
-
throw
|
|
3003
|
+
throw unsupportedCapability16({ dialect: "sqlite", feature: `inspect:${object.kind}` });
|
|
2819
3004
|
const sqliteParams = new ParamCollector(dialect);
|
|
2820
3005
|
if (object.kind === "column" || object.kind === "columnDefault" || object.kind === "generatedColumn") {
|
|
2821
3006
|
text = `SELECT x.type AS type, x."notnull" AS "notNull", x.pk AS primaryKeyPosition, x.hidden AS generated, x.dflt_value AS definition, (SELECT sql FROM ${catalog} WHERE name = ${sqliteParams.add(physical.name)} AND type = 'table') AS tableDefinition FROM pragma_table_xinfo(${sqliteParams.add(physical.name)}, ${sqliteParams.add(physical.namespace)}) x WHERE x.name = ${sqliteParams.add(object.column)}`;
|
|
@@ -2841,11 +3026,14 @@ function renderMysqlObjectMembers(params) {
|
|
|
2841
3026
|
return { text, values: collector.values, returning: "none" };
|
|
2842
3027
|
}
|
|
2843
3028
|
function renderMigrationDependencies(params) {
|
|
3029
|
+
return dependencyQuery({ ...params, collector: new ParamCollector(params.dialect) });
|
|
3030
|
+
}
|
|
3031
|
+
function dependencyQuery(params) {
|
|
2844
3032
|
if (params.dialect.name !== "postgres")
|
|
2845
|
-
throw
|
|
3033
|
+
throw unsupportedCapability16({ dialect: params.dialect.name, feature: "catalogDependencies" });
|
|
2846
3034
|
const object = params.identity;
|
|
2847
3035
|
const physical = "table" in object ? object.table : object.name;
|
|
2848
|
-
const collector =
|
|
3036
|
+
const collector = params.collector;
|
|
2849
3037
|
const namespace = collector.add(physical.namespace);
|
|
2850
3038
|
const name = collector.add(physical.name);
|
|
2851
3039
|
const relation = `SELECT c.oid FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname = ${namespace} AND c.relname = ${name}`;
|
|
@@ -2885,6 +3073,41 @@ function renderMigrationDependencies(params) {
|
|
|
2885
3073
|
}
|
|
2886
3074
|
return { text: `SELECT DISTINCT json_build_array(d.deptype, a.type, a.object_names, a.object_args)::text AS address FROM (${source}) s JOIN pg_catalog.pg_depend d ON d.classid = s.classid AND d.objid = s.objid AND d.objsubid = s.objsubid CROSS JOIN LATERAL pg_catalog.pg_identify_object_as_address(d.refclassid, d.refobjid, d.refobjsubid) a ORDER BY address`, values: collector.values, returning: "none" };
|
|
2887
3075
|
}
|
|
3076
|
+
function inspectionReferences(params) {
|
|
3077
|
+
const values = [];
|
|
3078
|
+
return { values, add(value) {
|
|
3079
|
+
values.push(value);
|
|
3080
|
+
return `request.${params.dialect.quoteIdent({ name: `p${values.length}` })}`;
|
|
3081
|
+
} };
|
|
3082
|
+
}
|
|
3083
|
+
function renderMigrationObjectBatch(params) {
|
|
3084
|
+
const { dialect } = params;
|
|
3085
|
+
if (dialect.name !== "postgres")
|
|
3086
|
+
throw unsupportedCapability16({ dialect: dialect.name, feature: "batchedMigrationInspection" });
|
|
3087
|
+
const groups = new Map;
|
|
3088
|
+
for (const [position, identity] of params.identities.entries()) {
|
|
3089
|
+
const kind = identity.kind === "constraint" ? `${identity.kind}:${identity.constraintType}` : identity.kind === "generatedColumn" ? "columnDefault" : identity.kind;
|
|
3090
|
+
const group = groups.get(kind) ?? [];
|
|
3091
|
+
group.push({ identity, position });
|
|
3092
|
+
groups.set(kind, group);
|
|
3093
|
+
}
|
|
3094
|
+
return [...groups.values()].map((group) => {
|
|
3095
|
+
const identity = group[0].identity;
|
|
3096
|
+
const facts = objectQuery({ dialect, identity, collector: inspectionReferences({ dialect }) });
|
|
3097
|
+
const dependencies = dependencyQuery({ dialect, identity, collector: inspectionReferences({ dialect }) });
|
|
3098
|
+
if (JSON.stringify(dependencies.values) !== JSON.stringify(facts.values))
|
|
3099
|
+
throw internalError3({ message: "Batched catalog queries bind their identity in different orders", meta: { kind: identity.kind } });
|
|
3100
|
+
const columns = facts.values.map((value, index) => `${dialect.quoteIdent({ name: `p${index + 1}` })} ${Array.isArray(value) ? "text[]" : "text"}`);
|
|
3101
|
+
const requests = group.map(({ identity, position }) => ({ position, ...Object.fromEntries(renderMigrationObjectQuery({ dialect, identity }).values.map((value, index) => [`p${index + 1}`, value])) }));
|
|
3102
|
+
const collector = new ParamCollector(dialect);
|
|
3103
|
+
return {
|
|
3104
|
+
text: `SELECT request.position, to_jsonb(facts) AS facts, ARRAY(SELECT address FROM (${dependencies.text}) dependency ORDER BY address) AS "dependencyAddresses" FROM jsonb_to_recordset(${collector.add(JSON.stringify(requests))}::text::jsonb) AS request(position integer, ${columns.join(", ")}) CROSS JOIN LATERAL (${facts.text}) facts`,
|
|
3105
|
+
values: collector.values,
|
|
3106
|
+
returning: "none",
|
|
3107
|
+
positions: group.map(({ position }) => position)
|
|
3108
|
+
};
|
|
3109
|
+
});
|
|
3110
|
+
}
|
|
2888
3111
|
function renderMigrationServerVersion(params) {
|
|
2889
3112
|
return { text: params.dialect.name === "sqlite" ? "SELECT sqlite_version() AS version" : "SELECT version() AS version", values: [], returning: "none" };
|
|
2890
3113
|
}
|
|
@@ -2893,16 +3116,16 @@ function renderMigrationNamespace(params) {
|
|
|
2893
3116
|
}
|
|
2894
3117
|
function renderCheckProbe(params) {
|
|
2895
3118
|
if (params.dialect.name !== "postgres")
|
|
2896
|
-
throw
|
|
3119
|
+
throw unsupportedCapability16({ dialect: params.dialect.name, feature: "rollbackCheckProbe" });
|
|
2897
3120
|
const q = (name) => params.dialect.quoteIdent({ name });
|
|
2898
3121
|
return { text: `ALTER TABLE ${q(params.table.namespace)}.${q(params.table.name)} ADD CONSTRAINT ${q(params.name)} CHECK (${params.expression}) NOT VALID`, values: [], returning: "none" };
|
|
2899
3122
|
}
|
|
2900
3123
|
// packages/sql/src/dialects/postgres-migration.ts
|
|
2901
|
-
import { VibeError as
|
|
3124
|
+
import { VibeError as VibeError10, unsupportedCapability as unsupportedCapability17 } from "@vibeorm/schema";
|
|
2902
3125
|
var SETTING_VALUE = /^[0-9]+(?:\.[0-9]+)?\s*(?:us|ms|s|min|h|d)?$/;
|
|
2903
3126
|
function requirePostgres2(params) {
|
|
2904
3127
|
if (params.dialect.name !== "postgres") {
|
|
2905
|
-
throw
|
|
3128
|
+
throw unsupportedCapability17({ dialect: params.dialect.name, feature: params.feature });
|
|
2906
3129
|
}
|
|
2907
3130
|
}
|
|
2908
3131
|
function renderMigrationSessionRead(params) {
|
|
@@ -2917,7 +3140,7 @@ function renderMigrationSessionSet(params) {
|
|
|
2917
3140
|
requirePostgres2({ dialect: params.dialect, feature: "migrationSessionSettings" });
|
|
2918
3141
|
const { milliseconds, setting } = params;
|
|
2919
3142
|
if (!Number.isSafeInteger(milliseconds) || milliseconds < 0) {
|
|
2920
|
-
throw new
|
|
3143
|
+
throw new VibeError10({
|
|
2921
3144
|
code: "VIBE_MIGRATION",
|
|
2922
3145
|
message: `${setting} must be a non-negative integer number of milliseconds (got ${String(milliseconds)})`,
|
|
2923
3146
|
meta: { reason: "execution-metadata-invalid", setting, value: milliseconds }
|
|
@@ -3005,113 +3228,122 @@ WHERE n.nspname = pg_catalog.current_schema() AND c.relname = ${table} AND a.att
|
|
|
3005
3228
|
};
|
|
3006
3229
|
}
|
|
3007
3230
|
export {
|
|
3008
|
-
|
|
3009
|
-
strictMatchPattern,
|
|
3010
|
-
startsWithPattern,
|
|
3011
|
-
sqliteTableConstraints,
|
|
3012
|
-
sqliteDialect,
|
|
3013
|
-
sqliteColumnClauses,
|
|
3014
|
-
sqlUsesIncoming,
|
|
3015
|
-
sql,
|
|
3016
|
-
renderStatement,
|
|
3017
|
-
renderSqliteRebuildObjects,
|
|
3018
|
-
renderSqliteForeignKeyInventory,
|
|
3019
|
-
renderSqliteColumnInventory,
|
|
3020
|
-
renderSqlFragment,
|
|
3021
|
-
renderRowLockClause,
|
|
3022
|
-
renderRlsRole,
|
|
3023
|
-
renderRlsReadinessQuery,
|
|
3024
|
-
renderRlsProbeTable,
|
|
3025
|
-
renderRlsPredicate,
|
|
3026
|
-
renderRlsPolicyPath,
|
|
3027
|
-
renderRlsPolicy,
|
|
3028
|
-
renderRlsNoForce,
|
|
3029
|
-
renderRlsForce,
|
|
3030
|
-
renderRlsEnable,
|
|
3031
|
-
renderRlsDropPolicy,
|
|
3032
|
-
renderRlsDisable,
|
|
3033
|
-
renderRlsContext,
|
|
3034
|
-
renderRlsColumnType,
|
|
3035
|
-
renderRelationStateQuery,
|
|
3036
|
-
renderPredicate,
|
|
3037
|
-
renderPostgresWorkload,
|
|
3038
|
-
renderPostgresExplain,
|
|
3039
|
-
renderPostgresDefaultFunctionIdentity,
|
|
3040
|
-
renderMysqlObjectMembers,
|
|
3041
|
-
renderMysqlCheckProbe,
|
|
3042
|
-
renderModuleJournal,
|
|
3043
|
-
renderMigrationVisibility,
|
|
3044
|
-
renderMigrationSessionSet,
|
|
3045
|
-
renderMigrationSessionRestore,
|
|
3046
|
-
renderMigrationSessionRead,
|
|
3047
|
-
renderMigrationServerVersion,
|
|
3048
|
-
renderMigrationObjectQuery,
|
|
3049
|
-
renderMigrationNamespace,
|
|
3050
|
-
renderMigrationInventory,
|
|
3051
|
-
renderMigrationHistoryQuery,
|
|
3052
|
-
renderMigrationDependencies,
|
|
3053
|
-
renderIndexStateQuery,
|
|
3054
|
-
renderFragment,
|
|
3055
|
-
renderExpr,
|
|
3056
|
-
renderExclusionSetup,
|
|
3057
|
-
renderExclusionProbe,
|
|
3058
|
-
renderExclusionDdl,
|
|
3059
|
-
renderExclusionCatalog,
|
|
3060
|
-
renderDiagnostic,
|
|
3061
|
-
renderConstraintStateQuery,
|
|
3062
|
-
renderConstraintOwnedIndexDrop,
|
|
3063
|
-
renderColumnStateQuery,
|
|
3064
|
-
renderCheckProbe,
|
|
3065
|
-
renderAdvisoryLock,
|
|
3066
|
-
projectionOutputName,
|
|
3067
|
-
postgresDialect,
|
|
3068
|
-
parsePgArrayLiteral,
|
|
3069
|
-
parseDateTimeText,
|
|
3070
|
-
mysqlDialect,
|
|
3071
|
-
mapConflictColumns,
|
|
3072
|
-
jsonParamCell,
|
|
3073
|
-
isSqlFragment,
|
|
3074
|
-
isSqlDefaultCell,
|
|
3075
|
-
isSetOperation,
|
|
3076
|
-
isListSetOperation,
|
|
3077
|
-
isJsonParamCell,
|
|
3078
|
-
isFixedDiagnostic,
|
|
3079
|
-
isExcludedRef,
|
|
3080
|
-
isDbNowMarker,
|
|
3081
|
-
getSqlDialect,
|
|
3082
|
-
excludedRef,
|
|
3083
|
-
escapeLikePattern,
|
|
3084
|
-
escapeGlobPattern,
|
|
3085
|
-
enumMembershipCodec,
|
|
3086
|
-
endsWithPattern,
|
|
3087
|
-
describeRowLock,
|
|
3088
|
-
decodeIsNoop,
|
|
3089
|
-
decode,
|
|
3090
|
-
dbNowMarker,
|
|
3091
|
-
containsPattern,
|
|
3092
|
-
compileSql,
|
|
3093
|
-
compileExclusion,
|
|
3094
|
-
SQL_DIALECTS,
|
|
3095
|
-
SQL_DEFAULT_CELL,
|
|
3096
|
-
SQLITE_SESSION_SQL,
|
|
3097
|
-
SQLITE_CODECS,
|
|
3098
|
-
SQLITE_CAPABILITIES,
|
|
3099
|
-
RLS_READINESS_SQL,
|
|
3100
|
-
ParamCollector,
|
|
3101
|
-
POSTGRES_WORKLOAD_LIMITS,
|
|
3102
|
-
POSTGRES_DIAGNOSTIC_SQL,
|
|
3103
|
-
POSTGRES_CODECS,
|
|
3104
|
-
POSTGRES_CAPABILITIES,
|
|
3105
|
-
NATIVE_RLS_PROBE_POLICY,
|
|
3106
|
-
NATIVE_RLS,
|
|
3107
|
-
MYSQL_CODECS,
|
|
3108
|
-
MYSQL_CAPABILITIES,
|
|
3109
|
-
MODULE_JOURNAL_COLUMN,
|
|
3110
|
-
JSON_TRANSPORT,
|
|
3111
|
-
DIALECT_CODECS,
|
|
3112
|
-
DIALECT_CAPABILITIES,
|
|
3231
|
+
ADVISORY_KEY_BOUNDS,
|
|
3113
3232
|
ADVISORY_LOCK_RESULT_COLUMN,
|
|
3114
|
-
|
|
3233
|
+
DIALECT_CAPABILITIES,
|
|
3234
|
+
DIALECT_CODECS,
|
|
3235
|
+
JSON_TRANSPORT,
|
|
3236
|
+
MODULE_JOURNAL_COLUMN,
|
|
3237
|
+
MYSQL_CAPABILITIES,
|
|
3238
|
+
MYSQL_CODECS,
|
|
3239
|
+
NATIVE_RLS,
|
|
3240
|
+
NATIVE_RLS_PROBE_POLICY,
|
|
3241
|
+
POSTGRES_CAPABILITIES,
|
|
3242
|
+
POSTGRES_CODECS,
|
|
3243
|
+
POSTGRES_DIAGNOSTIC_SQL,
|
|
3244
|
+
POSTGRES_WORKLOAD_LIMITS,
|
|
3245
|
+
ParamCollector,
|
|
3246
|
+
RLS_READINESS_SQL,
|
|
3247
|
+
SHADOW_CAPABILITIES,
|
|
3248
|
+
SHADOW_DATABASE,
|
|
3249
|
+
SQLITE_CAPABILITIES,
|
|
3250
|
+
SQLITE_CODECS,
|
|
3251
|
+
SQLITE_SESSION_SQL,
|
|
3252
|
+
SQL_DEFAULT_CELL,
|
|
3253
|
+
SQL_DIALECTS,
|
|
3254
|
+
compileExclusion,
|
|
3255
|
+
compileSql,
|
|
3256
|
+
containsPattern,
|
|
3257
|
+
dbNowMarker,
|
|
3258
|
+
decode,
|
|
3259
|
+
decodeIsNoop,
|
|
3260
|
+
describeRowLock,
|
|
3261
|
+
endsWithPattern,
|
|
3262
|
+
enumMembershipCodec,
|
|
3263
|
+
escapeGlobPattern,
|
|
3264
|
+
escapeLikePattern,
|
|
3265
|
+
excludedRef,
|
|
3266
|
+
getSqlDialect,
|
|
3267
|
+
isDbNowMarker,
|
|
3268
|
+
isExcludedRef,
|
|
3269
|
+
isFixedDiagnostic,
|
|
3270
|
+
isJsonParamCell,
|
|
3271
|
+
isListSetOperation,
|
|
3272
|
+
isSetOperation,
|
|
3273
|
+
isSqlDefaultCell,
|
|
3274
|
+
isSqlFragment,
|
|
3275
|
+
jsonParamCell,
|
|
3276
|
+
mapConflictColumns,
|
|
3277
|
+
mysqlDialect,
|
|
3278
|
+
parseDateTimeText,
|
|
3279
|
+
parsePgArrayLiteral,
|
|
3280
|
+
parsePostgresTypeName,
|
|
3281
|
+
postgresDialect,
|
|
3282
|
+
projectionOutputName,
|
|
3283
|
+
renderAdvisoryLock,
|
|
3284
|
+
renderCheckProbe,
|
|
3285
|
+
renderColumnStateQuery,
|
|
3286
|
+
renderConstraintOwnedIndexDrop,
|
|
3287
|
+
renderConstraintStateQuery,
|
|
3288
|
+
renderDiagnostic,
|
|
3289
|
+
renderExclusionCatalog,
|
|
3290
|
+
renderExclusionDdl,
|
|
3291
|
+
renderExclusionProbe,
|
|
3292
|
+
renderExclusionSetup,
|
|
3293
|
+
renderExpr,
|
|
3294
|
+
renderFragment,
|
|
3295
|
+
renderIndexStateQuery,
|
|
3296
|
+
renderMigrationDependencies,
|
|
3297
|
+
renderMigrationHistoryQuery,
|
|
3298
|
+
renderMigrationInventory,
|
|
3299
|
+
renderMigrationNamespace,
|
|
3300
|
+
renderMigrationObjectBatch,
|
|
3301
|
+
renderMigrationObjectQuery,
|
|
3302
|
+
renderMigrationServerVersion,
|
|
3303
|
+
renderMigrationSessionRead,
|
|
3304
|
+
renderMigrationSessionRestore,
|
|
3305
|
+
renderMigrationSessionSet,
|
|
3306
|
+
renderMigrationVisibility,
|
|
3307
|
+
renderModuleDependencyQuery,
|
|
3308
|
+
renderModuleJournal,
|
|
3309
|
+
renderMysqlCheckProbe,
|
|
3310
|
+
renderMysqlObjectMembers,
|
|
3311
|
+
renderPostgresDefaultFunctionIdentity,
|
|
3312
|
+
renderPostgresExplain,
|
|
3313
|
+
renderPostgresTypeIdentity,
|
|
3314
|
+
renderPostgresTypeName,
|
|
3315
|
+
renderPostgresWorkload,
|
|
3316
|
+
renderPredicate,
|
|
3317
|
+
renderRelationStateQuery,
|
|
3318
|
+
renderReplayCoverageGaps,
|
|
3319
|
+
renderRlsColumnType,
|
|
3320
|
+
renderRlsContext,
|
|
3321
|
+
renderRlsDisable,
|
|
3322
|
+
renderRlsDropPolicy,
|
|
3323
|
+
renderRlsEnable,
|
|
3324
|
+
renderRlsForce,
|
|
3325
|
+
renderRlsNoForce,
|
|
3326
|
+
renderRlsPolicy,
|
|
3327
|
+
renderRlsPolicyPath,
|
|
3328
|
+
renderRlsPredicate,
|
|
3329
|
+
renderRlsProbeTable,
|
|
3330
|
+
renderRlsReadinessQuery,
|
|
3331
|
+
renderRlsRole,
|
|
3332
|
+
renderRowLockClause,
|
|
3333
|
+
renderShadowOperation,
|
|
3334
|
+
renderSqlFragment,
|
|
3335
|
+
renderSqliteColumnInventory,
|
|
3336
|
+
renderSqliteForeignKeyInventory,
|
|
3337
|
+
renderSqliteRebuildObjects,
|
|
3338
|
+
renderStatement,
|
|
3339
|
+
sql,
|
|
3340
|
+
sqlUsesIncoming,
|
|
3341
|
+
sqliteColumnClauses,
|
|
3342
|
+
sqliteDialect,
|
|
3343
|
+
sqliteTableConstraints,
|
|
3344
|
+
startsWithPattern,
|
|
3345
|
+
strictMatchPattern,
|
|
3346
|
+
toPgArrayLiteral
|
|
3115
3347
|
};
|
|
3116
3348
|
|
|
3117
|
-
//# debugId=
|
|
3349
|
+
//# debugId=C1F0ADA45113049064756E2164756E21
|