rake-db 1.3.2 → 2.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/.env +3 -0
- package/.env.local +1 -0
- package/README.md +1 -545
- package/db.ts +16 -0
- package/dist/index.d.ts +94 -0
- package/dist/index.esm.js +190 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +201 -0
- package/dist/index.js.map +1 -0
- package/jest-setup.ts +3 -0
- package/migrations/20221009210157_first.ts +8 -0
- package/migrations/20221009210200_second.ts +5 -0
- package/package.json +55 -41
- package/rollup.config.js +3 -0
- package/src/commands/createOrDrop.test.ts +145 -0
- package/src/commands/createOrDrop.ts +107 -0
- package/src/commands/generate.test.ts +133 -0
- package/src/commands/generate.ts +85 -0
- package/src/commands/migrateOrRollback.test.ts +118 -0
- package/src/commands/migrateOrRollback.ts +108 -0
- package/src/common.test.ts +281 -0
- package/src/common.ts +224 -0
- package/src/index.ts +2 -0
- package/src/migration/change.ts +20 -0
- package/src/migration/changeTable.test.ts +417 -0
- package/src/migration/changeTable.ts +375 -0
- package/src/migration/createTable.test.ts +269 -0
- package/src/migration/createTable.ts +169 -0
- package/src/migration/migration.test.ts +341 -0
- package/src/migration/migration.ts +296 -0
- package/src/migration/migrationUtils.ts +281 -0
- package/src/rakeDb.ts +29 -0
- package/src/test-utils.ts +45 -0
- package/tsconfig.json +12 -0
- package/dist/lib/createAndDrop.d.ts +0 -2
- package/dist/lib/createAndDrop.js +0 -63
- package/dist/lib/defaults.d.ts +0 -2
- package/dist/lib/defaults.js +0 -5
- package/dist/lib/errorCodes.d.ts +0 -4
- package/dist/lib/errorCodes.js +0 -7
- package/dist/lib/generate.d.ts +0 -1
- package/dist/lib/generate.js +0 -99
- package/dist/lib/help.d.ts +0 -2
- package/dist/lib/help.js +0 -24
- package/dist/lib/init.d.ts +0 -2
- package/dist/lib/init.js +0 -276
- package/dist/lib/migrate.d.ts +0 -4
- package/dist/lib/migrate.js +0 -189
- package/dist/lib/migration.d.ts +0 -37
- package/dist/lib/migration.js +0 -159
- package/dist/lib/schema/changeTable.d.ts +0 -23
- package/dist/lib/schema/changeTable.js +0 -109
- package/dist/lib/schema/column.d.ts +0 -31
- package/dist/lib/schema/column.js +0 -201
- package/dist/lib/schema/createTable.d.ts +0 -10
- package/dist/lib/schema/createTable.js +0 -53
- package/dist/lib/schema/foreignKey.d.ts +0 -11
- package/dist/lib/schema/foreignKey.js +0 -53
- package/dist/lib/schema/index.d.ts +0 -3
- package/dist/lib/schema/index.js +0 -54
- package/dist/lib/schema/primaryKey.d.ts +0 -9
- package/dist/lib/schema/primaryKey.js +0 -24
- package/dist/lib/schema/table.d.ts +0 -43
- package/dist/lib/schema/table.js +0 -110
- package/dist/lib/schema/timestamps.d.ts +0 -3
- package/dist/lib/schema/timestamps.js +0 -9
- package/dist/lib/utils.d.ts +0 -26
- package/dist/lib/utils.js +0 -114
- package/dist/rake-db.d.ts +0 -2
- package/dist/rake-db.js +0 -34
- package/dist/types.d.ts +0 -94
- package/dist/types.js +0 -40
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ColumnType,
|
|
3
|
+
columnTypes,
|
|
4
|
+
getColumnTypes,
|
|
5
|
+
getTableData,
|
|
6
|
+
Operators,
|
|
7
|
+
quote,
|
|
8
|
+
} from 'pqb';
|
|
9
|
+
import {
|
|
10
|
+
TableOptions,
|
|
11
|
+
ColumnsShapeCallback,
|
|
12
|
+
Migration,
|
|
13
|
+
ColumnIndex,
|
|
14
|
+
ColumnComment,
|
|
15
|
+
JoinTableOptions,
|
|
16
|
+
} from './migration';
|
|
17
|
+
import {
|
|
18
|
+
addColumnComment,
|
|
19
|
+
addColumnIndex,
|
|
20
|
+
columnToSql,
|
|
21
|
+
constraintToSql,
|
|
22
|
+
getPrimaryKeysOfTable,
|
|
23
|
+
migrateComments,
|
|
24
|
+
migrateIndexes,
|
|
25
|
+
primaryKeyToSql,
|
|
26
|
+
} from './migrationUtils';
|
|
27
|
+
import { joinWords } from '../common';
|
|
28
|
+
import { singular } from 'pluralize';
|
|
29
|
+
|
|
30
|
+
class UnknownColumn extends ColumnType {
|
|
31
|
+
operators = Operators.any;
|
|
32
|
+
|
|
33
|
+
constructor(public dataType: string) {
|
|
34
|
+
super();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const createJoinTable = async (
|
|
39
|
+
migration: Migration,
|
|
40
|
+
up: boolean,
|
|
41
|
+
tables: string[],
|
|
42
|
+
options: JoinTableOptions,
|
|
43
|
+
fn?: ColumnsShapeCallback,
|
|
44
|
+
) => {
|
|
45
|
+
const tableName = options.tableName || joinWords(...tables);
|
|
46
|
+
|
|
47
|
+
if (!up) {
|
|
48
|
+
return createTable(migration, up, tableName, options, () => ({}));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const tablesWithPrimaryKeys = await Promise.all(
|
|
52
|
+
tables.map(
|
|
53
|
+
async (table) =>
|
|
54
|
+
[
|
|
55
|
+
table,
|
|
56
|
+
await getPrimaryKeysOfTable(migration, table).then((items) =>
|
|
57
|
+
items.map((item) => ({
|
|
58
|
+
...item,
|
|
59
|
+
joinedName: joinWords(singular(table), item.name),
|
|
60
|
+
})),
|
|
61
|
+
),
|
|
62
|
+
] as const,
|
|
63
|
+
),
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
return createTable(migration, up, tableName, options, (t) => {
|
|
67
|
+
const result: Record<string, ColumnType> = {};
|
|
68
|
+
|
|
69
|
+
tablesWithPrimaryKeys.forEach(([table, primaryKeys]) => {
|
|
70
|
+
if (primaryKeys.length === 1) {
|
|
71
|
+
const [{ type, joinedName, name }] = primaryKeys;
|
|
72
|
+
|
|
73
|
+
const column = new UnknownColumn(type);
|
|
74
|
+
|
|
75
|
+
result[joinedName] = column.foreignKey(table, name);
|
|
76
|
+
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
primaryKeys.forEach(({ joinedName, type }) => {
|
|
81
|
+
result[joinedName] = new UnknownColumn(type);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
t.foreignKey(
|
|
85
|
+
primaryKeys.map((key) => key.joinedName) as [string, ...string[]],
|
|
86
|
+
table,
|
|
87
|
+
primaryKeys.map((key) => key.name) as [string, ...string[]],
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
if (fn) {
|
|
92
|
+
Object.assign(result, fn(t));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
t.primaryKey(
|
|
96
|
+
tablesWithPrimaryKeys.flatMap(([, primaryKeys]) =>
|
|
97
|
+
primaryKeys.map((item) => item.joinedName),
|
|
98
|
+
),
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
return result;
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export const createTable = async (
|
|
106
|
+
migration: Migration,
|
|
107
|
+
up: boolean,
|
|
108
|
+
tableName: string,
|
|
109
|
+
options: TableOptions,
|
|
110
|
+
fn: ColumnsShapeCallback,
|
|
111
|
+
) => {
|
|
112
|
+
const shape = getColumnTypes(columnTypes, fn);
|
|
113
|
+
|
|
114
|
+
if (!up) {
|
|
115
|
+
const { dropMode } = options;
|
|
116
|
+
await migration.query(
|
|
117
|
+
`DROP TABLE "${tableName}"${dropMode ? ` ${dropMode}` : ''}`,
|
|
118
|
+
);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const lines: string[] = [];
|
|
123
|
+
|
|
124
|
+
const state: {
|
|
125
|
+
migration: Migration;
|
|
126
|
+
tableName: string;
|
|
127
|
+
values: unknown[];
|
|
128
|
+
indexes: ColumnIndex[];
|
|
129
|
+
comments: ColumnComment[];
|
|
130
|
+
} = {
|
|
131
|
+
migration,
|
|
132
|
+
tableName,
|
|
133
|
+
values: [],
|
|
134
|
+
indexes: [],
|
|
135
|
+
comments: [],
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
for (const key in shape) {
|
|
139
|
+
const item = shape[key];
|
|
140
|
+
addColumnIndex(state.indexes, key, item);
|
|
141
|
+
addColumnComment(state.comments, key, item);
|
|
142
|
+
lines.push(`\n ${columnToSql(key, item, state)}`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const tableData = getTableData();
|
|
146
|
+
if (tableData.primaryKey) {
|
|
147
|
+
lines.push(`\n ${primaryKeyToSql(tableData.primaryKey)}`);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
tableData.foreignKeys.forEach((foreignKey) => {
|
|
151
|
+
lines.push(`\n ${constraintToSql(state.tableName, up, foreignKey)}`);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
await migration.query({
|
|
155
|
+
text: `CREATE TABLE "${tableName}" (${lines.join(',')}\n)`,
|
|
156
|
+
values: state.values,
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
state.indexes.push(...tableData.indexes);
|
|
160
|
+
|
|
161
|
+
await migrateIndexes(state, state.indexes, up);
|
|
162
|
+
await migrateComments(state, state.comments);
|
|
163
|
+
|
|
164
|
+
if (options.comment) {
|
|
165
|
+
await migration.query(
|
|
166
|
+
`COMMENT ON TABLE "${tableName}" IS ${quote(options.comment)}`,
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
};
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import { expectSql, getDb, queryMock, resetDb, toLine } from '../test-utils';
|
|
2
|
+
import { getPrimaryKeysOfTable } from './migrationUtils';
|
|
3
|
+
|
|
4
|
+
const db = getDb();
|
|
5
|
+
|
|
6
|
+
jest.mock('./migrationUtils', () => ({
|
|
7
|
+
...jest.requireActual('./migrationUtils'),
|
|
8
|
+
getPrimaryKeysOfTable: jest.fn(),
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
describe('migration', () => {
|
|
12
|
+
beforeEach(resetDb);
|
|
13
|
+
|
|
14
|
+
describe('renameTable', () => {
|
|
15
|
+
it('should rename a table', async () => {
|
|
16
|
+
const fn = () => {
|
|
17
|
+
return db.renameTable('from', 'to');
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
await fn();
|
|
21
|
+
expectSql(`
|
|
22
|
+
ALTER TABLE "from" RENAME TO "to"
|
|
23
|
+
`);
|
|
24
|
+
|
|
25
|
+
db.up = false;
|
|
26
|
+
queryMock.mockClear();
|
|
27
|
+
await fn();
|
|
28
|
+
expectSql(`
|
|
29
|
+
ALTER TABLE "to" RENAME TO "from"
|
|
30
|
+
`);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
(['addColumn', 'dropColumn'] as const).forEach((action) => {
|
|
35
|
+
describe(action, () => {
|
|
36
|
+
it(`should use changeTable to ${
|
|
37
|
+
action === 'addColumn' ? 'add' : 'drop'
|
|
38
|
+
} a column`, async () => {
|
|
39
|
+
const fn = () => {
|
|
40
|
+
return db[action]('table', 'column', (t) => t.text());
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const expectAddColumn = () => {
|
|
44
|
+
expectSql(`
|
|
45
|
+
ALTER TABLE "table"
|
|
46
|
+
ADD COLUMN "column" text NOT NULL
|
|
47
|
+
`);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const expectDropColumn = () => {
|
|
51
|
+
expectSql(`
|
|
52
|
+
ALTER TABLE "table"
|
|
53
|
+
DROP COLUMN "column"
|
|
54
|
+
`);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
await fn();
|
|
58
|
+
(action === 'addColumn' ? expectAddColumn : expectDropColumn)();
|
|
59
|
+
|
|
60
|
+
db.up = false;
|
|
61
|
+
queryMock.mockClear();
|
|
62
|
+
await fn();
|
|
63
|
+
(action === 'addColumn' ? expectDropColumn : expectAddColumn)();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
(['addIndex', 'dropIndex'] as const).forEach((action) => {
|
|
69
|
+
describe(action, () => {
|
|
70
|
+
it(`should use changeTable to ${
|
|
71
|
+
action === 'addIndex' ? 'add' : 'drop'
|
|
72
|
+
} an index`, async () => {
|
|
73
|
+
const fn = () => {
|
|
74
|
+
return db[action](
|
|
75
|
+
'table',
|
|
76
|
+
['id', { column: 'name', order: 'DESC' }],
|
|
77
|
+
{
|
|
78
|
+
name: 'indexName',
|
|
79
|
+
},
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const expectAddIndex = () => {
|
|
84
|
+
expectSql(`
|
|
85
|
+
CREATE INDEX "indexName" ON "table" ("id", "name" DESC)
|
|
86
|
+
`);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const expectDropIndex = () => {
|
|
90
|
+
expectSql(`
|
|
91
|
+
DROP INDEX "indexName"
|
|
92
|
+
`);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
await fn();
|
|
96
|
+
(action === 'addIndex' ? expectAddIndex : expectDropIndex)();
|
|
97
|
+
|
|
98
|
+
db.up = false;
|
|
99
|
+
queryMock.mockClear();
|
|
100
|
+
await fn();
|
|
101
|
+
(action === 'addIndex' ? expectDropIndex : expectAddIndex)();
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
(['addForeignKey', 'dropForeignKey'] as const).forEach((action) => {
|
|
107
|
+
describe(action, () => {
|
|
108
|
+
it(`should use changeTable to ${
|
|
109
|
+
action === 'addForeignKey' ? 'add' : 'drop'
|
|
110
|
+
} a foreignKey`, async () => {
|
|
111
|
+
const fn = () => {
|
|
112
|
+
return db[action](
|
|
113
|
+
'table',
|
|
114
|
+
['id', 'name'],
|
|
115
|
+
'otherTable',
|
|
116
|
+
['foreignId', 'foreignName'],
|
|
117
|
+
{
|
|
118
|
+
name: 'constraintName',
|
|
119
|
+
match: 'FULL',
|
|
120
|
+
onUpdate: 'CASCADE',
|
|
121
|
+
onDelete: 'CASCADE',
|
|
122
|
+
dropMode: 'CASCADE',
|
|
123
|
+
},
|
|
124
|
+
);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const expectAddForeignKey = () => {
|
|
128
|
+
const expectedConstraint = toLine(`
|
|
129
|
+
ADD CONSTRAINT "constraintName"
|
|
130
|
+
FOREIGN KEY ("id", "name")
|
|
131
|
+
REFERENCES "otherTable"("foreignId", "foreignName")
|
|
132
|
+
MATCH FULL
|
|
133
|
+
ON DELETE CASCADE
|
|
134
|
+
ON UPDATE CASCADE
|
|
135
|
+
`);
|
|
136
|
+
expectSql(`
|
|
137
|
+
ALTER TABLE "table"
|
|
138
|
+
${expectedConstraint}
|
|
139
|
+
`);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const expectDropForeignKey = () => {
|
|
143
|
+
expectSql(`
|
|
144
|
+
ALTER TABLE "table"
|
|
145
|
+
DROP CONSTRAINT "constraintName" CASCADE
|
|
146
|
+
`);
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
await fn();
|
|
150
|
+
(action === 'addForeignKey'
|
|
151
|
+
? expectAddForeignKey
|
|
152
|
+
: expectDropForeignKey)();
|
|
153
|
+
|
|
154
|
+
db.up = false;
|
|
155
|
+
queryMock.mockClear();
|
|
156
|
+
await fn();
|
|
157
|
+
(action === 'addForeignKey'
|
|
158
|
+
? expectDropForeignKey
|
|
159
|
+
: expectAddForeignKey)();
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
(['addPrimaryKey', 'dropPrimaryKey'] as const).forEach((action) => {
|
|
165
|
+
describe(action, () => {
|
|
166
|
+
it(`should use changeTable to ${
|
|
167
|
+
action === 'addPrimaryKey' ? 'add' : 'drop'
|
|
168
|
+
} primary key`, async () => {
|
|
169
|
+
const fn = () => {
|
|
170
|
+
return db[action]('table', ['id', 'name']);
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const expectAddPrimaryKey = () => {
|
|
174
|
+
expectSql(`
|
|
175
|
+
ALTER TABLE "table"
|
|
176
|
+
ADD PRIMARY KEY ("id", "name")
|
|
177
|
+
`);
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const expectDropPrimaryKey = () => {
|
|
181
|
+
expectSql(`
|
|
182
|
+
ALTER TABLE "table"
|
|
183
|
+
DROP CONSTRAINT "table_pkey"
|
|
184
|
+
`);
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
await fn();
|
|
188
|
+
(action === 'addPrimaryKey'
|
|
189
|
+
? expectAddPrimaryKey
|
|
190
|
+
: expectDropPrimaryKey)();
|
|
191
|
+
|
|
192
|
+
db.up = false;
|
|
193
|
+
queryMock.mockClear();
|
|
194
|
+
await fn();
|
|
195
|
+
(action === 'addPrimaryKey'
|
|
196
|
+
? expectDropPrimaryKey
|
|
197
|
+
: expectAddPrimaryKey)();
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('should use changeTable to add primary key with constraint name', async () => {
|
|
201
|
+
const fn = () => {
|
|
202
|
+
return db.addPrimaryKey('table', ['id', 'name'], {
|
|
203
|
+
name: 'primaryKeyName',
|
|
204
|
+
});
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
await fn();
|
|
208
|
+
expectSql(`
|
|
209
|
+
ALTER TABLE "table"
|
|
210
|
+
ADD CONSTRAINT "primaryKeyName" PRIMARY KEY ("id", "name")
|
|
211
|
+
`);
|
|
212
|
+
|
|
213
|
+
db.up = false;
|
|
214
|
+
queryMock.mockClear();
|
|
215
|
+
await fn();
|
|
216
|
+
expectSql(`
|
|
217
|
+
ALTER TABLE "table"
|
|
218
|
+
DROP CONSTRAINT "primaryKeyName"
|
|
219
|
+
`);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
describe('renameColumn', () => {
|
|
225
|
+
it('should use changeTable to rename a column', async () => {
|
|
226
|
+
const fn = () => {
|
|
227
|
+
return db.renameColumn('table', 'from', 'to');
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
await fn();
|
|
231
|
+
expectSql(`
|
|
232
|
+
ALTER TABLE "table"
|
|
233
|
+
RENAME COLUMN "from" TO "to"
|
|
234
|
+
`);
|
|
235
|
+
|
|
236
|
+
db.up = false;
|
|
237
|
+
queryMock.mockClear();
|
|
238
|
+
await fn();
|
|
239
|
+
expectSql(`
|
|
240
|
+
ALTER TABLE "table"
|
|
241
|
+
RENAME COLUMN "to" TO "from"
|
|
242
|
+
`);
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
(['createJoinTable', 'dropJoinTable'] as const).forEach((action) => {
|
|
247
|
+
describe(action, () => {
|
|
248
|
+
it(`should ${
|
|
249
|
+
action === 'createJoinTable' ? 'create' : 'drop'
|
|
250
|
+
} a join table`, async () => {
|
|
251
|
+
const fn = () => {
|
|
252
|
+
return db[action](['posts', 'comments'], (t) => ({
|
|
253
|
+
...t.timestamps(),
|
|
254
|
+
}));
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const expectCreateTable = async () => {
|
|
258
|
+
(getPrimaryKeysOfTable as jest.Mock)
|
|
259
|
+
.mockResolvedValueOnce([
|
|
260
|
+
{
|
|
261
|
+
name: 'uuid',
|
|
262
|
+
type: 'uuid',
|
|
263
|
+
},
|
|
264
|
+
])
|
|
265
|
+
.mockResolvedValueOnce([
|
|
266
|
+
{
|
|
267
|
+
name: 'id',
|
|
268
|
+
type: 'integer',
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
name: 'authorName',
|
|
272
|
+
type: 'text',
|
|
273
|
+
},
|
|
274
|
+
]);
|
|
275
|
+
|
|
276
|
+
await fn();
|
|
277
|
+
|
|
278
|
+
expectSql(`
|
|
279
|
+
CREATE TABLE "postsComments" (
|
|
280
|
+
"postUuid" uuid NOT NULL REFERENCES "posts"("uuid"),
|
|
281
|
+
"commentId" integer NOT NULL,
|
|
282
|
+
"commentAuthorName" text NOT NULL,
|
|
283
|
+
"createdAt" timestamp NOT NULL DEFAULT now(),
|
|
284
|
+
"updatedAt" timestamp NOT NULL DEFAULT now(),
|
|
285
|
+
PRIMARY KEY ("postUuid", "commentId", "commentAuthorName"),
|
|
286
|
+
CONSTRAINT "postsCommentsToComments" FOREIGN KEY ("commentId", "commentAuthorName") REFERENCES "comments"("id", "authorName")
|
|
287
|
+
)
|
|
288
|
+
`);
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
const expectDropTable = async () => {
|
|
292
|
+
await fn();
|
|
293
|
+
|
|
294
|
+
expectSql(`
|
|
295
|
+
DROP TABLE "postsComments"
|
|
296
|
+
`);
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
await (action === 'createJoinTable'
|
|
300
|
+
? expectCreateTable
|
|
301
|
+
: expectDropTable)();
|
|
302
|
+
|
|
303
|
+
db.up = false;
|
|
304
|
+
queryMock.mockClear();
|
|
305
|
+
await (action === 'createJoinTable'
|
|
306
|
+
? expectDropTable
|
|
307
|
+
: expectCreateTable)();
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
describe('tableExists', () => {
|
|
313
|
+
it('should return boolean', async () => {
|
|
314
|
+
queryMock.mockResolvedValueOnce({ rowCount: 1 });
|
|
315
|
+
expect(await db.tableExists('table')).toBe(true);
|
|
316
|
+
|
|
317
|
+
queryMock.mockResolvedValueOnce({ rowCount: 0 });
|
|
318
|
+
expect(await db.tableExists('table')).toBe(false);
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
describe('columnExists', () => {
|
|
323
|
+
it('should return boolean', async () => {
|
|
324
|
+
queryMock.mockResolvedValueOnce({ rowCount: 1 });
|
|
325
|
+
expect(await db.columnExists('table', 'colum')).toBe(true);
|
|
326
|
+
|
|
327
|
+
queryMock.mockResolvedValueOnce({ rowCount: 0 });
|
|
328
|
+
expect(await db.columnExists('table', 'colum')).toBe(false);
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
describe('constraintExists', () => {
|
|
333
|
+
it('should return boolean', async () => {
|
|
334
|
+
queryMock.mockResolvedValueOnce({ rowCount: 1 });
|
|
335
|
+
expect(await db.constraintExists('constraintName')).toBe(true);
|
|
336
|
+
|
|
337
|
+
queryMock.mockResolvedValueOnce({ rowCount: 0 });
|
|
338
|
+
expect(await db.constraintExists('constraintName')).toBe(false);
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
});
|