@strapi/database 5.12.1 → 5.12.3
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/dist/connection.js +43 -0
- package/dist/connection.js.map +1 -0
- package/dist/connection.mjs +41 -0
- package/dist/connection.mjs.map +1 -0
- package/dist/dialects/dialect.js +54 -0
- package/dist/dialects/dialect.js.map +1 -0
- package/dist/dialects/dialect.mjs +52 -0
- package/dist/dialects/dialect.mjs.map +1 -0
- package/dist/dialects/index.js +44 -0
- package/dist/dialects/index.js.map +1 -0
- package/dist/dialects/index.mjs +42 -0
- package/dist/dialects/index.mjs.map +1 -0
- package/dist/dialects/mysql/constants.js +8 -0
- package/dist/dialects/mysql/constants.js.map +1 -0
- package/dist/dialects/mysql/constants.mjs +5 -0
- package/dist/dialects/mysql/constants.mjs.map +1 -0
- package/dist/dialects/mysql/database-inspector.js +35 -0
- package/dist/dialects/mysql/database-inspector.js.map +1 -0
- package/dist/dialects/mysql/database-inspector.mjs +33 -0
- package/dist/dialects/mysql/database-inspector.mjs.map +1 -0
- package/dist/dialects/mysql/index.js +75 -0
- package/dist/dialects/mysql/index.js.map +1 -0
- package/dist/dialects/mysql/index.mjs +73 -0
- package/dist/dialects/mysql/index.mjs.map +1 -0
- package/dist/dialects/mysql/schema-inspector.js +297 -0
- package/dist/dialects/mysql/schema-inspector.js.map +1 -0
- package/dist/dialects/mysql/schema-inspector.mjs +295 -0
- package/dist/dialects/mysql/schema-inspector.mjs.map +1 -0
- package/dist/dialects/postgresql/index.js +62 -0
- package/dist/dialects/postgresql/index.js.map +1 -0
- package/dist/dialects/postgresql/index.mjs +60 -0
- package/dist/dialects/postgresql/index.mjs.map +1 -0
- package/dist/dialects/postgresql/schema-inspector.js +316 -0
- package/dist/dialects/postgresql/schema-inspector.js.map +1 -0
- package/dist/dialects/postgresql/schema-inspector.mjs +314 -0
- package/dist/dialects/postgresql/schema-inspector.mjs.map +1 -0
- package/dist/dialects/sqlite/index.js +82 -0
- package/dist/dialects/sqlite/index.js.map +1 -0
- package/dist/dialects/sqlite/index.mjs +80 -0
- package/dist/dialects/sqlite/index.mjs.map +1 -0
- package/dist/dialects/sqlite/schema-inspector.js +211 -0
- package/dist/dialects/sqlite/schema-inspector.js.map +1 -0
- package/dist/dialects/sqlite/schema-inspector.mjs +209 -0
- package/dist/dialects/sqlite/schema-inspector.mjs.map +1 -0
- package/dist/entity-manager/entity-repository.js +139 -0
- package/dist/entity-manager/entity-repository.js.map +1 -0
- package/dist/entity-manager/entity-repository.mjs +137 -0
- package/dist/entity-manager/entity-repository.mjs.map +1 -0
- package/dist/entity-manager/index.js +1186 -0
- package/dist/entity-manager/index.js.map +1 -0
- package/dist/entity-manager/index.mjs +1184 -0
- package/dist/entity-manager/index.mjs.map +1 -0
- package/dist/entity-manager/morph-relations.js +73 -0
- package/dist/entity-manager/morph-relations.js.map +1 -0
- package/dist/entity-manager/morph-relations.mjs +69 -0
- package/dist/entity-manager/morph-relations.mjs.map +1 -0
- package/dist/entity-manager/regular-relations.js +247 -0
- package/dist/entity-manager/regular-relations.js.map +1 -0
- package/dist/entity-manager/regular-relations.mjs +242 -0
- package/dist/entity-manager/regular-relations.mjs.map +1 -0
- package/dist/entity-manager/relations-orderer.js +221 -0
- package/dist/entity-manager/relations-orderer.js.map +1 -0
- package/dist/entity-manager/relations-orderer.mjs +218 -0
- package/dist/entity-manager/relations-orderer.mjs.map +1 -0
- package/dist/errors/database.js +13 -0
- package/dist/errors/database.js.map +1 -0
- package/dist/errors/database.mjs +11 -0
- package/dist/errors/database.mjs.map +1 -0
- package/dist/errors/index.js +18 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/index.mjs +7 -0
- package/dist/errors/index.mjs.map +1 -0
- package/dist/errors/invalid-date.js +13 -0
- package/dist/errors/invalid-date.js.map +1 -0
- package/dist/errors/invalid-date.mjs +11 -0
- package/dist/errors/invalid-date.mjs.map +1 -0
- package/dist/errors/invalid-datetime.js +13 -0
- package/dist/errors/invalid-datetime.js.map +1 -0
- package/dist/errors/invalid-datetime.mjs +11 -0
- package/dist/errors/invalid-datetime.mjs.map +1 -0
- package/dist/errors/invalid-relation.js +13 -0
- package/dist/errors/invalid-relation.js.map +1 -0
- package/dist/errors/invalid-relation.mjs +11 -0
- package/dist/errors/invalid-relation.mjs.map +1 -0
- package/dist/errors/invalid-time.js +13 -0
- package/dist/errors/invalid-time.js.map +1 -0
- package/dist/errors/invalid-time.mjs +11 -0
- package/dist/errors/invalid-time.mjs.map +1 -0
- package/dist/errors/not-null.js +17 -0
- package/dist/errors/not-null.js.map +1 -0
- package/dist/errors/not-null.mjs +15 -0
- package/dist/errors/not-null.mjs.map +1 -0
- package/dist/fields/biginteger.js +9 -0
- package/dist/fields/biginteger.js.map +1 -0
- package/dist/fields/biginteger.mjs +7 -0
- package/dist/fields/biginteger.mjs.map +1 -0
- package/dist/fields/boolean.js +48 -0
- package/dist/fields/boolean.js.map +1 -0
- package/dist/fields/boolean.mjs +46 -0
- package/dist/fields/boolean.mjs.map +1 -0
- package/dist/fields/date.js +16 -0
- package/dist/fields/date.js.map +1 -0
- package/dist/fields/date.mjs +14 -0
- package/dist/fields/date.mjs.map +1 -0
- package/dist/fields/datetime.js +37 -0
- package/dist/fields/datetime.js.map +1 -0
- package/dist/fields/datetime.mjs +16 -0
- package/dist/fields/datetime.mjs.map +1 -0
- package/dist/fields/field.js +16 -0
- package/dist/fields/field.js.map +1 -0
- package/dist/fields/field.mjs +14 -0
- package/dist/fields/field.mjs.map +1 -0
- package/dist/fields/index.js +45 -0
- package/dist/fields/index.js.map +1 -0
- package/dist/fields/index.mjs +43 -0
- package/dist/fields/index.mjs.map +1 -0
- package/dist/fields/json.js +36 -0
- package/dist/fields/json.js.map +1 -0
- package/dist/fields/json.mjs +34 -0
- package/dist/fields/json.mjs.map +1 -0
- package/dist/fields/number.js +20 -0
- package/dist/fields/number.js.map +1 -0
- package/dist/fields/number.mjs +18 -0
- package/dist/fields/number.mjs.map +1 -0
- package/dist/fields/shared/parsers.js +91 -0
- package/dist/fields/shared/parsers.js.map +1 -0
- package/dist/fields/shared/parsers.mjs +68 -0
- package/dist/fields/shared/parsers.mjs.map +1 -0
- package/dist/fields/string.js +16 -0
- package/dist/fields/string.js.map +1 -0
- package/dist/fields/string.mjs +14 -0
- package/dist/fields/string.mjs.map +1 -0
- package/dist/fields/time.js +17 -0
- package/dist/fields/time.js.map +1 -0
- package/dist/fields/time.mjs +15 -0
- package/dist/fields/time.mjs.map +1 -0
- package/dist/fields/timestamp.js +37 -0
- package/dist/fields/timestamp.js.map +1 -0
- package/dist/fields/timestamp.mjs +16 -0
- package/dist/fields/timestamp.mjs.map +1 -0
- package/dist/index.js +33 -8569
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +16 -8532
- package/dist/index.mjs.map +1 -1
- package/dist/lifecycles/index.js +73 -0
- package/dist/lifecycles/index.js.map +1 -0
- package/dist/lifecycles/index.mjs +71 -0
- package/dist/lifecycles/index.mjs.map +1 -0
- package/dist/lifecycles/subscribers/index.js +10 -0
- package/dist/lifecycles/subscribers/index.js.map +1 -0
- package/dist/lifecycles/subscribers/index.mjs +8 -0
- package/dist/lifecycles/subscribers/index.mjs.map +1 -0
- package/dist/lifecycles/subscribers/models-lifecycles.js +13 -0
- package/dist/lifecycles/subscribers/models-lifecycles.js.map +1 -0
- package/dist/lifecycles/subscribers/models-lifecycles.mjs +11 -0
- package/dist/lifecycles/subscribers/models-lifecycles.mjs.map +1 -0
- package/dist/lifecycles/subscribers/timestamps.js +55 -0
- package/dist/lifecycles/subscribers/timestamps.js.map +1 -0
- package/dist/lifecycles/subscribers/timestamps.mjs +53 -0
- package/dist/lifecycles/subscribers/timestamps.mjs.map +1 -0
- package/dist/metadata/index.js +24 -0
- package/dist/metadata/index.js.map +1 -0
- package/dist/metadata/index.mjs +16 -0
- package/dist/metadata/index.mjs.map +1 -0
- package/dist/metadata/metadata.js +100 -0
- package/dist/metadata/metadata.js.map +1 -0
- package/dist/metadata/metadata.mjs +98 -0
- package/dist/metadata/metadata.mjs.map +1 -0
- package/dist/metadata/relations.js +545 -0
- package/dist/metadata/relations.js.map +1 -0
- package/dist/metadata/relations.mjs +536 -0
- package/dist/metadata/relations.mjs.map +1 -0
- package/dist/migrations/common.js +8 -0
- package/dist/migrations/common.js.map +1 -0
- package/dist/migrations/common.mjs +6 -0
- package/dist/migrations/common.mjs.map +1 -0
- package/dist/migrations/index.js +39 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/migrations/index.mjs +37 -0
- package/dist/migrations/index.mjs.map +1 -0
- package/dist/migrations/internal-migrations/5.0.0-01-convert-identifiers-long-than-max-length.js +179 -0
- package/dist/migrations/internal-migrations/5.0.0-01-convert-identifiers-long-than-max-length.js.map +1 -0
- package/dist/migrations/internal-migrations/5.0.0-01-convert-identifiers-long-than-max-length.mjs +177 -0
- package/dist/migrations/internal-migrations/5.0.0-01-convert-identifiers-long-than-max-length.mjs.map +1 -0
- package/dist/migrations/internal-migrations/5.0.0-02-document-id.js +125 -0
- package/dist/migrations/internal-migrations/5.0.0-02-document-id.js.map +1 -0
- package/dist/migrations/internal-migrations/5.0.0-02-document-id.mjs +123 -0
- package/dist/migrations/internal-migrations/5.0.0-02-document-id.mjs.map +1 -0
- package/dist/migrations/internal-migrations/5.0.0-03-locale.js +41 -0
- package/dist/migrations/internal-migrations/5.0.0-03-locale.js.map +1 -0
- package/dist/migrations/internal-migrations/5.0.0-03-locale.mjs +39 -0
- package/dist/migrations/internal-migrations/5.0.0-03-locale.mjs.map +1 -0
- package/dist/migrations/internal-migrations/5.0.0-04-published-at.js +45 -0
- package/dist/migrations/internal-migrations/5.0.0-04-published-at.js.map +1 -0
- package/dist/migrations/internal-migrations/5.0.0-04-published-at.mjs +43 -0
- package/dist/migrations/internal-migrations/5.0.0-04-published-at.mjs.map +1 -0
- package/dist/migrations/internal-migrations/5.0.0-05-drop-slug-unique-index.js +43 -0
- package/dist/migrations/internal-migrations/5.0.0-05-drop-slug-unique-index.js.map +1 -0
- package/dist/migrations/internal-migrations/5.0.0-05-drop-slug-unique-index.mjs +41 -0
- package/dist/migrations/internal-migrations/5.0.0-05-drop-slug-unique-index.mjs.map +1 -0
- package/dist/migrations/internal-migrations/index.js +26 -0
- package/dist/migrations/internal-migrations/index.js.map +1 -0
- package/dist/migrations/internal-migrations/index.mjs +24 -0
- package/dist/migrations/internal-migrations/index.mjs.map +1 -0
- package/dist/migrations/internal.js +63 -0
- package/dist/migrations/internal.js.map +1 -0
- package/dist/migrations/internal.mjs +61 -0
- package/dist/migrations/internal.mjs.map +1 -0
- package/dist/migrations/logger.js +24 -0
- package/dist/migrations/logger.js.map +1 -0
- package/dist/migrations/logger.mjs +22 -0
- package/dist/migrations/logger.mjs.map +1 -0
- package/dist/migrations/storage.js +39 -0
- package/dist/migrations/storage.js.map +1 -0
- package/dist/migrations/storage.mjs +37 -0
- package/dist/migrations/storage.mjs.map +1 -0
- package/dist/migrations/users.js +87 -0
- package/dist/migrations/users.js.map +1 -0
- package/dist/migrations/users.mjs +85 -0
- package/dist/migrations/users.mjs.map +1 -0
- package/dist/query/helpers/join.js +127 -0
- package/dist/query/helpers/join.js.map +1 -0
- package/dist/query/helpers/join.mjs +122 -0
- package/dist/query/helpers/join.mjs.map +1 -0
- package/dist/query/helpers/order-by.js +167 -0
- package/dist/query/helpers/order-by.js.map +1 -0
- package/dist/query/helpers/order-by.mjs +163 -0
- package/dist/query/helpers/order-by.mjs.map +1 -0
- package/dist/query/helpers/populate/apply.js +592 -0
- package/dist/query/helpers/populate/apply.js.map +1 -0
- package/dist/query/helpers/populate/apply.mjs +590 -0
- package/dist/query/helpers/populate/apply.mjs.map +1 -0
- package/dist/query/helpers/populate/process.js +92 -0
- package/dist/query/helpers/populate/process.js.map +1 -0
- package/dist/query/helpers/populate/process.mjs +90 -0
- package/dist/query/helpers/populate/process.mjs.map +1 -0
- package/dist/query/helpers/search.js +67 -0
- package/dist/query/helpers/search.js.map +1 -0
- package/dist/query/helpers/search.mjs +65 -0
- package/dist/query/helpers/search.mjs.map +1 -0
- package/dist/query/helpers/streams/readable.js +131 -0
- package/dist/query/helpers/streams/readable.js.map +1 -0
- package/dist/query/helpers/streams/readable.mjs +129 -0
- package/dist/query/helpers/streams/readable.mjs.map +1 -0
- package/dist/query/helpers/transform.js +77 -0
- package/dist/query/helpers/transform.js.map +1 -0
- package/dist/query/helpers/transform.mjs +73 -0
- package/dist/query/helpers/transform.mjs.map +1 -0
- package/dist/query/helpers/where.js +372 -0
- package/dist/query/helpers/where.js.map +1 -0
- package/dist/query/helpers/where.mjs +369 -0
- package/dist/query/helpers/where.mjs.map +1 -0
- package/dist/query/query-builder.js +507 -0
- package/dist/query/query-builder.js.map +1 -0
- package/dist/query/query-builder.mjs +505 -0
- package/dist/query/query-builder.mjs.map +1 -0
- package/dist/repairs/index.js +13 -0
- package/dist/repairs/index.js.map +1 -0
- package/dist/repairs/index.mjs +11 -0
- package/dist/repairs/index.mjs.map +1 -0
- package/dist/repairs/operations/remove-orphan-morph-types.js +54 -0
- package/dist/repairs/operations/remove-orphan-morph-types.js.map +1 -0
- package/dist/repairs/operations/remove-orphan-morph-types.mjs +52 -0
- package/dist/repairs/operations/remove-orphan-morph-types.mjs.map +1 -0
- package/dist/schema/builder.js +354 -0
- package/dist/schema/builder.js.map +1 -0
- package/dist/schema/builder.mjs +352 -0
- package/dist/schema/builder.mjs.map +1 -0
- package/dist/schema/diff.js +379 -0
- package/dist/schema/diff.js.map +1 -0
- package/dist/schema/diff.mjs +377 -0
- package/dist/schema/diff.mjs.map +1 -0
- package/dist/schema/index.js +93 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/index.mjs +91 -0
- package/dist/schema/index.mjs.map +1 -0
- package/dist/schema/schema.js +266 -0
- package/dist/schema/schema.js.map +1 -0
- package/dist/schema/schema.mjs +264 -0
- package/dist/schema/schema.mjs.map +1 -0
- package/dist/schema/storage.js +58 -0
- package/dist/schema/storage.js.map +1 -0
- package/dist/schema/storage.mjs +56 -0
- package/dist/schema/storage.mjs.map +1 -0
- package/dist/transaction-context.js +65 -0
- package/dist/transaction-context.js.map +1 -0
- package/dist/transaction-context.mjs +63 -0
- package/dist/transaction-context.mjs.map +1 -0
- package/dist/utils/async-curry.js +19 -0
- package/dist/utils/async-curry.js.map +1 -0
- package/dist/utils/async-curry.mjs +17 -0
- package/dist/utils/async-curry.mjs.map +1 -0
- package/dist/utils/identifiers/hash.js +30 -0
- package/dist/utils/identifiers/hash.js.map +1 -0
- package/dist/utils/identifiers/hash.mjs +28 -0
- package/dist/utils/identifiers/hash.mjs.map +1 -0
- package/dist/utils/identifiers/index.js +414 -0
- package/dist/utils/identifiers/index.js.map +1 -0
- package/dist/utils/identifiers/index.mjs +411 -0
- package/dist/utils/identifiers/index.mjs.map +1 -0
- package/dist/utils/knex.js +21 -0
- package/dist/utils/knex.js.map +1 -0
- package/dist/utils/knex.mjs +18 -0
- package/dist/utils/knex.mjs.map +1 -0
- package/dist/utils/types.js +51 -0
- package/dist/utils/types.js.map +1 -0
- package/dist/utils/types.mjs +44 -0
- package/dist/utils/types.mjs.map +1 -0
- package/dist/validations/index.js +12 -0
- package/dist/validations/index.js.map +1 -0
- package/dist/validations/index.mjs +10 -0
- package/dist/validations/index.mjs.map +1 -0
- package/dist/validations/relations/bidirectional.js +64 -0
- package/dist/validations/relations/bidirectional.js.map +1 -0
- package/dist/validations/relations/bidirectional.mjs +62 -0
- package/dist/validations/relations/bidirectional.mjs.map +1 -0
- package/dist/validations/relations/index.js +13 -0
- package/dist/validations/relations/index.js.map +1 -0
- package/dist/validations/relations/index.mjs +11 -0
- package/dist/validations/relations/index.mjs.map +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _ = require('lodash/fp');
|
|
4
|
+
var relations = require('../metadata/relations.js');
|
|
5
|
+
require('../utils/identifiers/index.js');
|
|
6
|
+
var queryBuilder = require('../query/query-builder.js');
|
|
7
|
+
var knex = require('../utils/knex.js');
|
|
8
|
+
|
|
9
|
+
// TODO: This is a short term solution, to not steal relations from the same document.
|
|
10
|
+
const getDocumentSiblingIdsQuery = (tableName, id)=>{
|
|
11
|
+
// Find if the model is a content type or something else (e.g. component)
|
|
12
|
+
// to only get the documentId if it's a content type
|
|
13
|
+
const models = Array.from(strapi.db.metadata.values());
|
|
14
|
+
const isContentType = models.find((model)=>{
|
|
15
|
+
return model.tableName === tableName && model.attributes.documentId;
|
|
16
|
+
});
|
|
17
|
+
if (!isContentType) {
|
|
18
|
+
return [
|
|
19
|
+
id
|
|
20
|
+
];
|
|
21
|
+
}
|
|
22
|
+
// NOTE: SubQueries are wrapped in a function to not reuse the same connection,
|
|
23
|
+
// which causes infinite self references
|
|
24
|
+
return function(query) {
|
|
25
|
+
query.select('id').from(tableName)// Get all child ids of the document id
|
|
26
|
+
.whereIn('document_id', (documentIDSubQuery)=>{
|
|
27
|
+
documentIDSubQuery.from(tableName)// get document id related to the current id
|
|
28
|
+
.select('document_id').where('id', id);
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* If some relations currently exist for this oneToX relation, on the one side, this function removes them and update the inverse order if needed.
|
|
34
|
+
*/ const deletePreviousOneToAnyRelations = async ({ id, attribute, relIdsToadd, db, transaction: trx })=>{
|
|
35
|
+
if (!(relations.isBidirectional(attribute) && relations.isOneToAny(attribute))) {
|
|
36
|
+
throw new Error('deletePreviousOneToAnyRelations can only be called for bidirectional oneToAny relations');
|
|
37
|
+
}
|
|
38
|
+
const { joinTable } = attribute;
|
|
39
|
+
const { joinColumn, inverseJoinColumn } = joinTable;
|
|
40
|
+
const con = db.getConnection();
|
|
41
|
+
await con.delete().from(joinTable.name)// Exclude the ids of the current document
|
|
42
|
+
.whereNotIn(joinColumn.name, getDocumentSiblingIdsQuery(joinColumn.referencedTable, id))// Include all the ids that are being connected
|
|
43
|
+
.whereIn(inverseJoinColumn.name, relIdsToadd).where(joinTable.on || {}).transacting(trx);
|
|
44
|
+
await cleanOrderColumns({
|
|
45
|
+
attribute,
|
|
46
|
+
db,
|
|
47
|
+
inverseRelIds: relIdsToadd,
|
|
48
|
+
transaction: trx
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* If a relation currently exists for this xToOne relations, this function removes it and update the inverse order if needed.
|
|
53
|
+
*/ const deletePreviousAnyToOneRelations = async ({ id, attribute, relIdToadd, db, transaction: trx })=>{
|
|
54
|
+
const { joinTable } = attribute;
|
|
55
|
+
const { joinColumn, inverseJoinColumn } = joinTable;
|
|
56
|
+
const con = db.getConnection();
|
|
57
|
+
if (!relations.isAnyToOne(attribute)) {
|
|
58
|
+
throw new Error('deletePreviousAnyToOneRelations can only be called for anyToOne relations');
|
|
59
|
+
}
|
|
60
|
+
// handling manyToOne
|
|
61
|
+
if (relations.isManyToAny(attribute)) {
|
|
62
|
+
// if the database integrity was not broken relsToDelete is supposed to be of length 1
|
|
63
|
+
const relsToDelete = await con.select(inverseJoinColumn.name).from(joinTable.name).where(joinColumn.name, id).whereNotIn(inverseJoinColumn.name, getDocumentSiblingIdsQuery(inverseJoinColumn.referencedTable, relIdToadd)).where(joinTable.on || {}).transacting(trx);
|
|
64
|
+
const relIdsToDelete = _.map(inverseJoinColumn.name, relsToDelete);
|
|
65
|
+
await queryBuilder(joinTable.name, db).delete().where({
|
|
66
|
+
[joinColumn.name]: id,
|
|
67
|
+
[inverseJoinColumn.name]: {
|
|
68
|
+
$in: relIdsToDelete
|
|
69
|
+
}
|
|
70
|
+
}).where(joinTable.on || {}).transacting(trx).execute();
|
|
71
|
+
await cleanOrderColumns({
|
|
72
|
+
attribute,
|
|
73
|
+
db,
|
|
74
|
+
inverseRelIds: relIdsToDelete,
|
|
75
|
+
transaction: trx
|
|
76
|
+
});
|
|
77
|
+
// handling oneToOne
|
|
78
|
+
} else {
|
|
79
|
+
await con.delete().from(joinTable.name).where(joinColumn.name, id)// Exclude the ids of the current document
|
|
80
|
+
.whereNotIn(inverseJoinColumn.name, getDocumentSiblingIdsQuery(inverseJoinColumn.referencedTable, relIdToadd)).where(joinTable.on || {}).transacting(trx);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Delete all or some relations of entity field
|
|
85
|
+
*/ const deleteRelations = async ({ id, attribute, db, relIdsToNotDelete = [], relIdsToDelete = [], transaction: trx })=>{
|
|
86
|
+
const { joinTable } = attribute;
|
|
87
|
+
const { joinColumn, inverseJoinColumn } = joinTable;
|
|
88
|
+
const all = relIdsToDelete === 'all';
|
|
89
|
+
if (relations.hasOrderColumn(attribute) || relations.hasInverseOrderColumn(attribute)) {
|
|
90
|
+
let lastId = 0;
|
|
91
|
+
let done = false;
|
|
92
|
+
const batchSize = 100;
|
|
93
|
+
while(!done){
|
|
94
|
+
const batchToDelete = await queryBuilder(joinTable.name, db).select(inverseJoinColumn.name).where({
|
|
95
|
+
[joinColumn.name]: id,
|
|
96
|
+
id: {
|
|
97
|
+
$gt: lastId
|
|
98
|
+
},
|
|
99
|
+
[inverseJoinColumn.name]: {
|
|
100
|
+
$notIn: relIdsToNotDelete
|
|
101
|
+
},
|
|
102
|
+
...all ? {} : {
|
|
103
|
+
[inverseJoinColumn.name]: {
|
|
104
|
+
$in: relIdsToDelete
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}).where(joinTable.on || {}).orderBy('id').limit(batchSize).transacting(trx).execute();
|
|
108
|
+
done = batchToDelete.length < batchSize;
|
|
109
|
+
lastId = batchToDelete[batchToDelete.length - 1]?.id || 0;
|
|
110
|
+
const batchIds = _.map(inverseJoinColumn.name, batchToDelete);
|
|
111
|
+
await queryBuilder(joinTable.name, db).delete().where({
|
|
112
|
+
[joinColumn.name]: id,
|
|
113
|
+
[inverseJoinColumn.name]: {
|
|
114
|
+
$in: batchIds
|
|
115
|
+
}
|
|
116
|
+
}).where(joinTable.on || {}).transacting(trx).execute();
|
|
117
|
+
await cleanOrderColumns({
|
|
118
|
+
attribute,
|
|
119
|
+
db,
|
|
120
|
+
id,
|
|
121
|
+
inverseRelIds: batchIds,
|
|
122
|
+
transaction: trx
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
await queryBuilder(joinTable.name, db).delete().where({
|
|
127
|
+
[joinColumn.name]: id,
|
|
128
|
+
[inverseJoinColumn.name]: {
|
|
129
|
+
$notIn: relIdsToNotDelete
|
|
130
|
+
},
|
|
131
|
+
...all ? {} : {
|
|
132
|
+
[inverseJoinColumn.name]: {
|
|
133
|
+
$in: relIdsToDelete
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}).where(joinTable.on || {}).transacting(trx).execute();
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* Clean the order columns by ensuring the order value are continuous (ex: 1, 2, 3 and not 1, 5, 10)
|
|
141
|
+
*/ const cleanOrderColumns = async ({ id, attribute, db, inverseRelIds = [], transaction: trx })=>{
|
|
142
|
+
if (!(relations.hasOrderColumn(attribute) && id) && !(relations.hasInverseOrderColumn(attribute) && !_.isEmpty(inverseRelIds))) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const { joinTable } = attribute;
|
|
146
|
+
const { joinColumn, inverseJoinColumn, orderColumnName, inverseOrderColumnName } = joinTable;
|
|
147
|
+
/**
|
|
148
|
+
UPDATE :joinTable: as a,
|
|
149
|
+
(
|
|
150
|
+
SELECT
|
|
151
|
+
id,
|
|
152
|
+
ROW_NUMBER() OVER ( PARTITION BY :joinColumn: ORDER BY :orderColumn:) AS src_order,
|
|
153
|
+
FROM :joinTable:
|
|
154
|
+
WHERE :joinColumn: = :id
|
|
155
|
+
) AS b
|
|
156
|
+
SET :orderColumn: = b.src_order
|
|
157
|
+
WHERE b.id = a.id;
|
|
158
|
+
*/ const updateOrderColumn = async ()=>{
|
|
159
|
+
if (!relations.hasOrderColumn(attribute) || !id) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const selectRowsToOrder = (joinTableName)=>db.connection(joinTableName).select('id').rowNumber('src_order', orderColumnName, joinColumn.name).where(joinColumn.name, id).toSQL();
|
|
163
|
+
switch(strapi.db.dialect.client){
|
|
164
|
+
case 'mysql':
|
|
165
|
+
{
|
|
166
|
+
// Here it's MariaDB and MySQL 8
|
|
167
|
+
const select = selectRowsToOrder(joinTable.name);
|
|
168
|
+
await db.getConnection().raw(`UPDATE ?? as a, ( ${select.sql} ) AS b
|
|
169
|
+
SET ?? = b.src_order
|
|
170
|
+
WHERE b.id = a.id`, [
|
|
171
|
+
joinTable.name,
|
|
172
|
+
...select.bindings,
|
|
173
|
+
orderColumnName
|
|
174
|
+
]).transacting(trx);
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
default:
|
|
178
|
+
{
|
|
179
|
+
const joinTableName = knex.addSchema(db, joinTable.name);
|
|
180
|
+
const select = selectRowsToOrder(joinTableName);
|
|
181
|
+
// raw query as knex doesn't allow updating from a subquery
|
|
182
|
+
await db.connection.raw(`UPDATE ?? as a
|
|
183
|
+
SET ?? = b.src_order
|
|
184
|
+
FROM ( ${select.sql} ) AS b
|
|
185
|
+
WHERE b.id = a.id`, [
|
|
186
|
+
joinTableName,
|
|
187
|
+
orderColumnName,
|
|
188
|
+
...select.bindings
|
|
189
|
+
]).transacting(trx);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
/**
|
|
194
|
+
UPDATE :joinTable: as a,
|
|
195
|
+
(
|
|
196
|
+
SELECT
|
|
197
|
+
id,
|
|
198
|
+
ROW_NUMBER() OVER ( PARTITION BY :inverseJoinColumn: ORDER BY :inverseOrderColumn:) AS inv_order
|
|
199
|
+
FROM :joinTable:
|
|
200
|
+
WHERE :inverseJoinColumn: IN (:inverseRelIds)
|
|
201
|
+
) AS b
|
|
202
|
+
SET :inverseOrderColumn: = b.inv_order
|
|
203
|
+
WHERE b.id = a.id;
|
|
204
|
+
*/ const updateInverseOrderColumn = async ()=>{
|
|
205
|
+
if (!relations.hasInverseOrderColumn(attribute) || _.isEmpty(inverseRelIds)) return;
|
|
206
|
+
const selectRowsToOrder = (joinTableName)=>db.connection(joinTableName).select('id').rowNumber('inv_order', inverseOrderColumnName, inverseJoinColumn.name).where(inverseJoinColumn.name, 'in', inverseRelIds).toSQL();
|
|
207
|
+
switch(strapi.db.dialect.client){
|
|
208
|
+
case 'mysql':
|
|
209
|
+
{
|
|
210
|
+
// Here it's MariaDB and MySQL 8
|
|
211
|
+
const select = selectRowsToOrder(joinTable.name);
|
|
212
|
+
await db.getConnection().raw(`UPDATE ?? as a, ( ${select.sql} ) AS b
|
|
213
|
+
SET ?? = b.inv_order
|
|
214
|
+
WHERE b.id = a.id`, [
|
|
215
|
+
joinTable.name,
|
|
216
|
+
...select.bindings,
|
|
217
|
+
inverseOrderColumnName
|
|
218
|
+
]).transacting(trx);
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
default:
|
|
222
|
+
{
|
|
223
|
+
const joinTableName = knex.addSchema(db, joinTable.name);
|
|
224
|
+
const select = selectRowsToOrder(joinTableName);
|
|
225
|
+
// raw query as knex doesn't allow updating from a subquery
|
|
226
|
+
await db.connection.raw(`UPDATE ?? as a
|
|
227
|
+
SET ?? = b.inv_order
|
|
228
|
+
FROM ( ${select.sql} ) AS b
|
|
229
|
+
WHERE b.id = a.id`, [
|
|
230
|
+
joinTableName,
|
|
231
|
+
inverseOrderColumnName,
|
|
232
|
+
...select.bindings
|
|
233
|
+
]).transacting(trx);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
return Promise.all([
|
|
238
|
+
updateOrderColumn(),
|
|
239
|
+
updateInverseOrderColumn()
|
|
240
|
+
]);
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
exports.cleanOrderColumns = cleanOrderColumns;
|
|
244
|
+
exports.deletePreviousAnyToOneRelations = deletePreviousAnyToOneRelations;
|
|
245
|
+
exports.deletePreviousOneToAnyRelations = deletePreviousOneToAnyRelations;
|
|
246
|
+
exports.deleteRelations = deleteRelations;
|
|
247
|
+
//# sourceMappingURL=regular-relations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regular-relations.js","sources":["../../src/entity-manager/regular-relations.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-namespace */\nimport { map, isEmpty } from 'lodash/fp';\nimport type { Knex } from 'knex';\n\nimport {\n isBidirectional,\n isOneToAny,\n isManyToAny,\n isAnyToOne,\n hasOrderColumn,\n hasInverseOrderColumn,\n} from '../metadata';\nimport { createQueryBuilder } from '../query';\nimport { addSchema } from '../utils/knex';\nimport type { Database } from '..';\nimport type { ID, Relation, Model } from '../types';\n\ndeclare module 'knex' {\n namespace Knex {\n interface ChainableInterface {\n transacting(trx?: Knex.Transaction): this;\n }\n }\n}\n\n// TODO: This is a short term solution, to not steal relations from the same document.\nconst getDocumentSiblingIdsQuery = (tableName: string, id: ID) => {\n // Find if the model is a content type or something else (e.g. component)\n // to only get the documentId if it's a content type\n const models: Model[] = Array.from(strapi.db.metadata.values());\n\n const isContentType = models.find((model) => {\n return model.tableName === tableName && model.attributes.documentId;\n });\n\n if (!isContentType) {\n return [id];\n }\n\n // NOTE: SubQueries are wrapped in a function to not reuse the same connection,\n // which causes infinite self references\n return function (query) {\n query\n .select('id')\n .from(tableName)\n // Get all child ids of the document id\n .whereIn('document_id', (documentIDSubQuery) => {\n documentIDSubQuery\n .from(tableName)\n // get document id related to the current id\n .select('document_id')\n .where('id', id);\n });\n } satisfies Knex.QueryCallback;\n};\n\n/**\n * If some relations currently exist for this oneToX relation, on the one side, this function removes them and update the inverse order if needed.\n */\nconst deletePreviousOneToAnyRelations = async ({\n id,\n attribute,\n relIdsToadd,\n db,\n transaction: trx,\n}: {\n id: ID;\n attribute: Relation.Bidirectional;\n relIdsToadd: ID[];\n db: Database;\n transaction?: Knex.Transaction;\n}) => {\n if (!(isBidirectional(attribute) && isOneToAny(attribute))) {\n throw new Error(\n 'deletePreviousOneToAnyRelations can only be called for bidirectional oneToAny relations'\n );\n }\n const { joinTable } = attribute;\n const { joinColumn, inverseJoinColumn } = joinTable;\n\n const con = db.getConnection();\n\n await con\n .delete()\n .from(joinTable.name)\n // Exclude the ids of the current document\n .whereNotIn(joinColumn.name, getDocumentSiblingIdsQuery(joinColumn.referencedTable!, id))\n // Include all the ids that are being connected\n .whereIn(inverseJoinColumn.name, relIdsToadd)\n .where(joinTable.on || {})\n .transacting(trx);\n\n await cleanOrderColumns({ attribute, db, inverseRelIds: relIdsToadd, transaction: trx });\n};\n\n/**\n * If a relation currently exists for this xToOne relations, this function removes it and update the inverse order if needed.\n */\nconst deletePreviousAnyToOneRelations = async ({\n id,\n attribute,\n relIdToadd,\n db,\n transaction: trx,\n}: {\n id: ID;\n attribute: Relation.Bidirectional;\n relIdToadd: ID;\n db: Database;\n transaction?: Knex.Transaction;\n}) => {\n const { joinTable } = attribute;\n const { joinColumn, inverseJoinColumn } = joinTable;\n const con = db.getConnection();\n\n if (!isAnyToOne(attribute)) {\n throw new Error('deletePreviousAnyToOneRelations can only be called for anyToOne relations');\n }\n // handling manyToOne\n if (isManyToAny(attribute)) {\n // if the database integrity was not broken relsToDelete is supposed to be of length 1\n const relsToDelete = await con\n .select(inverseJoinColumn.name)\n .from(joinTable.name)\n .where(joinColumn.name, id)\n .whereNotIn(\n inverseJoinColumn.name,\n getDocumentSiblingIdsQuery(inverseJoinColumn.referencedTable!, relIdToadd)\n )\n .where(joinTable.on || {})\n .transacting(trx);\n\n const relIdsToDelete = map(inverseJoinColumn.name, relsToDelete);\n\n await createQueryBuilder(joinTable.name, db)\n .delete()\n .where({\n [joinColumn.name]: id,\n [inverseJoinColumn.name]: { $in: relIdsToDelete },\n })\n .where(joinTable.on || {})\n .transacting(trx)\n .execute();\n\n await cleanOrderColumns({ attribute, db, inverseRelIds: relIdsToDelete, transaction: trx });\n\n // handling oneToOne\n } else {\n await con\n .delete()\n .from(joinTable.name)\n .where(joinColumn.name, id)\n // Exclude the ids of the current document\n .whereNotIn(\n inverseJoinColumn.name,\n getDocumentSiblingIdsQuery(inverseJoinColumn.referencedTable!, relIdToadd)\n )\n .where(joinTable.on || {})\n .transacting(trx);\n }\n};\n\n/**\n * Delete all or some relations of entity field\n */\nconst deleteRelations = async ({\n id,\n attribute,\n db,\n relIdsToNotDelete = [],\n relIdsToDelete = [],\n transaction: trx,\n}: {\n id: ID;\n attribute: Relation.Bidirectional;\n db: Database;\n relIdsToNotDelete?: ID[];\n relIdsToDelete?: ID[] | 'all';\n transaction?: Knex.Transaction;\n}) => {\n const { joinTable } = attribute;\n const { joinColumn, inverseJoinColumn } = joinTable;\n const all = relIdsToDelete === 'all';\n\n if (hasOrderColumn(attribute) || hasInverseOrderColumn(attribute)) {\n let lastId: ID = 0;\n let done = false;\n const batchSize = 100;\n\n while (!done) {\n const batchToDelete: { id: ID }[] = await createQueryBuilder(joinTable.name, db)\n .select(inverseJoinColumn.name)\n .where({\n [joinColumn.name]: id,\n id: { $gt: lastId },\n [inverseJoinColumn.name]: { $notIn: relIdsToNotDelete },\n ...(all ? {} : { [inverseJoinColumn.name]: { $in: relIdsToDelete } }),\n })\n .where(joinTable.on || {})\n .orderBy('id')\n .limit(batchSize)\n .transacting(trx)\n .execute();\n\n done = batchToDelete.length < batchSize;\n lastId = batchToDelete[batchToDelete.length - 1]?.id || 0;\n\n const batchIds = map(inverseJoinColumn.name, batchToDelete);\n\n await createQueryBuilder(joinTable.name, db)\n .delete()\n .where({\n [joinColumn.name]: id,\n [inverseJoinColumn.name]: { $in: batchIds },\n })\n .where(joinTable.on || {})\n .transacting(trx)\n .execute();\n\n await cleanOrderColumns({ attribute, db, id, inverseRelIds: batchIds, transaction: trx });\n }\n } else {\n await createQueryBuilder(joinTable.name, db)\n .delete()\n .where({\n [joinColumn.name]: id,\n [inverseJoinColumn.name]: { $notIn: relIdsToNotDelete },\n ...(all ? {} : { [inverseJoinColumn.name]: { $in: relIdsToDelete } }),\n })\n .where(joinTable.on || {})\n .transacting(trx)\n .execute();\n }\n};\n\n/**\n * Clean the order columns by ensuring the order value are continuous (ex: 1, 2, 3 and not 1, 5, 10)\n */\nconst cleanOrderColumns = async ({\n id,\n attribute,\n db,\n inverseRelIds = [],\n transaction: trx,\n}: {\n id?: ID;\n attribute: Relation.Bidirectional;\n db: Database;\n inverseRelIds?: ID[];\n transaction?: Knex.Transaction;\n}) => {\n if (\n !(hasOrderColumn(attribute) && id) &&\n !(hasInverseOrderColumn(attribute) && !isEmpty(inverseRelIds))\n ) {\n return;\n }\n\n const { joinTable } = attribute;\n const { joinColumn, inverseJoinColumn, orderColumnName, inverseOrderColumnName } = joinTable;\n\n /**\n UPDATE :joinTable: as a,\n (\n SELECT\n id,\n ROW_NUMBER() OVER ( PARTITION BY :joinColumn: ORDER BY :orderColumn:) AS src_order,\n FROM :joinTable:\n WHERE :joinColumn: = :id\n ) AS b\n SET :orderColumn: = b.src_order\n WHERE b.id = a.id;\n */\n const updateOrderColumn = async () => {\n if (!hasOrderColumn(attribute) || !id) {\n return;\n }\n\n const selectRowsToOrder = (joinTableName: string) =>\n db\n .connection(joinTableName)\n .select('id')\n .rowNumber('src_order', orderColumnName, joinColumn.name)\n .where(joinColumn.name, id)\n .toSQL();\n\n switch (strapi.db.dialect.client) {\n case 'mysql': {\n // Here it's MariaDB and MySQL 8\n const select = selectRowsToOrder(joinTable.name);\n\n await db\n .getConnection()\n .raw(\n `UPDATE ?? as a, ( ${select.sql} ) AS b\n SET ?? = b.src_order\n WHERE b.id = a.id`,\n [joinTable.name, ...select.bindings, orderColumnName]\n )\n .transacting(trx);\n\n break;\n }\n default: {\n const joinTableName = addSchema(db, joinTable.name);\n const select = selectRowsToOrder(joinTableName);\n\n // raw query as knex doesn't allow updating from a subquery\n await db.connection\n .raw(\n `UPDATE ?? as a\n SET ?? = b.src_order\n FROM ( ${select.sql} ) AS b\n WHERE b.id = a.id`,\n [joinTableName, orderColumnName, ...select.bindings]\n )\n .transacting(trx);\n }\n }\n };\n\n /**\n UPDATE :joinTable: as a,\n (\n SELECT\n id,\n ROW_NUMBER() OVER ( PARTITION BY :inverseJoinColumn: ORDER BY :inverseOrderColumn:) AS inv_order\n FROM :joinTable:\n WHERE :inverseJoinColumn: IN (:inverseRelIds)\n ) AS b\n SET :inverseOrderColumn: = b.inv_order\n WHERE b.id = a.id;\n */\n const updateInverseOrderColumn = async () => {\n if (!hasInverseOrderColumn(attribute) || isEmpty(inverseRelIds)) return;\n\n const selectRowsToOrder = (joinTableName: string) =>\n db\n .connection(joinTableName)\n .select('id')\n .rowNumber('inv_order', inverseOrderColumnName, inverseJoinColumn.name)\n .where(inverseJoinColumn.name, 'in', inverseRelIds)\n .toSQL();\n\n switch (strapi.db.dialect.client) {\n case 'mysql': {\n // Here it's MariaDB and MySQL 8\n const select = selectRowsToOrder(joinTable.name);\n\n await db\n .getConnection()\n .raw(\n `UPDATE ?? as a, ( ${select.sql} ) AS b\n SET ?? = b.inv_order\n WHERE b.id = a.id`,\n [joinTable.name, ...select.bindings, inverseOrderColumnName]\n )\n .transacting(trx);\n break;\n }\n default: {\n const joinTableName = addSchema(db, joinTable.name);\n const select = selectRowsToOrder(joinTableName);\n\n // raw query as knex doesn't allow updating from a subquery\n await db.connection\n .raw(\n `UPDATE ?? as a\n SET ?? = b.inv_order\n FROM ( ${select.sql} ) AS b\n WHERE b.id = a.id`,\n [joinTableName, inverseOrderColumnName, ...select.bindings]\n )\n .transacting(trx);\n }\n }\n };\n\n return Promise.all([updateOrderColumn(), updateInverseOrderColumn()]);\n};\n\nexport {\n deletePreviousOneToAnyRelations,\n deletePreviousAnyToOneRelations,\n deleteRelations,\n cleanOrderColumns,\n};\n"],"names":["getDocumentSiblingIdsQuery","tableName","id","models","Array","from","strapi","db","metadata","values","isContentType","find","model","attributes","documentId","query","select","whereIn","documentIDSubQuery","where","deletePreviousOneToAnyRelations","attribute","relIdsToadd","transaction","trx","isBidirectional","isOneToAny","Error","joinTable","joinColumn","inverseJoinColumn","con","getConnection","delete","name","whereNotIn","referencedTable","on","transacting","cleanOrderColumns","inverseRelIds","deletePreviousAnyToOneRelations","relIdToadd","isAnyToOne","isManyToAny","relsToDelete","relIdsToDelete","map","createQueryBuilder","$in","execute","deleteRelations","relIdsToNotDelete","all","hasOrderColumn","hasInverseOrderColumn","lastId","done","batchSize","batchToDelete","$gt","$notIn","orderBy","limit","length","batchIds","isEmpty","orderColumnName","inverseOrderColumnName","updateOrderColumn","selectRowsToOrder","joinTableName","connection","rowNumber","toSQL","dialect","client","raw","sql","bindings","addSchema","updateInverseOrderColumn","Promise"],"mappings":"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"}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { map, isEmpty } from 'lodash/fp';
|
|
2
|
+
import { isBidirectional, isOneToAny, isAnyToOne, isManyToAny, hasOrderColumn, hasInverseOrderColumn } from '../metadata/relations.mjs';
|
|
3
|
+
import '../utils/identifiers/index.mjs';
|
|
4
|
+
import createQueryBuilder from '../query/query-builder.mjs';
|
|
5
|
+
import { addSchema } from '../utils/knex.mjs';
|
|
6
|
+
|
|
7
|
+
// TODO: This is a short term solution, to not steal relations from the same document.
|
|
8
|
+
const getDocumentSiblingIdsQuery = (tableName, id)=>{
|
|
9
|
+
// Find if the model is a content type or something else (e.g. component)
|
|
10
|
+
// to only get the documentId if it's a content type
|
|
11
|
+
const models = Array.from(strapi.db.metadata.values());
|
|
12
|
+
const isContentType = models.find((model)=>{
|
|
13
|
+
return model.tableName === tableName && model.attributes.documentId;
|
|
14
|
+
});
|
|
15
|
+
if (!isContentType) {
|
|
16
|
+
return [
|
|
17
|
+
id
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
// NOTE: SubQueries are wrapped in a function to not reuse the same connection,
|
|
21
|
+
// which causes infinite self references
|
|
22
|
+
return function(query) {
|
|
23
|
+
query.select('id').from(tableName)// Get all child ids of the document id
|
|
24
|
+
.whereIn('document_id', (documentIDSubQuery)=>{
|
|
25
|
+
documentIDSubQuery.from(tableName)// get document id related to the current id
|
|
26
|
+
.select('document_id').where('id', id);
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* If some relations currently exist for this oneToX relation, on the one side, this function removes them and update the inverse order if needed.
|
|
32
|
+
*/ const deletePreviousOneToAnyRelations = async ({ id, attribute, relIdsToadd, db, transaction: trx })=>{
|
|
33
|
+
if (!(isBidirectional(attribute) && isOneToAny(attribute))) {
|
|
34
|
+
throw new Error('deletePreviousOneToAnyRelations can only be called for bidirectional oneToAny relations');
|
|
35
|
+
}
|
|
36
|
+
const { joinTable } = attribute;
|
|
37
|
+
const { joinColumn, inverseJoinColumn } = joinTable;
|
|
38
|
+
const con = db.getConnection();
|
|
39
|
+
await con.delete().from(joinTable.name)// Exclude the ids of the current document
|
|
40
|
+
.whereNotIn(joinColumn.name, getDocumentSiblingIdsQuery(joinColumn.referencedTable, id))// Include all the ids that are being connected
|
|
41
|
+
.whereIn(inverseJoinColumn.name, relIdsToadd).where(joinTable.on || {}).transacting(trx);
|
|
42
|
+
await cleanOrderColumns({
|
|
43
|
+
attribute,
|
|
44
|
+
db,
|
|
45
|
+
inverseRelIds: relIdsToadd,
|
|
46
|
+
transaction: trx
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* If a relation currently exists for this xToOne relations, this function removes it and update the inverse order if needed.
|
|
51
|
+
*/ const deletePreviousAnyToOneRelations = async ({ id, attribute, relIdToadd, db, transaction: trx })=>{
|
|
52
|
+
const { joinTable } = attribute;
|
|
53
|
+
const { joinColumn, inverseJoinColumn } = joinTable;
|
|
54
|
+
const con = db.getConnection();
|
|
55
|
+
if (!isAnyToOne(attribute)) {
|
|
56
|
+
throw new Error('deletePreviousAnyToOneRelations can only be called for anyToOne relations');
|
|
57
|
+
}
|
|
58
|
+
// handling manyToOne
|
|
59
|
+
if (isManyToAny(attribute)) {
|
|
60
|
+
// if the database integrity was not broken relsToDelete is supposed to be of length 1
|
|
61
|
+
const relsToDelete = await con.select(inverseJoinColumn.name).from(joinTable.name).where(joinColumn.name, id).whereNotIn(inverseJoinColumn.name, getDocumentSiblingIdsQuery(inverseJoinColumn.referencedTable, relIdToadd)).where(joinTable.on || {}).transacting(trx);
|
|
62
|
+
const relIdsToDelete = map(inverseJoinColumn.name, relsToDelete);
|
|
63
|
+
await createQueryBuilder(joinTable.name, db).delete().where({
|
|
64
|
+
[joinColumn.name]: id,
|
|
65
|
+
[inverseJoinColumn.name]: {
|
|
66
|
+
$in: relIdsToDelete
|
|
67
|
+
}
|
|
68
|
+
}).where(joinTable.on || {}).transacting(trx).execute();
|
|
69
|
+
await cleanOrderColumns({
|
|
70
|
+
attribute,
|
|
71
|
+
db,
|
|
72
|
+
inverseRelIds: relIdsToDelete,
|
|
73
|
+
transaction: trx
|
|
74
|
+
});
|
|
75
|
+
// handling oneToOne
|
|
76
|
+
} else {
|
|
77
|
+
await con.delete().from(joinTable.name).where(joinColumn.name, id)// Exclude the ids of the current document
|
|
78
|
+
.whereNotIn(inverseJoinColumn.name, getDocumentSiblingIdsQuery(inverseJoinColumn.referencedTable, relIdToadd)).where(joinTable.on || {}).transacting(trx);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Delete all or some relations of entity field
|
|
83
|
+
*/ const deleteRelations = async ({ id, attribute, db, relIdsToNotDelete = [], relIdsToDelete = [], transaction: trx })=>{
|
|
84
|
+
const { joinTable } = attribute;
|
|
85
|
+
const { joinColumn, inverseJoinColumn } = joinTable;
|
|
86
|
+
const all = relIdsToDelete === 'all';
|
|
87
|
+
if (hasOrderColumn(attribute) || hasInverseOrderColumn(attribute)) {
|
|
88
|
+
let lastId = 0;
|
|
89
|
+
let done = false;
|
|
90
|
+
const batchSize = 100;
|
|
91
|
+
while(!done){
|
|
92
|
+
const batchToDelete = await createQueryBuilder(joinTable.name, db).select(inverseJoinColumn.name).where({
|
|
93
|
+
[joinColumn.name]: id,
|
|
94
|
+
id: {
|
|
95
|
+
$gt: lastId
|
|
96
|
+
},
|
|
97
|
+
[inverseJoinColumn.name]: {
|
|
98
|
+
$notIn: relIdsToNotDelete
|
|
99
|
+
},
|
|
100
|
+
...all ? {} : {
|
|
101
|
+
[inverseJoinColumn.name]: {
|
|
102
|
+
$in: relIdsToDelete
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}).where(joinTable.on || {}).orderBy('id').limit(batchSize).transacting(trx).execute();
|
|
106
|
+
done = batchToDelete.length < batchSize;
|
|
107
|
+
lastId = batchToDelete[batchToDelete.length - 1]?.id || 0;
|
|
108
|
+
const batchIds = map(inverseJoinColumn.name, batchToDelete);
|
|
109
|
+
await createQueryBuilder(joinTable.name, db).delete().where({
|
|
110
|
+
[joinColumn.name]: id,
|
|
111
|
+
[inverseJoinColumn.name]: {
|
|
112
|
+
$in: batchIds
|
|
113
|
+
}
|
|
114
|
+
}).where(joinTable.on || {}).transacting(trx).execute();
|
|
115
|
+
await cleanOrderColumns({
|
|
116
|
+
attribute,
|
|
117
|
+
db,
|
|
118
|
+
id,
|
|
119
|
+
inverseRelIds: batchIds,
|
|
120
|
+
transaction: trx
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
} else {
|
|
124
|
+
await createQueryBuilder(joinTable.name, db).delete().where({
|
|
125
|
+
[joinColumn.name]: id,
|
|
126
|
+
[inverseJoinColumn.name]: {
|
|
127
|
+
$notIn: relIdsToNotDelete
|
|
128
|
+
},
|
|
129
|
+
...all ? {} : {
|
|
130
|
+
[inverseJoinColumn.name]: {
|
|
131
|
+
$in: relIdsToDelete
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}).where(joinTable.on || {}).transacting(trx).execute();
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* Clean the order columns by ensuring the order value are continuous (ex: 1, 2, 3 and not 1, 5, 10)
|
|
139
|
+
*/ const cleanOrderColumns = async ({ id, attribute, db, inverseRelIds = [], transaction: trx })=>{
|
|
140
|
+
if (!(hasOrderColumn(attribute) && id) && !(hasInverseOrderColumn(attribute) && !isEmpty(inverseRelIds))) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const { joinTable } = attribute;
|
|
144
|
+
const { joinColumn, inverseJoinColumn, orderColumnName, inverseOrderColumnName } = joinTable;
|
|
145
|
+
/**
|
|
146
|
+
UPDATE :joinTable: as a,
|
|
147
|
+
(
|
|
148
|
+
SELECT
|
|
149
|
+
id,
|
|
150
|
+
ROW_NUMBER() OVER ( PARTITION BY :joinColumn: ORDER BY :orderColumn:) AS src_order,
|
|
151
|
+
FROM :joinTable:
|
|
152
|
+
WHERE :joinColumn: = :id
|
|
153
|
+
) AS b
|
|
154
|
+
SET :orderColumn: = b.src_order
|
|
155
|
+
WHERE b.id = a.id;
|
|
156
|
+
*/ const updateOrderColumn = async ()=>{
|
|
157
|
+
if (!hasOrderColumn(attribute) || !id) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const selectRowsToOrder = (joinTableName)=>db.connection(joinTableName).select('id').rowNumber('src_order', orderColumnName, joinColumn.name).where(joinColumn.name, id).toSQL();
|
|
161
|
+
switch(strapi.db.dialect.client){
|
|
162
|
+
case 'mysql':
|
|
163
|
+
{
|
|
164
|
+
// Here it's MariaDB and MySQL 8
|
|
165
|
+
const select = selectRowsToOrder(joinTable.name);
|
|
166
|
+
await db.getConnection().raw(`UPDATE ?? as a, ( ${select.sql} ) AS b
|
|
167
|
+
SET ?? = b.src_order
|
|
168
|
+
WHERE b.id = a.id`, [
|
|
169
|
+
joinTable.name,
|
|
170
|
+
...select.bindings,
|
|
171
|
+
orderColumnName
|
|
172
|
+
]).transacting(trx);
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
default:
|
|
176
|
+
{
|
|
177
|
+
const joinTableName = addSchema(db, joinTable.name);
|
|
178
|
+
const select = selectRowsToOrder(joinTableName);
|
|
179
|
+
// raw query as knex doesn't allow updating from a subquery
|
|
180
|
+
await db.connection.raw(`UPDATE ?? as a
|
|
181
|
+
SET ?? = b.src_order
|
|
182
|
+
FROM ( ${select.sql} ) AS b
|
|
183
|
+
WHERE b.id = a.id`, [
|
|
184
|
+
joinTableName,
|
|
185
|
+
orderColumnName,
|
|
186
|
+
...select.bindings
|
|
187
|
+
]).transacting(trx);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
/**
|
|
192
|
+
UPDATE :joinTable: as a,
|
|
193
|
+
(
|
|
194
|
+
SELECT
|
|
195
|
+
id,
|
|
196
|
+
ROW_NUMBER() OVER ( PARTITION BY :inverseJoinColumn: ORDER BY :inverseOrderColumn:) AS inv_order
|
|
197
|
+
FROM :joinTable:
|
|
198
|
+
WHERE :inverseJoinColumn: IN (:inverseRelIds)
|
|
199
|
+
) AS b
|
|
200
|
+
SET :inverseOrderColumn: = b.inv_order
|
|
201
|
+
WHERE b.id = a.id;
|
|
202
|
+
*/ const updateInverseOrderColumn = async ()=>{
|
|
203
|
+
if (!hasInverseOrderColumn(attribute) || isEmpty(inverseRelIds)) return;
|
|
204
|
+
const selectRowsToOrder = (joinTableName)=>db.connection(joinTableName).select('id').rowNumber('inv_order', inverseOrderColumnName, inverseJoinColumn.name).where(inverseJoinColumn.name, 'in', inverseRelIds).toSQL();
|
|
205
|
+
switch(strapi.db.dialect.client){
|
|
206
|
+
case 'mysql':
|
|
207
|
+
{
|
|
208
|
+
// Here it's MariaDB and MySQL 8
|
|
209
|
+
const select = selectRowsToOrder(joinTable.name);
|
|
210
|
+
await db.getConnection().raw(`UPDATE ?? as a, ( ${select.sql} ) AS b
|
|
211
|
+
SET ?? = b.inv_order
|
|
212
|
+
WHERE b.id = a.id`, [
|
|
213
|
+
joinTable.name,
|
|
214
|
+
...select.bindings,
|
|
215
|
+
inverseOrderColumnName
|
|
216
|
+
]).transacting(trx);
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
default:
|
|
220
|
+
{
|
|
221
|
+
const joinTableName = addSchema(db, joinTable.name);
|
|
222
|
+
const select = selectRowsToOrder(joinTableName);
|
|
223
|
+
// raw query as knex doesn't allow updating from a subquery
|
|
224
|
+
await db.connection.raw(`UPDATE ?? as a
|
|
225
|
+
SET ?? = b.inv_order
|
|
226
|
+
FROM ( ${select.sql} ) AS b
|
|
227
|
+
WHERE b.id = a.id`, [
|
|
228
|
+
joinTableName,
|
|
229
|
+
inverseOrderColumnName,
|
|
230
|
+
...select.bindings
|
|
231
|
+
]).transacting(trx);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
return Promise.all([
|
|
236
|
+
updateOrderColumn(),
|
|
237
|
+
updateInverseOrderColumn()
|
|
238
|
+
]);
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
export { cleanOrderColumns, deletePreviousAnyToOneRelations, deletePreviousOneToAnyRelations, deleteRelations };
|
|
242
|
+
//# sourceMappingURL=regular-relations.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regular-relations.mjs","sources":["../../src/entity-manager/regular-relations.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-namespace */\nimport { map, isEmpty } from 'lodash/fp';\nimport type { Knex } from 'knex';\n\nimport {\n isBidirectional,\n isOneToAny,\n isManyToAny,\n isAnyToOne,\n hasOrderColumn,\n hasInverseOrderColumn,\n} from '../metadata';\nimport { createQueryBuilder } from '../query';\nimport { addSchema } from '../utils/knex';\nimport type { Database } from '..';\nimport type { ID, Relation, Model } from '../types';\n\ndeclare module 'knex' {\n namespace Knex {\n interface ChainableInterface {\n transacting(trx?: Knex.Transaction): this;\n }\n }\n}\n\n// TODO: This is a short term solution, to not steal relations from the same document.\nconst getDocumentSiblingIdsQuery = (tableName: string, id: ID) => {\n // Find if the model is a content type or something else (e.g. component)\n // to only get the documentId if it's a content type\n const models: Model[] = Array.from(strapi.db.metadata.values());\n\n const isContentType = models.find((model) => {\n return model.tableName === tableName && model.attributes.documentId;\n });\n\n if (!isContentType) {\n return [id];\n }\n\n // NOTE: SubQueries are wrapped in a function to not reuse the same connection,\n // which causes infinite self references\n return function (query) {\n query\n .select('id')\n .from(tableName)\n // Get all child ids of the document id\n .whereIn('document_id', (documentIDSubQuery) => {\n documentIDSubQuery\n .from(tableName)\n // get document id related to the current id\n .select('document_id')\n .where('id', id);\n });\n } satisfies Knex.QueryCallback;\n};\n\n/**\n * If some relations currently exist for this oneToX relation, on the one side, this function removes them and update the inverse order if needed.\n */\nconst deletePreviousOneToAnyRelations = async ({\n id,\n attribute,\n relIdsToadd,\n db,\n transaction: trx,\n}: {\n id: ID;\n attribute: Relation.Bidirectional;\n relIdsToadd: ID[];\n db: Database;\n transaction?: Knex.Transaction;\n}) => {\n if (!(isBidirectional(attribute) && isOneToAny(attribute))) {\n throw new Error(\n 'deletePreviousOneToAnyRelations can only be called for bidirectional oneToAny relations'\n );\n }\n const { joinTable } = attribute;\n const { joinColumn, inverseJoinColumn } = joinTable;\n\n const con = db.getConnection();\n\n await con\n .delete()\n .from(joinTable.name)\n // Exclude the ids of the current document\n .whereNotIn(joinColumn.name, getDocumentSiblingIdsQuery(joinColumn.referencedTable!, id))\n // Include all the ids that are being connected\n .whereIn(inverseJoinColumn.name, relIdsToadd)\n .where(joinTable.on || {})\n .transacting(trx);\n\n await cleanOrderColumns({ attribute, db, inverseRelIds: relIdsToadd, transaction: trx });\n};\n\n/**\n * If a relation currently exists for this xToOne relations, this function removes it and update the inverse order if needed.\n */\nconst deletePreviousAnyToOneRelations = async ({\n id,\n attribute,\n relIdToadd,\n db,\n transaction: trx,\n}: {\n id: ID;\n attribute: Relation.Bidirectional;\n relIdToadd: ID;\n db: Database;\n transaction?: Knex.Transaction;\n}) => {\n const { joinTable } = attribute;\n const { joinColumn, inverseJoinColumn } = joinTable;\n const con = db.getConnection();\n\n if (!isAnyToOne(attribute)) {\n throw new Error('deletePreviousAnyToOneRelations can only be called for anyToOne relations');\n }\n // handling manyToOne\n if (isManyToAny(attribute)) {\n // if the database integrity was not broken relsToDelete is supposed to be of length 1\n const relsToDelete = await con\n .select(inverseJoinColumn.name)\n .from(joinTable.name)\n .where(joinColumn.name, id)\n .whereNotIn(\n inverseJoinColumn.name,\n getDocumentSiblingIdsQuery(inverseJoinColumn.referencedTable!, relIdToadd)\n )\n .where(joinTable.on || {})\n .transacting(trx);\n\n const relIdsToDelete = map(inverseJoinColumn.name, relsToDelete);\n\n await createQueryBuilder(joinTable.name, db)\n .delete()\n .where({\n [joinColumn.name]: id,\n [inverseJoinColumn.name]: { $in: relIdsToDelete },\n })\n .where(joinTable.on || {})\n .transacting(trx)\n .execute();\n\n await cleanOrderColumns({ attribute, db, inverseRelIds: relIdsToDelete, transaction: trx });\n\n // handling oneToOne\n } else {\n await con\n .delete()\n .from(joinTable.name)\n .where(joinColumn.name, id)\n // Exclude the ids of the current document\n .whereNotIn(\n inverseJoinColumn.name,\n getDocumentSiblingIdsQuery(inverseJoinColumn.referencedTable!, relIdToadd)\n )\n .where(joinTable.on || {})\n .transacting(trx);\n }\n};\n\n/**\n * Delete all or some relations of entity field\n */\nconst deleteRelations = async ({\n id,\n attribute,\n db,\n relIdsToNotDelete = [],\n relIdsToDelete = [],\n transaction: trx,\n}: {\n id: ID;\n attribute: Relation.Bidirectional;\n db: Database;\n relIdsToNotDelete?: ID[];\n relIdsToDelete?: ID[] | 'all';\n transaction?: Knex.Transaction;\n}) => {\n const { joinTable } = attribute;\n const { joinColumn, inverseJoinColumn } = joinTable;\n const all = relIdsToDelete === 'all';\n\n if (hasOrderColumn(attribute) || hasInverseOrderColumn(attribute)) {\n let lastId: ID = 0;\n let done = false;\n const batchSize = 100;\n\n while (!done) {\n const batchToDelete: { id: ID }[] = await createQueryBuilder(joinTable.name, db)\n .select(inverseJoinColumn.name)\n .where({\n [joinColumn.name]: id,\n id: { $gt: lastId },\n [inverseJoinColumn.name]: { $notIn: relIdsToNotDelete },\n ...(all ? {} : { [inverseJoinColumn.name]: { $in: relIdsToDelete } }),\n })\n .where(joinTable.on || {})\n .orderBy('id')\n .limit(batchSize)\n .transacting(trx)\n .execute();\n\n done = batchToDelete.length < batchSize;\n lastId = batchToDelete[batchToDelete.length - 1]?.id || 0;\n\n const batchIds = map(inverseJoinColumn.name, batchToDelete);\n\n await createQueryBuilder(joinTable.name, db)\n .delete()\n .where({\n [joinColumn.name]: id,\n [inverseJoinColumn.name]: { $in: batchIds },\n })\n .where(joinTable.on || {})\n .transacting(trx)\n .execute();\n\n await cleanOrderColumns({ attribute, db, id, inverseRelIds: batchIds, transaction: trx });\n }\n } else {\n await createQueryBuilder(joinTable.name, db)\n .delete()\n .where({\n [joinColumn.name]: id,\n [inverseJoinColumn.name]: { $notIn: relIdsToNotDelete },\n ...(all ? {} : { [inverseJoinColumn.name]: { $in: relIdsToDelete } }),\n })\n .where(joinTable.on || {})\n .transacting(trx)\n .execute();\n }\n};\n\n/**\n * Clean the order columns by ensuring the order value are continuous (ex: 1, 2, 3 and not 1, 5, 10)\n */\nconst cleanOrderColumns = async ({\n id,\n attribute,\n db,\n inverseRelIds = [],\n transaction: trx,\n}: {\n id?: ID;\n attribute: Relation.Bidirectional;\n db: Database;\n inverseRelIds?: ID[];\n transaction?: Knex.Transaction;\n}) => {\n if (\n !(hasOrderColumn(attribute) && id) &&\n !(hasInverseOrderColumn(attribute) && !isEmpty(inverseRelIds))\n ) {\n return;\n }\n\n const { joinTable } = attribute;\n const { joinColumn, inverseJoinColumn, orderColumnName, inverseOrderColumnName } = joinTable;\n\n /**\n UPDATE :joinTable: as a,\n (\n SELECT\n id,\n ROW_NUMBER() OVER ( PARTITION BY :joinColumn: ORDER BY :orderColumn:) AS src_order,\n FROM :joinTable:\n WHERE :joinColumn: = :id\n ) AS b\n SET :orderColumn: = b.src_order\n WHERE b.id = a.id;\n */\n const updateOrderColumn = async () => {\n if (!hasOrderColumn(attribute) || !id) {\n return;\n }\n\n const selectRowsToOrder = (joinTableName: string) =>\n db\n .connection(joinTableName)\n .select('id')\n .rowNumber('src_order', orderColumnName, joinColumn.name)\n .where(joinColumn.name, id)\n .toSQL();\n\n switch (strapi.db.dialect.client) {\n case 'mysql': {\n // Here it's MariaDB and MySQL 8\n const select = selectRowsToOrder(joinTable.name);\n\n await db\n .getConnection()\n .raw(\n `UPDATE ?? as a, ( ${select.sql} ) AS b\n SET ?? = b.src_order\n WHERE b.id = a.id`,\n [joinTable.name, ...select.bindings, orderColumnName]\n )\n .transacting(trx);\n\n break;\n }\n default: {\n const joinTableName = addSchema(db, joinTable.name);\n const select = selectRowsToOrder(joinTableName);\n\n // raw query as knex doesn't allow updating from a subquery\n await db.connection\n .raw(\n `UPDATE ?? as a\n SET ?? = b.src_order\n FROM ( ${select.sql} ) AS b\n WHERE b.id = a.id`,\n [joinTableName, orderColumnName, ...select.bindings]\n )\n .transacting(trx);\n }\n }\n };\n\n /**\n UPDATE :joinTable: as a,\n (\n SELECT\n id,\n ROW_NUMBER() OVER ( PARTITION BY :inverseJoinColumn: ORDER BY :inverseOrderColumn:) AS inv_order\n FROM :joinTable:\n WHERE :inverseJoinColumn: IN (:inverseRelIds)\n ) AS b\n SET :inverseOrderColumn: = b.inv_order\n WHERE b.id = a.id;\n */\n const updateInverseOrderColumn = async () => {\n if (!hasInverseOrderColumn(attribute) || isEmpty(inverseRelIds)) return;\n\n const selectRowsToOrder = (joinTableName: string) =>\n db\n .connection(joinTableName)\n .select('id')\n .rowNumber('inv_order', inverseOrderColumnName, inverseJoinColumn.name)\n .where(inverseJoinColumn.name, 'in', inverseRelIds)\n .toSQL();\n\n switch (strapi.db.dialect.client) {\n case 'mysql': {\n // Here it's MariaDB and MySQL 8\n const select = selectRowsToOrder(joinTable.name);\n\n await db\n .getConnection()\n .raw(\n `UPDATE ?? as a, ( ${select.sql} ) AS b\n SET ?? = b.inv_order\n WHERE b.id = a.id`,\n [joinTable.name, ...select.bindings, inverseOrderColumnName]\n )\n .transacting(trx);\n break;\n }\n default: {\n const joinTableName = addSchema(db, joinTable.name);\n const select = selectRowsToOrder(joinTableName);\n\n // raw query as knex doesn't allow updating from a subquery\n await db.connection\n .raw(\n `UPDATE ?? as a\n SET ?? = b.inv_order\n FROM ( ${select.sql} ) AS b\n WHERE b.id = a.id`,\n [joinTableName, inverseOrderColumnName, ...select.bindings]\n )\n .transacting(trx);\n }\n }\n };\n\n return Promise.all([updateOrderColumn(), updateInverseOrderColumn()]);\n};\n\nexport {\n deletePreviousOneToAnyRelations,\n deletePreviousAnyToOneRelations,\n deleteRelations,\n cleanOrderColumns,\n};\n"],"names":["getDocumentSiblingIdsQuery","tableName","id","models","Array","from","strapi","db","metadata","values","isContentType","find","model","attributes","documentId","query","select","whereIn","documentIDSubQuery","where","deletePreviousOneToAnyRelations","attribute","relIdsToadd","transaction","trx","isBidirectional","isOneToAny","Error","joinTable","joinColumn","inverseJoinColumn","con","getConnection","delete","name","whereNotIn","referencedTable","on","transacting","cleanOrderColumns","inverseRelIds","deletePreviousAnyToOneRelations","relIdToadd","isAnyToOne","isManyToAny","relsToDelete","relIdsToDelete","map","createQueryBuilder","$in","execute","deleteRelations","relIdsToNotDelete","all","hasOrderColumn","hasInverseOrderColumn","lastId","done","batchSize","batchToDelete","$gt","$notIn","orderBy","limit","length","batchIds","isEmpty","orderColumnName","inverseOrderColumnName","updateOrderColumn","selectRowsToOrder","joinTableName","connection","rowNumber","toSQL","dialect","client","raw","sql","bindings","addSchema","updateInverseOrderColumn","Promise"],"mappings":"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"}
|