@vibeorm/sql 4.3.0 → 5.0.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/dist/ast.d.ts +101 -8
- package/dist/codecs.d.ts +44 -0
- package/dist/dialect.d.ts +52 -4
- package/dist/dialects/migration-inventory.d.ts +58 -1
- package/dist/dialects/migration-objects.d.ts +36 -0
- package/dist/dialects/migration-visibility.d.ts +6 -1
- package/dist/dialects/mysql.d.ts +3 -2
- package/dist/dialects/postgres-rls.d.ts +16 -1
- package/dist/index.d.ts +7 -6
- package/dist/index.js +314 -81
- package/dist/index.js.map +12 -12
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -317,6 +317,7 @@ var mysqlDecimalCodec = {
|
|
|
317
317
|
};
|
|
318
318
|
var ZONE_LESS_DATETIME = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}(?::\d{2}(?:\.\d{1,9})?)?$/;
|
|
319
319
|
var PG_ZONED_DATETIME = /^(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2}(?::\d{2})?)(\.\d{1,9})?([+-]\d{2})(?::?(\d{2}))?$/;
|
|
320
|
+
var EXTENDED_DATETIME = /^(\d{4,})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,9}))?)?)?(?:([+-])(\d{2})(?::?(\d{2}))?(?::?(\d{2}))?)?( BC)?$/;
|
|
320
321
|
function parseDateTimeText(params) {
|
|
321
322
|
const trimmed = params.text.trim();
|
|
322
323
|
const date = parseDateTimeInstant({ trimmed });
|
|
@@ -341,11 +342,34 @@ function parseDateTimeInstant(params) {
|
|
|
341
342
|
if (!Number.isNaN(iso.getTime()))
|
|
342
343
|
return iso;
|
|
343
344
|
}
|
|
345
|
+
const extended = parseExtendedDateTimeText({ text: trimmed });
|
|
346
|
+
if (extended !== undefined)
|
|
347
|
+
return extended;
|
|
344
348
|
const parsed = new Date(trimmed);
|
|
345
349
|
return Number.isNaN(parsed.getTime()) ? undefined : parsed;
|
|
346
350
|
}
|
|
351
|
+
function parseExtendedDateTimeText(params) {
|
|
352
|
+
const match = EXTENDED_DATETIME.exec(params.text.trim());
|
|
353
|
+
if (match === null)
|
|
354
|
+
return;
|
|
355
|
+
const [, yearText, month, day, hours, minutes, seconds, fraction, sign, offsetHours, offsetMinutes, offsetSeconds, era] = match;
|
|
356
|
+
if (yearText.length < 5 && era === undefined)
|
|
357
|
+
return;
|
|
358
|
+
const year = era === undefined ? Number(yearText) : 1 - Number(yearText);
|
|
359
|
+
const date = new Date(0);
|
|
360
|
+
date.setUTCFullYear(year, Number(month) - 1, Number(day));
|
|
361
|
+
date.setUTCHours(Number(hours ?? 0), Number(minutes ?? 0), Number(seconds ?? 0), Number((fraction ?? "").padEnd(3, "0").slice(0, 3)));
|
|
362
|
+
if (sign !== undefined) {
|
|
363
|
+
const offset = (Number(offsetHours) * 3600 + Number(offsetMinutes ?? 0) * 60 + Number(offsetSeconds ?? 0)) * 1000;
|
|
364
|
+
date.setTime(date.getTime() - (sign === "-" ? -offset : offset));
|
|
365
|
+
}
|
|
366
|
+
return Number.isNaN(date.getTime()) ? undefined : date;
|
|
367
|
+
}
|
|
368
|
+
function decodedDateTimeRefusal() {
|
|
369
|
+
return new VibeError({ code: "VIBE_DATA_INVALID", message: "DateTime requires a finite timestamp; use an explicit extended timestamp decoder for infinity" });
|
|
370
|
+
}
|
|
347
371
|
function invalidDecodedDateTime() {
|
|
348
|
-
throw
|
|
372
|
+
throw decodedDateTimeRefusal();
|
|
349
373
|
}
|
|
350
374
|
var dateNativeCodec = {
|
|
351
375
|
encode: (value) => {
|
|
@@ -2330,6 +2354,8 @@ var sqliteDialect = {
|
|
|
2330
2354
|
keyListStrategy: "values",
|
|
2331
2355
|
keysetSeekStrategy: "rowValue",
|
|
2332
2356
|
keyPageStrategy: "inLimit",
|
|
2357
|
+
lateralJson: null,
|
|
2358
|
+
relationStrategyDefault: "query",
|
|
2333
2359
|
relationFilterStrategy: "inSelect",
|
|
2334
2360
|
deferredJoinPage: null,
|
|
2335
2361
|
nativeNullsOrder: "low",
|
|
@@ -2842,6 +2868,10 @@ function isDbNowMarker(value) {
|
|
|
2842
2868
|
return candidate.__dbNow === true && typeof candidate.offsetSeconds === "number" && Number.isFinite(candidate.offsetSeconds);
|
|
2843
2869
|
}
|
|
2844
2870
|
var SQL_DEFAULT_CELL = Object.freeze({ __sqlDefault: true });
|
|
2871
|
+
var SQL_KEEP_CELL = Object.freeze({ __sqlKeep: true });
|
|
2872
|
+
function isSqlKeepCell(value) {
|
|
2873
|
+
return value === SQL_KEEP_CELL;
|
|
2874
|
+
}
|
|
2845
2875
|
function isSqlDefaultCell(value) {
|
|
2846
2876
|
return value === SQL_DEFAULT_CELL;
|
|
2847
2877
|
}
|
|
@@ -2979,6 +3009,8 @@ var postgresDialect = {
|
|
|
2979
3009
|
keyListStrategy: "unnest",
|
|
2980
3010
|
keysetSeekStrategy: "rowValue",
|
|
2981
3011
|
keyPageStrategy: "lateral",
|
|
3012
|
+
lateralJson: { rowArray: "json_build_array", arrayAgg: "json_agg", emptyArray: "'[]'::json", order: "inAggregate", timeOfDayAsText: false, requiresUtcDateTimeWire: false },
|
|
3013
|
+
relationStrategyDefault: "join",
|
|
2982
3014
|
relationFilterStrategy: "exists",
|
|
2983
3015
|
deferredJoinPage: { minSkip: 1000, requiresCoveringIndex: true },
|
|
2984
3016
|
nativeNullsOrder: "high",
|
|
@@ -3064,6 +3096,8 @@ var mysqlDialect = {
|
|
|
3064
3096
|
keyListStrategy: "rowValue",
|
|
3065
3097
|
keysetSeekStrategy: "or",
|
|
3066
3098
|
keyPageStrategy: "window",
|
|
3099
|
+
lateralJson: { rowArray: "JSON_ARRAY", arrayAgg: "JSON_ARRAYAGG", emptyArray: "JSON_ARRAY()", order: "positionSlot", timeOfDayAsText: true, requiresUtcDateTimeWire: true },
|
|
3100
|
+
relationStrategyDefault: "join",
|
|
3067
3101
|
relationFilterStrategy: "exists",
|
|
3068
3102
|
deferredJoinPage: { minSkip: 1000, requiresCoveringIndex: false },
|
|
3069
3103
|
nativeNullsOrder: "low",
|
|
@@ -3077,7 +3111,7 @@ var mysqlDialect = {
|
|
|
3077
3111
|
duplicatesInOneStatement: "lastWriteWins"
|
|
3078
3112
|
},
|
|
3079
3113
|
excludedRowRef: { form: "rowAlias", alias: "new" },
|
|
3080
|
-
doNothingForm: "
|
|
3114
|
+
doNothingForm: "duplicateKeyKeep",
|
|
3081
3115
|
insensitiveLike: "lower",
|
|
3082
3116
|
strictMatchStrategy: "binary",
|
|
3083
3117
|
greatestForm: "wrapped-frame",
|
|
@@ -3752,11 +3786,14 @@ function renderRlsPolicy(params) {
|
|
|
3752
3786
|
}
|
|
3753
3787
|
function renderRlsContext(params) {
|
|
3754
3788
|
requireRls(params);
|
|
3755
|
-
|
|
3789
|
+
const extra = params.role !== undefined || params.readOnly === true || params.backend === true;
|
|
3790
|
+
if (validateRlsContextIR({ context: params.context }).length !== 0 || Object.keys(params.context).length === 0 && !extra || typeof params.values !== "object" || params.values === null || Array.isArray(params.values)) {
|
|
3756
3791
|
throw new RlsContextError({ reason: "invalid" });
|
|
3757
3792
|
}
|
|
3758
3793
|
const collector = new ParamCollector(params.dialect);
|
|
3759
3794
|
const parts = [];
|
|
3795
|
+
if (params.role !== undefined)
|
|
3796
|
+
parts.push(`set_config('role', ${collector.add(runtimeRoleOf({ role: params.role }))}, true)`);
|
|
3760
3797
|
for (const [key, slot] of Object.entries(params.context)) {
|
|
3761
3798
|
if (!Object.hasOwn(params.values, key))
|
|
3762
3799
|
throw new RlsContextError({ reason: "missing", key });
|
|
@@ -3770,15 +3807,24 @@ function renderRlsContext(params) {
|
|
|
3770
3807
|
if (typeof key !== "string" || !Object.hasOwn(params.context, key))
|
|
3771
3808
|
throw new RlsContextError({ reason: "invalid" });
|
|
3772
3809
|
}
|
|
3810
|
+
if (params.readOnly === true)
|
|
3811
|
+
parts.push("set_config('transaction_read_only', 'on', true)");
|
|
3812
|
+
if (params.backend === true) {
|
|
3813
|
+
parts.push(`pg_catalog.pg_backend_pid()::text AS ${identifier2({ dialect: params.dialect, name: "backendPid" })}`, `(SELECT a.backend_start::text FROM pg_catalog.pg_stat_activity a WHERE a.pid = pg_catalog.pg_backend_pid()) AS ${identifier2({ dialect: params.dialect, name: "backendStart" })}`);
|
|
3814
|
+
}
|
|
3773
3815
|
return query({ text: `SELECT ${parts.join(", ")}`, values: collector.values });
|
|
3774
3816
|
}
|
|
3775
|
-
function
|
|
3776
|
-
requireRls(params);
|
|
3817
|
+
function runtimeRoleOf(params) {
|
|
3777
3818
|
if (typeof params.role !== "string" || params.role.trim().length === 0 || params.role.includes("\x00")) {
|
|
3778
3819
|
throw new VibeError22({ code: "VIBE_CONFIG", message: "PGlite native RLS requires a trusted nonempty runtime role name" });
|
|
3779
3820
|
}
|
|
3821
|
+
return params.role;
|
|
3822
|
+
}
|
|
3823
|
+
function renderRlsRole(params) {
|
|
3824
|
+
requireRls(params);
|
|
3825
|
+
const role = runtimeRoleOf({ role: params.role });
|
|
3780
3826
|
const collector = new ParamCollector(params.dialect);
|
|
3781
|
-
return query({ text: `SELECT set_config('role', ${collector.add(
|
|
3827
|
+
return query({ text: `SELECT set_config('role', ${collector.add(role)}, true)`, values: collector.values });
|
|
3782
3828
|
}
|
|
3783
3829
|
|
|
3784
3830
|
// packages/sql/src/dialects/postgres-rls-readiness.ts
|
|
@@ -4037,7 +4083,7 @@ function renderStatement(params) {
|
|
|
4037
4083
|
case "rlsPolicy":
|
|
4038
4084
|
return renderRlsPolicy({ dialect, ...statement });
|
|
4039
4085
|
case "rlsContext":
|
|
4040
|
-
return renderRlsContext({ dialect,
|
|
4086
|
+
return renderRlsContext({ dialect, ...statement });
|
|
4041
4087
|
case "rlsRole":
|
|
4042
4088
|
return renderRlsRole({ dialect, role: statement.role });
|
|
4043
4089
|
}
|
|
@@ -4090,9 +4136,13 @@ function quoteProjection(dialect, column) {
|
|
|
4090
4136
|
const alias = dialect.quoteIdent({ name: column.alias ?? column.name });
|
|
4091
4137
|
if (column.transform === "castText")
|
|
4092
4138
|
return `${textProjection({ dialect, expression: ref })} AS ${alias}`;
|
|
4139
|
+
if (column.transform === "encodeBase64" && dialect.name === "mysql")
|
|
4140
|
+
return `TO_BASE64(${ref}) AS ${alias}`;
|
|
4093
4141
|
if (dialect.name !== "postgres") {
|
|
4094
|
-
throw internalError3({ message:
|
|
4142
|
+
throw internalError3({ message: `${column.transform} is a postgres construct` });
|
|
4095
4143
|
}
|
|
4144
|
+
if (column.transform === "encodeArrayBase64")
|
|
4145
|
+
return `encode(array_send(${ref}), 'base64') AS ${alias}`;
|
|
4096
4146
|
return `encode(${ref}, 'base64') AS ${alias}`;
|
|
4097
4147
|
}
|
|
4098
4148
|
function textProjection(params) {
|
|
@@ -4494,6 +4544,35 @@ function renderKeyPage(params) {
|
|
|
4494
4544
|
});
|
|
4495
4545
|
return `SELECT ${[...projection, rank].join(", ")} FROM (VALUES ${tuples.join(", ")}) AS ${keys} INNER JOIN ${rows} ON ${membership}`;
|
|
4496
4546
|
}
|
|
4547
|
+
function renderKeyRows(params) {
|
|
4548
|
+
const { dialect, statement, keys, collector } = params;
|
|
4549
|
+
if (statement.fromSelect !== undefined || statement.keyPage !== undefined || statement.fromUnion !== undefined || statement.table.alias !== undefined) {
|
|
4550
|
+
throw internalError3({ message: "fromKeys uses table.name as the derived-table alias \u2014 fromSelect, keyPage, fromUnion and table.alias must be unset" });
|
|
4551
|
+
}
|
|
4552
|
+
if (statement.rowLock !== undefined)
|
|
4553
|
+
throw internalError3({ message: "a locking read cannot read from key rows" });
|
|
4554
|
+
const arity = keys.columns.length;
|
|
4555
|
+
if (arity === 0 || keys.members.length !== arity) {
|
|
4556
|
+
throw internalError3({ message: `fromKeys has ${keys.members.length} members for ${arity} columns` });
|
|
4557
|
+
}
|
|
4558
|
+
if (keys.rows.length === 0)
|
|
4559
|
+
throw internalError3({ message: "fromKeys needs at least one key row" });
|
|
4560
|
+
for (const row of keys.rows) {
|
|
4561
|
+
if (row.length !== arity)
|
|
4562
|
+
throw internalError3({ message: `fromKeys row has ${row.length} values for ${arity} columns` });
|
|
4563
|
+
}
|
|
4564
|
+
if (dialect.keyListStrategy !== "unnest" || keyListBindsUntypedRows({ members: keys.members })) {
|
|
4565
|
+
throw unsupportedCapability27({
|
|
4566
|
+
dialect: dialect.name,
|
|
4567
|
+
feature: dialect.keyListStrategy !== "unnest" ? "a key-rows FROM (fromKeys)" : "a key-rows FROM over a DateTime key without a declared native type",
|
|
4568
|
+
hint: "the runtime keeps the per-relation loads for this write"
|
|
4569
|
+
});
|
|
4570
|
+
}
|
|
4571
|
+
const types = keys.members.map((member) => postgresKeyListElementType({ dialect, member }));
|
|
4572
|
+
const arrays = types.map((type, index) => `${collector.add(keys.rows.map((row) => row[index]))}::${type}[]`);
|
|
4573
|
+
const names = keys.columns.map((name) => dialect.quoteIdent({ name }));
|
|
4574
|
+
return `unnest(${arrays.join(", ")}) AS ${dialect.quoteIdent({ name: statement.table.name })} (${names.join(", ")})`;
|
|
4575
|
+
}
|
|
4497
4576
|
var UNION_BRANCH_MEMBERS = new Set(["kind", "table", "columns", "where", "orderBy", "limit"]);
|
|
4498
4577
|
function renderUnionPage(params) {
|
|
4499
4578
|
const { dialect, statement, collector } = params;
|
|
@@ -4679,22 +4758,31 @@ function renderSelectExpr(params) {
|
|
|
4679
4758
|
}
|
|
4680
4759
|
function renderPositionalRow(params) {
|
|
4681
4760
|
const { dialect, join, subAlias } = params;
|
|
4682
|
-
|
|
4761
|
+
const json = lateralJsonOf({ dialect });
|
|
4762
|
+
const position = join.select.rowNumber;
|
|
4763
|
+
const positioned = position !== undefined && json.order === "positionSlot" && join.agg === "jsonArray" && position.partitionBy.length === 0 && position.orderBy.length > 0;
|
|
4764
|
+
if (join.select.columns.length === 0 || join.select.selectExpr !== undefined || (join.select.aggregates?.length ?? 0) > 0 || position !== undefined && !positioned) {
|
|
4683
4765
|
throw internalError3({ message: "positional lateral rows require an explicit column-only projection" });
|
|
4684
4766
|
}
|
|
4685
|
-
const names = join.select.columns.map((column) => projectionOutputName({ column }));
|
|
4767
|
+
const names = [...join.select.columns.map((column) => projectionOutputName({ column })), ...positioned ? [position.alias] : []];
|
|
4686
4768
|
if (new Set(names).size !== names.length) {
|
|
4687
4769
|
throw internalError3({ message: "positional lateral projection has duplicate output names" });
|
|
4688
4770
|
}
|
|
4689
4771
|
const values = names.map((name) => `${subAlias}.${dialect.quoteIdent({ name })}`);
|
|
4690
4772
|
const chunks = [];
|
|
4691
4773
|
for (let index = 0;index < values.length; index += JSON_TRANSPORT.chunkSize) {
|
|
4692
|
-
chunks.push(
|
|
4774
|
+
chunks.push(`${json.rowArray}(${values.slice(index, index + JSON_TRANSPORT.chunkSize).join(", ")})`);
|
|
4693
4775
|
}
|
|
4694
4776
|
if (chunks.length > JSON_TRANSPORT.chunkSize) {
|
|
4695
4777
|
throw internalError3({ message: "positional lateral projection exceeds the transport width limit" });
|
|
4696
4778
|
}
|
|
4697
|
-
return chunks.length === 1 ? chunks[0] :
|
|
4779
|
+
return chunks.length === 1 ? chunks[0] : `${json.rowArray}(${chunks.join(", ")})`;
|
|
4780
|
+
}
|
|
4781
|
+
function lateralJsonOf(params) {
|
|
4782
|
+
const json = params.dialect.lateralJson;
|
|
4783
|
+
if (json === null)
|
|
4784
|
+
throw internalError3({ message: "lateral JSON rendering on a dialect without LATERAL" });
|
|
4785
|
+
return json;
|
|
4698
4786
|
}
|
|
4699
4787
|
function renderLateralJoin(params) {
|
|
4700
4788
|
const { dialect, join, collector } = params;
|
|
@@ -4707,8 +4795,9 @@ function renderLateralJoin(params) {
|
|
|
4707
4795
|
}
|
|
4708
4796
|
const columnAlias = dialect.quoteIdent({ name: join.columnAlias });
|
|
4709
4797
|
const subAlias = dialect.quoteIdent({ name: "__sub" });
|
|
4798
|
+
const json = lateralJsonOf({ dialect });
|
|
4710
4799
|
let aggOrder = "";
|
|
4711
|
-
if (join.agg === "jsonArray" && join.select.orderBy !== undefined && join.select.orderBy.length > 0) {
|
|
4800
|
+
if (json.order === "inAggregate" && join.agg === "jsonArray" && join.select.orderBy !== undefined && join.select.orderBy.length > 0) {
|
|
4712
4801
|
const projected = new Set(join.select.columns.filter((column) => column.transform === undefined && column.castReal !== true).map((column) => column.name));
|
|
4713
4802
|
const terms = join.select.orderBy;
|
|
4714
4803
|
const columnTerms = terms.filter((term) => ("column" in term));
|
|
@@ -4724,8 +4813,11 @@ function renderLateralJoin(params) {
|
|
|
4724
4813
|
aggOrder = ` ORDER BY ${rendered.join(", ")}`;
|
|
4725
4814
|
}
|
|
4726
4815
|
}
|
|
4816
|
+
if (join.rowFormat !== "positional" && json.order !== "inAggregate") {
|
|
4817
|
+
throw unsupportedCapability27({ dialect: dialect.name, feature: "object-format lateral rows", hint: 'lateral relation rows render positional (rowFormat "positional") on this dialect' });
|
|
4818
|
+
}
|
|
4727
4819
|
const rowJson = join.rowFormat === "positional" ? renderPositionalRow({ dialect, join, subAlias }) : `to_json(${subAlias}.*)`;
|
|
4728
|
-
const projection = join.agg === "jsonArray" ? `COALESCE(
|
|
4820
|
+
const projection = join.agg === "jsonArray" ? `COALESCE(${json.arrayAgg}(${rowJson}${aggOrder}), ${json.emptyArray}) AS ${columnAlias}` : `${rowJson} AS ${columnAlias}`;
|
|
4729
4821
|
const alias = dialect.quoteIdent({ name: join.alias });
|
|
4730
4822
|
return `LEFT JOIN LATERAL (SELECT ${projection} FROM (${inner.text}) AS ${subAlias}) AS ${alias} ON true`;
|
|
4731
4823
|
}
|
|
@@ -4848,12 +4940,12 @@ function renderSelect(params) {
|
|
|
4848
4940
|
}
|
|
4849
4941
|
if (statement.rowNumber !== undefined) {
|
|
4850
4942
|
const rowNumber = statement.rowNumber;
|
|
4851
|
-
if (rowNumber.partitionBy.length === 0) {
|
|
4852
|
-
throw internalError3({ message: "rowNumber needs
|
|
4943
|
+
if (rowNumber.partitionBy.length === 0 && rowNumber.orderBy.length === 0) {
|
|
4944
|
+
throw internalError3({ message: "rowNumber needs a partition column or an order" });
|
|
4853
4945
|
}
|
|
4854
|
-
const partition = rowNumber.partitionBy.map((column) => quoteCol(dialect, column)).join(", ")
|
|
4855
|
-
const order = rowNumber.orderBy.length === 0 ? "" :
|
|
4856
|
-
columnList.push(`ROW_NUMBER() OVER (
|
|
4946
|
+
const partition = rowNumber.partitionBy.length === 0 ? "" : `PARTITION BY ${rowNumber.partitionBy.map((column) => quoteCol(dialect, column)).join(", ")}`;
|
|
4947
|
+
const order = rowNumber.orderBy.length === 0 ? "" : `${partition === "" ? "" : " "}ORDER BY ${rowNumber.orderBy.map((term) => renderOrderTerm({ dialect, term, collector })).join(", ")}`;
|
|
4948
|
+
columnList.push(`ROW_NUMBER() OVER (${partition}${order}) AS ${dialect.quoteIdent({ name: rowNumber.alias })}`);
|
|
4857
4949
|
}
|
|
4858
4950
|
let distinctPrefix = statement.distinct === true ? "DISTINCT " : "";
|
|
4859
4951
|
if (statement.distinct === true && statement.distinctOn !== undefined) {
|
|
@@ -4871,7 +4963,9 @@ function renderSelect(params) {
|
|
|
4871
4963
|
}
|
|
4872
4964
|
const columns = columnList.length === 0 ? "*" : columnList.join(", ");
|
|
4873
4965
|
let from;
|
|
4874
|
-
if (statement.
|
|
4966
|
+
if (statement.fromKeys !== undefined) {
|
|
4967
|
+
from = renderKeyRows({ dialect, statement, keys: statement.fromKeys, collector });
|
|
4968
|
+
} else if (statement.fromUnion !== undefined) {
|
|
4875
4969
|
from = `(${renderUnionPage({ dialect, statement, collector })}) AS ${dialect.quoteIdent({ name: statement.table.name })}`;
|
|
4876
4970
|
} else if (statement.keyPage !== undefined) {
|
|
4877
4971
|
if (statement.fromSelect !== undefined || statement.table.alias !== undefined) {
|
|
@@ -4909,7 +5003,7 @@ function renderSelect(params) {
|
|
|
4909
5003
|
}
|
|
4910
5004
|
}
|
|
4911
5005
|
if (statement.lateralJoins !== undefined && statement.lateralJoins.length > 0) {
|
|
4912
|
-
if (!dialect.capabilities.lateralJoin) {
|
|
5006
|
+
if (!dialect.capabilities.lateralJoin || dialect.lateralJson === null) {
|
|
4913
5007
|
throw unsupportedCapability27({
|
|
4914
5008
|
dialect: dialect.name,
|
|
4915
5009
|
feature: "LATERAL JOIN relation loading",
|
|
@@ -5029,8 +5123,7 @@ function renderInsert(params) {
|
|
|
5029
5123
|
}
|
|
5030
5124
|
}
|
|
5031
5125
|
const onConflict = statement.onConflict;
|
|
5032
|
-
const
|
|
5033
|
-
const insertKeyword = skipConflicts && dialect.doNothingForm === "insertIgnore" ? "INSERT IGNORE INTO" : "INSERT INTO";
|
|
5126
|
+
const insertKeyword = "INSERT INTO";
|
|
5034
5127
|
const columnList = statement.columns.map((name) => dialect.quoteIdent({ name })).join(", ");
|
|
5035
5128
|
const unnestSource = statement.unnest === undefined ? undefined : renderUnnestRows({ dialect, statement, members: statement.unnest, collector });
|
|
5036
5129
|
const rowsSql = unnestSource !== undefined ? "" : statement.rows.map((row) => `(${row.map((value) => {
|
|
@@ -5072,12 +5165,25 @@ function renderInsert(params) {
|
|
|
5072
5165
|
}
|
|
5073
5166
|
}
|
|
5074
5167
|
text += ` ON CONFLICT${target} DO NOTHING`;
|
|
5075
|
-
} else
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5168
|
+
} else {
|
|
5169
|
+
if (onConflict.constraint !== undefined || onConflict.conflictWhere !== undefined) {
|
|
5170
|
+
throw unsupportedCapability27({
|
|
5171
|
+
dialect: dialect.name,
|
|
5172
|
+
feature: "a refined conflict target (constraint / partial-index predicate) on ON DUPLICATE KEY UPDATE",
|
|
5173
|
+
hint: "mysql skips on any duplicate key \u2014 drop the refinement or gate the call per dialect"
|
|
5174
|
+
});
|
|
5175
|
+
}
|
|
5176
|
+
const keepName = onConflict.keepColumn ?? statement.columns[0];
|
|
5177
|
+
if (keepName === undefined) {
|
|
5178
|
+
throw internalError3({ message: "a skip-duplicates insert of an all-default row must name its keepColumn" });
|
|
5179
|
+
}
|
|
5180
|
+
const keep = dialect.quoteIdent({ name: keepName });
|
|
5181
|
+
const current = `${dialect.quoteIdent({ name: statement.table.name })}.${keep}`;
|
|
5182
|
+
const flag = onConflict.duplicateFlag;
|
|
5183
|
+
if (flag !== undefined && !/^\d{1,20}$/.test(flag)) {
|
|
5184
|
+
throw internalError3({ message: `duplicateFlag must be a decimal literal, got ${JSON.stringify(flag)}` });
|
|
5185
|
+
}
|
|
5186
|
+
text += flag === undefined ? ` ON DUPLICATE KEY UPDATE ${keep} = ${current}` : ` ON DUPLICATE KEY UPDATE ${keep} = IF(LAST_INSERT_ID(${flag}), ${current}, ${current})`;
|
|
5081
5187
|
}
|
|
5082
5188
|
} else {
|
|
5083
5189
|
const updates = Object.entries(onConflict.update);
|
|
@@ -5134,7 +5240,7 @@ function renderUpdate(params) {
|
|
|
5134
5240
|
if (assignments.length === 0) {
|
|
5135
5241
|
throw internalError3({ message: "update must set at least one column" });
|
|
5136
5242
|
}
|
|
5137
|
-
const setSql = renderAssignments({ dialect, entries: assignments, collector });
|
|
5243
|
+
const setSql = renderAssignments({ dialect, entries: assignments, collector, ...params.earlier === undefined ? {} : { steps: params.earlier } });
|
|
5138
5244
|
let text = `UPDATE ${renderTable(dialect, statement.table)} SET ${setSql}`;
|
|
5139
5245
|
if (statement.where !== undefined) {
|
|
5140
5246
|
text += ` WHERE ${renderExpr({ dialect, expr: statement.where, collector })}`;
|
|
@@ -5153,6 +5259,12 @@ function renderAssignments(params) {
|
|
|
5153
5259
|
return entries.map(([name, value]) => {
|
|
5154
5260
|
const column = dialect.quoteIdent({ name });
|
|
5155
5261
|
const read = selfRef === undefined ? column : `${selfRef}.${column}`;
|
|
5262
|
+
if (isStepColumnRef(value)) {
|
|
5263
|
+
if (params.steps === undefined || !params.steps.has(value.step)) {
|
|
5264
|
+
throw internalError3({ message: `an UPDATE set value reads step "${value.step}", which is not an earlier chain step` });
|
|
5265
|
+
}
|
|
5266
|
+
return `${column} = (SELECT ${dialect.quoteIdent({ name: value.column })} FROM ${dialect.quoteIdent({ name: value.step })})`;
|
|
5267
|
+
}
|
|
5156
5268
|
if (isSqlFragment(value)) {
|
|
5157
5269
|
if (params.allowExcluded !== true || selfRef === undefined)
|
|
5158
5270
|
throw internalError3({ message: "SQL assignment fragments require a conflict update" });
|
|
@@ -5166,6 +5278,11 @@ function renderAssignments(params) {
|
|
|
5166
5278
|
}
|
|
5167
5279
|
return `${column} = ${renderIncomingRowColumn({ dialect, column: value.column })}`;
|
|
5168
5280
|
}
|
|
5281
|
+
if (isSqlKeepCell(value)) {
|
|
5282
|
+
if (params.allowExcluded !== true || selfRef === undefined)
|
|
5283
|
+
throw internalError3({ message: "a keep-column cell is only meaningful inside an upsert's update arm" });
|
|
5284
|
+
return `${column} = ${read}`;
|
|
5285
|
+
}
|
|
5169
5286
|
if (isJsonParamCell(value)) {
|
|
5170
5287
|
return `${column} = ${collector.add(value.text)}${jsonCellCast(dialect, value)}`;
|
|
5171
5288
|
}
|
|
@@ -5259,7 +5376,7 @@ function renderChainStep(params) {
|
|
|
5259
5376
|
case "insertSelect":
|
|
5260
5377
|
return renderInsertSelect({ dialect, statement, collector, earlier: params.earlier });
|
|
5261
5378
|
case "update":
|
|
5262
|
-
return renderUpdate({ dialect, statement, collector }).text;
|
|
5379
|
+
return renderUpdate({ dialect, statement, collector, earlier: params.earlier }).text;
|
|
5263
5380
|
case "delete":
|
|
5264
5381
|
return renderDelete({ dialect, statement, collector }).text;
|
|
5265
5382
|
}
|
|
@@ -5360,6 +5477,19 @@ function renderInsertSelect(params) {
|
|
|
5360
5477
|
if (statement.where !== undefined) {
|
|
5361
5478
|
text += ` WHERE ${renderExpr({ dialect, expr: statement.where, collector })}`;
|
|
5362
5479
|
}
|
|
5480
|
+
const conflict = statement.conflictDoNothing;
|
|
5481
|
+
if (conflict !== undefined) {
|
|
5482
|
+
if (conflict.columns.length === 0)
|
|
5483
|
+
throw internalError3({ message: "an INSERT \u2026 SELECT conflict clause needs at least one column" });
|
|
5484
|
+
if (dialect.doNothingForm !== "onConflictDoNothing") {
|
|
5485
|
+
throw unsupportedCapability27({
|
|
5486
|
+
dialect: dialect.name,
|
|
5487
|
+
feature: "ON CONFLICT DO NOTHING on an INSERT \u2026 SELECT chain step",
|
|
5488
|
+
hint: "gate on SqlDialect.statementChain and keep the multi-statement path"
|
|
5489
|
+
});
|
|
5490
|
+
}
|
|
5491
|
+
text += ` ON CONFLICT (${conflict.columns.map((name) => dialect.quoteIdent({ name })).join(", ")}) DO NOTHING`;
|
|
5492
|
+
}
|
|
5363
5493
|
return text + applyReturning({ dialect, requested: statement.returning }).suffix;
|
|
5364
5494
|
}
|
|
5365
5495
|
// packages/sql/src/dialects/postgres-type-identity.ts
|
|
@@ -5504,31 +5634,54 @@ function sqliteTableConstraints(params) {
|
|
|
5504
5634
|
return result;
|
|
5505
5635
|
}
|
|
5506
5636
|
// packages/sql/src/dialects/migration-visibility.ts
|
|
5507
|
-
import { unsupportedCapability as unsupportedCapability32 } from "@vibeorm/schema";
|
|
5508
|
-
function renderMigrationVisibility(params) {
|
|
5509
|
-
if (params.dialect.name !== "mysql")
|
|
5510
|
-
throw unsupportedCapability32({ dialect: params.dialect.name, feature: "mysqlCatalogVisibility" });
|
|
5511
|
-
const collector = new ParamCollector(params.dialect);
|
|
5512
|
-
const grantee = "CONCAT(QUOTE(SUBSTRING_INDEX(CURRENT_USER(), '@', 1)), '@', QUOTE(SUBSTRING_INDEX(CURRENT_USER(), '@', -1)))";
|
|
5513
|
-
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" };
|
|
5514
|
-
}
|
|
5515
|
-
// packages/sql/src/dialects/migration-inventory.ts
|
|
5516
5637
|
import { unsupportedCapability as unsupportedCapability33 } from "@vibeorm/schema";
|
|
5638
|
+
|
|
5639
|
+
// packages/sql/src/dialects/migration-inventory.ts
|
|
5640
|
+
import { unsupportedCapability as unsupportedCapability32 } from "@vibeorm/schema";
|
|
5641
|
+
var MYSQL_NO_ROW_LIMIT = " LIMIT 18446744073709551615";
|
|
5517
5642
|
function renderSqliteColumnInventory(params) {
|
|
5518
5643
|
if (params.dialect.name !== "sqlite")
|
|
5519
|
-
throw
|
|
5644
|
+
throw unsupportedCapability32({ dialect: params.dialect.name, feature: "sqliteColumnInventory" });
|
|
5520
5645
|
const collector = new ParamCollector(params.dialect);
|
|
5521
5646
|
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" };
|
|
5522
5647
|
}
|
|
5523
5648
|
function renderSqliteForeignKeyInventory(params) {
|
|
5524
5649
|
if (params.dialect.name !== "sqlite")
|
|
5525
|
-
throw
|
|
5650
|
+
throw unsupportedCapability32({ dialect: params.dialect.name, feature: "sqliteForeignKeyInventory" });
|
|
5526
5651
|
const collector = new ParamCollector(params.dialect);
|
|
5527
5652
|
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" };
|
|
5528
5653
|
}
|
|
5654
|
+
function renderSqliteColumnInventoryBatch(params) {
|
|
5655
|
+
if (params.dialect.name !== "sqlite")
|
|
5656
|
+
throw unsupportedCapability32({ dialect: params.dialect.name, feature: "sqliteColumnInventory" });
|
|
5657
|
+
const collector = new ParamCollector(params.dialect);
|
|
5658
|
+
const request = params.dialect.quoteIdent({ name: "vibe_request" });
|
|
5659
|
+
return { text: `SELECT j.key AS ${request}, x.name AS name, x.hidden AS hidden, x.pk AS pk, x.dflt_value AS definition FROM json_each(${collector.add(JSON.stringify(params.tables))}) j LEFT JOIN pragma_table_xinfo(j.value, ${collector.add(params.namespace)}) x ORDER BY j.key, x.cid`, values: collector.values, returning: "none" };
|
|
5660
|
+
}
|
|
5661
|
+
function renderSqliteForeignKeyInventoryBatch(params) {
|
|
5662
|
+
if (params.dialect.name !== "sqlite")
|
|
5663
|
+
throw unsupportedCapability32({ dialect: params.dialect.name, feature: "sqliteForeignKeyInventory" });
|
|
5664
|
+
const collector = new ParamCollector(params.dialect);
|
|
5665
|
+
const request = params.dialect.quoteIdent({ name: "vibe_request" });
|
|
5666
|
+
return { text: `SELECT j.key AS ${request}, f.id AS id, f.seq AS seq, f."from" AS "from", f."to" AS "to", f."table" AS "table", f.on_update AS on_update, f.on_delete AS on_delete, f.match AS match FROM json_each(${collector.add(JSON.stringify(params.tables))}) j LEFT JOIN pragma_foreign_key_list(j.value, ${collector.add(params.namespace)}) f ORDER BY j.key, f.id, f.seq`, values: collector.values, returning: "none" };
|
|
5667
|
+
}
|
|
5668
|
+
var SQLITE_INTROSPECTION_PRAGMA_ORDER = Object.freeze({
|
|
5669
|
+
table_xinfo: "p.cid",
|
|
5670
|
+
index_list: "p.seq",
|
|
5671
|
+
index_xinfo: "p.seqno",
|
|
5672
|
+
foreign_key_list: "p.id, p.seq"
|
|
5673
|
+
});
|
|
5674
|
+
function renderSqliteIntrospectionPragmaBatch(params) {
|
|
5675
|
+
if (params.dialect.name !== "sqlite")
|
|
5676
|
+
throw unsupportedCapability32({ dialect: params.dialect.name, feature: "sqliteIntrospectionPragmaBatch" });
|
|
5677
|
+
const order = SQLITE_INTROSPECTION_PRAGMA_ORDER[params.pragma];
|
|
5678
|
+
if (order === undefined)
|
|
5679
|
+
throw unsupportedCapability32({ dialect: "sqlite", feature: `introspectionPragma:${String(params.pragma)}` });
|
|
5680
|
+
return { text: `SELECT j.key AS ${params.dialect.quoteIdent({ name: "vibe_request" })}, p.* FROM json_each(${params.dialect.quoteStringLiteral({ value: JSON.stringify(params.names) })}) j LEFT JOIN pragma_${params.pragma}(j.value) p ORDER BY j.key, ${order}`, values: [], returning: "none" };
|
|
5681
|
+
}
|
|
5529
5682
|
function renderSqliteRebuildObjects(params) {
|
|
5530
5683
|
if (params.dialect.name !== "sqlite")
|
|
5531
|
-
throw
|
|
5684
|
+
throw unsupportedCapability32({ dialect: params.dialect.name, feature: "sqliteRebuildObjects" });
|
|
5532
5685
|
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" };
|
|
5533
5686
|
}
|
|
5534
5687
|
function renderMigrationInventory(params) {
|
|
@@ -5561,11 +5714,20 @@ UNION ALL SELECT 'trigger', TRIGGER_NAME, EVENT_OBJECT_TABLE, NULL, NULL, NULL F
|
|
|
5561
5714
|
UNION ALL SELECT 'column', COLUMN_NAME, TABLE_NAME, NULL, NULL, NULL FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ${n()} AND TABLE_NAME <> '_vibe_migrations'
|
|
5562
5715
|
UNION ALL SELECT CASE WHEN GENERATION_EXPRESSION <> '' THEN 'generatedColumn' ELSE 'columnDefault' END, COLUMN_NAME, TABLE_NAME, NULL, NULL, NULL FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ${n()} AND TABLE_NAME <> '_vibe_migrations' AND (COLUMN_DEFAULT IS NOT NULL OR GENERATION_EXPRESSION <> '')
|
|
5563
5716
|
UNION ALL SELECT 'function', ROUTINE_NAME, NULL, NULL, '[]', NULL FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = ${n()} AND ROUTINE_TYPE = 'FUNCTION'
|
|
5564
|
-
ORDER BY kind, parent, name`, values: collector.values, returning: "none" };
|
|
5717
|
+
ORDER BY kind, parent, name${MYSQL_NO_ROW_LIMIT}`, values: collector.values, returning: "none" };
|
|
5565
5718
|
}
|
|
5566
5719
|
const schema = params.dialect.quoteIdent({ name: params.namespace });
|
|
5567
5720
|
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" };
|
|
5568
5721
|
}
|
|
5722
|
+
|
|
5723
|
+
// packages/sql/src/dialects/migration-visibility.ts
|
|
5724
|
+
function renderMigrationVisibility(params) {
|
|
5725
|
+
if (params.dialect.name !== "mysql")
|
|
5726
|
+
throw unsupportedCapability33({ dialect: params.dialect.name, feature: "mysqlCatalogVisibility" });
|
|
5727
|
+
const collector = new ParamCollector(params.dialect);
|
|
5728
|
+
const grantee = "CONCAT(QUOTE(SUBSTRING_INDEX(CURRENT_USER(), '@', 1)), '@', QUOTE(SUBSTRING_INDEX(CURRENT_USER(), '@', -1)))";
|
|
5729
|
+
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${MYSQL_NO_ROW_LIMIT}`, values: collector.values, returning: "none" };
|
|
5730
|
+
}
|
|
5569
5731
|
// packages/sql/src/dialects/migration-objects.ts
|
|
5570
5732
|
import { internalError as internalError4, unsupportedCapability as unsupportedCapability34 } from "@vibeorm/schema";
|
|
5571
5733
|
function renderMigrationObjectQuery(params) {
|
|
@@ -5622,35 +5784,12 @@ function objectQuery(params) {
|
|
|
5622
5784
|
break;
|
|
5623
5785
|
}
|
|
5624
5786
|
} else if (dialect.name === "mysql") {
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
break;
|
|
5632
|
-
case "function":
|
|
5633
|
-
text = `SELECT ROUTINE_DEFINITION AS definition, DTD_IDENTIFIER AS result, IS_DETERMINISTIC AS deterministic, SQL_DATA_ACCESS AS dataAccess, SECURITY_TYPE AS securityType, SQL_MODE AS sqlMode, DEFINER AS definer FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = ${namespace} AND ROUTINE_NAME = ${name} AND ROUTINE_TYPE = 'FUNCTION'`;
|
|
5634
|
-
break;
|
|
5635
|
-
case "column":
|
|
5636
|
-
case "columnDefault":
|
|
5637
|
-
case "generatedColumn":
|
|
5638
|
-
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)}`;
|
|
5639
|
-
break;
|
|
5640
|
-
case "constraint":
|
|
5641
|
-
if (object.constraintType === "exclusion")
|
|
5642
|
-
throw unsupportedCapability34({ dialect: "mysql", feature: "exclusionConstraints" });
|
|
5643
|
-
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)}`;
|
|
5644
|
-
break;
|
|
5645
|
-
case "index":
|
|
5646
|
-
text = `SELECT INDEX_NAME AS name, NON_UNIQUE AS nonUnique, INDEX_TYPE AS method, IS_VISIBLE AS visible FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = ${namespace} AND TABLE_NAME = ${name} AND INDEX_NAME = ${collector.add(object.name)} GROUP BY INDEX_NAME, NON_UNIQUE, INDEX_TYPE, IS_VISIBLE`;
|
|
5647
|
-
break;
|
|
5648
|
-
case "table":
|
|
5649
|
-
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}`;
|
|
5650
|
-
break;
|
|
5651
|
-
default:
|
|
5652
|
-
throw unsupportedCapability34({ dialect: "mysql", feature: `inspect:${object.kind}` });
|
|
5653
|
-
}
|
|
5787
|
+
if (object.kind === "constraint" && object.constraintType === "exclusion")
|
|
5788
|
+
throw unsupportedCapability34({ dialect: "mysql", feature: "exclusionConstraints" });
|
|
5789
|
+
const mysql = mysqlFactsText({ dialect, identity: object, namespace, name, collector });
|
|
5790
|
+
if (mysql === undefined)
|
|
5791
|
+
throw unsupportedCapability34({ dialect: "mysql", feature: `inspect:${object.kind}` });
|
|
5792
|
+
text = mysql;
|
|
5654
5793
|
} else {
|
|
5655
5794
|
if (physical.namespace !== "main" && physical.namespace !== "temp")
|
|
5656
5795
|
throw unsupportedCapability34({ dialect: "sqlite", feature: "attachedSchemaInspection" });
|
|
@@ -5669,18 +5808,103 @@ function objectQuery(params) {
|
|
|
5669
5808
|
}
|
|
5670
5809
|
return { text, values: collector.values, returning: "none" };
|
|
5671
5810
|
}
|
|
5672
|
-
function
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5811
|
+
function mysqlFactsText(params) {
|
|
5812
|
+
const { dialect, identity: object, namespace, name, collector } = params;
|
|
5813
|
+
switch (object.kind) {
|
|
5814
|
+
case "view":
|
|
5815
|
+
return `SELECT VIEW_DEFINITION AS definition, CHECK_OPTION AS checkOption, SECURITY_TYPE AS securityType, DEFINER AS definer FROM information_schema.VIEWS WHERE TABLE_SCHEMA = ${namespace} AND TABLE_NAME = ${name}`;
|
|
5816
|
+
case "trigger":
|
|
5817
|
+
return `SELECT ACTION_STATEMENT AS definition, ACTION_TIMING AS timing, EVENT_MANIPULATION AS event, ACTION_ORDER AS actionOrder, SQL_MODE AS sqlMode, DEFINER AS definer FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = ${namespace} AND EVENT_OBJECT_TABLE = ${name} AND TRIGGER_NAME = ${collector.add(object.name)}`;
|
|
5818
|
+
case "function":
|
|
5819
|
+
return `SELECT ROUTINE_DEFINITION AS definition, DTD_IDENTIFIER AS result, IS_DETERMINISTIC AS deterministic, SQL_DATA_ACCESS AS dataAccess, SECURITY_TYPE AS securityType, SQL_MODE AS sqlMode, DEFINER AS definer FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = ${namespace} AND ROUTINE_NAME = ${name} AND ROUTINE_TYPE = 'FUNCTION'`;
|
|
5820
|
+
case "column":
|
|
5821
|
+
case "columnDefault":
|
|
5822
|
+
case "generatedColumn":
|
|
5823
|
+
return `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)}`;
|
|
5824
|
+
case "constraint":
|
|
5825
|
+
if (object.constraintType === "exclusion")
|
|
5826
|
+
return;
|
|
5827
|
+
return `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)}`;
|
|
5828
|
+
case "index":
|
|
5829
|
+
return `SELECT INDEX_NAME AS name, NON_UNIQUE AS nonUnique, INDEX_TYPE AS method, IS_VISIBLE AS visible FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = ${namespace} AND TABLE_NAME = ${name} AND INDEX_NAME = ${collector.add(object.name)} GROUP BY INDEX_NAME, NON_UNIQUE, INDEX_TYPE, IS_VISIBLE`;
|
|
5830
|
+
case "table":
|
|
5831
|
+
return `SELECT TABLE_TYPE AS type, ENGINE AS engine, TABLE_COLLATION AS collation FROM information_schema.TABLES WHERE TABLE_SCHEMA = ${namespace} AND TABLE_NAME = ${name}`;
|
|
5832
|
+
default:
|
|
5833
|
+
return;
|
|
5834
|
+
}
|
|
5835
|
+
}
|
|
5836
|
+
function mysqlMemberParts(params) {
|
|
5837
|
+
const { identity: object, collector } = params;
|
|
5676
5838
|
if (object.kind !== "function" && object.kind !== "index" && object.kind !== "constraint")
|
|
5677
5839
|
return;
|
|
5678
|
-
const collector = new ParamCollector(params.dialect);
|
|
5679
5840
|
const physical = "table" in object ? object.table : object.name;
|
|
5680
5841
|
const namespace = collector.add(physical.namespace);
|
|
5681
5842
|
const name = collector.add(physical.name);
|
|
5682
|
-
|
|
5683
|
-
|
|
5843
|
+
return object.kind === "function" ? { columns: "PARAMETER_MODE AS mode, PARAMETER_NAME AS name, DTD_IDENTIFIER AS type, CHARACTER_SET_NAME AS characterSet, COLLATION_NAME AS collation", source: `information_schema.PARAMETERS WHERE SPECIFIC_SCHEMA = ${namespace} AND SPECIFIC_NAME = ${name}`, ordinal: "ORDINAL_POSITION" } : object.kind === "index" ? { columns: "COLUMN_NAME AS name, EXPRESSION AS expression, SUB_PART AS prefixLength, COLLATION AS collation", source: `information_schema.STATISTICS WHERE TABLE_SCHEMA = ${namespace} AND TABLE_NAME = ${name} AND INDEX_NAME = ${collector.add(object.name)}`, ordinal: "SEQ_IN_INDEX" } : { columns: "COLUMN_NAME AS name, REFERENCED_TABLE_SCHEMA AS referenceNamespace, REFERENCED_TABLE_NAME AS referenceTable, REFERENCED_COLUMN_NAME AS referenceColumn", source: `information_schema.KEY_COLUMN_USAGE WHERE CONSTRAINT_SCHEMA = ${namespace} AND TABLE_NAME = ${name} AND CONSTRAINT_NAME = ${collector.add(object.name)}`, ordinal: "ORDINAL_POSITION" };
|
|
5844
|
+
}
|
|
5845
|
+
function renderMysqlObjectMembers(params) {
|
|
5846
|
+
if (params.dialect.name !== "mysql")
|
|
5847
|
+
return;
|
|
5848
|
+
const collector = new ParamCollector(params.dialect);
|
|
5849
|
+
const parts = mysqlMemberParts({ identity: params.identity, collector });
|
|
5850
|
+
if (parts === undefined)
|
|
5851
|
+
return;
|
|
5852
|
+
return { text: `SELECT ${parts.columns} FROM ${parts.source} ORDER BY ${parts.ordinal}`, values: collector.values, returning: "none" };
|
|
5853
|
+
}
|
|
5854
|
+
var MYSQL_OBJECT_BATCH_SIZE = 100;
|
|
5855
|
+
var MYSQL_BATCH_NO_ROW_LIMIT = " LIMIT 18446744073709551615";
|
|
5856
|
+
function mysqlBatches(params) {
|
|
5857
|
+
const batches = [];
|
|
5858
|
+
for (const group of params.groups.values()) {
|
|
5859
|
+
for (let offset = 0;offset < group.length; offset += MYSQL_OBJECT_BATCH_SIZE) {
|
|
5860
|
+
const chunk = group.slice(offset, offset + MYSQL_OBJECT_BATCH_SIZE);
|
|
5861
|
+
batches.push({
|
|
5862
|
+
text: `${chunk.map((entry, index) => entry.branch(index)).join(" UNION ALL ")}${params.suffix}${MYSQL_BATCH_NO_ROW_LIMIT}`,
|
|
5863
|
+
values: chunk.flatMap((entry) => entry.values),
|
|
5864
|
+
returning: "none",
|
|
5865
|
+
positions: chunk.map((entry) => entry.position)
|
|
5866
|
+
});
|
|
5867
|
+
}
|
|
5868
|
+
}
|
|
5869
|
+
return batches;
|
|
5870
|
+
}
|
|
5871
|
+
function renderMysqlObjectBatch(params) {
|
|
5872
|
+
const { dialect } = params;
|
|
5873
|
+
if (dialect.name !== "mysql")
|
|
5874
|
+
throw unsupportedCapability34({ dialect: dialect.name, feature: "batchedMigrationInspection" });
|
|
5875
|
+
const position = dialect.quoteIdent({ name: "vibe_position" });
|
|
5876
|
+
const groups = new Map;
|
|
5877
|
+
for (const [index, identity] of params.identities.entries()) {
|
|
5878
|
+
if (identity.kind === "namespace")
|
|
5879
|
+
continue;
|
|
5880
|
+
const physical = "table" in identity ? identity.table : identity.name;
|
|
5881
|
+
const collector = new ParamCollector(dialect);
|
|
5882
|
+
const text = mysqlFactsText({ dialect, identity, namespace: collector.add(physical.namespace), name: collector.add(physical.name), collector });
|
|
5883
|
+
if (text === undefined)
|
|
5884
|
+
continue;
|
|
5885
|
+
const group = groups.get(text) ?? [];
|
|
5886
|
+
group.push({ position: index, branch: (branch) => `SELECT ${branch} AS ${position}, q.* FROM (${text}) q`, values: collector.values });
|
|
5887
|
+
groups.set(text, group);
|
|
5888
|
+
}
|
|
5889
|
+
return mysqlBatches({ groups, suffix: "" });
|
|
5890
|
+
}
|
|
5891
|
+
function renderMysqlObjectMembersBatch(params) {
|
|
5892
|
+
const { dialect } = params;
|
|
5893
|
+
if (dialect.name !== "mysql")
|
|
5894
|
+
throw unsupportedCapability34({ dialect: dialect.name, feature: "batchedMigrationInspection" });
|
|
5895
|
+
const position = dialect.quoteIdent({ name: "vibe_position" });
|
|
5896
|
+
const ordinal = dialect.quoteIdent({ name: "vibe_ordinal" });
|
|
5897
|
+
const groups = new Map;
|
|
5898
|
+
for (const [index, identity] of params.identities.entries()) {
|
|
5899
|
+
const collector = new ParamCollector(dialect);
|
|
5900
|
+
const parts = mysqlMemberParts({ identity, collector });
|
|
5901
|
+
if (parts === undefined)
|
|
5902
|
+
continue;
|
|
5903
|
+
const group = groups.get(identity.kind) ?? [];
|
|
5904
|
+
group.push({ position: index, branch: (branch) => `SELECT ${branch} AS ${position}, ${parts.ordinal} AS ${ordinal}, ${parts.columns} FROM ${parts.source}`, values: collector.values });
|
|
5905
|
+
groups.set(identity.kind, group);
|
|
5906
|
+
}
|
|
5907
|
+
return mysqlBatches({ groups, suffix: ` ORDER BY ${position}, ${ordinal}` });
|
|
5684
5908
|
}
|
|
5685
5909
|
function renderMigrationDependencies(params) {
|
|
5686
5910
|
return dependencyQuery({ ...params, collector: new ParamCollector(params.dialect) });
|
|
@@ -5919,6 +6143,7 @@ export {
|
|
|
5919
6143
|
SQLITE_SESSION_SQL,
|
|
5920
6144
|
SQL_DEFAULT_CELL,
|
|
5921
6145
|
SQL_DIALECTS,
|
|
6146
|
+
SQL_KEEP_CELL,
|
|
5922
6147
|
assertIndexExpressionVersion,
|
|
5923
6148
|
assertSqlParamBuilding,
|
|
5924
6149
|
chainVetoToken,
|
|
@@ -5940,6 +6165,7 @@ export {
|
|
|
5940
6165
|
dbNowMarker,
|
|
5941
6166
|
decode,
|
|
5942
6167
|
decodeIsNoop,
|
|
6168
|
+
decodedDateTimeRefusal,
|
|
5943
6169
|
describeRowLock,
|
|
5944
6170
|
encode,
|
|
5945
6171
|
endsWithPattern,
|
|
@@ -5966,6 +6192,7 @@ export {
|
|
|
5966
6192
|
isSqlCommand,
|
|
5967
6193
|
isSqlDefaultCell,
|
|
5968
6194
|
isSqlFragment,
|
|
6195
|
+
isSqlKeepCell,
|
|
5969
6196
|
isSqlParam,
|
|
5970
6197
|
isSqlQuery,
|
|
5971
6198
|
isStepColumnRef,
|
|
@@ -5977,6 +6204,7 @@ export {
|
|
|
5977
6204
|
mysqlDialect,
|
|
5978
6205
|
nativeEnumArrayParameter,
|
|
5979
6206
|
parseDateTimeText,
|
|
6207
|
+
parseExtendedDateTimeText,
|
|
5980
6208
|
parseJsonText,
|
|
5981
6209
|
parsePgArrayLiteral,
|
|
5982
6210
|
parsePgArrayLiteralNested,
|
|
@@ -6024,7 +6252,9 @@ export {
|
|
|
6024
6252
|
renderModuleJournal,
|
|
6025
6253
|
renderMysqlCheckProbe,
|
|
6026
6254
|
renderMysqlGeneratedColumnProbe,
|
|
6255
|
+
renderMysqlObjectBatch,
|
|
6027
6256
|
renderMysqlObjectMembers,
|
|
6257
|
+
renderMysqlObjectMembersBatch,
|
|
6028
6258
|
renderPostgresDefaultFunctionIdentity,
|
|
6029
6259
|
renderPostgresDropGeneratedExpression,
|
|
6030
6260
|
renderPostgresExplain,
|
|
@@ -6059,8 +6289,11 @@ export {
|
|
|
6059
6289
|
renderShadowOperation,
|
|
6060
6290
|
renderSqlFragment,
|
|
6061
6291
|
renderSqliteColumnInventory,
|
|
6292
|
+
renderSqliteColumnInventoryBatch,
|
|
6062
6293
|
renderSqliteForeignKeyInventory,
|
|
6294
|
+
renderSqliteForeignKeyInventoryBatch,
|
|
6063
6295
|
renderSqliteFtsUpdateTrigger,
|
|
6296
|
+
renderSqliteIntrospectionPragmaBatch,
|
|
6064
6297
|
renderSqliteRebuildObjects,
|
|
6065
6298
|
renderStatement,
|
|
6066
6299
|
resolveIndexKeys,
|
|
@@ -6089,4 +6322,4 @@ export {
|
|
|
6089
6322
|
toPgArrayLiteral
|
|
6090
6323
|
};
|
|
6091
6324
|
|
|
6092
|
-
//# debugId=
|
|
6325
|
+
//# debugId=0FD86C4E8226D05064756E2164756E21
|