rake-db 2.36.14 → 2.36.16
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.d.ts +5 -3
- package/dist/index.js +51 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +51 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Adapter, Column as Column$1, ColumnSchemaConfig,
|
|
1
|
+
import { Adapter, Column as Column$1, ColumnSchemaConfig, ColumnsByType, ColumnsShape, DbDomainArg, DbResult, DbStructureDomainsMap, DefaultColumnTypes, DefaultPrivileges, DefaultSchemaConfig, EmptyObject, EnumColumn, Grant, MaybeArray, MaybePromise, NoPrimaryKeyOption, NonUniqDataItem, PickQueryQ, QueryData, QueryLogObject, QueryLogOptions, QueryLogger, QuerySchema, RawSqlBase, RecordOptionalString, RecordString, RlsPolicy, SearchWeight, TableData, TableDataFn, TableDataItem, TableDataMethods, raw } from "pqb/internal";
|
|
2
2
|
import { Db } from "pqb";
|
|
3
3
|
declare namespace DbStructure {
|
|
4
4
|
interface TableNameAndSchemaName {
|
|
@@ -87,6 +87,8 @@ declare namespace DbStructure {
|
|
|
87
87
|
name: string;
|
|
88
88
|
using: string;
|
|
89
89
|
unique: boolean;
|
|
90
|
+
/** Deferrability mode when the unique index is backed by a constraint. */
|
|
91
|
+
deferrable?: false | 'immediate' | 'deferred';
|
|
90
92
|
columns: (({
|
|
91
93
|
column: string;
|
|
92
94
|
} | {
|
|
@@ -576,7 +578,7 @@ declare namespace RakeDbAst {
|
|
|
576
578
|
export {};
|
|
577
579
|
}
|
|
578
580
|
interface TableMethods {
|
|
579
|
-
enum(name: string): EnumColumn<
|
|
581
|
+
enum(name: string): EnumColumn<DefaultSchemaConfig, undefined, [string, ...string[]]>;
|
|
580
582
|
}
|
|
581
583
|
type Add = typeof add;
|
|
582
584
|
declare function add(item: Column$1, options?: {
|
|
@@ -721,7 +723,7 @@ type TableOptions = {
|
|
|
721
723
|
language?: string;
|
|
722
724
|
};
|
|
723
725
|
type MigrationColumnTypes<CT> = Omit<CT, 'enum'> & {
|
|
724
|
-
enum: (name: string) => EnumColumn<
|
|
726
|
+
enum: (name: string) => EnumColumn<DefaultSchemaConfig, unknown, readonly string[]>;
|
|
725
727
|
};
|
|
726
728
|
type ColumnsShapeCallback<CT, Shape extends ColumnsShape = ColumnsShape> = (t: MigrationColumnTypes<CT> & {
|
|
727
729
|
raw: typeof raw;
|
package/dist/index.js
CHANGED
|
@@ -266,17 +266,20 @@ const getExcludeName = (table, columns) => getIndexOrExcludeName(table, columns,
|
|
|
266
266
|
const indexesToQuery = (up, { schema, name: tableName }, indexes, snakeCase, language) => {
|
|
267
267
|
return indexes.map((index) => {
|
|
268
268
|
const { options } = index;
|
|
269
|
+
const isDeferrableUnique = isActiveUniqueDeferrable(options.deferrable);
|
|
270
|
+
if (isDeferrableUnique && !options.unique) throw new Error("Only unique indexes can be deferrable");
|
|
269
271
|
const { columns, include, name } = getIndexOrExcludeMainOptions(tableName, index, getIndexName, snakeCase);
|
|
270
|
-
if (!up) return { text: `DROP INDEX "${name}"${options.dropMode ? ` ${options.dropMode}` : ""}` };
|
|
272
|
+
if (!up) return { text: `${isDeferrableUnique ? `ALTER TABLE ${quoteTable(schema, tableName)} DROP CONSTRAINT "${name}"` : `DROP INDEX "${name}"`}${options.dropMode ? ` ${options.dropMode}` : ""}` };
|
|
273
|
+
if (isDeferrableUnique) validateDeferrableUnique(index);
|
|
271
274
|
const values = [];
|
|
272
|
-
const sql = ["CREATE"];
|
|
273
|
-
if (options.unique) sql.push("UNIQUE");
|
|
274
|
-
sql.push(`INDEX "${name}" ON ${quoteTable(schema, tableName)}`);
|
|
275
|
+
const sql = isDeferrableUnique ? [`ALTER TABLE ${quoteTable(schema, tableName)} ADD CONSTRAINT "${name}"`, `UNIQUE${options.nullsNotDistinct ? " NULLS NOT DISTINCT" : ""}`] : ["CREATE"];
|
|
276
|
+
if (!isDeferrableUnique && options.unique) sql.push("UNIQUE");
|
|
277
|
+
if (!isDeferrableUnique) sql.push(`INDEX "${name}" ON ${quoteTable(schema, tableName)}`);
|
|
275
278
|
const u = options.using || options.tsVector && "GIN";
|
|
276
|
-
if (u) sql.push(`USING ${u}`);
|
|
279
|
+
if (!isDeferrableUnique && u) sql.push(`USING ${u}`);
|
|
277
280
|
const lang = options.tsVector && options.languageColumn ? `"${options.languageColumn}"` : options.language ? `'${options.language}'` : `'${language || "english"}'`;
|
|
278
|
-
let hasWeight = options.tsVector && columns.some((column) => !!column.weight);
|
|
279
|
-
const columnsSql = columns.map((column) => {
|
|
281
|
+
let hasWeight = !isDeferrableUnique && options.tsVector && columns.some((column) => !!column.weight);
|
|
282
|
+
const columnsSql = isDeferrableUnique ? columns.map(uniqueConstraintColumnToSql) : columns.map((column) => {
|
|
280
283
|
let sql = [
|
|
281
284
|
"expression" in column ? `(${column.expression})` : `"${column.column}"`,
|
|
282
285
|
column.collate && `COLLATE ${quoteNameFromString(schema, column.collate)}`,
|
|
@@ -298,16 +301,45 @@ const indexesToQuery = (up, { schema, name: tableName }, indexes, snakeCase, lan
|
|
|
298
301
|
else columnList = columnsSql.join(", ");
|
|
299
302
|
sql.push(`(${columnList})`);
|
|
300
303
|
if (include && include.length) sql.push(`INCLUDE (${include.map((column) => `"${column}"`).join(", ")})`);
|
|
301
|
-
if (options.nullsNotDistinct) sql.push(`NULLS NOT DISTINCT`);
|
|
304
|
+
if (!isDeferrableUnique && options.nullsNotDistinct) sql.push(`NULLS NOT DISTINCT`);
|
|
302
305
|
if (options.with) sql.push(`WITH (${options.with})`);
|
|
303
|
-
if (options.tablespace) sql.push(`TABLESPACE ${options.tablespace}`);
|
|
304
|
-
if (options.where) sql.push(`WHERE ${(0, pqb_internal.isRawSQL)(options.where) ? options.where.toSQL({ values }) : options.where}`);
|
|
306
|
+
if (options.tablespace) sql.push(isDeferrableUnique ? `USING INDEX TABLESPACE ${options.tablespace}` : `TABLESPACE ${options.tablespace}`);
|
|
307
|
+
if (!isDeferrableUnique && options.where) sql.push(`WHERE ${(0, pqb_internal.isRawSQL)(options.where) ? options.where.toSQL({ values }) : options.where}`);
|
|
308
|
+
if (isDeferrableUnique) sql.push(`DEFERRABLE INITIALLY ${options.deferrable === "deferred" ? "DEFERRED" : "IMMEDIATE"}`);
|
|
305
309
|
return {
|
|
306
310
|
text: sql.join(" "),
|
|
307
311
|
values
|
|
308
312
|
};
|
|
309
313
|
});
|
|
310
314
|
};
|
|
315
|
+
const isActiveUniqueDeferrable = (deferrable) => deferrable === "immediate" || deferrable === "deferred";
|
|
316
|
+
const uniqueConstraintColumnToSql = (column) => {
|
|
317
|
+
if ("expression" in column) throw new Error("Deferrable unique constraints do not support expression indexes");
|
|
318
|
+
return `"${column.column}"`;
|
|
319
|
+
};
|
|
320
|
+
const validateDeferrableUnique = (index) => {
|
|
321
|
+
const { options } = index;
|
|
322
|
+
if (options.where) throw new Error("Deferrable unique constraints do not support partial indexes");
|
|
323
|
+
const unsupportedOption = getUnsupportedDeferrableUniqueIndexOption(options);
|
|
324
|
+
if (unsupportedOption) throw new Error(`Deferrable unique constraints do not support index option: ${unsupportedOption}`);
|
|
325
|
+
for (const column of index.columns) {
|
|
326
|
+
if ("expression" in column) throw new Error("Deferrable unique constraints do not support expression indexes");
|
|
327
|
+
const unsupportedColumnOption = getUnsupportedDeferrableUniqueColumnOption(column);
|
|
328
|
+
if (unsupportedColumnOption) throw new Error(`Deferrable unique constraints do not support index column option: ${unsupportedColumnOption}`);
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
const getUnsupportedDeferrableUniqueIndexOption = (options) => {
|
|
332
|
+
if (options.using) return "using";
|
|
333
|
+
if (options.tsVector) return "tsVector";
|
|
334
|
+
if (options.language) return "language";
|
|
335
|
+
if (options.languageColumn) return "languageColumn";
|
|
336
|
+
};
|
|
337
|
+
const getUnsupportedDeferrableUniqueColumnOption = (column) => {
|
|
338
|
+
if (column.collate) return "collate";
|
|
339
|
+
if (column.opclass) return "opclass";
|
|
340
|
+
if (column.order) return "order";
|
|
341
|
+
if (column.weight) return "weight";
|
|
342
|
+
};
|
|
311
343
|
const excludesToQuery = (up, { schema, name: tableName }, excludes, snakeCase) => {
|
|
312
344
|
return excludes.map((exclude) => {
|
|
313
345
|
const { options } = exclude;
|
|
@@ -4769,6 +4801,10 @@ const indexesSql = `SELECT
|
|
|
4769
4801
|
ic.relname "name",
|
|
4770
4802
|
am.amname AS "using",
|
|
4771
4803
|
i.indisunique "unique",
|
|
4804
|
+
CASE
|
|
4805
|
+
WHEN c.condeferrable AND c.condeferred THEN 'deferred'
|
|
4806
|
+
WHEN c.condeferrable THEN 'immediate'
|
|
4807
|
+
END AS "deferrable",
|
|
4772
4808
|
(
|
|
4773
4809
|
SELECT json_agg(
|
|
4774
4810
|
(
|
|
@@ -4865,6 +4901,9 @@ JOIN pg_class t ON t.oid = i.indrelid
|
|
|
4865
4901
|
JOIN pg_namespace n ON n.oid = t.relnamespace
|
|
4866
4902
|
JOIN pg_class ic ON ic.oid = i.indexrelid
|
|
4867
4903
|
JOIN pg_am am ON am.oid = ic.relam
|
|
4904
|
+
LEFT JOIN pg_constraint c
|
|
4905
|
+
ON c.conindid = ic.oid
|
|
4906
|
+
AND c.contype = 'u'
|
|
4868
4907
|
LEFT JOIN pg_catalog.pg_class tc ON (ic.reltoastrelid = tc.oid)
|
|
4869
4908
|
WHERE ${filterSchema("n.nspname")}
|
|
4870
4909
|
AND NOT i.indisprimary
|
|
@@ -5218,6 +5257,7 @@ async function introspectDbSchema(db, params) {
|
|
|
5218
5257
|
const excludes = [];
|
|
5219
5258
|
for (const index of raw.indexes) {
|
|
5220
5259
|
nullsToUndefined(index);
|
|
5260
|
+
if (!index.deferrable) index.deferrable = void 0;
|
|
5221
5261
|
for (const column of index.columns) {
|
|
5222
5262
|
if (!("expression" in column)) continue;
|
|
5223
5263
|
const s = column.expression;
|
|
@@ -5767,6 +5807,7 @@ const makeIndexOrExcludeOptions = (tableName, index, key) => {
|
|
|
5767
5807
|
name: index.name !== (key === "indexes" ? getIndexName : getExcludeName)(tableName, index.columns) ? index.name : void 0,
|
|
5768
5808
|
using: index.using === "btree" ? void 0 : index.using,
|
|
5769
5809
|
unique: index.unique || void 0,
|
|
5810
|
+
deferrable: index.deferrable || void 0,
|
|
5770
5811
|
include: index.include,
|
|
5771
5812
|
nullsNotDistinct: index.nullsNotDistinct || void 0,
|
|
5772
5813
|
with: index.with,
|