@strapi/database 4.0.0-beta.11 → 4.0.0-beta.15
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/lib/dialects/mysql/schema-inspector.js +0 -4
- package/lib/dialects/postgresql/schema-inspector.js +1 -1
- package/lib/index.js +29 -2
- package/lib/migrations/index.js +1 -1
- package/lib/migrations/storage.js +9 -7
- package/lib/query/helpers/join.js +1 -1
- package/lib/query/query-builder.js +7 -4
- package/lib/schema/builder.js +45 -22
- package/lib/schema/storage.js +14 -10
- package/package.json +2 -2
|
@@ -123,10 +123,6 @@ class MysqlSchemaInspector {
|
|
|
123
123
|
return schema;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
getDatabaseSchema() {
|
|
127
|
-
return this.db.connection.client.connectionSettings.schema || 'public';
|
|
128
|
-
}
|
|
129
|
-
|
|
130
126
|
async getTables() {
|
|
131
127
|
const [rows] = await this.db.connection.raw(SQL_QUERIES.TABLE_LIST);
|
|
132
128
|
|
package/lib/index.js
CHANGED
|
@@ -13,16 +13,32 @@ const errors = require('./errors');
|
|
|
13
13
|
// TODO: move back into strapi
|
|
14
14
|
const { transformContentTypes } = require('./utils/content-types');
|
|
15
15
|
|
|
16
|
+
const createConnection = config => {
|
|
17
|
+
const knexInstance = knex(config);
|
|
18
|
+
|
|
19
|
+
return Object.assign(knexInstance, {
|
|
20
|
+
getSchemaName() {
|
|
21
|
+
return this.client.connectionSettings.schema;
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
16
26
|
class Database {
|
|
17
27
|
constructor(config) {
|
|
18
28
|
this.metadata = createMetadata(config.models);
|
|
19
29
|
|
|
20
|
-
this.config =
|
|
30
|
+
this.config = {
|
|
31
|
+
connection: {},
|
|
32
|
+
settings: {
|
|
33
|
+
forceMigration: true,
|
|
34
|
+
},
|
|
35
|
+
...config,
|
|
36
|
+
};
|
|
21
37
|
|
|
22
38
|
this.dialect = getDialect(this);
|
|
23
39
|
this.dialect.configure();
|
|
24
40
|
|
|
25
|
-
this.connection =
|
|
41
|
+
this.connection = createConnection(this.config.connection);
|
|
26
42
|
|
|
27
43
|
this.dialect.initialize();
|
|
28
44
|
|
|
@@ -42,6 +58,17 @@ class Database {
|
|
|
42
58
|
return this.entityManager.getRepository(uid);
|
|
43
59
|
}
|
|
44
60
|
|
|
61
|
+
getConnection(tableName) {
|
|
62
|
+
const schema = this.connection.getSchemaName();
|
|
63
|
+
const connection = tableName ? this.connection(tableName) : this.connection;
|
|
64
|
+
return schema ? connection.withSchema(schema) : connection;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
getSchemaConnection(trx = this.connection) {
|
|
68
|
+
const schema = this.connection.getSchemaName();
|
|
69
|
+
return schema ? trx.schema.withSchema(schema) : trx.schema;
|
|
70
|
+
}
|
|
71
|
+
|
|
45
72
|
queryBuilder(uid) {
|
|
46
73
|
return this.entityManager.createQueryBuilder(uid);
|
|
47
74
|
}
|
package/lib/migrations/index.js
CHANGED
|
@@ -27,7 +27,7 @@ const createUmzugProvider = db => {
|
|
|
27
27
|
|
|
28
28
|
fse.ensureDirSync(migrationDir);
|
|
29
29
|
|
|
30
|
-
const wrapFn = fn => db => db.
|
|
30
|
+
const wrapFn = fn => db => db.getConnection().transaction(trx => Promise.resolve(fn(trx)));
|
|
31
31
|
const storage = createStorage({ db, tableName: 'strapi_migrations' });
|
|
32
32
|
|
|
33
33
|
return new Umzug({
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const createStorage = (opts = {}) => {
|
|
4
|
-
const
|
|
5
|
-
const knex = opts.db.connection;
|
|
4
|
+
const { db, tableName = 'strapi_migrations' } = opts;
|
|
6
5
|
|
|
7
|
-
const hasMigrationTable = () =>
|
|
6
|
+
const hasMigrationTable = () => db.getSchemaConnection().hasTable(tableName);
|
|
8
7
|
|
|
9
8
|
const createMigrationTable = () => {
|
|
10
|
-
return
|
|
9
|
+
return db.getSchemaConnection().createTable(tableName, table => {
|
|
11
10
|
table.increments('id');
|
|
12
11
|
table.string('name');
|
|
13
12
|
table.datetime('time', { useTz: false });
|
|
@@ -16,7 +15,8 @@ const createStorage = (opts = {}) => {
|
|
|
16
15
|
|
|
17
16
|
return {
|
|
18
17
|
async logMigration(migrationName) {
|
|
19
|
-
await
|
|
18
|
+
await db
|
|
19
|
+
.getConnection()
|
|
20
20
|
.insert({
|
|
21
21
|
name: migrationName,
|
|
22
22
|
time: new Date(),
|
|
@@ -25,7 +25,8 @@ const createStorage = (opts = {}) => {
|
|
|
25
25
|
},
|
|
26
26
|
|
|
27
27
|
async unlogMigration(migrationName) {
|
|
28
|
-
await
|
|
28
|
+
await db
|
|
29
|
+
.getConnection(tableName)
|
|
29
30
|
.del()
|
|
30
31
|
.where({ name: migrationName });
|
|
31
32
|
},
|
|
@@ -36,7 +37,8 @@ const createStorage = (opts = {}) => {
|
|
|
36
37
|
return [];
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
const logs = await
|
|
40
|
+
const logs = await db
|
|
41
|
+
.getConnection(tableName)
|
|
40
42
|
.select()
|
|
41
43
|
.from(tableName)
|
|
42
44
|
.orderBy('time');
|
|
@@ -67,7 +67,7 @@ const applyJoin = (qb, join) => {
|
|
|
67
67
|
orderBy,
|
|
68
68
|
} = join;
|
|
69
69
|
|
|
70
|
-
qb[method]({
|
|
70
|
+
qb[method](`${referencedTable} as ${alias}`, inner => {
|
|
71
71
|
inner.on(`${rootTable}.${rootColumn}`, `${alias}.${referencedColumn}`);
|
|
72
72
|
|
|
73
73
|
if (on) {
|
|
@@ -205,10 +205,13 @@ const createQueryBuilder = (uid, db) => {
|
|
|
205
205
|
this.select('id');
|
|
206
206
|
const subQB = this.getKnexQuery();
|
|
207
207
|
|
|
208
|
-
const nestedSubQuery = db
|
|
208
|
+
const nestedSubQuery = db
|
|
209
|
+
.getConnection()
|
|
210
|
+
.select('id')
|
|
211
|
+
.from(subQB.as('subQuery'));
|
|
209
212
|
|
|
210
213
|
return db
|
|
211
|
-
.
|
|
214
|
+
.getConnection(tableName)
|
|
212
215
|
[state.type]()
|
|
213
216
|
.whereIn('id', nestedSubQuery);
|
|
214
217
|
},
|
|
@@ -257,9 +260,9 @@ const createQueryBuilder = (uid, db) => {
|
|
|
257
260
|
this.select('*');
|
|
258
261
|
}
|
|
259
262
|
|
|
260
|
-
const aliasedTableName = this.mustUseAlias() ? {
|
|
263
|
+
const aliasedTableName = this.mustUseAlias() ? `${tableName} as ${this.alias}` : tableName;
|
|
261
264
|
|
|
262
|
-
const qb = db.
|
|
265
|
+
const qb = db.getConnection(aliasedTableName);
|
|
263
266
|
|
|
264
267
|
if (this.shouldUseSubQuery()) {
|
|
265
268
|
return this.runSubQuery();
|
package/lib/schema/builder.js
CHANGED
|
@@ -11,8 +11,8 @@ module.exports = db => {
|
|
|
11
11
|
* Returns a knex schema builder instance
|
|
12
12
|
* @param {string} table - table name
|
|
13
13
|
*/
|
|
14
|
-
getSchemaBuilder(
|
|
15
|
-
return
|
|
14
|
+
getSchemaBuilder(trx) {
|
|
15
|
+
return db.getSchemaConnection(trx);
|
|
16
16
|
},
|
|
17
17
|
|
|
18
18
|
/**
|
|
@@ -20,10 +20,7 @@ module.exports = db => {
|
|
|
20
20
|
* @param {Schema} schema - database schema
|
|
21
21
|
*/
|
|
22
22
|
async createSchema(schema) {
|
|
23
|
-
// TODO: ensure database exists;
|
|
24
|
-
|
|
25
23
|
await db.connection.transaction(async trx => {
|
|
26
|
-
// create tables without FKs first do avoid ordering issues
|
|
27
24
|
await this.createTables(schema.tables, trx);
|
|
28
25
|
});
|
|
29
26
|
},
|
|
@@ -36,14 +33,14 @@ module.exports = db => {
|
|
|
36
33
|
async createTables(tables, trx) {
|
|
37
34
|
for (const table of tables) {
|
|
38
35
|
debug(`Creating table: ${table.name}`);
|
|
39
|
-
const schemaBuilder = this.getSchemaBuilder(
|
|
36
|
+
const schemaBuilder = this.getSchemaBuilder(trx);
|
|
40
37
|
await helpers.createTable(schemaBuilder, table);
|
|
41
38
|
}
|
|
42
39
|
|
|
43
40
|
// create FKs once all the tables exist
|
|
44
41
|
for (const table of tables) {
|
|
45
42
|
debug(`Creating table foreign keys: ${table.name}`);
|
|
46
|
-
const schemaBuilder = this.getSchemaBuilder(
|
|
43
|
+
const schemaBuilder = this.getSchemaBuilder(trx);
|
|
47
44
|
await helpers.createTableForeignKeys(schemaBuilder, table);
|
|
48
45
|
}
|
|
49
46
|
},
|
|
@@ -61,7 +58,7 @@ module.exports = db => {
|
|
|
61
58
|
|
|
62
59
|
await db.connection.transaction(async trx => {
|
|
63
60
|
for (const table of schema.tables.reverse()) {
|
|
64
|
-
const schemaBuilder = this.getSchemaBuilder(
|
|
61
|
+
const schemaBuilder = this.getSchemaBuilder(trx);
|
|
65
62
|
await helpers.dropTable(schemaBuilder, table);
|
|
66
63
|
}
|
|
67
64
|
});
|
|
@@ -73,29 +70,33 @@ module.exports = db => {
|
|
|
73
70
|
*/
|
|
74
71
|
// TODO: implement force option to disable removal in DB
|
|
75
72
|
async updateSchema(schemaDiff) {
|
|
73
|
+
const { forceMigration } = db.config.settings;
|
|
74
|
+
|
|
76
75
|
await db.dialect.startSchemaUpdate();
|
|
77
76
|
await db.connection.transaction(async trx => {
|
|
78
77
|
await this.createTables(schemaDiff.tables.added, trx);
|
|
79
78
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
if (forceMigration) {
|
|
80
|
+
// drop all delete table foreign keys then delete the tables
|
|
81
|
+
for (const table of schemaDiff.tables.removed) {
|
|
82
|
+
debug(`Removing table foreign keys: ${table.name}`);
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
const schemaBuilder = this.getSchemaBuilder(trx);
|
|
85
|
+
await helpers.dropTableForeignKeys(schemaBuilder, table);
|
|
86
|
+
}
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
for (const table of schemaDiff.tables.removed) {
|
|
89
|
+
debug(`Removing table: ${table.name}`);
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
const schemaBuilder = this.getSchemaBuilder(trx);
|
|
92
|
+
await helpers.dropTable(schemaBuilder, table);
|
|
93
|
+
}
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
for (const table of schemaDiff.tables.updated) {
|
|
96
97
|
debug(`Updating table: ${table.name}`);
|
|
97
98
|
// alter table
|
|
98
|
-
const schemaBuilder = this.getSchemaBuilder(
|
|
99
|
+
const schemaBuilder = this.getSchemaBuilder(trx);
|
|
99
100
|
|
|
100
101
|
await helpers.alterTable(schemaBuilder, table);
|
|
101
102
|
}
|
|
@@ -118,7 +119,11 @@ const createHelpers = db => {
|
|
|
118
119
|
const constraint = tableBuilder
|
|
119
120
|
.foreign(columns, name)
|
|
120
121
|
.references(referencedColumns)
|
|
121
|
-
.inTable(
|
|
122
|
+
.inTable(
|
|
123
|
+
db.connection.getSchemaName()
|
|
124
|
+
? `${db.connection.getSchemaName()}.${referencedTable}`
|
|
125
|
+
: referencedTable
|
|
126
|
+
);
|
|
122
127
|
|
|
123
128
|
if (onDelete) {
|
|
124
129
|
constraint.onDelete(onDelete);
|
|
@@ -167,6 +172,10 @@ const createHelpers = db => {
|
|
|
167
172
|
* @param {Index} index
|
|
168
173
|
*/
|
|
169
174
|
const dropIndex = (tableBuilder, index) => {
|
|
175
|
+
if (!db.config.settings.forceMigration) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
170
179
|
const { type, columns, name } = index;
|
|
171
180
|
|
|
172
181
|
switch (type) {
|
|
@@ -221,7 +230,11 @@ const createHelpers = db => {
|
|
|
221
230
|
* @param {Column} column
|
|
222
231
|
*/
|
|
223
232
|
const dropColumn = (tableBuilder, column) => {
|
|
224
|
-
|
|
233
|
+
if (!db.config.settings.forceMigration) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return tableBuilder.dropColumn(column.name);
|
|
225
238
|
};
|
|
226
239
|
|
|
227
240
|
/**
|
|
@@ -316,7 +329,13 @@ const createHelpers = db => {
|
|
|
316
329
|
* @param {Knex.SchemaBuilder} schemaBuilder
|
|
317
330
|
* @param {Table} table
|
|
318
331
|
*/
|
|
319
|
-
const dropTable = (schemaBuilder, table) =>
|
|
332
|
+
const dropTable = (schemaBuilder, table) => {
|
|
333
|
+
if (!db.config.settings.forceMigration) {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return schemaBuilder.dropTableIfExists(table.name);
|
|
338
|
+
};
|
|
320
339
|
|
|
321
340
|
/**
|
|
322
341
|
* Creates a table foreign keys constraints
|
|
@@ -336,6 +355,10 @@ const createHelpers = db => {
|
|
|
336
355
|
* @param {Table} table
|
|
337
356
|
*/
|
|
338
357
|
const dropTableForeignKeys = async (schemaBuilder, table) => {
|
|
358
|
+
if (!db.config.settings.forceMigration) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
|
|
339
362
|
// foreign keys
|
|
340
363
|
await schemaBuilder.table(table.name, tableBuilder => {
|
|
341
364
|
(table.foreignKeys || []).forEach(foreignKey => dropForeignKey(tableBuilder, foreignKey));
|
package/lib/schema/storage.js
CHANGED
|
@@ -5,10 +5,10 @@ const crypto = require('crypto');
|
|
|
5
5
|
const TABLE_NAME = 'strapi_database_schema';
|
|
6
6
|
|
|
7
7
|
module.exports = db => {
|
|
8
|
-
const hasSchemaTable = () => db.
|
|
8
|
+
const hasSchemaTable = () => db.getSchemaConnection().hasTable(TABLE_NAME);
|
|
9
9
|
|
|
10
10
|
const createSchemaTable = () => {
|
|
11
|
-
return db.
|
|
11
|
+
return db.getSchemaConnection().createTable(TABLE_NAME, t => {
|
|
12
12
|
t.increments('id');
|
|
13
13
|
t.json('schema');
|
|
14
14
|
t.datetime('time', { useTz: false });
|
|
@@ -26,7 +26,8 @@ module.exports = db => {
|
|
|
26
26
|
async read() {
|
|
27
27
|
await checkTableExists();
|
|
28
28
|
|
|
29
|
-
const res = await db
|
|
29
|
+
const res = await db
|
|
30
|
+
.getConnection()
|
|
30
31
|
.select('*')
|
|
31
32
|
.from(TABLE_NAME)
|
|
32
33
|
.orderBy('time', 'DESC')
|
|
@@ -55,21 +56,24 @@ module.exports = db => {
|
|
|
55
56
|
await checkTableExists();
|
|
56
57
|
|
|
57
58
|
// NOTE: we can remove this to add history
|
|
58
|
-
await db.
|
|
59
|
+
await db.getConnection(TABLE_NAME).delete();
|
|
59
60
|
|
|
60
61
|
const time = new Date();
|
|
61
62
|
|
|
62
|
-
await db
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
await db
|
|
64
|
+
.getConnection()
|
|
65
|
+
.insert({
|
|
66
|
+
schema: JSON.stringify(schema),
|
|
67
|
+
hash: this.hashSchema(schema),
|
|
68
|
+
time,
|
|
69
|
+
})
|
|
70
|
+
.into(TABLE_NAME);
|
|
67
71
|
},
|
|
68
72
|
|
|
69
73
|
async clear() {
|
|
70
74
|
await checkTableExists();
|
|
71
75
|
|
|
72
|
-
await db.
|
|
76
|
+
await db.getConnection(TABLE_NAME).truncate();
|
|
73
77
|
},
|
|
74
78
|
};
|
|
75
79
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strapi/database",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.15",
|
|
4
4
|
"description": "Strapi's database layer",
|
|
5
5
|
"homepage": "https://strapi.io",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -35,5 +35,5 @@
|
|
|
35
35
|
"lodash": "4.17.21",
|
|
36
36
|
"umzug": "2.3.0"
|
|
37
37
|
},
|
|
38
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "c69713bf7f437a7cee66ffdeed95227d6246a872"
|
|
39
39
|
}
|