@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.
@@ -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
 
@@ -139,7 +139,7 @@ class PostgresqlSchemaInspector {
139
139
  }
140
140
 
141
141
  getDatabaseSchema() {
142
- return this.db.connection.client.connectionSettings.schema || 'public';
142
+ return this.db.connection.getSchemaName() || 'public';
143
143
  }
144
144
 
145
145
  async getTables() {
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 = 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 = knex(this.config.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
  }
@@ -27,7 +27,7 @@ const createUmzugProvider = db => {
27
27
 
28
28
  fse.ensureDirSync(migrationDir);
29
29
 
30
- const wrapFn = fn => db => db.connection.transaction(trx => Promise.resolve(fn(trx)));
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 tableName = opts.tableName || 'strapi_migrations';
5
- const knex = opts.db.connection;
4
+ const { db, tableName = 'strapi_migrations' } = opts;
6
5
 
7
- const hasMigrationTable = () => knex.schema.hasTable(tableName);
6
+ const hasMigrationTable = () => db.getSchemaConnection().hasTable(tableName);
8
7
 
9
8
  const createMigrationTable = () => {
10
- return knex.schema.createTable(tableName, table => {
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 knex
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 knex(tableName)
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 knex
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]({ [alias]: referencedTable }, inner => {
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.connection.select('id').from(subQB.as('subQuery'));
208
+ const nestedSubQuery = db
209
+ .getConnection()
210
+ .select('id')
211
+ .from(subQB.as('subQuery'));
209
212
 
210
213
  return db
211
- .connection(tableName)
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() ? { [this.alias]: tableName } : tableName;
263
+ const aliasedTableName = this.mustUseAlias() ? `${tableName} as ${this.alias}` : tableName;
261
264
 
262
- const qb = db.connection(aliasedTableName);
265
+ const qb = db.getConnection(aliasedTableName);
263
266
 
264
267
  if (this.shouldUseSubQuery()) {
265
268
  return this.runSubQuery();
@@ -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(table, trx = db.connection) {
15
- return table.schema ? trx.schema.withSchema(table.schema) : trx.schema;
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(table, trx);
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(table, trx);
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(table, trx);
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
- // 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}`);
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
- const schemaBuilder = this.getSchemaBuilder(table, trx);
85
- await helpers.dropTableForeignKeys(schemaBuilder, table);
86
- }
84
+ const schemaBuilder = this.getSchemaBuilder(trx);
85
+ await helpers.dropTableForeignKeys(schemaBuilder, table);
86
+ }
87
87
 
88
- for (const table of schemaDiff.tables.removed) {
89
- debug(`Removing table: ${table.name}`);
88
+ for (const table of schemaDiff.tables.removed) {
89
+ debug(`Removing table: ${table.name}`);
90
90
 
91
- const schemaBuilder = this.getSchemaBuilder(table, trx);
92
- await helpers.dropTable(schemaBuilder, table);
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(table, trx);
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(referencedTable);
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
- tableBuilder.dropColumn(column.name);
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) => schemaBuilder.dropTableIfExists(table.name);
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));
@@ -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.connection.schema.hasTable(TABLE_NAME);
8
+ const hasSchemaTable = () => db.getSchemaConnection().hasTable(TABLE_NAME);
9
9
 
10
10
  const createSchemaTable = () => {
11
- return db.connection.schema.createTable(TABLE_NAME, t => {
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.connection
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.connection(TABLE_NAME).delete();
59
+ await db.getConnection(TABLE_NAME).delete();
59
60
 
60
61
  const time = new Date();
61
62
 
62
- await db.connection(TABLE_NAME).insert({
63
- schema: JSON.stringify(schema),
64
- hash: this.hashSchema(schema),
65
- time,
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.connection(TABLE_NAME).truncate();
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.11",
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": "5b04fa152dc597fc3aa80afb25796217b60403f3"
38
+ "gitHead": "c69713bf7f437a7cee66ffdeed95227d6246a872"
39
39
  }