rake-db 2.2.5 → 2.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/db.ts +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.esm.js +91 -59
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +91 -59
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/ast.ts +4 -0
- package/src/commands/migrateOrRollback.ts +8 -6
- package/src/common.test.ts +8 -6
- package/src/common.ts +20 -10
- package/src/migration/changeTable.test.ts +17 -0
- package/src/migration/changeTable.ts +13 -10
- package/src/migration/createJoinTable.test.ts +96 -0
- package/src/migration/createJoinTable.ts +17 -6
- package/src/migration/createTable.test.ts +16 -0
- package/src/migration/createTable.ts +11 -8
- package/src/migration/migration.test.ts +18 -86
- package/src/migration/migration.ts +18 -4
- package/src/migration/migrationUtils.ts +33 -21
- package/src/pull/dbStructure.test.ts +158 -0
- package/src/pull/dbStructure.ts +272 -0
- package/src/pull/getColumnByType.ts +15 -0
- package/src/pull/structureToAst.test.ts +308 -0
- package/src/pull/structureToAst.ts +145 -0
package/CHANGELOG.md
CHANGED
package/db.ts
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -113,6 +113,7 @@ declare namespace RakeDbAst {
|
|
|
113
113
|
type Table = {
|
|
114
114
|
type: 'table';
|
|
115
115
|
action: 'create' | 'drop';
|
|
116
|
+
schema?: string;
|
|
116
117
|
name: string;
|
|
117
118
|
shape: ColumnsShape;
|
|
118
119
|
noPrimaryKey: NoPrimaryKeyOption;
|
|
@@ -121,6 +122,7 @@ declare namespace RakeDbAst {
|
|
|
121
122
|
} & TableData;
|
|
122
123
|
type ChangeTable = {
|
|
123
124
|
type: 'changeTable';
|
|
125
|
+
schema?: string;
|
|
124
126
|
name: string;
|
|
125
127
|
comment?: string | null;
|
|
126
128
|
shape: Record<string, ChangeTableItem>;
|
|
@@ -162,7 +164,9 @@ declare namespace RakeDbAst {
|
|
|
162
164
|
};
|
|
163
165
|
type RenameTable = {
|
|
164
166
|
type: 'renameTable';
|
|
167
|
+
fromSchema?: string;
|
|
165
168
|
from: string;
|
|
169
|
+
toSchema?: string;
|
|
166
170
|
to: string;
|
|
167
171
|
};
|
|
168
172
|
type Schema = {
|
package/dist/index.esm.js
CHANGED
|
@@ -95,9 +95,9 @@ const setAdminCredentialsToOptions = async (options) => {
|
|
|
95
95
|
const createSchemaMigrations = async (db, config) => {
|
|
96
96
|
try {
|
|
97
97
|
await db.query(
|
|
98
|
-
`CREATE TABLE ${
|
|
99
|
-
config.migrationsTable
|
|
100
|
-
)} ( version TEXT NOT NULL )`
|
|
98
|
+
`CREATE TABLE ${quoteWithSchema({
|
|
99
|
+
name: config.migrationsTable
|
|
100
|
+
})} ( version TEXT NOT NULL )`
|
|
101
101
|
);
|
|
102
102
|
console.log("Created versions table");
|
|
103
103
|
} catch (err) {
|
|
@@ -173,13 +173,15 @@ const joinWords = (...words) => {
|
|
|
173
173
|
const joinColumns = (columns) => {
|
|
174
174
|
return columns.map((column) => `"${column}"`).join(", ");
|
|
175
175
|
};
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
|
|
176
|
+
const quoteWithSchema = ({
|
|
177
|
+
schema,
|
|
178
|
+
name
|
|
179
|
+
}) => {
|
|
180
|
+
return schema ? `"${schema}"."${name}"` : `"${name}"`;
|
|
181
|
+
};
|
|
182
|
+
const getSchemaAndTableFromName = (name) => {
|
|
183
|
+
const index = name.indexOf(".");
|
|
184
|
+
return index !== -1 ? [name.slice(0, index), name.slice(index + 1)] : [void 0, name];
|
|
183
185
|
};
|
|
184
186
|
|
|
185
187
|
let currentMigration;
|
|
@@ -230,7 +232,7 @@ const columnToSql = (key, item, values, hasMultiplePrimaryKeys) => {
|
|
|
230
232
|
}
|
|
231
233
|
if (item.isPrimaryKey && !hasMultiplePrimaryKeys) {
|
|
232
234
|
line.push("PRIMARY KEY");
|
|
233
|
-
} else if (!item.isNullable) {
|
|
235
|
+
} else if (!item.data.isNullable) {
|
|
234
236
|
line.push("NOT NULL");
|
|
235
237
|
}
|
|
236
238
|
if (item.data.default !== void 0) {
|
|
@@ -242,13 +244,13 @@ const columnToSql = (key, item, values, hasMultiplePrimaryKeys) => {
|
|
|
242
244
|
}
|
|
243
245
|
const { foreignKey } = item.data;
|
|
244
246
|
if (foreignKey) {
|
|
245
|
-
const table = getForeignKeyTable(
|
|
247
|
+
const [schema, table] = getForeignKeyTable(
|
|
246
248
|
"fn" in foreignKey ? foreignKey.fn : foreignKey.table
|
|
247
249
|
);
|
|
248
250
|
if (foreignKey.name) {
|
|
249
251
|
line.push(`CONSTRAINT "${foreignKey.name}"`);
|
|
250
252
|
}
|
|
251
|
-
line.push(referencesToSql(table, foreignKey.columns, foreignKey));
|
|
253
|
+
line.push(referencesToSql(schema, table, foreignKey.columns, foreignKey));
|
|
252
254
|
}
|
|
253
255
|
return line.join(" ");
|
|
254
256
|
};
|
|
@@ -269,25 +271,32 @@ const addColumnComment = (comments, key, item) => {
|
|
|
269
271
|
};
|
|
270
272
|
const getForeignKeyTable = (fnOrTable) => {
|
|
271
273
|
if (typeof fnOrTable === "string") {
|
|
272
|
-
return fnOrTable;
|
|
274
|
+
return getSchemaAndTableFromName(fnOrTable);
|
|
273
275
|
}
|
|
274
|
-
const
|
|
275
|
-
return
|
|
276
|
+
const item = new (fnOrTable())();
|
|
277
|
+
return [item.schema, item.table];
|
|
276
278
|
};
|
|
277
|
-
const constraintToSql = (
|
|
278
|
-
const constraintName = foreignKey.options.name || `${
|
|
279
|
+
const constraintToSql = ({ name }, up, foreignKey) => {
|
|
280
|
+
const constraintName = foreignKey.options.name || `${name}_${foreignKey.columns.join("_")}_fkey`;
|
|
279
281
|
if (!up) {
|
|
280
282
|
const { dropMode } = foreignKey.options;
|
|
281
283
|
return `CONSTRAINT "${constraintName}"${dropMode ? ` ${dropMode}` : ""}`;
|
|
282
284
|
}
|
|
283
|
-
const table = getForeignKeyTable(foreignKey.fnOrTable);
|
|
285
|
+
const [schema, table] = getForeignKeyTable(foreignKey.fnOrTable);
|
|
284
286
|
return `CONSTRAINT "${constraintName}" FOREIGN KEY (${joinColumns(
|
|
285
287
|
foreignKey.columns
|
|
286
|
-
)}) ${referencesToSql(
|
|
287
|
-
|
|
288
|
-
|
|
288
|
+
)}) ${referencesToSql(
|
|
289
|
+
schema,
|
|
290
|
+
table,
|
|
291
|
+
foreignKey.foreignColumns,
|
|
292
|
+
foreignKey.options
|
|
293
|
+
)}`;
|
|
294
|
+
};
|
|
295
|
+
const referencesToSql = (schema, table, columns, foreignKey) => {
|
|
289
296
|
const sql = [
|
|
290
|
-
`REFERENCES ${
|
|
297
|
+
`REFERENCES ${quoteWithSchema({ schema, name: table })}(${joinColumns(
|
|
298
|
+
columns
|
|
299
|
+
)})`
|
|
291
300
|
];
|
|
292
301
|
if (foreignKey.match) {
|
|
293
302
|
sql.push(`MATCH ${foreignKey.match.toUpperCase()}`);
|
|
@@ -300,9 +309,9 @@ const referencesToSql = (table, columns, foreignKey) => {
|
|
|
300
309
|
}
|
|
301
310
|
return sql.join(" ");
|
|
302
311
|
};
|
|
303
|
-
const indexesToQuery = (up,
|
|
312
|
+
const indexesToQuery = (up, { schema, name }, indexes) => {
|
|
304
313
|
return indexes.map(({ columns, options }) => {
|
|
305
|
-
const indexName = options.name || joinWords(
|
|
314
|
+
const indexName = options.name || joinWords(name, ...columns.map(({ column }) => column), "index");
|
|
306
315
|
if (!up) {
|
|
307
316
|
return {
|
|
308
317
|
text: `DROP INDEX "${indexName}"${options.dropMode ? ` ${options.dropMode}` : ""}`,
|
|
@@ -314,7 +323,7 @@ const indexesToQuery = (up, tableName, indexes) => {
|
|
|
314
323
|
if (options.unique) {
|
|
315
324
|
sql.push("UNIQUE");
|
|
316
325
|
}
|
|
317
|
-
sql.push(`INDEX "${indexName}" ON ${
|
|
326
|
+
sql.push(`INDEX "${indexName}" ON ${quoteWithSchema({ schema, name })}`);
|
|
318
327
|
if (options.using) {
|
|
319
328
|
sql.push(`USING ${options.using}`);
|
|
320
329
|
}
|
|
@@ -354,11 +363,11 @@ const indexesToQuery = (up, tableName, indexes) => {
|
|
|
354
363
|
return { text: sql.join(" "), values };
|
|
355
364
|
});
|
|
356
365
|
};
|
|
357
|
-
const commentsToQuery = (
|
|
366
|
+
const commentsToQuery = (schemaTable, comments) => {
|
|
358
367
|
return comments.map(({ column, comment }) => ({
|
|
359
|
-
text: `COMMENT ON COLUMN ${
|
|
360
|
-
|
|
361
|
-
)}`,
|
|
368
|
+
text: `COMMENT ON COLUMN ${quoteWithSchema(
|
|
369
|
+
schemaTable
|
|
370
|
+
)}."${column}" IS ${quote(comment)}`,
|
|
362
371
|
values: []
|
|
363
372
|
}));
|
|
364
373
|
};
|
|
@@ -440,10 +449,12 @@ const makeAst$1 = (up, tableName, shape, tableData, options, noPrimaryKey) => {
|
|
|
440
449
|
}
|
|
441
450
|
}
|
|
442
451
|
const primaryKey = tableData.primaryKey;
|
|
452
|
+
const [schema, table] = getSchemaAndTableFromName(tableName);
|
|
443
453
|
return __spreadProps$3(__spreadValues$4(__spreadProps$3(__spreadValues$4({
|
|
444
454
|
type: "table",
|
|
445
455
|
action: up ? "create" : "drop",
|
|
446
|
-
|
|
456
|
+
schema,
|
|
457
|
+
name: table,
|
|
447
458
|
shape
|
|
448
459
|
}, tableData), {
|
|
449
460
|
primaryKey: shapePKeys.length <= 1 ? primaryKey : primaryKey ? __spreadProps$3(__spreadValues$4({}, primaryKey), { columns: [...shapePKeys, ...primaryKey.columns] }) : { columns: shapePKeys }
|
|
@@ -477,7 +488,7 @@ const astToQueries$1 = (ast) => {
|
|
|
477
488
|
if (ast.action === "drop") {
|
|
478
489
|
return [
|
|
479
490
|
{
|
|
480
|
-
text: `DROP TABLE ${
|
|
491
|
+
text: `DROP TABLE ${quoteWithSchema(ast)}${ast.dropMode ? ` ${ast.dropMode}` : ""}`,
|
|
481
492
|
values: []
|
|
482
493
|
}
|
|
483
494
|
];
|
|
@@ -499,21 +510,21 @@ const astToQueries$1 = (ast) => {
|
|
|
499
510
|
}
|
|
500
511
|
ast.foreignKeys.forEach((foreignKey) => {
|
|
501
512
|
lines.push(`
|
|
502
|
-
${constraintToSql(ast
|
|
513
|
+
${constraintToSql(ast, true, foreignKey)}`);
|
|
503
514
|
});
|
|
504
515
|
indexes.push(...ast.indexes);
|
|
505
516
|
const result = [
|
|
506
517
|
{
|
|
507
|
-
text: `CREATE TABLE ${
|
|
518
|
+
text: `CREATE TABLE ${quoteWithSchema(ast)} (${lines.join(",")}
|
|
508
519
|
)`,
|
|
509
520
|
values
|
|
510
521
|
},
|
|
511
|
-
...indexesToQuery(true, ast
|
|
512
|
-
...commentsToQuery(ast
|
|
522
|
+
...indexesToQuery(true, ast, indexes),
|
|
523
|
+
...commentsToQuery(ast, comments)
|
|
513
524
|
];
|
|
514
525
|
if (ast.comment) {
|
|
515
526
|
result.push({
|
|
516
|
-
text: `COMMENT ON TABLE ${
|
|
527
|
+
text: `COMMENT ON TABLE ${quoteWithSchema(ast)} IS ${quote(ast.comment)}`,
|
|
517
528
|
values: []
|
|
518
529
|
});
|
|
519
530
|
}
|
|
@@ -608,7 +619,7 @@ const columnTypeToColumnChange = (item) => {
|
|
|
608
619
|
return __spreadProps$2(__spreadValues$3({
|
|
609
620
|
column: item,
|
|
610
621
|
type: item.toSQL(),
|
|
611
|
-
nullable: item.isNullable,
|
|
622
|
+
nullable: item.data.isNullable,
|
|
612
623
|
primaryKey: item.isPrimaryKey
|
|
613
624
|
}, item.data), {
|
|
614
625
|
foreignKey
|
|
@@ -681,9 +692,11 @@ const makeAst = (up, name, changeData, changeTableData2, options) => {
|
|
|
681
692
|
}
|
|
682
693
|
}
|
|
683
694
|
}
|
|
695
|
+
const [schema, table] = getSchemaAndTableFromName(name);
|
|
684
696
|
return __spreadValues$3({
|
|
685
697
|
type: "changeTable",
|
|
686
|
-
|
|
698
|
+
schema,
|
|
699
|
+
name: table,
|
|
687
700
|
comment: comment ? up ? Array.isArray(comment) ? comment[1] : comment : Array.isArray(comment) ? comment[0] : null : void 0,
|
|
688
701
|
shape
|
|
689
702
|
}, up ? changeTableData2 : { add: changeTableData2.drop, drop: changeTableData2.add });
|
|
@@ -693,7 +706,7 @@ const astToQueries = (ast) => {
|
|
|
693
706
|
const result = [];
|
|
694
707
|
if (ast.comment !== void 0) {
|
|
695
708
|
result.push({
|
|
696
|
-
text: `COMMENT ON TABLE ${
|
|
709
|
+
text: `COMMENT ON TABLE ${quoteWithSchema(ast)} IS ${quote(ast.comment)}`,
|
|
697
710
|
values: []
|
|
698
711
|
});
|
|
699
712
|
}
|
|
@@ -830,7 +843,7 @@ const astToQueries = (ast) => {
|
|
|
830
843
|
prependAlterTable.push(
|
|
831
844
|
...dropForeignKeys.map(
|
|
832
845
|
(foreignKey) => `
|
|
833
|
-
DROP ${constraintToSql(ast
|
|
846
|
+
DROP ${constraintToSql(ast, false, foreignKey)}`
|
|
834
847
|
)
|
|
835
848
|
);
|
|
836
849
|
alterTable.unshift(...prependAlterTable);
|
|
@@ -840,19 +853,19 @@ const astToQueries = (ast) => {
|
|
|
840
853
|
alterTable.push(
|
|
841
854
|
...addForeignKeys.map(
|
|
842
855
|
(foreignKey) => `
|
|
843
|
-
ADD ${constraintToSql(ast
|
|
856
|
+
ADD ${constraintToSql(ast, true, foreignKey)}`
|
|
844
857
|
)
|
|
845
858
|
);
|
|
846
859
|
if (alterTable.length) {
|
|
847
860
|
result.push({
|
|
848
|
-
text: `ALTER TABLE ${
|
|
861
|
+
text: `ALTER TABLE ${quoteWithSchema(ast)}
|
|
849
862
|
${alterTable.join(",\n ")}`,
|
|
850
863
|
values
|
|
851
864
|
});
|
|
852
865
|
}
|
|
853
|
-
result.push(...indexesToQuery(false, ast
|
|
854
|
-
result.push(...indexesToQuery(true, ast
|
|
855
|
-
result.push(...commentsToQuery(ast
|
|
866
|
+
result.push(...indexesToQuery(false, ast, dropIndexes));
|
|
867
|
+
result.push(...indexesToQuery(true, ast, addIndexes));
|
|
868
|
+
result.push(...commentsToQuery(ast, comments));
|
|
856
869
|
return result;
|
|
857
870
|
};
|
|
858
871
|
|
|
@@ -903,21 +916,28 @@ const createJoinTable = async (migration, up, tables, options, fn) => {
|
|
|
903
916
|
joinedName: joinWords(singular(table), item.name)
|
|
904
917
|
}))
|
|
905
918
|
);
|
|
919
|
+
const [schema, name] = getSchemaAndTableFromName(table);
|
|
906
920
|
if (!primaryKeys.length) {
|
|
907
921
|
throw new Error(
|
|
908
|
-
`Primary key for table ${
|
|
922
|
+
`Primary key for table ${quoteWithSchema({
|
|
923
|
+
schema,
|
|
924
|
+
name
|
|
925
|
+
})} is not defined`
|
|
909
926
|
);
|
|
910
927
|
}
|
|
911
|
-
return [table, primaryKeys];
|
|
928
|
+
return [schema, table, primaryKeys];
|
|
912
929
|
})
|
|
913
930
|
);
|
|
914
931
|
return createTable(migration, up, tableName, options, (t) => {
|
|
915
932
|
const result = {};
|
|
916
|
-
tablesWithPrimaryKeys.forEach(([table, primaryKeys]) => {
|
|
933
|
+
tablesWithPrimaryKeys.forEach(([schema, table, primaryKeys]) => {
|
|
917
934
|
if (primaryKeys.length === 1) {
|
|
918
935
|
const [{ type, joinedName, name }] = primaryKeys;
|
|
919
936
|
const column = new UnknownColumn(type);
|
|
920
|
-
result[joinedName] = column.foreignKey(
|
|
937
|
+
result[joinedName] = column.foreignKey(
|
|
938
|
+
schema ? `${schema}.${table}` : table,
|
|
939
|
+
name
|
|
940
|
+
);
|
|
921
941
|
return;
|
|
922
942
|
}
|
|
923
943
|
primaryKeys.forEach(({ joinedName, type }) => {
|
|
@@ -934,7 +954,7 @@ const createJoinTable = async (migration, up, tables, options, fn) => {
|
|
|
934
954
|
}
|
|
935
955
|
t.primaryKey(
|
|
936
956
|
tablesWithPrimaryKeys.flatMap(
|
|
937
|
-
([, primaryKeys]) => primaryKeys.map((item) => item.joinedName)
|
|
957
|
+
([, , primaryKeys]) => primaryKeys.map((item) => item.joinedName)
|
|
938
958
|
)
|
|
939
959
|
);
|
|
940
960
|
return result;
|
|
@@ -1000,13 +1020,23 @@ class Migration extends TransactionAdapter {
|
|
|
1000
1020
|
return changeTable(this, this.up, tableName, options, fn);
|
|
1001
1021
|
}
|
|
1002
1022
|
async renameTable(from, to) {
|
|
1023
|
+
const [fromSchema, f] = getSchemaAndTableFromName(this.up ? from : to);
|
|
1024
|
+
const [toSchema, t] = getSchemaAndTableFromName(this.up ? to : from);
|
|
1003
1025
|
const ast = {
|
|
1004
1026
|
type: "renameTable",
|
|
1005
|
-
|
|
1006
|
-
|
|
1027
|
+
fromSchema,
|
|
1028
|
+
from: f,
|
|
1029
|
+
toSchema,
|
|
1030
|
+
to: t
|
|
1007
1031
|
};
|
|
1008
1032
|
await this.query(
|
|
1009
|
-
`ALTER TABLE ${
|
|
1033
|
+
`ALTER TABLE ${quoteWithSchema({
|
|
1034
|
+
schema: ast.fromSchema,
|
|
1035
|
+
name: ast.from
|
|
1036
|
+
})} RENAME TO ${quoteWithSchema({
|
|
1037
|
+
schema: ast.toSchema,
|
|
1038
|
+
name: ast.to
|
|
1039
|
+
})}`
|
|
1010
1040
|
);
|
|
1011
1041
|
await runCodeUpdater(this, ast);
|
|
1012
1042
|
}
|
|
@@ -1230,20 +1260,22 @@ const processMigration = async (db, up, file, config, options, appCodeUpdaterCac
|
|
|
1230
1260
|
};
|
|
1231
1261
|
const saveMigratedVersion = async (db, version, config) => {
|
|
1232
1262
|
await db.query(
|
|
1233
|
-
`INSERT INTO ${
|
|
1263
|
+
`INSERT INTO ${quoteWithSchema({
|
|
1264
|
+
name: config.migrationsTable
|
|
1265
|
+
})} VALUES ('${version}')`
|
|
1234
1266
|
);
|
|
1235
1267
|
};
|
|
1236
1268
|
const removeMigratedVersion = async (db, version, config) => {
|
|
1237
1269
|
await db.query(
|
|
1238
|
-
`DELETE FROM ${
|
|
1239
|
-
config.migrationsTable
|
|
1240
|
-
)} WHERE version = '${version}'`
|
|
1270
|
+
`DELETE FROM ${quoteWithSchema({
|
|
1271
|
+
name: config.migrationsTable
|
|
1272
|
+
})} WHERE version = '${version}'`
|
|
1241
1273
|
);
|
|
1242
1274
|
};
|
|
1243
1275
|
const getMigratedVersionsMap = async (db, config) => {
|
|
1244
1276
|
try {
|
|
1245
1277
|
const result = await db.arrays(
|
|
1246
|
-
`SELECT * FROM ${
|
|
1278
|
+
`SELECT * FROM ${quoteWithSchema({ name: config.migrationsTable })}`
|
|
1247
1279
|
);
|
|
1248
1280
|
return Object.fromEntries(result.rows.map((row) => [row[0], true]));
|
|
1249
1281
|
} catch (err) {
|