@restura/core 2.0.0 → 2.0.2
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/index.js +126 -50
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -506,8 +506,9 @@ var ResponseValidator = class _ResponseValidator {
|
|
|
506
506
|
static isCustomRoute(route) {
|
|
507
507
|
return route.type === "CUSTOM_ONE" || route.type === "CUSTOM_ARRAY" || route.type === "CUSTOM_PAGED";
|
|
508
508
|
}
|
|
509
|
+
static VALIDATOR_STRINGS = ["boolean", "string", "number", "object", "any"];
|
|
509
510
|
static validatorIsValidString(validator) {
|
|
510
|
-
return
|
|
511
|
+
return _ResponseValidator.VALIDATOR_STRINGS.includes(validator);
|
|
511
512
|
}
|
|
512
513
|
};
|
|
513
514
|
|
|
@@ -2858,7 +2859,11 @@ async function getNewPublicSchemaAndScratchPool(targetPool, scratchDbName) {
|
|
|
2858
2859
|
connectionTimeoutMillis: targetPool.poolConfig.connectionTimeoutMillis
|
|
2859
2860
|
});
|
|
2860
2861
|
await scratchPool.runQuery(`DROP SCHEMA public CASCADE;`, [], systemUser);
|
|
2861
|
-
await scratchPool.runQuery(
|
|
2862
|
+
await scratchPool.runQuery(
|
|
2863
|
+
`CREATE SCHEMA public AUTHORIZATION ${escapeColumnName(targetPool.poolConfig.user)};`,
|
|
2864
|
+
[],
|
|
2865
|
+
systemUser
|
|
2866
|
+
);
|
|
2862
2867
|
const schemaComment = await targetPool.runQuery(
|
|
2863
2868
|
`
|
|
2864
2869
|
SELECT pg_description.description
|
|
@@ -2869,7 +2874,8 @@ async function getNewPublicSchemaAndScratchPool(targetPool, scratchDbName) {
|
|
|
2869
2874
|
systemUser
|
|
2870
2875
|
);
|
|
2871
2876
|
if (schemaComment[0]?.description) {
|
|
2872
|
-
|
|
2877
|
+
const escaped = schemaComment[0].description.replace(/'/g, "''");
|
|
2878
|
+
await scratchPool.runQuery(`COMMENT ON SCHEMA public IS '${escaped}';`, [], systemUser);
|
|
2873
2879
|
}
|
|
2874
2880
|
return scratchPool;
|
|
2875
2881
|
}
|
|
@@ -2989,11 +2995,9 @@ var PsqlEngine = class extends SqlEngine {
|
|
|
2989
2995
|
});
|
|
2990
2996
|
try {
|
|
2991
2997
|
await this.triggerClient.connect();
|
|
2992
|
-
const
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
promises.push(this.triggerClient.query("LISTEN delete"));
|
|
2996
|
-
await Promise.all(promises);
|
|
2998
|
+
for (const channel of ["insert", "update", "delete"]) {
|
|
2999
|
+
await this.triggerClient.query(`LISTEN ${channel}`);
|
|
3000
|
+
}
|
|
2997
3001
|
this.triggerClient.on("error", async (error) => {
|
|
2998
3002
|
logger.error(`Trigger client error: ${error}`);
|
|
2999
3003
|
await this.reconnectTriggerClient();
|
|
@@ -3949,7 +3953,7 @@ async function introspectDatabase(pool) {
|
|
|
3949
3953
|
const order = row.indexdef.toUpperCase().includes(" DESC") ? "DESC" : "ASC";
|
|
3950
3954
|
const columnMatch = row.indexdef.match(/\((.+?)\)(?:\s+WHERE\s+(.+))?$/i);
|
|
3951
3955
|
const columns = columnMatch ? columnMatch[1].split(",").map(
|
|
3952
|
-
(colExpr) => colExpr.trim().replace(
|
|
3956
|
+
(colExpr) => colExpr.trim().replace(/\s+(ASC|DESC)$/i, "").replace(/^"(.*)"$/, "$1")
|
|
3953
3957
|
) : [];
|
|
3954
3958
|
const whereClause = columnMatch?.[2] ?? null;
|
|
3955
3959
|
table.indexes.push({
|
|
@@ -3996,7 +4000,7 @@ function diffSchemaToDatabase(schema, snapshot) {
|
|
|
3996
4000
|
const changedChecksPerTable = /* @__PURE__ */ new Map();
|
|
3997
4001
|
for (const desired of tablesToAlter) {
|
|
3998
4002
|
const live = liveTableMap.get(desired.name);
|
|
3999
|
-
const desiredFkNames = new Set(desired.foreignKeys.map((fk) => fk.name));
|
|
4003
|
+
const desiredFkNames = new Set(desired.foreignKeys.map((fk) => pgTruncate(fk.name)));
|
|
4000
4004
|
for (const liveFk of live.foreignKeys) {
|
|
4001
4005
|
if (!desiredFkNames.has(liveFk.name) || isFkChanged(desired, liveFk)) {
|
|
4002
4006
|
statements.push(`ALTER TABLE "${desired.name}" DROP CONSTRAINT "${liveFk.name}";`);
|
|
@@ -4004,11 +4008,14 @@ function diffSchemaToDatabase(schema, snapshot) {
|
|
|
4004
4008
|
}
|
|
4005
4009
|
const desiredCheckExprMap = /* @__PURE__ */ new Map();
|
|
4006
4010
|
for (const check of desired.checkConstraints) {
|
|
4007
|
-
desiredCheckExprMap.set(check.name, check.check);
|
|
4011
|
+
desiredCheckExprMap.set(pgTruncate(check.name), check.check);
|
|
4008
4012
|
}
|
|
4009
4013
|
for (const col of desired.columns) {
|
|
4010
4014
|
if (col.type === "ENUM" && col.value) {
|
|
4011
|
-
desiredCheckExprMap.set(
|
|
4015
|
+
desiredCheckExprMap.set(
|
|
4016
|
+
pgTruncate(`${desired.name}_${col.name}_check`),
|
|
4017
|
+
`"${col.name}" IN (${col.value})`
|
|
4018
|
+
);
|
|
4012
4019
|
}
|
|
4013
4020
|
}
|
|
4014
4021
|
const changedChecks = /* @__PURE__ */ new Set();
|
|
@@ -4024,18 +4031,27 @@ function diffSchemaToDatabase(schema, snapshot) {
|
|
|
4024
4031
|
const desiredIdxSignatures = /* @__PURE__ */ new Map();
|
|
4025
4032
|
for (const idx of desired.indexes) {
|
|
4026
4033
|
if (idx.isPrimaryKey) continue;
|
|
4027
|
-
desiredIdxSignatures.set(
|
|
4034
|
+
desiredIdxSignatures.set(
|
|
4035
|
+
pgTruncate(idx.name),
|
|
4036
|
+
indexSignature(pgTruncate(idx.name), idx.columns, idx.isUnique, idx.order, idx.where)
|
|
4037
|
+
);
|
|
4028
4038
|
}
|
|
4029
4039
|
const autoUniqueNames = /* @__PURE__ */ new Set();
|
|
4030
4040
|
for (const col of desired.columns) {
|
|
4031
4041
|
if (col.isUnique) {
|
|
4032
|
-
autoUniqueNames.add(`${desired.name}_${col.name}_unique_index`);
|
|
4042
|
+
autoUniqueNames.add(pgTruncate(`${desired.name}_${col.name}_unique_index`));
|
|
4033
4043
|
}
|
|
4034
4044
|
}
|
|
4035
4045
|
for (const liveIdx of live.indexes) {
|
|
4036
4046
|
if (liveIdx.isPrimary) continue;
|
|
4037
4047
|
if (autoUniqueNames.has(liveIdx.name)) continue;
|
|
4038
|
-
const liveSig = indexSignature(
|
|
4048
|
+
const liveSig = indexSignature(
|
|
4049
|
+
liveIdx.name,
|
|
4050
|
+
liveIdx.columns,
|
|
4051
|
+
liveIdx.isUnique,
|
|
4052
|
+
liveIdx.order,
|
|
4053
|
+
liveIdx.where
|
|
4054
|
+
);
|
|
4039
4055
|
const desiredSig = desiredIdxSignatures.get(liveIdx.name);
|
|
4040
4056
|
if (!desiredSig || desiredSig !== liveSig) {
|
|
4041
4057
|
statements.push(`DROP INDEX "${liveIdx.name}";`);
|
|
@@ -4065,8 +4081,14 @@ function diffSchemaToDatabase(schema, snapshot) {
|
|
|
4065
4081
|
}
|
|
4066
4082
|
for (const index of desired.indexes) {
|
|
4067
4083
|
if (index.isPrimaryKey) continue;
|
|
4068
|
-
const desiredSig = indexSignature(
|
|
4069
|
-
|
|
4084
|
+
const desiredSig = indexSignature(
|
|
4085
|
+
pgTruncate(index.name),
|
|
4086
|
+
index.columns,
|
|
4087
|
+
index.isUnique,
|
|
4088
|
+
index.order,
|
|
4089
|
+
index.where
|
|
4090
|
+
);
|
|
4091
|
+
const liveSig = liveIdxSignatures.get(pgTruncate(index.name));
|
|
4070
4092
|
if (!liveSig || liveSig !== desiredSig) {
|
|
4071
4093
|
statements.push(buildCreateIndex(desired.name, index));
|
|
4072
4094
|
}
|
|
@@ -4083,9 +4105,9 @@ function diffSchemaToDatabase(schema, snapshot) {
|
|
|
4083
4105
|
const live = liveTableMap.get(desired.name);
|
|
4084
4106
|
const liveFkNames = new Set(live.foreignKeys.map((fk) => fk.name));
|
|
4085
4107
|
for (const fk of desired.foreignKeys) {
|
|
4086
|
-
if (!liveFkNames.has(fk.name) || isFkChanged(
|
|
4108
|
+
if (!liveFkNames.has(pgTruncate(fk.name)) || isFkChanged(
|
|
4087
4109
|
desired,
|
|
4088
|
-
liveTableMap.get(desired.name).foreignKeys.find((liveFk) => liveFk.name === fk.name)
|
|
4110
|
+
liveTableMap.get(desired.name).foreignKeys.find((liveFk) => liveFk.name === pgTruncate(fk.name))
|
|
4089
4111
|
)) {
|
|
4090
4112
|
statements.push(buildAddForeignKey(desired.name, fk));
|
|
4091
4113
|
}
|
|
@@ -4096,13 +4118,13 @@ function diffSchemaToDatabase(schema, snapshot) {
|
|
|
4096
4118
|
const liveCheckNames = new Set(live.checkConstraints.map((check) => check.name));
|
|
4097
4119
|
const changedChecks = changedChecksPerTable.get(desired.name) ?? /* @__PURE__ */ new Set();
|
|
4098
4120
|
for (const check of desired.checkConstraints) {
|
|
4099
|
-
if (!liveCheckNames.has(check.name) || changedChecks.has(check.name)) {
|
|
4121
|
+
if (!liveCheckNames.has(pgTruncate(check.name)) || changedChecks.has(pgTruncate(check.name))) {
|
|
4100
4122
|
statements.push(buildAddCheckConstraint(desired.name, check));
|
|
4101
4123
|
}
|
|
4102
4124
|
}
|
|
4103
4125
|
for (const col of desired.columns) {
|
|
4104
4126
|
if (col.type === "ENUM" && col.value) {
|
|
4105
|
-
const checkName = `${desired.name}_${col.name}_check
|
|
4127
|
+
const checkName = pgTruncate(`${desired.name}_${col.name}_check`);
|
|
4106
4128
|
if (!liveCheckNames.has(checkName) || changedChecks.has(checkName)) {
|
|
4107
4129
|
statements.push(
|
|
4108
4130
|
`ALTER TABLE "${desired.name}" ADD CONSTRAINT "${checkName}" CHECK ("${col.name}" IN (${col.value}));`
|
|
@@ -4154,8 +4176,8 @@ function diffColumns(desired, live, statements) {
|
|
|
4154
4176
|
}
|
|
4155
4177
|
}
|
|
4156
4178
|
function topologicalSortTables(tables) {
|
|
4157
|
-
const tableNames = new Set(tables.map((
|
|
4158
|
-
const tableMap = new Map(tables.map((
|
|
4179
|
+
const tableNames = new Set(tables.map((table) => table.name));
|
|
4180
|
+
const tableMap = new Map(tables.map((table) => [table.name, table]));
|
|
4159
4181
|
const inDegree = /* @__PURE__ */ new Map();
|
|
4160
4182
|
const tableDeps = /* @__PURE__ */ new Map();
|
|
4161
4183
|
const reverseDeps = /* @__PURE__ */ new Map();
|
|
@@ -4189,7 +4211,7 @@ function topologicalSortTables(tables) {
|
|
|
4189
4211
|
}
|
|
4190
4212
|
const sortedSet = new Set(sorted);
|
|
4191
4213
|
const deferredFkNames = /* @__PURE__ */ new Set();
|
|
4192
|
-
const cycleTables = tables.filter((
|
|
4214
|
+
const cycleTables = tables.filter((table) => !sortedSet.has(table.name));
|
|
4193
4215
|
const placed = new Set(sorted);
|
|
4194
4216
|
for (const table of cycleTables) {
|
|
4195
4217
|
sorted.push(table.name);
|
|
@@ -4207,7 +4229,8 @@ function buildCreateTable(table, deferredFkNames = /* @__PURE__ */ new Set()) {
|
|
|
4207
4229
|
for (const column of table.columns) {
|
|
4208
4230
|
let definition = `"${column.name}" ${buildColumnType(column)}`;
|
|
4209
4231
|
if (column.isPrimary) definition += " PRIMARY KEY";
|
|
4210
|
-
if (column.isUnique)
|
|
4232
|
+
if (column.isUnique)
|
|
4233
|
+
definition += ` CONSTRAINT "${pgTruncate(`${table.name}_${column.name}_unique_index`)}" UNIQUE`;
|
|
4211
4234
|
if (!column.isNullable) definition += " NOT NULL";
|
|
4212
4235
|
else definition += " NULL";
|
|
4213
4236
|
if (column.default) definition += ` DEFAULT ${column.default}`;
|
|
@@ -4216,16 +4239,16 @@ function buildCreateTable(table, deferredFkNames = /* @__PURE__ */ new Set()) {
|
|
|
4216
4239
|
for (const fk of table.foreignKeys) {
|
|
4217
4240
|
if (deferredFkNames.has(fk.name)) continue;
|
|
4218
4241
|
definitions.push(
|
|
4219
|
-
`CONSTRAINT "${fk.name}" FOREIGN KEY ("${fk.column}") REFERENCES "${fk.refTable}" ("${fk.refColumn}") ON DELETE ${fk.onDelete} ON UPDATE ${fk.onUpdate}`
|
|
4242
|
+
`CONSTRAINT "${pgTruncate(fk.name)}" FOREIGN KEY ("${fk.column}") REFERENCES "${fk.refTable}" ("${fk.refColumn}") ON DELETE ${fk.onDelete} ON UPDATE ${fk.onUpdate}`
|
|
4220
4243
|
);
|
|
4221
4244
|
}
|
|
4222
4245
|
for (const check of table.checkConstraints) {
|
|
4223
|
-
definitions.push(`CONSTRAINT "${check.name}" CHECK (${check.check})`);
|
|
4246
|
+
definitions.push(`CONSTRAINT "${pgTruncate(check.name)}" CHECK (${check.check})`);
|
|
4224
4247
|
}
|
|
4225
4248
|
for (const col of table.columns) {
|
|
4226
4249
|
if (col.type === "ENUM" && col.value) {
|
|
4227
4250
|
definitions.push(
|
|
4228
|
-
`CONSTRAINT "${table.name}_${col.name}_check" CHECK ("${col.name}" IN (${col.value}))`
|
|
4251
|
+
`CONSTRAINT "${pgTruncate(`${table.name}_${col.name}_check`)}" CHECK ("${col.name}" IN (${col.value}))`
|
|
4229
4252
|
);
|
|
4230
4253
|
}
|
|
4231
4254
|
}
|
|
@@ -4249,7 +4272,7 @@ function buildColumnType(column) {
|
|
|
4249
4272
|
function buildAddColumn(tableName, column) {
|
|
4250
4273
|
let definition = `ALTER TABLE "${tableName}" ADD COLUMN "${column.name}" ${buildColumnType(column)}`;
|
|
4251
4274
|
if (column.isPrimary) definition += " PRIMARY KEY";
|
|
4252
|
-
if (column.isUnique) definition += ` CONSTRAINT "${tableName}_${column.name}_unique_index" UNIQUE`;
|
|
4275
|
+
if (column.isUnique) definition += ` CONSTRAINT "${pgTruncate(`${tableName}_${column.name}_unique_index`)}" UNIQUE`;
|
|
4253
4276
|
if (!column.isNullable) definition += " NOT NULL";
|
|
4254
4277
|
else definition += " NULL";
|
|
4255
4278
|
if (column.default) definition += ` DEFAULT ${column.default}`;
|
|
@@ -4258,36 +4281,88 @@ function buildAddColumn(tableName, column) {
|
|
|
4258
4281
|
}
|
|
4259
4282
|
function buildCreateIndex(tableName, index) {
|
|
4260
4283
|
const unique = index.isUnique ? "UNIQUE " : "";
|
|
4261
|
-
let sql = `CREATE ${unique}INDEX "${index.name}" ON "${tableName}" (${index.columns.map((column) => `"${column}" ${index.order}`).join(", ")})`;
|
|
4284
|
+
let sql = `CREATE ${unique}INDEX "${pgTruncate(index.name)}" ON "${tableName}" (${index.columns.map((column) => `"${column}" ${index.order}`).join(", ")})`;
|
|
4262
4285
|
if (index.where) sql += ` WHERE ${index.where}`;
|
|
4263
4286
|
sql += ";";
|
|
4264
4287
|
return sql;
|
|
4265
4288
|
}
|
|
4266
4289
|
function buildAddForeignKey(tableName, foreignKey) {
|
|
4267
|
-
return `ALTER TABLE "${tableName}" ADD CONSTRAINT "${foreignKey.name}" FOREIGN KEY ("${foreignKey.column}") REFERENCES "${foreignKey.refTable}" ("${foreignKey.refColumn}") ON DELETE ${foreignKey.onDelete} ON UPDATE ${foreignKey.onUpdate};`;
|
|
4290
|
+
return `ALTER TABLE "${tableName}" ADD CONSTRAINT "${pgTruncate(foreignKey.name)}" FOREIGN KEY ("${foreignKey.column}") REFERENCES "${foreignKey.refTable}" ("${foreignKey.refColumn}") ON DELETE ${foreignKey.onDelete} ON UPDATE ${foreignKey.onUpdate};`;
|
|
4268
4291
|
}
|
|
4269
4292
|
function buildAddCheckConstraint(tableName, constraint) {
|
|
4270
|
-
return `ALTER TABLE "${tableName}" ADD CONSTRAINT "${constraint.name}" CHECK (${constraint.check});`;
|
|
4293
|
+
return `ALTER TABLE "${tableName}" ADD CONSTRAINT "${pgTruncate(constraint.name)}" CHECK (${constraint.check});`;
|
|
4294
|
+
}
|
|
4295
|
+
function lowercaseOutsideStrings(s) {
|
|
4296
|
+
return s.replace(/'(?:[^']|'')*'|[^']+/g, (match) => {
|
|
4297
|
+
if (match.startsWith("'")) return match;
|
|
4298
|
+
return match.toLowerCase();
|
|
4299
|
+
});
|
|
4300
|
+
}
|
|
4301
|
+
function stripLeafParens(expr) {
|
|
4302
|
+
let prev = "";
|
|
4303
|
+
let curr = expr;
|
|
4304
|
+
while (prev !== curr) {
|
|
4305
|
+
prev = curr;
|
|
4306
|
+
curr = curr.replace(/\(([^()]*)\)/g, (match, inner) => {
|
|
4307
|
+
if (/\b(?:and|or)\b/i.test(inner)) return match;
|
|
4308
|
+
return inner;
|
|
4309
|
+
});
|
|
4310
|
+
}
|
|
4311
|
+
return curr;
|
|
4312
|
+
}
|
|
4313
|
+
function normalizeWhere(whereExpr) {
|
|
4314
|
+
if (!whereExpr) return "";
|
|
4315
|
+
let normalized = whereExpr.replace(/::\w+(\[\])?/g, "").replace(/"(\w+)"/g, "$1").replace(/\((\w+)\)/g, "$1").replace(/\s+/g, " ").trim();
|
|
4316
|
+
normalized = lowercaseOutsideStrings(normalized);
|
|
4317
|
+
while (normalized.startsWith("(") && normalized.endsWith(")")) {
|
|
4318
|
+
const inner = normalized.slice(1, -1);
|
|
4319
|
+
let depth = 0;
|
|
4320
|
+
let balanced = true;
|
|
4321
|
+
for (const char of inner) {
|
|
4322
|
+
if (char === "(") depth++;
|
|
4323
|
+
if (char === ")") depth--;
|
|
4324
|
+
if (depth < 0) {
|
|
4325
|
+
balanced = false;
|
|
4326
|
+
break;
|
|
4327
|
+
}
|
|
4328
|
+
}
|
|
4329
|
+
if (balanced && depth === 0) normalized = inner.trim();
|
|
4330
|
+
else break;
|
|
4331
|
+
}
|
|
4332
|
+
normalized = stripLeafParens(normalized);
|
|
4333
|
+
return normalized;
|
|
4271
4334
|
}
|
|
4272
4335
|
function indexSignature(name, columns, isUnique, order, where) {
|
|
4273
|
-
return `${name}|${columns.join(",")}|${isUnique}|${order}|${where
|
|
4336
|
+
return `${name}|${columns.join(",")}|${isUnique}|${order}|${normalizeWhere(where)}`;
|
|
4274
4337
|
}
|
|
4275
4338
|
function isFkChanged(desired, liveFk) {
|
|
4276
|
-
const desiredFk = desired.foreignKeys.find((fk) => fk.name === liveFk.name);
|
|
4339
|
+
const desiredFk = desired.foreignKeys.find((fk) => pgTruncate(fk.name) === liveFk.name);
|
|
4277
4340
|
if (!desiredFk) return true;
|
|
4278
4341
|
return desiredFk.column !== liveFk.column || desiredFk.refTable !== liveFk.refTable || desiredFk.refColumn !== liveFk.refColumn || desiredFk.onDelete !== liveFk.onDelete || desiredFk.onUpdate !== liveFk.onUpdate;
|
|
4279
4342
|
}
|
|
4343
|
+
var PG_MAX_IDENTIFIER = 63;
|
|
4344
|
+
function pgTruncate(name) {
|
|
4345
|
+
const buf = Buffer.from(name, "utf8");
|
|
4346
|
+
if (buf.length <= PG_MAX_IDENTIFIER) return name;
|
|
4347
|
+
let end = PG_MAX_IDENTIFIER;
|
|
4348
|
+
while (end > 0 && (buf[end] & 192) === 128) end--;
|
|
4349
|
+
return buf.subarray(0, end).toString("utf8");
|
|
4350
|
+
}
|
|
4280
4351
|
function normalizeCheckExpression(expr) {
|
|
4281
|
-
let
|
|
4282
|
-
const checkMatch =
|
|
4283
|
-
if (checkMatch)
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4352
|
+
let normalized = expr;
|
|
4353
|
+
const checkMatch = normalized.match(/^CHECK\s*\(([\s\S]*)\)\s*$/i);
|
|
4354
|
+
if (checkMatch) normalized = checkMatch[1];
|
|
4355
|
+
normalized = normalized.replace(/::\w+(\[\])?/g, "");
|
|
4356
|
+
normalized = normalized.replace(/=\s*ANY\s*\(\s*\(\s*ARRAY\s*\[([^\]]*)\]\s*\)\s*\)/gi, "IN ($1)");
|
|
4357
|
+
normalized = normalized.replace(/=\s*ANY\s*\(\s*ARRAY\s*\[([^\]]*)\]\s*\)/gi, "IN ($1)");
|
|
4358
|
+
normalized = normalized.replace(/\bIN\s*\(\s*('(?:[^']|'')*')\s*\)/gi, "= $1");
|
|
4359
|
+
normalized = normalized.replace(/"(\w+)"/g, "$1");
|
|
4360
|
+
normalized = normalized.replace(/\((\w+)\)/g, "$1");
|
|
4361
|
+
normalized = normalized.replace(/\s+/g, " ").trim();
|
|
4362
|
+
normalized = lowercaseOutsideStrings(normalized);
|
|
4363
|
+
normalized = normalized.replace(/<>/g, "!=");
|
|
4364
|
+
while (normalized.startsWith("(") && normalized.endsWith(")")) {
|
|
4365
|
+
const inner = normalized.slice(1, -1);
|
|
4291
4366
|
let depth = 0;
|
|
4292
4367
|
let balanced = true;
|
|
4293
4368
|
for (const char of inner) {
|
|
@@ -4298,11 +4373,12 @@ function normalizeCheckExpression(expr) {
|
|
|
4298
4373
|
break;
|
|
4299
4374
|
}
|
|
4300
4375
|
}
|
|
4301
|
-
if (balanced && depth === 0)
|
|
4376
|
+
if (balanced && depth === 0) normalized = inner.trim();
|
|
4302
4377
|
else break;
|
|
4303
4378
|
}
|
|
4304
|
-
|
|
4305
|
-
|
|
4379
|
+
normalized = stripLeafParens(normalized);
|
|
4380
|
+
normalized = normalized.replace(/\s*,\s*/g, ", ");
|
|
4381
|
+
return normalized;
|
|
4306
4382
|
}
|
|
4307
4383
|
function isSerialMatch(column, liveCol) {
|
|
4308
4384
|
if (column.hasAutoIncrement || column.type === "BIGSERIAL" || column.type === "SERIAL") {
|
|
@@ -4315,7 +4391,7 @@ function modifiersDiffer(column, liveColumn) {
|
|
|
4315
4391
|
const desiredLength = column.length ?? null;
|
|
4316
4392
|
if (desiredLength !== liveColumn.characterMaximumLength) return true;
|
|
4317
4393
|
if (column.type === "DECIMAL" && column.value) {
|
|
4318
|
-
const parts = column.value.replace(/['"]/g, "").split(
|
|
4394
|
+
const parts = column.value.replace(/['"]/g, "").split(/[-,]/);
|
|
4319
4395
|
const desiredPrecision = parseInt(parts[0], 10);
|
|
4320
4396
|
const desiredScale = parts.length > 1 ? parseInt(parts[1], 10) : 0;
|
|
4321
4397
|
if (liveColumn.numericPrecision !== desiredPrecision || liveColumn.numericScale !== desiredScale) return true;
|
|
@@ -4350,8 +4426,8 @@ function defaultsMatch(desired, live, column) {
|
|
|
4350
4426
|
if (column.hasAutoIncrement || column.type === "BIGSERIAL" || column.type === "SERIAL") return true;
|
|
4351
4427
|
if (desired === null && live === null) return true;
|
|
4352
4428
|
if (desired === null || live === null) return false;
|
|
4353
|
-
const normalizedLive = live.replace(/::[
|
|
4354
|
-
return desired.trim() === normalizedLive;
|
|
4429
|
+
const normalizedLive = live.replace(/::[a-z][a-z0-9_ ]*(\[\])?$/gi, "").trim();
|
|
4430
|
+
return lowercaseOutsideStrings(desired.trim()) === lowercaseOutsideStrings(normalizedLive);
|
|
4355
4431
|
}
|
|
4356
4432
|
|
|
4357
4433
|
// src/restura/sql/PsqlTransaction.ts
|