@strapi/database 4.0.0-next.6 → 4.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/lib/dialects/dialect.js +45 -0
- package/lib/dialects/index.js +6 -112
- package/lib/dialects/mysql/index.js +51 -0
- package/lib/dialects/mysql/schema-inspector.js +199 -0
- package/lib/dialects/postgresql/index.js +49 -0
- package/lib/dialects/postgresql/schema-inspector.js +232 -0
- package/lib/dialects/sqlite/index.js +74 -0
- package/lib/dialects/sqlite/schema-inspector.js +151 -0
- package/lib/entity-manager.js +18 -14
- package/lib/entity-repository.js +2 -3
- package/lib/errors.js +45 -3
- package/lib/fields.d.ts +2 -3
- package/lib/fields.js +7 -16
- package/lib/index.d.ts +67 -22
- package/lib/index.js +44 -27
- package/lib/lifecycles/index.d.ts +50 -0
- package/lib/{lifecycles.js → lifecycles/index.js} +25 -14
- package/lib/lifecycles/subscribers/index.d.ts +9 -0
- package/lib/lifecycles/subscribers/models-lifecycles.js +19 -0
- package/lib/lifecycles/subscribers/timestamps.js +65 -0
- package/lib/metadata/index.js +84 -95
- package/lib/metadata/relations.js +16 -0
- package/lib/migrations/index.d.ts +9 -0
- package/lib/migrations/index.js +69 -0
- package/lib/migrations/storage.js +51 -0
- package/lib/query/helpers/join.js +3 -5
- package/lib/query/helpers/order-by.js +21 -11
- package/lib/query/helpers/populate.js +35 -10
- package/lib/query/helpers/search.js +26 -12
- package/lib/query/helpers/transform.js +42 -14
- package/lib/query/helpers/where.js +92 -57
- package/lib/query/query-builder.js +116 -34
- package/lib/schema/__tests__/schema-diff.test.js +14 -1
- package/lib/schema/builder.js +315 -284
- package/lib/schema/diff.js +376 -0
- package/lib/schema/index.d.ts +49 -0
- package/lib/schema/index.js +47 -50
- package/lib/schema/schema.js +21 -18
- package/lib/schema/storage.js +79 -0
- package/lib/utils/content-types.js +1 -2
- package/package.json +26 -21
- package/lib/configuration.js +0 -49
- package/lib/schema/schema-diff.js +0 -337
- package/lib/schema/schema-storage.js +0 -44
|
@@ -29,22 +29,17 @@ const createQueryBuilder = (uid, db) => {
|
|
|
29
29
|
return {
|
|
30
30
|
alias: getAlias(),
|
|
31
31
|
getAlias,
|
|
32
|
+
state,
|
|
32
33
|
|
|
33
34
|
select(args) {
|
|
34
35
|
state.type = 'select';
|
|
35
|
-
state.select = _.uniq(_.castArray(args))
|
|
36
|
+
state.select = _.uniq(_.castArray(args));
|
|
36
37
|
|
|
37
38
|
return this;
|
|
38
39
|
},
|
|
39
40
|
|
|
40
41
|
addSelect(args) {
|
|
41
|
-
_.uniq(_.castArray(args))
|
|
42
|
-
.map(col => this.aliasColumn(col))
|
|
43
|
-
.forEach(toSelect => {
|
|
44
|
-
if (!state.select.includes(toSelect)) {
|
|
45
|
-
state.select.push(toSelect);
|
|
46
|
-
}
|
|
47
|
-
});
|
|
42
|
+
state.select = _.uniq([...state.select, ..._.castArray(args)]);
|
|
48
43
|
|
|
49
44
|
return this;
|
|
50
45
|
},
|
|
@@ -62,6 +57,10 @@ const createQueryBuilder = (uid, db) => {
|
|
|
62
57
|
return this;
|
|
63
58
|
},
|
|
64
59
|
|
|
60
|
+
ref(name) {
|
|
61
|
+
return db.connection.ref(helpers.toColumnName(meta, name));
|
|
62
|
+
},
|
|
63
|
+
|
|
65
64
|
update(data) {
|
|
66
65
|
state.type = 'update';
|
|
67
66
|
state.data = data;
|
|
@@ -77,9 +76,11 @@ const createQueryBuilder = (uid, db) => {
|
|
|
77
76
|
},
|
|
78
77
|
|
|
79
78
|
where(where = {}) {
|
|
80
|
-
|
|
79
|
+
if (!_.isPlainObject(where)) {
|
|
80
|
+
throw new Error('Where must be an object');
|
|
81
|
+
}
|
|
81
82
|
|
|
82
|
-
state.where.push(
|
|
83
|
+
state.where.push(where);
|
|
83
84
|
|
|
84
85
|
return this;
|
|
85
86
|
},
|
|
@@ -95,7 +96,7 @@ const createQueryBuilder = (uid, db) => {
|
|
|
95
96
|
},
|
|
96
97
|
|
|
97
98
|
orderBy(orderBy) {
|
|
98
|
-
state.orderBy =
|
|
99
|
+
state.orderBy = orderBy;
|
|
99
100
|
return this;
|
|
100
101
|
},
|
|
101
102
|
|
|
@@ -105,7 +106,7 @@ const createQueryBuilder = (uid, db) => {
|
|
|
105
106
|
},
|
|
106
107
|
|
|
107
108
|
populate(populate) {
|
|
108
|
-
state.populate =
|
|
109
|
+
state.populate = populate;
|
|
109
110
|
return this;
|
|
110
111
|
},
|
|
111
112
|
|
|
@@ -115,7 +116,7 @@ const createQueryBuilder = (uid, db) => {
|
|
|
115
116
|
},
|
|
116
117
|
|
|
117
118
|
init(params = {}) {
|
|
118
|
-
const { _q, where, select, limit, offset, orderBy, groupBy, populate } = params;
|
|
119
|
+
const { _q, filters, where, select, limit, offset, orderBy, groupBy, populate } = params;
|
|
119
120
|
|
|
120
121
|
if (!_.isNil(where)) {
|
|
121
122
|
this.where(where);
|
|
@@ -151,9 +152,17 @@ const createQueryBuilder = (uid, db) => {
|
|
|
151
152
|
this.populate(populate);
|
|
152
153
|
}
|
|
153
154
|
|
|
155
|
+
if (!_.isNil(filters)) {
|
|
156
|
+
this.filters(filters);
|
|
157
|
+
}
|
|
158
|
+
|
|
154
159
|
return this;
|
|
155
160
|
},
|
|
156
161
|
|
|
162
|
+
filters(filters) {
|
|
163
|
+
state.filters = filters;
|
|
164
|
+
},
|
|
165
|
+
|
|
157
166
|
first() {
|
|
158
167
|
state.first = true;
|
|
159
168
|
return this;
|
|
@@ -164,43 +173,111 @@ const createQueryBuilder = (uid, db) => {
|
|
|
164
173
|
return this;
|
|
165
174
|
},
|
|
166
175
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
176
|
+
mustUseAlias() {
|
|
177
|
+
return ['select', 'count'].includes(state.type);
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
aliasColumn(key, alias) {
|
|
181
|
+
if (typeof key !== 'string') {
|
|
182
|
+
return key;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (key.indexOf('.') >= 0) {
|
|
186
|
+
return key;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (!_.isNil(alias)) {
|
|
190
|
+
return `${alias}.${key}`;
|
|
170
191
|
}
|
|
171
192
|
|
|
172
|
-
|
|
173
|
-
return this.alias + '.' + columnName;
|
|
193
|
+
return this.mustUseAlias() ? `${this.alias}.${key}` : key;
|
|
174
194
|
},
|
|
175
195
|
|
|
176
196
|
raw(...args) {
|
|
177
197
|
return db.connection.raw(...args);
|
|
178
198
|
},
|
|
179
199
|
|
|
180
|
-
|
|
181
|
-
|
|
200
|
+
shouldUseSubQuery() {
|
|
201
|
+
return ['delete', 'update'].includes(state.type) && state.joins.length > 0;
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
runSubQuery() {
|
|
205
|
+
this.select('id');
|
|
206
|
+
const subQB = this.getKnexQuery();
|
|
182
207
|
|
|
183
|
-
const
|
|
208
|
+
const nestedSubQuery = db
|
|
209
|
+
.getConnection()
|
|
210
|
+
.select('id')
|
|
211
|
+
.from(subQB.as('subQuery'));
|
|
184
212
|
|
|
213
|
+
return db
|
|
214
|
+
.getConnection(tableName)
|
|
215
|
+
[state.type]()
|
|
216
|
+
.whereIn('id', nestedSubQuery);
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
processState() {
|
|
220
|
+
state.orderBy = helpers.processOrderBy(state.orderBy, { qb: this, uid, db });
|
|
221
|
+
|
|
222
|
+
if (!_.isNil(state.filters)) {
|
|
223
|
+
if (_.isFunction(state.filters)) {
|
|
224
|
+
const filters = state.filters({ qb: this, uid, meta, db });
|
|
225
|
+
|
|
226
|
+
if (!_.isNil(filters)) {
|
|
227
|
+
state.where.push(filters);
|
|
228
|
+
}
|
|
229
|
+
} else {
|
|
230
|
+
state.where.push(state.filters);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
state.where = helpers.processWhere(state.where, { qb: this, uid, db });
|
|
235
|
+
state.populate = helpers.processPopulate(state.populate, { qb: this, uid, db });
|
|
236
|
+
state.data = helpers.toRow(meta, state.data);
|
|
237
|
+
|
|
238
|
+
this.processSelect();
|
|
239
|
+
},
|
|
240
|
+
|
|
241
|
+
shouldUseDistinct() {
|
|
242
|
+
return state.joins.length > 0 && _.isEmpty(state.groupBy);
|
|
243
|
+
},
|
|
244
|
+
|
|
245
|
+
processSelect() {
|
|
246
|
+
state.select = state.select.map(field => helpers.toColumnName(meta, field));
|
|
247
|
+
|
|
248
|
+
if (this.shouldUseDistinct()) {
|
|
249
|
+
const joinsOrderByColumns = state.joins.flatMap(join => {
|
|
250
|
+
return _.keys(join.orderBy).map(key => this.aliasColumn(key, join.alias));
|
|
251
|
+
});
|
|
252
|
+
const orderByColumns = state.orderBy.map(({ column }) => column);
|
|
253
|
+
|
|
254
|
+
state.select = _.uniq([...joinsOrderByColumns, ...orderByColumns, ...state.select]);
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
|
|
258
|
+
getKnexQuery() {
|
|
185
259
|
if (!state.type) {
|
|
186
260
|
this.select('*');
|
|
187
261
|
}
|
|
188
262
|
|
|
263
|
+
const aliasedTableName = this.mustUseAlias() ? `${tableName} as ${this.alias}` : tableName;
|
|
264
|
+
|
|
265
|
+
const qb = db.getConnection(aliasedTableName);
|
|
266
|
+
|
|
267
|
+
if (this.shouldUseSubQuery()) {
|
|
268
|
+
return this.runSubQuery();
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
this.processState();
|
|
272
|
+
|
|
189
273
|
switch (state.type) {
|
|
190
274
|
case 'select': {
|
|
191
|
-
|
|
192
|
-
state.select = [this.aliasColumn('*')];
|
|
193
|
-
}
|
|
275
|
+
qb.select(state.select.map(column => this.aliasColumn(column)));
|
|
194
276
|
|
|
195
|
-
if (
|
|
196
|
-
|
|
197
|
-
// TODO: make sure we return the right data
|
|
198
|
-
qb.distinct(`${this.alias}.id`);
|
|
199
|
-
// TODO: add column if they aren't there already
|
|
200
|
-
state.select.unshift(...state.orderBy.map(({ column }) => column));
|
|
277
|
+
if (this.shouldUseDistinct()) {
|
|
278
|
+
qb.distinct();
|
|
201
279
|
}
|
|
202
280
|
|
|
203
|
-
qb.select(state.select);
|
|
204
281
|
break;
|
|
205
282
|
}
|
|
206
283
|
case 'count': {
|
|
@@ -218,14 +295,17 @@ const createQueryBuilder = (uid, db) => {
|
|
|
218
295
|
}
|
|
219
296
|
case 'update': {
|
|
220
297
|
qb.update(state.data);
|
|
221
|
-
|
|
222
298
|
break;
|
|
223
299
|
}
|
|
224
300
|
case 'delete': {
|
|
225
|
-
qb.
|
|
301
|
+
qb.delete();
|
|
226
302
|
|
|
227
303
|
break;
|
|
228
304
|
}
|
|
305
|
+
case 'truncate': {
|
|
306
|
+
db.truncate();
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
229
309
|
}
|
|
230
310
|
|
|
231
311
|
if (state.limit) {
|
|
@@ -248,13 +328,15 @@ const createQueryBuilder = (uid, db) => {
|
|
|
248
328
|
qb.groupBy(state.groupBy);
|
|
249
329
|
}
|
|
250
330
|
|
|
331
|
+
// if there are joins and it is a delete or update use a sub query
|
|
251
332
|
if (state.where) {
|
|
252
333
|
helpers.applyWhere(qb, state.where);
|
|
253
334
|
}
|
|
254
335
|
|
|
336
|
+
// if there are joins and it is a delete or update use a sub query
|
|
255
337
|
if (state.search) {
|
|
256
338
|
qb.where(subQb => {
|
|
257
|
-
helpers.applySearch(subQb, state.search, {
|
|
339
|
+
helpers.applySearch(subQb, state.search, { qb: this, db, uid });
|
|
258
340
|
});
|
|
259
341
|
}
|
|
260
342
|
|
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const createSchemaDiff = require('../diff');
|
|
4
4
|
|
|
5
|
+
let diffSchemas;
|
|
5
6
|
describe('diffSchemas', () => {
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
const schemaDiff = createSchemaDiff({
|
|
9
|
+
dialect: {
|
|
10
|
+
usesForeignKeys() {
|
|
11
|
+
return true;
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
diffSchemas = schemaDiff.diff.bind(schemaDiff);
|
|
17
|
+
});
|
|
18
|
+
|
|
6
19
|
test('New Table', () => {
|
|
7
20
|
const testTable = {
|
|
8
21
|
name: 'my_table',
|