@strapi/database 4.2.1-alpha.0 → 4.3.0-beta.2
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 +60 -21
- package/lib/dialects/postgresql/schema-inspector.js +75 -29
- package/lib/entity-manager.js +1 -1
- package/lib/index.d.ts +25 -4
- package/lib/index.js +4 -0
- package/lib/metadata/index.js +1 -0
- package/lib/migrations/index.js +1 -1
- package/lib/query/query-builder.js +37 -1
- package/package.json +3 -3
|
@@ -26,19 +26,32 @@ const SQL_QUERIES = {
|
|
|
26
26
|
`,
|
|
27
27
|
FOREIGN_KEY_LIST: /* sql */ `
|
|
28
28
|
SELECT
|
|
29
|
-
tc.constraint_name as constraint_name
|
|
29
|
+
tc.constraint_name as constraint_name
|
|
30
|
+
FROM information_schema.table_constraints tc
|
|
31
|
+
WHERE tc.constraint_type = 'FOREIGN KEY'
|
|
32
|
+
AND tc.table_schema = database()
|
|
33
|
+
AND tc.table_name = ?;
|
|
34
|
+
`,
|
|
35
|
+
FOREIGN_KEY_REFERENCES: /* sql */ `
|
|
36
|
+
SELECT
|
|
37
|
+
kcu.constraint_name as constraint_name,
|
|
30
38
|
kcu.column_name as column_name,
|
|
31
39
|
kcu.referenced_table_name as referenced_table_name,
|
|
32
|
-
kcu.referenced_column_name as referenced_column_name
|
|
40
|
+
kcu.referenced_column_name as referenced_column_name
|
|
41
|
+
FROM information_schema.key_column_usage kcu
|
|
42
|
+
WHERE kcu.constraint_name in (?)
|
|
43
|
+
AND kcu.table_schema = database()
|
|
44
|
+
AND kcu.table_name = ?;
|
|
45
|
+
`,
|
|
46
|
+
FOREIGN_KEY_REFERENTIALS_CONSTRAINTS: /* sql */ `
|
|
47
|
+
SELECT
|
|
48
|
+
rc.constraint_name as constraint_name,
|
|
33
49
|
rc.update_rule as on_update,
|
|
34
50
|
rc.delete_rule as on_delete
|
|
35
|
-
FROM information_schema.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
AND tc.table_schema = database()
|
|
40
|
-
AND tc.table_name = ?;
|
|
41
|
-
|
|
51
|
+
FROM information_schema.referential_constraints AS rc
|
|
52
|
+
WHERE rc.constraint_name in (?)
|
|
53
|
+
AND rc.constraint_schema = database()
|
|
54
|
+
AND rc.table_name = ?;
|
|
42
55
|
`,
|
|
43
56
|
};
|
|
44
57
|
|
|
@@ -177,18 +190,44 @@ class MysqlSchemaInspector {
|
|
|
177
190
|
const ret = {};
|
|
178
191
|
|
|
179
192
|
for (const fk of rows) {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
193
|
+
ret[fk.constraint_name] = {
|
|
194
|
+
name: fk.constraint_name,
|
|
195
|
+
columns: [],
|
|
196
|
+
referencedColumns: [],
|
|
197
|
+
referencedTable: null,
|
|
198
|
+
onUpdate: null,
|
|
199
|
+
onDelete: null,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const contraintNames = Object.keys(ret);
|
|
204
|
+
|
|
205
|
+
if (contraintNames.length > 0) {
|
|
206
|
+
const [fkReferences] = await this.db.connection.raw(SQL_QUERIES.FOREIGN_KEY_REFERENCES, [
|
|
207
|
+
contraintNames,
|
|
208
|
+
tableName,
|
|
209
|
+
]);
|
|
210
|
+
|
|
211
|
+
for (const fkReference of fkReferences) {
|
|
212
|
+
ret[fkReference.constraint_name].referencedTable = fkReference.referenced_table_name;
|
|
213
|
+
ret[fkReference.constraint_name].columns.push(fkReference.column_name);
|
|
214
|
+
ret[fkReference.constraint_name].referencedColumns.push(fkReference.referenced_column_name);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const [
|
|
218
|
+
fkReferentialConstraints,
|
|
219
|
+
] = await this.db.connection.raw(SQL_QUERIES.FOREIGN_KEY_REFERENTIALS_CONSTRAINTS, [
|
|
220
|
+
contraintNames,
|
|
221
|
+
tableName,
|
|
222
|
+
]);
|
|
223
|
+
|
|
224
|
+
for (const fkReferentialConstraint of fkReferentialConstraints) {
|
|
225
|
+
ret[
|
|
226
|
+
fkReferentialConstraint.constraint_name
|
|
227
|
+
].onUpdate = fkReferentialConstraint.on_update.toUpperCase();
|
|
228
|
+
ret[
|
|
229
|
+
fkReferentialConstraint.constraint_name
|
|
230
|
+
].onDelete = fkReferentialConstraint.on_delete.toUpperCase();
|
|
192
231
|
}
|
|
193
232
|
}
|
|
194
233
|
|
|
@@ -40,29 +40,41 @@ const SQL_QUERIES = {
|
|
|
40
40
|
`,
|
|
41
41
|
FOREIGN_KEY_LIST: /* sql */ `
|
|
42
42
|
SELECT
|
|
43
|
-
tco."constraint_name" as constraint_name
|
|
44
|
-
kcu."column_name" as column_name,
|
|
45
|
-
rel_kcu."table_name" as foreign_table,
|
|
46
|
-
rel_kcu."column_name" as fk_column_name,
|
|
47
|
-
rco.update_rule as on_update,
|
|
48
|
-
rco.delete_rule as on_delete
|
|
43
|
+
tco."constraint_name" as constraint_name
|
|
49
44
|
FROM information_schema.table_constraints tco
|
|
50
|
-
JOIN information_schema.key_column_usage kcu
|
|
51
|
-
ON tco.constraint_schema = kcu.constraint_schema
|
|
52
|
-
AND tco.constraint_name = kcu.constraint_name
|
|
53
|
-
JOIN information_schema.referential_constraints rco
|
|
54
|
-
ON tco.constraint_schema = rco.constraint_schema
|
|
55
|
-
AND tco.constraint_name = rco.constraint_name
|
|
56
|
-
JOIN information_schema.key_column_usage rel_kcu
|
|
57
|
-
ON rco.unique_constraint_schema = rel_kcu.constraint_schema
|
|
58
|
-
AND rco.unique_constraint_name = rel_kcu.constraint_name
|
|
59
|
-
AND kcu.ordinal_position = rel_kcu.ordinal_position
|
|
60
45
|
WHERE
|
|
61
46
|
tco.constraint_type = 'FOREIGN KEY'
|
|
62
47
|
AND tco.constraint_schema = ?
|
|
63
48
|
AND tco.table_name = ?
|
|
64
|
-
ORDER BY kcu.table_schema, kcu.table_name, kcu.ordinal_position, kcu.constraint_name;
|
|
65
49
|
`,
|
|
50
|
+
FOREIGN_KEY_REFERENCES: /* sql */ `
|
|
51
|
+
SELECT
|
|
52
|
+
kcu."constraint_name" as constraint_name,
|
|
53
|
+
kcu."column_name" as column_name
|
|
54
|
+
|
|
55
|
+
FROM information_schema.key_column_usage kcu
|
|
56
|
+
WHERE kcu.constraint_name=ANY(?)
|
|
57
|
+
AND kcu.table_schema = ?
|
|
58
|
+
AND kcu.table_name = ?;
|
|
59
|
+
`,
|
|
60
|
+
|
|
61
|
+
FOREIGN_KEY_REFERENCES_CONSTRAIN: /* sql */ `
|
|
62
|
+
SELECT
|
|
63
|
+
rco.update_rule as on_update,
|
|
64
|
+
rco.delete_rule as on_delete,
|
|
65
|
+
rco."unique_constraint_name" as unique_constraint_name
|
|
66
|
+
FROM information_schema.referential_constraints rco
|
|
67
|
+
WHERE rco.constraint_name=ANY(?)
|
|
68
|
+
AND rco.constraint_schema = ?
|
|
69
|
+
`,
|
|
70
|
+
FOREIGN_KEY_REFERENCES_CONSTRAIN_RFERENCE: /* sql */ `
|
|
71
|
+
SELECT
|
|
72
|
+
rel_kcu."table_name" as foreign_table,
|
|
73
|
+
rel_kcu."column_name" as fk_column_name
|
|
74
|
+
FROM information_schema.key_column_usage rel_kcu
|
|
75
|
+
WHERE rel_kcu.constraint_name=?
|
|
76
|
+
AND rel_kcu.table_schema = ?
|
|
77
|
+
`,
|
|
66
78
|
};
|
|
67
79
|
|
|
68
80
|
const toStrapiType = column => {
|
|
@@ -210,18 +222,52 @@ class PostgresqlSchemaInspector {
|
|
|
210
222
|
const ret = {};
|
|
211
223
|
|
|
212
224
|
for (const fk of rows) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
+
ret[fk.constraint_name] = {
|
|
226
|
+
name: fk.constraint_name,
|
|
227
|
+
columns: [],
|
|
228
|
+
referencedColumns: [],
|
|
229
|
+
referencedTable: null,
|
|
230
|
+
onUpdate: null,
|
|
231
|
+
onDelete: null,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
const constraintNames = Object.keys(ret);
|
|
235
|
+
const dbSchema = this.getDatabaseSchema();
|
|
236
|
+
if (constraintNames.length > 0) {
|
|
237
|
+
const {
|
|
238
|
+
rows: fkReferences,
|
|
239
|
+
} = await this.db.connection.raw(SQL_QUERIES.FOREIGN_KEY_REFERENCES, [
|
|
240
|
+
[constraintNames],
|
|
241
|
+
dbSchema,
|
|
242
|
+
tableName,
|
|
243
|
+
]);
|
|
244
|
+
|
|
245
|
+
for (const fkReference of fkReferences) {
|
|
246
|
+
ret[fkReference.constraint_name].columns.push(fkReference.column_name);
|
|
247
|
+
|
|
248
|
+
const {
|
|
249
|
+
rows: fkReferencesConstraint,
|
|
250
|
+
} = await this.db.connection.raw(SQL_QUERIES.FOREIGN_KEY_REFERENCES_CONSTRAIN, [
|
|
251
|
+
[fkReference.constraint_name],
|
|
252
|
+
dbSchema,
|
|
253
|
+
]);
|
|
254
|
+
|
|
255
|
+
for (const fkReferenceC of fkReferencesConstraint) {
|
|
256
|
+
const {
|
|
257
|
+
rows: fkReferencesConstraintReferece,
|
|
258
|
+
} = await this.db.connection.raw(SQL_QUERIES.FOREIGN_KEY_REFERENCES_CONSTRAIN_RFERENCE, [
|
|
259
|
+
fkReferenceC.unique_constraint_name,
|
|
260
|
+
dbSchema,
|
|
261
|
+
]);
|
|
262
|
+
for (const fkReferenceConst of fkReferencesConstraintReferece) {
|
|
263
|
+
ret[fkReference.constraint_name].referencedTable = fkReferenceConst.foreign_table;
|
|
264
|
+
ret[fkReference.constraint_name].referencedColumns.push(
|
|
265
|
+
fkReferenceConst.fk_column_name
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
ret[fkReference.constraint_name].onUpdate = fkReferenceC.on_update.toUpperCase();
|
|
269
|
+
ret[fkReference.constraint_name].onDelete = fkReferenceC.on_delete.toUpperCase();
|
|
270
|
+
}
|
|
225
271
|
}
|
|
226
272
|
}
|
|
227
273
|
|
package/lib/entity-manager.js
CHANGED
package/lib/index.d.ts
CHANGED
|
@@ -2,16 +2,37 @@ import { LifecycleProvider } from './lifecycles';
|
|
|
2
2
|
import { MigrationProvider } from './migrations';
|
|
3
3
|
import { SchemaProvideer } from './schema';
|
|
4
4
|
|
|
5
|
-
type
|
|
5
|
+
type LogicalOperators<T> = {
|
|
6
6
|
$and?: WhereParams<T>[];
|
|
7
7
|
$or?: WhereParams<T>[];
|
|
8
8
|
$not?: WhereParams<T>;
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
type
|
|
12
|
-
[K
|
|
11
|
+
type AttributeOperators<T, K extends keyof T> = {
|
|
12
|
+
$eq?: T[K] | Array<T[K]>;
|
|
13
|
+
$ne?: T[K] | Array<T[K]>;
|
|
14
|
+
$in?: T[K][];
|
|
15
|
+
$notIn?: T[K][];
|
|
16
|
+
$lt?: T[K];
|
|
17
|
+
$lte?: T[K];
|
|
18
|
+
$gt?: T[K];
|
|
19
|
+
$gte?: T[K];
|
|
20
|
+
$between?: [T[K], T[K]];
|
|
21
|
+
$contains?: T[K];
|
|
22
|
+
$notContains?: T[K];
|
|
23
|
+
$containsi?: T[K];
|
|
24
|
+
$notContainsi?: T[K];
|
|
25
|
+
$startsWith?: T[K];
|
|
26
|
+
$endsWith?: T[K];
|
|
27
|
+
$null?: boolean;
|
|
28
|
+
$notNull?: boolean;
|
|
29
|
+
$not?: WhereParams<T> | AttributeOperators<T, K>;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type WhereParams<T> = {
|
|
33
|
+
[K in keyof T]?: T[K] | T[K][] | AttributeOperators<T, K>;
|
|
13
34
|
} &
|
|
14
|
-
|
|
35
|
+
LogicalOperators<T>;
|
|
15
36
|
|
|
16
37
|
type Sortables<T> = {
|
|
17
38
|
// check sortable
|
package/lib/index.js
CHANGED
package/lib/metadata/index.js
CHANGED
package/lib/migrations/index.js
CHANGED
|
@@ -34,7 +34,7 @@ const migrationResolver = ({ name, path, context }) => {
|
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
const createUmzugProvider = db => {
|
|
37
|
-
const migrationDir = path.join(strapi.dirs.root, 'database/migrations');
|
|
37
|
+
const migrationDir = path.join(strapi.dirs.app.root, 'database/migrations');
|
|
38
38
|
|
|
39
39
|
fse.ensureDirSync(migrationDir);
|
|
40
40
|
|
|
@@ -12,6 +12,7 @@ const createQueryBuilder = (uid, db) => {
|
|
|
12
12
|
type: 'select',
|
|
13
13
|
select: [],
|
|
14
14
|
count: null,
|
|
15
|
+
max: null,
|
|
15
16
|
first: false,
|
|
16
17
|
data: null,
|
|
17
18
|
where: [],
|
|
@@ -19,6 +20,8 @@ const createQueryBuilder = (uid, db) => {
|
|
|
19
20
|
populate: null,
|
|
20
21
|
limit: null,
|
|
21
22
|
offset: null,
|
|
23
|
+
transaction: null,
|
|
24
|
+
forUpdate: false,
|
|
22
25
|
orderBy: [],
|
|
23
26
|
groupBy: [],
|
|
24
27
|
};
|
|
@@ -75,6 +78,13 @@ const createQueryBuilder = (uid, db) => {
|
|
|
75
78
|
return this;
|
|
76
79
|
},
|
|
77
80
|
|
|
81
|
+
max(column) {
|
|
82
|
+
state.type = 'max';
|
|
83
|
+
state.max = column;
|
|
84
|
+
|
|
85
|
+
return this;
|
|
86
|
+
},
|
|
87
|
+
|
|
78
88
|
where(where = {}) {
|
|
79
89
|
if (!_.isPlainObject(where)) {
|
|
80
90
|
throw new Error('Where must be an object');
|
|
@@ -115,6 +125,16 @@ const createQueryBuilder = (uid, db) => {
|
|
|
115
125
|
return this;
|
|
116
126
|
},
|
|
117
127
|
|
|
128
|
+
transacting(transaction) {
|
|
129
|
+
state.transaction = transaction;
|
|
130
|
+
return this;
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
forUpdate() {
|
|
134
|
+
state.forUpdate = true;
|
|
135
|
+
return this;
|
|
136
|
+
},
|
|
137
|
+
|
|
118
138
|
init(params = {}) {
|
|
119
139
|
const { _q, filters, where, select, limit, offset, orderBy, groupBy, populate } = params;
|
|
120
140
|
|
|
@@ -281,7 +301,15 @@ const createQueryBuilder = (uid, db) => {
|
|
|
281
301
|
break;
|
|
282
302
|
}
|
|
283
303
|
case 'count': {
|
|
284
|
-
|
|
304
|
+
const dbColumnName =
|
|
305
|
+
state.count === '*' ? '*' : this.aliasColumn(helpers.toColumnName(meta, state.count));
|
|
306
|
+
|
|
307
|
+
qb.count({ count: dbColumnName });
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
310
|
+
case 'max': {
|
|
311
|
+
const dbColumnName = this.aliasColumn(helpers.toColumnName(meta, state.max));
|
|
312
|
+
qb.max({ max: dbColumnName });
|
|
285
313
|
break;
|
|
286
314
|
}
|
|
287
315
|
case 'insert': {
|
|
@@ -308,6 +336,14 @@ const createQueryBuilder = (uid, db) => {
|
|
|
308
336
|
}
|
|
309
337
|
}
|
|
310
338
|
|
|
339
|
+
if (state.transaction) {
|
|
340
|
+
qb.transacting(state.transaction);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (state.forUpdate) {
|
|
344
|
+
qb.forUpdate();
|
|
345
|
+
}
|
|
346
|
+
|
|
311
347
|
if (state.limit) {
|
|
312
348
|
qb.limit(state.limit);
|
|
313
349
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strapi/database",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.0-beta.2",
|
|
4
4
|
"description": "Strapi's database layer",
|
|
5
5
|
"homepage": "https://strapi.io",
|
|
6
6
|
"bugs": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"test:unit": "jest --verbose"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"date-fns": "2.
|
|
34
|
+
"date-fns": "2.28.0",
|
|
35
35
|
"debug": "4.3.1",
|
|
36
36
|
"fs-extra": "10.0.0",
|
|
37
37
|
"knex": "1.0.4",
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"node": ">=14.19.1 <=16.x.x",
|
|
43
43
|
"npm": ">=6.0.0"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "42aba356ad1b0751584d3b375e83baa4a2c18f65"
|
|
46
46
|
}
|