@strapi/database 5.12.1 → 5.12.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.
Files changed (321) hide show
  1. package/dist/connection.js +43 -0
  2. package/dist/connection.js.map +1 -0
  3. package/dist/connection.mjs +41 -0
  4. package/dist/connection.mjs.map +1 -0
  5. package/dist/dialects/dialect.js +54 -0
  6. package/dist/dialects/dialect.js.map +1 -0
  7. package/dist/dialects/dialect.mjs +52 -0
  8. package/dist/dialects/dialect.mjs.map +1 -0
  9. package/dist/dialects/index.js +44 -0
  10. package/dist/dialects/index.js.map +1 -0
  11. package/dist/dialects/index.mjs +42 -0
  12. package/dist/dialects/index.mjs.map +1 -0
  13. package/dist/dialects/mysql/constants.js +8 -0
  14. package/dist/dialects/mysql/constants.js.map +1 -0
  15. package/dist/dialects/mysql/constants.mjs +5 -0
  16. package/dist/dialects/mysql/constants.mjs.map +1 -0
  17. package/dist/dialects/mysql/database-inspector.js +35 -0
  18. package/dist/dialects/mysql/database-inspector.js.map +1 -0
  19. package/dist/dialects/mysql/database-inspector.mjs +33 -0
  20. package/dist/dialects/mysql/database-inspector.mjs.map +1 -0
  21. package/dist/dialects/mysql/index.js +75 -0
  22. package/dist/dialects/mysql/index.js.map +1 -0
  23. package/dist/dialects/mysql/index.mjs +73 -0
  24. package/dist/dialects/mysql/index.mjs.map +1 -0
  25. package/dist/dialects/mysql/schema-inspector.js +297 -0
  26. package/dist/dialects/mysql/schema-inspector.js.map +1 -0
  27. package/dist/dialects/mysql/schema-inspector.mjs +295 -0
  28. package/dist/dialects/mysql/schema-inspector.mjs.map +1 -0
  29. package/dist/dialects/postgresql/index.js +62 -0
  30. package/dist/dialects/postgresql/index.js.map +1 -0
  31. package/dist/dialects/postgresql/index.mjs +60 -0
  32. package/dist/dialects/postgresql/index.mjs.map +1 -0
  33. package/dist/dialects/postgresql/schema-inspector.js +316 -0
  34. package/dist/dialects/postgresql/schema-inspector.js.map +1 -0
  35. package/dist/dialects/postgresql/schema-inspector.mjs +314 -0
  36. package/dist/dialects/postgresql/schema-inspector.mjs.map +1 -0
  37. package/dist/dialects/sqlite/index.js +82 -0
  38. package/dist/dialects/sqlite/index.js.map +1 -0
  39. package/dist/dialects/sqlite/index.mjs +80 -0
  40. package/dist/dialects/sqlite/index.mjs.map +1 -0
  41. package/dist/dialects/sqlite/schema-inspector.js +211 -0
  42. package/dist/dialects/sqlite/schema-inspector.js.map +1 -0
  43. package/dist/dialects/sqlite/schema-inspector.mjs +209 -0
  44. package/dist/dialects/sqlite/schema-inspector.mjs.map +1 -0
  45. package/dist/entity-manager/entity-repository.js +139 -0
  46. package/dist/entity-manager/entity-repository.js.map +1 -0
  47. package/dist/entity-manager/entity-repository.mjs +137 -0
  48. package/dist/entity-manager/entity-repository.mjs.map +1 -0
  49. package/dist/entity-manager/index.js +1186 -0
  50. package/dist/entity-manager/index.js.map +1 -0
  51. package/dist/entity-manager/index.mjs +1184 -0
  52. package/dist/entity-manager/index.mjs.map +1 -0
  53. package/dist/entity-manager/morph-relations.js +73 -0
  54. package/dist/entity-manager/morph-relations.js.map +1 -0
  55. package/dist/entity-manager/morph-relations.mjs +69 -0
  56. package/dist/entity-manager/morph-relations.mjs.map +1 -0
  57. package/dist/entity-manager/regular-relations.js +247 -0
  58. package/dist/entity-manager/regular-relations.js.map +1 -0
  59. package/dist/entity-manager/regular-relations.mjs +242 -0
  60. package/dist/entity-manager/regular-relations.mjs.map +1 -0
  61. package/dist/entity-manager/relations-orderer.js +221 -0
  62. package/dist/entity-manager/relations-orderer.js.map +1 -0
  63. package/dist/entity-manager/relations-orderer.mjs +218 -0
  64. package/dist/entity-manager/relations-orderer.mjs.map +1 -0
  65. package/dist/errors/database.js +13 -0
  66. package/dist/errors/database.js.map +1 -0
  67. package/dist/errors/database.mjs +11 -0
  68. package/dist/errors/database.mjs.map +1 -0
  69. package/dist/errors/index.js +18 -0
  70. package/dist/errors/index.js.map +1 -0
  71. package/dist/errors/index.mjs +7 -0
  72. package/dist/errors/index.mjs.map +1 -0
  73. package/dist/errors/invalid-date.js +13 -0
  74. package/dist/errors/invalid-date.js.map +1 -0
  75. package/dist/errors/invalid-date.mjs +11 -0
  76. package/dist/errors/invalid-date.mjs.map +1 -0
  77. package/dist/errors/invalid-datetime.js +13 -0
  78. package/dist/errors/invalid-datetime.js.map +1 -0
  79. package/dist/errors/invalid-datetime.mjs +11 -0
  80. package/dist/errors/invalid-datetime.mjs.map +1 -0
  81. package/dist/errors/invalid-relation.js +13 -0
  82. package/dist/errors/invalid-relation.js.map +1 -0
  83. package/dist/errors/invalid-relation.mjs +11 -0
  84. package/dist/errors/invalid-relation.mjs.map +1 -0
  85. package/dist/errors/invalid-time.js +13 -0
  86. package/dist/errors/invalid-time.js.map +1 -0
  87. package/dist/errors/invalid-time.mjs +11 -0
  88. package/dist/errors/invalid-time.mjs.map +1 -0
  89. package/dist/errors/not-null.js +17 -0
  90. package/dist/errors/not-null.js.map +1 -0
  91. package/dist/errors/not-null.mjs +15 -0
  92. package/dist/errors/not-null.mjs.map +1 -0
  93. package/dist/fields/biginteger.js +9 -0
  94. package/dist/fields/biginteger.js.map +1 -0
  95. package/dist/fields/biginteger.mjs +7 -0
  96. package/dist/fields/biginteger.mjs.map +1 -0
  97. package/dist/fields/boolean.js +48 -0
  98. package/dist/fields/boolean.js.map +1 -0
  99. package/dist/fields/boolean.mjs +46 -0
  100. package/dist/fields/boolean.mjs.map +1 -0
  101. package/dist/fields/date.js +16 -0
  102. package/dist/fields/date.js.map +1 -0
  103. package/dist/fields/date.mjs +14 -0
  104. package/dist/fields/date.mjs.map +1 -0
  105. package/dist/fields/datetime.js +37 -0
  106. package/dist/fields/datetime.js.map +1 -0
  107. package/dist/fields/datetime.mjs +16 -0
  108. package/dist/fields/datetime.mjs.map +1 -0
  109. package/dist/fields/field.js +16 -0
  110. package/dist/fields/field.js.map +1 -0
  111. package/dist/fields/field.mjs +14 -0
  112. package/dist/fields/field.mjs.map +1 -0
  113. package/dist/fields/index.js +45 -0
  114. package/dist/fields/index.js.map +1 -0
  115. package/dist/fields/index.mjs +43 -0
  116. package/dist/fields/index.mjs.map +1 -0
  117. package/dist/fields/json.js +36 -0
  118. package/dist/fields/json.js.map +1 -0
  119. package/dist/fields/json.mjs +34 -0
  120. package/dist/fields/json.mjs.map +1 -0
  121. package/dist/fields/number.js +20 -0
  122. package/dist/fields/number.js.map +1 -0
  123. package/dist/fields/number.mjs +18 -0
  124. package/dist/fields/number.mjs.map +1 -0
  125. package/dist/fields/shared/parsers.js +91 -0
  126. package/dist/fields/shared/parsers.js.map +1 -0
  127. package/dist/fields/shared/parsers.mjs +68 -0
  128. package/dist/fields/shared/parsers.mjs.map +1 -0
  129. package/dist/fields/string.js +16 -0
  130. package/dist/fields/string.js.map +1 -0
  131. package/dist/fields/string.mjs +14 -0
  132. package/dist/fields/string.mjs.map +1 -0
  133. package/dist/fields/time.js +17 -0
  134. package/dist/fields/time.js.map +1 -0
  135. package/dist/fields/time.mjs +15 -0
  136. package/dist/fields/time.mjs.map +1 -0
  137. package/dist/fields/timestamp.js +37 -0
  138. package/dist/fields/timestamp.js.map +1 -0
  139. package/dist/fields/timestamp.mjs +16 -0
  140. package/dist/fields/timestamp.mjs.map +1 -0
  141. package/dist/index.js +33 -8569
  142. package/dist/index.js.map +1 -1
  143. package/dist/index.mjs +16 -8532
  144. package/dist/index.mjs.map +1 -1
  145. package/dist/lifecycles/index.js +73 -0
  146. package/dist/lifecycles/index.js.map +1 -0
  147. package/dist/lifecycles/index.mjs +71 -0
  148. package/dist/lifecycles/index.mjs.map +1 -0
  149. package/dist/lifecycles/subscribers/index.js +10 -0
  150. package/dist/lifecycles/subscribers/index.js.map +1 -0
  151. package/dist/lifecycles/subscribers/index.mjs +8 -0
  152. package/dist/lifecycles/subscribers/index.mjs.map +1 -0
  153. package/dist/lifecycles/subscribers/models-lifecycles.js +13 -0
  154. package/dist/lifecycles/subscribers/models-lifecycles.js.map +1 -0
  155. package/dist/lifecycles/subscribers/models-lifecycles.mjs +11 -0
  156. package/dist/lifecycles/subscribers/models-lifecycles.mjs.map +1 -0
  157. package/dist/lifecycles/subscribers/timestamps.js +55 -0
  158. package/dist/lifecycles/subscribers/timestamps.js.map +1 -0
  159. package/dist/lifecycles/subscribers/timestamps.mjs +53 -0
  160. package/dist/lifecycles/subscribers/timestamps.mjs.map +1 -0
  161. package/dist/metadata/index.js +24 -0
  162. package/dist/metadata/index.js.map +1 -0
  163. package/dist/metadata/index.mjs +16 -0
  164. package/dist/metadata/index.mjs.map +1 -0
  165. package/dist/metadata/metadata.js +100 -0
  166. package/dist/metadata/metadata.js.map +1 -0
  167. package/dist/metadata/metadata.mjs +98 -0
  168. package/dist/metadata/metadata.mjs.map +1 -0
  169. package/dist/metadata/relations.js +545 -0
  170. package/dist/metadata/relations.js.map +1 -0
  171. package/dist/metadata/relations.mjs +536 -0
  172. package/dist/metadata/relations.mjs.map +1 -0
  173. package/dist/migrations/common.js +8 -0
  174. package/dist/migrations/common.js.map +1 -0
  175. package/dist/migrations/common.mjs +6 -0
  176. package/dist/migrations/common.mjs.map +1 -0
  177. package/dist/migrations/index.js +39 -0
  178. package/dist/migrations/index.js.map +1 -0
  179. package/dist/migrations/index.mjs +37 -0
  180. package/dist/migrations/index.mjs.map +1 -0
  181. package/dist/migrations/internal-migrations/5.0.0-01-convert-identifiers-long-than-max-length.js +179 -0
  182. package/dist/migrations/internal-migrations/5.0.0-01-convert-identifiers-long-than-max-length.js.map +1 -0
  183. package/dist/migrations/internal-migrations/5.0.0-01-convert-identifiers-long-than-max-length.mjs +177 -0
  184. package/dist/migrations/internal-migrations/5.0.0-01-convert-identifiers-long-than-max-length.mjs.map +1 -0
  185. package/dist/migrations/internal-migrations/5.0.0-02-document-id.js +125 -0
  186. package/dist/migrations/internal-migrations/5.0.0-02-document-id.js.map +1 -0
  187. package/dist/migrations/internal-migrations/5.0.0-02-document-id.mjs +123 -0
  188. package/dist/migrations/internal-migrations/5.0.0-02-document-id.mjs.map +1 -0
  189. package/dist/migrations/internal-migrations/5.0.0-03-locale.js +41 -0
  190. package/dist/migrations/internal-migrations/5.0.0-03-locale.js.map +1 -0
  191. package/dist/migrations/internal-migrations/5.0.0-03-locale.mjs +39 -0
  192. package/dist/migrations/internal-migrations/5.0.0-03-locale.mjs.map +1 -0
  193. package/dist/migrations/internal-migrations/5.0.0-04-published-at.js +45 -0
  194. package/dist/migrations/internal-migrations/5.0.0-04-published-at.js.map +1 -0
  195. package/dist/migrations/internal-migrations/5.0.0-04-published-at.mjs +43 -0
  196. package/dist/migrations/internal-migrations/5.0.0-04-published-at.mjs.map +1 -0
  197. package/dist/migrations/internal-migrations/5.0.0-05-drop-slug-unique-index.js +43 -0
  198. package/dist/migrations/internal-migrations/5.0.0-05-drop-slug-unique-index.js.map +1 -0
  199. package/dist/migrations/internal-migrations/5.0.0-05-drop-slug-unique-index.mjs +41 -0
  200. package/dist/migrations/internal-migrations/5.0.0-05-drop-slug-unique-index.mjs.map +1 -0
  201. package/dist/migrations/internal-migrations/index.js +26 -0
  202. package/dist/migrations/internal-migrations/index.js.map +1 -0
  203. package/dist/migrations/internal-migrations/index.mjs +24 -0
  204. package/dist/migrations/internal-migrations/index.mjs.map +1 -0
  205. package/dist/migrations/internal.js +63 -0
  206. package/dist/migrations/internal.js.map +1 -0
  207. package/dist/migrations/internal.mjs +61 -0
  208. package/dist/migrations/internal.mjs.map +1 -0
  209. package/dist/migrations/logger.js +24 -0
  210. package/dist/migrations/logger.js.map +1 -0
  211. package/dist/migrations/logger.mjs +22 -0
  212. package/dist/migrations/logger.mjs.map +1 -0
  213. package/dist/migrations/storage.js +39 -0
  214. package/dist/migrations/storage.js.map +1 -0
  215. package/dist/migrations/storage.mjs +37 -0
  216. package/dist/migrations/storage.mjs.map +1 -0
  217. package/dist/migrations/users.js +87 -0
  218. package/dist/migrations/users.js.map +1 -0
  219. package/dist/migrations/users.mjs +85 -0
  220. package/dist/migrations/users.mjs.map +1 -0
  221. package/dist/query/helpers/join.js +127 -0
  222. package/dist/query/helpers/join.js.map +1 -0
  223. package/dist/query/helpers/join.mjs +122 -0
  224. package/dist/query/helpers/join.mjs.map +1 -0
  225. package/dist/query/helpers/order-by.js +167 -0
  226. package/dist/query/helpers/order-by.js.map +1 -0
  227. package/dist/query/helpers/order-by.mjs +163 -0
  228. package/dist/query/helpers/order-by.mjs.map +1 -0
  229. package/dist/query/helpers/populate/apply.js +592 -0
  230. package/dist/query/helpers/populate/apply.js.map +1 -0
  231. package/dist/query/helpers/populate/apply.mjs +590 -0
  232. package/dist/query/helpers/populate/apply.mjs.map +1 -0
  233. package/dist/query/helpers/populate/process.js +92 -0
  234. package/dist/query/helpers/populate/process.js.map +1 -0
  235. package/dist/query/helpers/populate/process.mjs +90 -0
  236. package/dist/query/helpers/populate/process.mjs.map +1 -0
  237. package/dist/query/helpers/search.js +67 -0
  238. package/dist/query/helpers/search.js.map +1 -0
  239. package/dist/query/helpers/search.mjs +65 -0
  240. package/dist/query/helpers/search.mjs.map +1 -0
  241. package/dist/query/helpers/streams/readable.js +131 -0
  242. package/dist/query/helpers/streams/readable.js.map +1 -0
  243. package/dist/query/helpers/streams/readable.mjs +129 -0
  244. package/dist/query/helpers/streams/readable.mjs.map +1 -0
  245. package/dist/query/helpers/transform.js +77 -0
  246. package/dist/query/helpers/transform.js.map +1 -0
  247. package/dist/query/helpers/transform.mjs +73 -0
  248. package/dist/query/helpers/transform.mjs.map +1 -0
  249. package/dist/query/helpers/where.js +372 -0
  250. package/dist/query/helpers/where.js.map +1 -0
  251. package/dist/query/helpers/where.mjs +369 -0
  252. package/dist/query/helpers/where.mjs.map +1 -0
  253. package/dist/query/query-builder.js +507 -0
  254. package/dist/query/query-builder.js.map +1 -0
  255. package/dist/query/query-builder.mjs +505 -0
  256. package/dist/query/query-builder.mjs.map +1 -0
  257. package/dist/repairs/index.js +13 -0
  258. package/dist/repairs/index.js.map +1 -0
  259. package/dist/repairs/index.mjs +11 -0
  260. package/dist/repairs/index.mjs.map +1 -0
  261. package/dist/repairs/operations/remove-orphan-morph-types.js +54 -0
  262. package/dist/repairs/operations/remove-orphan-morph-types.js.map +1 -0
  263. package/dist/repairs/operations/remove-orphan-morph-types.mjs +52 -0
  264. package/dist/repairs/operations/remove-orphan-morph-types.mjs.map +1 -0
  265. package/dist/schema/builder.js +354 -0
  266. package/dist/schema/builder.js.map +1 -0
  267. package/dist/schema/builder.mjs +352 -0
  268. package/dist/schema/builder.mjs.map +1 -0
  269. package/dist/schema/diff.js +379 -0
  270. package/dist/schema/diff.js.map +1 -0
  271. package/dist/schema/diff.mjs +377 -0
  272. package/dist/schema/diff.mjs.map +1 -0
  273. package/dist/schema/index.js +93 -0
  274. package/dist/schema/index.js.map +1 -0
  275. package/dist/schema/index.mjs +91 -0
  276. package/dist/schema/index.mjs.map +1 -0
  277. package/dist/schema/schema.js +266 -0
  278. package/dist/schema/schema.js.map +1 -0
  279. package/dist/schema/schema.mjs +264 -0
  280. package/dist/schema/schema.mjs.map +1 -0
  281. package/dist/schema/storage.js +58 -0
  282. package/dist/schema/storage.js.map +1 -0
  283. package/dist/schema/storage.mjs +56 -0
  284. package/dist/schema/storage.mjs.map +1 -0
  285. package/dist/transaction-context.js +65 -0
  286. package/dist/transaction-context.js.map +1 -0
  287. package/dist/transaction-context.mjs +63 -0
  288. package/dist/transaction-context.mjs.map +1 -0
  289. package/dist/utils/async-curry.js +19 -0
  290. package/dist/utils/async-curry.js.map +1 -0
  291. package/dist/utils/async-curry.mjs +17 -0
  292. package/dist/utils/async-curry.mjs.map +1 -0
  293. package/dist/utils/identifiers/hash.js +30 -0
  294. package/dist/utils/identifiers/hash.js.map +1 -0
  295. package/dist/utils/identifiers/hash.mjs +28 -0
  296. package/dist/utils/identifiers/hash.mjs.map +1 -0
  297. package/dist/utils/identifiers/index.js +414 -0
  298. package/dist/utils/identifiers/index.js.map +1 -0
  299. package/dist/utils/identifiers/index.mjs +411 -0
  300. package/dist/utils/identifiers/index.mjs.map +1 -0
  301. package/dist/utils/knex.js +21 -0
  302. package/dist/utils/knex.js.map +1 -0
  303. package/dist/utils/knex.mjs +18 -0
  304. package/dist/utils/knex.mjs.map +1 -0
  305. package/dist/utils/types.js +51 -0
  306. package/dist/utils/types.js.map +1 -0
  307. package/dist/utils/types.mjs +44 -0
  308. package/dist/utils/types.mjs.map +1 -0
  309. package/dist/validations/index.js +12 -0
  310. package/dist/validations/index.js.map +1 -0
  311. package/dist/validations/index.mjs +10 -0
  312. package/dist/validations/index.mjs.map +1 -0
  313. package/dist/validations/relations/bidirectional.js +64 -0
  314. package/dist/validations/relations/bidirectional.js.map +1 -0
  315. package/dist/validations/relations/bidirectional.mjs +62 -0
  316. package/dist/validations/relations/bidirectional.mjs.map +1 -0
  317. package/dist/validations/relations/index.js +13 -0
  318. package/dist/validations/relations/index.js.map +1 -0
  319. package/dist/validations/relations/index.mjs +11 -0
  320. package/dist/validations/relations/index.mjs.map +1 -0
  321. 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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"}