joist-core 2.3.0-next.11 → 2.3.0-next.13

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 (287) hide show
  1. package/build/AliasAssigner.d.ts +0 -1
  2. package/build/Aliases.d.ts +0 -1
  3. package/build/BaseEntity.d.ts +0 -1
  4. package/build/ConditionBuilder.d.ts +0 -1
  5. package/build/ConditionBuilder.js +1 -1
  6. package/build/ConditionBuilder.js.map +1 -1
  7. package/build/Entity.d.ts +0 -1
  8. package/build/EntityFields.d.ts +0 -1
  9. package/build/EntityFilter.d.ts +0 -1
  10. package/build/EntityGraphQLFilter.d.ts +0 -1
  11. package/build/EntityManager.d.ts +1 -2
  12. package/build/EntityManager.js +6 -5
  13. package/build/EntityManager.js.map +1 -1
  14. package/build/EntityMetadata.d.ts +0 -1
  15. package/build/EnumMetadata.d.ts +0 -1
  16. package/build/FlushLock.d.ts +0 -1
  17. package/build/HintTree.d.ts +0 -1
  18. package/build/IndexManager.d.ts +0 -1
  19. package/build/InstanceData.d.ts +0 -1
  20. package/build/IsLoadedCache.d.ts +0 -1
  21. package/build/JoinRows.d.ts +0 -1
  22. package/build/PendingChanges.d.ts +0 -1
  23. package/build/PluginManager.d.ts +0 -1
  24. package/build/QueryParser.collectionJoins.d.ts +0 -1
  25. package/build/QueryParser.d.ts +0 -1
  26. package/build/QueryParser.pruning.d.ts +0 -1
  27. package/build/QueryVisitor.d.ts +0 -1
  28. package/build/ReactionsManager.d.ts +1 -2
  29. package/build/ReactionsManager.js +17 -17
  30. package/build/ReactionsManager.js.map +1 -1
  31. package/build/Todo.d.ts +0 -1
  32. package/build/batchloaders/BatchLoader.d.ts +0 -1
  33. package/build/batchloaders/enumCollectionBatchLoader.d.ts +0 -1
  34. package/build/batchloaders/loadBatchLoader.d.ts +0 -1
  35. package/build/batchloaders/manyToManyBatchLoader.d.ts +0 -1
  36. package/build/batchloaders/oneToManyBatchLoader.d.ts +0 -1
  37. package/build/batchloaders/oneToOneBatchLoader.d.ts +0 -1
  38. package/build/batchloaders/populateBatchLoader.d.ts +0 -1
  39. package/build/batchloaders/recursiveChildrenBatchLoader.d.ts +0 -1
  40. package/build/batchloaders/recursiveM2mBatchLoader.d.ts +0 -1
  41. package/build/batchloaders/recursiveParentsBatchLoader.d.ts +0 -1
  42. package/build/changes.d.ts +0 -1
  43. package/build/config.d.ts +0 -1
  44. package/build/configure.d.ts +0 -1
  45. package/build/dataloaders/fastWhereFilterHash.d.ts +0 -1
  46. package/build/dataloaders/findByUniqueDataLoader.d.ts +0 -1
  47. package/build/dataloaders/findCountDataLoader.d.ts +0 -1
  48. package/build/dataloaders/findDataLoader.d.ts +0 -1
  49. package/build/dataloaders/findDataLoader.js +2 -2
  50. package/build/dataloaders/findDataLoader.js.map +1 -1
  51. package/build/dataloaders/findIdsDataLoader.d.ts +0 -1
  52. package/build/dataloaders/findOrCreateDataLoader.d.ts +0 -1
  53. package/build/dataloaders/findOrCreateDataLoader.js +2 -2
  54. package/build/dataloaders/findOrCreateDataLoader.js.map +1 -1
  55. package/build/dataloaders/findPaginatedDataLoader.d.ts +0 -1
  56. package/build/dataloaders/lensDataLoader.d.ts +0 -1
  57. package/build/dataloaders/manyToManyFindDataLoader.d.ts +0 -1
  58. package/build/dataloaders/oneToManyFindDataLoader.d.ts +0 -1
  59. package/build/defaults.d.ts +0 -1
  60. package/build/driverApi.d.ts +0 -1
  61. package/build/drivers/Driver.d.ts +0 -1
  62. package/build/drivers/EntityWriter.d.ts +0 -1
  63. package/build/drivers/IdAssigner.d.ts +0 -1
  64. package/build/drivers/buildRawQuery.d.ts +0 -1
  65. package/build/drivers/buildUtils.d.ts +0 -1
  66. package/build/drivers/index.d.ts +0 -1
  67. package/build/fields.d.ts +0 -1
  68. package/build/fields.js +2 -2
  69. package/build/fields.js.map +1 -1
  70. package/build/getProperties.d.ts +0 -1
  71. package/build/index.d.ts +0 -1
  72. package/build/json.d.ts +0 -1
  73. package/build/k.d.ts +0 -1
  74. package/build/keys.d.ts +0 -1
  75. package/build/keywords.d.ts +0 -1
  76. package/build/loadHints.d.ts +0 -1
  77. package/build/loadLens.d.ts +0 -1
  78. package/build/logging/FactoryLogger.d.ts +0 -1
  79. package/build/logging/FieldLogger.d.ts +2 -1
  80. package/build/logging/FieldLogger.js +10 -1
  81. package/build/logging/FieldLogger.js.map +1 -1
  82. package/build/logging/ReactionLogger.d.ts +2 -1
  83. package/build/logging/ReactionLogger.js +15 -1
  84. package/build/logging/ReactionLogger.js.map +1 -1
  85. package/build/newEntity.d.ts +0 -1
  86. package/build/newTestInstance.d.ts +0 -1
  87. package/build/normalizeHints.d.ts +0 -1
  88. package/build/plugins/ImmutableEntitiesPlugin.d.ts +0 -1
  89. package/build/plugins/PreloadPlugin.d.ts +0 -1
  90. package/build/preloading/JsonAggregatePreloader.d.ts +0 -1
  91. package/build/preloading/JsonAggregatePreloader.js +2 -1
  92. package/build/preloading/JsonAggregatePreloader.js.map +1 -1
  93. package/build/preloading/canPreload.d.ts +0 -1
  94. package/build/preloading/partitionHint.d.ts +0 -1
  95. package/build/reactiveHints.d.ts +0 -1
  96. package/build/relations/AbstractPropertyImpl.d.ts +0 -1
  97. package/build/relations/AbstractRelationImpl.d.ts +0 -1
  98. package/build/relations/AsyncProperty.d.ts +0 -1
  99. package/build/relations/AsyncReactiveField.d.ts +0 -1
  100. package/build/relations/Collection.d.ts +0 -1
  101. package/build/relations/CustomCollection.d.ts +0 -1
  102. package/build/relations/CustomReference.d.ts +0 -1
  103. package/build/relations/EnumCollection.d.ts +0 -1
  104. package/build/relations/LargeCollection.d.ts +0 -1
  105. package/build/relations/ManyToManyCollection.d.ts +0 -1
  106. package/build/relations/ManyToManyLargeCollection.d.ts +0 -1
  107. package/build/relations/ManyToOneReference.d.ts +0 -1
  108. package/build/relations/OneToManyCollection.d.ts +0 -1
  109. package/build/relations/OneToManyLargeCollection.d.ts +0 -1
  110. package/build/relations/OneToOneReference.d.ts +0 -1
  111. package/build/relations/OneToOneReference.js +1 -1
  112. package/build/relations/OneToOneReference.js.map +1 -1
  113. package/build/relations/PolymorphicReference.d.ts +0 -1
  114. package/build/relations/ReactiveField.d.ts +0 -1
  115. package/build/relations/ReactiveGetter.d.ts +0 -1
  116. package/build/relations/ReactiveManyToMany.d.ts +0 -1
  117. package/build/relations/ReactiveManyToManyOtherSide.d.ts +0 -1
  118. package/build/relations/ReactiveReference.d.ts +0 -1
  119. package/build/relations/ReadOnlyCollection.d.ts +0 -1
  120. package/build/relations/RecursiveCollection.d.ts +0 -1
  121. package/build/relations/RecursiveCycleError.d.ts +0 -1
  122. package/build/relations/Reference.d.ts +0 -1
  123. package/build/relations/Relation.d.ts +0 -1
  124. package/build/relations/hasAsyncMethod.d.ts +0 -1
  125. package/build/relations/hasManyDerived.d.ts +0 -1
  126. package/build/relations/hasManyThrough.d.ts +0 -1
  127. package/build/relations/hasOneDerived.d.ts +0 -1
  128. package/build/relations/hasOneThrough.d.ts +0 -1
  129. package/build/relations/hasProperty.d.ts +0 -1
  130. package/build/relations/index.d.ts +0 -1
  131. package/build/resurrection.d.ts +0 -1
  132. package/build/rules.d.ts +0 -1
  133. package/build/runtimeConfig.d.ts +0 -1
  134. package/build/scopes.d.ts +0 -1
  135. package/build/serde.d.ts +0 -1
  136. package/build/temporal.d.ts +0 -1
  137. package/build/temporalMappers.d.ts +0 -1
  138. package/build/trusted.d.ts +0 -1
  139. package/build/typeMap.d.ts +0 -1
  140. package/build/unnest.d.ts +0 -1
  141. package/build/upsert.d.ts +0 -1
  142. package/build/utils.d.ts +0 -1
  143. package/build/withLoaded.d.ts +0 -1
  144. package/package.json +2 -2
  145. package/build/AliasAssigner.d.ts.map +0 -1
  146. package/build/Aliases.d.ts.map +0 -1
  147. package/build/BaseEntity.d.ts.map +0 -1
  148. package/build/ConditionBuilder.d.ts.map +0 -1
  149. package/build/Entity.d.ts.map +0 -1
  150. package/build/EntityFields.d.ts.map +0 -1
  151. package/build/EntityFilter.d.ts.map +0 -1
  152. package/build/EntityGraphQLFilter.d.ts.map +0 -1
  153. package/build/EntityManager.d.ts.map +0 -1
  154. package/build/EntityMetadata.d.ts.map +0 -1
  155. package/build/EnumMetadata.d.ts.map +0 -1
  156. package/build/FlushLock.d.ts.map +0 -1
  157. package/build/HintTree.d.ts.map +0 -1
  158. package/build/IndexManager.d.ts.map +0 -1
  159. package/build/InstanceData.d.ts.map +0 -1
  160. package/build/IsLoadedCache.d.ts.map +0 -1
  161. package/build/JoinRows.d.ts.map +0 -1
  162. package/build/PendingChanges.d.ts.map +0 -1
  163. package/build/PluginManager.d.ts.map +0 -1
  164. package/build/QueryParser.collectionJoins.d.ts.map +0 -1
  165. package/build/QueryParser.collectionJoins.test.d.ts +0 -2
  166. package/build/QueryParser.collectionJoins.test.d.ts.map +0 -1
  167. package/build/QueryParser.collectionJoins.test.js +0 -772
  168. package/build/QueryParser.collectionJoins.test.js.map +0 -1
  169. package/build/QueryParser.d.ts.map +0 -1
  170. package/build/QueryParser.pruning.d.ts.map +0 -1
  171. package/build/QueryParser.pruning.test.d.ts +0 -2
  172. package/build/QueryParser.pruning.test.d.ts.map +0 -1
  173. package/build/QueryParser.pruning.test.js +0 -106
  174. package/build/QueryParser.pruning.test.js.map +0 -1
  175. package/build/QueryParser.test.d.ts +0 -2
  176. package/build/QueryParser.test.d.ts.map +0 -1
  177. package/build/QueryParser.test.js +0 -27
  178. package/build/QueryParser.test.js.map +0 -1
  179. package/build/QueryVisitor.d.ts.map +0 -1
  180. package/build/ReactionsManager.d.ts.map +0 -1
  181. package/build/Todo.d.ts.map +0 -1
  182. package/build/batchloaders/BatchLoader.d.ts.map +0 -1
  183. package/build/batchloaders/enumCollectionBatchLoader.d.ts.map +0 -1
  184. package/build/batchloaders/loadBatchLoader.d.ts.map +0 -1
  185. package/build/batchloaders/manyToManyBatchLoader.d.ts.map +0 -1
  186. package/build/batchloaders/oneToManyBatchLoader.d.ts.map +0 -1
  187. package/build/batchloaders/oneToOneBatchLoader.d.ts.map +0 -1
  188. package/build/batchloaders/populateBatchLoader.d.ts.map +0 -1
  189. package/build/batchloaders/recursiveChildrenBatchLoader.d.ts.map +0 -1
  190. package/build/batchloaders/recursiveM2mBatchLoader.d.ts.map +0 -1
  191. package/build/batchloaders/recursiveParentsBatchLoader.d.ts.map +0 -1
  192. package/build/changes.d.ts.map +0 -1
  193. package/build/config.d.ts.map +0 -1
  194. package/build/config.test.d.ts +0 -2
  195. package/build/config.test.d.ts.map +0 -1
  196. package/build/config.test.js +0 -53
  197. package/build/config.test.js.map +0 -1
  198. package/build/configure.d.ts.map +0 -1
  199. package/build/dataloaders/fastWhereFilterHash.d.ts.map +0 -1
  200. package/build/dataloaders/fastWhereFilterHash.test.d.ts +0 -2
  201. package/build/dataloaders/fastWhereFilterHash.test.d.ts.map +0 -1
  202. package/build/dataloaders/fastWhereFilterHash.test.js +0 -59
  203. package/build/dataloaders/fastWhereFilterHash.test.js.map +0 -1
  204. package/build/dataloaders/findByUniqueDataLoader.d.ts.map +0 -1
  205. package/build/dataloaders/findCountDataLoader.d.ts.map +0 -1
  206. package/build/dataloaders/findDataLoader.d.ts.map +0 -1
  207. package/build/dataloaders/findIdsDataLoader.d.ts.map +0 -1
  208. package/build/dataloaders/findOrCreateDataLoader.d.ts.map +0 -1
  209. package/build/dataloaders/findPaginatedDataLoader.d.ts.map +0 -1
  210. package/build/dataloaders/lensDataLoader.d.ts.map +0 -1
  211. package/build/dataloaders/manyToManyFindDataLoader.d.ts.map +0 -1
  212. package/build/dataloaders/oneToManyFindDataLoader.d.ts.map +0 -1
  213. package/build/defaults.d.ts.map +0 -1
  214. package/build/driverApi.d.ts.map +0 -1
  215. package/build/drivers/Driver.d.ts.map +0 -1
  216. package/build/drivers/EntityWriter.d.ts.map +0 -1
  217. package/build/drivers/IdAssigner.d.ts.map +0 -1
  218. package/build/drivers/buildRawQuery.d.ts.map +0 -1
  219. package/build/drivers/buildUtils.d.ts.map +0 -1
  220. package/build/drivers/index.d.ts.map +0 -1
  221. package/build/fields.d.ts.map +0 -1
  222. package/build/getProperties.d.ts.map +0 -1
  223. package/build/index.d.ts.map +0 -1
  224. package/build/json.d.ts.map +0 -1
  225. package/build/k.d.ts.map +0 -1
  226. package/build/keys.d.ts.map +0 -1
  227. package/build/keywords.d.ts.map +0 -1
  228. package/build/loadHints.d.ts.map +0 -1
  229. package/build/loadLens.d.ts.map +0 -1
  230. package/build/logging/FactoryLogger.d.ts.map +0 -1
  231. package/build/logging/FieldLogger.d.ts.map +0 -1
  232. package/build/logging/ReactionLogger.d.ts.map +0 -1
  233. package/build/newEntity.d.ts.map +0 -1
  234. package/build/newTestInstance.d.ts.map +0 -1
  235. package/build/normalizeHints.d.ts.map +0 -1
  236. package/build/plugins/ImmutableEntitiesPlugin.d.ts.map +0 -1
  237. package/build/plugins/PreloadPlugin.d.ts.map +0 -1
  238. package/build/preloading/JsonAggregatePreloader.d.ts.map +0 -1
  239. package/build/preloading/canPreload.d.ts.map +0 -1
  240. package/build/preloading/partitionHint.d.ts.map +0 -1
  241. package/build/reactiveHints.d.ts.map +0 -1
  242. package/build/relations/AbstractPropertyImpl.d.ts.map +0 -1
  243. package/build/relations/AbstractRelationImpl.d.ts.map +0 -1
  244. package/build/relations/AsyncProperty.d.ts.map +0 -1
  245. package/build/relations/AsyncReactiveField.d.ts.map +0 -1
  246. package/build/relations/Collection.d.ts.map +0 -1
  247. package/build/relations/CustomCollection.d.ts.map +0 -1
  248. package/build/relations/CustomReference.d.ts.map +0 -1
  249. package/build/relations/EnumCollection.d.ts.map +0 -1
  250. package/build/relations/LargeCollection.d.ts.map +0 -1
  251. package/build/relations/ManyToManyCollection.d.ts.map +0 -1
  252. package/build/relations/ManyToManyLargeCollection.d.ts.map +0 -1
  253. package/build/relations/ManyToOneReference.d.ts.map +0 -1
  254. package/build/relations/OneToManyCollection.d.ts.map +0 -1
  255. package/build/relations/OneToManyLargeCollection.d.ts.map +0 -1
  256. package/build/relations/OneToOneReference.d.ts.map +0 -1
  257. package/build/relations/PolymorphicReference.d.ts.map +0 -1
  258. package/build/relations/ReactiveField.d.ts.map +0 -1
  259. package/build/relations/ReactiveGetter.d.ts.map +0 -1
  260. package/build/relations/ReactiveManyToMany.d.ts.map +0 -1
  261. package/build/relations/ReactiveManyToManyOtherSide.d.ts.map +0 -1
  262. package/build/relations/ReactiveReference.d.ts.map +0 -1
  263. package/build/relations/ReadOnlyCollection.d.ts.map +0 -1
  264. package/build/relations/RecursiveCollection.d.ts.map +0 -1
  265. package/build/relations/RecursiveCycleError.d.ts.map +0 -1
  266. package/build/relations/Reference.d.ts.map +0 -1
  267. package/build/relations/Relation.d.ts.map +0 -1
  268. package/build/relations/hasAsyncMethod.d.ts.map +0 -1
  269. package/build/relations/hasManyDerived.d.ts.map +0 -1
  270. package/build/relations/hasManyThrough.d.ts.map +0 -1
  271. package/build/relations/hasOneDerived.d.ts.map +0 -1
  272. package/build/relations/hasOneThrough.d.ts.map +0 -1
  273. package/build/relations/hasProperty.d.ts.map +0 -1
  274. package/build/relations/index.d.ts.map +0 -1
  275. package/build/resurrection.d.ts.map +0 -1
  276. package/build/rules.d.ts.map +0 -1
  277. package/build/runtimeConfig.d.ts.map +0 -1
  278. package/build/scopes.d.ts.map +0 -1
  279. package/build/serde.d.ts.map +0 -1
  280. package/build/temporal.d.ts.map +0 -1
  281. package/build/temporalMappers.d.ts.map +0 -1
  282. package/build/trusted.d.ts.map +0 -1
  283. package/build/typeMap.d.ts.map +0 -1
  284. package/build/unnest.d.ts.map +0 -1
  285. package/build/upsert.d.ts.map +0 -1
  286. package/build/utils.d.ts.map +0 -1
  287. package/build/withLoaded.d.ts.map +0 -1
@@ -1,772 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const QueryParser_collectionJoins_1 = require("./QueryParser.collectionJoins");
4
- describe("QueryParser.collectionJoins", () => {
5
- it("allows unblocked multiple collection left joins before pruning", () => {
6
- const query = {
7
- selects: ["a.*"],
8
- tables: [
9
- { alias: "a", table: "authors", join: "primary" },
10
- {
11
- alias: "b",
12
- table: "books",
13
- join: "outer",
14
- col1: "a.id",
15
- col2: "b.author_id",
16
- collection: { parentAlias: "a", rootAlias: "b", kind: "o2m" },
17
- },
18
- {
19
- alias: "c",
20
- table: "comments",
21
- join: "outer",
22
- col1: "a.id",
23
- col2: "c.parent_author_id",
24
- collection: { parentAlias: "a", rootAlias: "c", kind: "o2m" },
25
- },
26
- ],
27
- orderBys: [],
28
- };
29
- (0, QueryParser_collectionJoins_1.optimizeCollectionJoins)(query, { pruneJoins: false });
30
- expect(query.tables).toMatchObject([
31
- { alias: "a", table: "authors", join: "primary" },
32
- { alias: "b", table: "books", join: "outer" },
33
- { alias: "c", table: "comments", join: "outer" },
34
- ]);
35
- });
36
- it("prunes unblocked multiple collection left joins after checking fanout safety", () => {
37
- const query = {
38
- selects: ["a.*"],
39
- tables: [
40
- { alias: "a", table: "authors", join: "primary" },
41
- {
42
- alias: "b",
43
- table: "books",
44
- join: "outer",
45
- col1: "a.id",
46
- col2: "b.author_id",
47
- collection: { parentAlias: "a", rootAlias: "b", kind: "o2m" },
48
- },
49
- {
50
- alias: "c",
51
- table: "comments",
52
- join: "outer",
53
- col1: "a.id",
54
- col2: "c.parent_author_id",
55
- collection: { parentAlias: "a", rootAlias: "c", kind: "o2m" },
56
- },
57
- ],
58
- orderBys: [],
59
- };
60
- (0, QueryParser_collectionJoins_1.optimizeCollectionJoins)(query);
61
- expect(query.tables).toMatchObject([{ alias: "a", table: "authors", join: "primary" }]);
62
- expect(query.condition).toBeUndefined();
63
- });
64
- it("skips join-to-exists optimization when disabled", () => {
65
- const query = {
66
- selects: ["a.*"],
67
- tables: [
68
- { alias: "a", table: "authors", join: "primary" },
69
- {
70
- alias: "b",
71
- table: "books",
72
- join: "outer",
73
- col1: "a.id",
74
- col2: "b.author_id",
75
- collection: { parentAlias: "a", rootAlias: "b", kind: "o2m" },
76
- },
77
- ],
78
- condition: {
79
- kind: "exp",
80
- op: "and",
81
- conditions: [{ kind: "column", alias: "b", column: "title", dbType: "text", cond: { kind: "eq", value: "b1" } }],
82
- },
83
- orderBys: [],
84
- };
85
- (0, QueryParser_collectionJoins_1.optimizeCollectionJoins)(query, { optimizeJoinsToExists: false });
86
- expect(query.tables).toMatchObject([
87
- { alias: "a", table: "authors", join: "primary" },
88
- { alias: "b", table: "books", join: "outer" },
89
- ]);
90
- expect(query.condition).toMatchObject({
91
- op: "and",
92
- conditions: [{ kind: "column", alias: "b", column: "title" }],
93
- });
94
- });
95
- it("does not rewrite sibling OR when an alias is selected outside the OR", () => {
96
- const query = {
97
- selects: ["a.*", "b.title as book_title"],
98
- tables: [
99
- { alias: "a", table: "authors", join: "primary" },
100
- {
101
- alias: "b",
102
- table: "books",
103
- join: "outer",
104
- col1: "a.id",
105
- col2: "b.author_id",
106
- collection: { parentAlias: "a", rootAlias: "b", kind: "o2m" },
107
- },
108
- {
109
- alias: "c",
110
- table: "comments",
111
- join: "outer",
112
- col1: "a.id",
113
- col2: "c.parent_author_id",
114
- collection: { parentAlias: "a", rootAlias: "c", kind: "o2m" },
115
- },
116
- ],
117
- condition: {
118
- kind: "exp",
119
- op: "or",
120
- conditions: [
121
- { kind: "column", alias: "b", column: "id", dbType: "int", cond: { kind: "not-null" } },
122
- { kind: "column", alias: "c", column: "id", dbType: "int", cond: { kind: "not-null" } },
123
- ],
124
- },
125
- orderBys: [],
126
- };
127
- (0, QueryParser_collectionJoins_1.optimizeCollectionJoins)(query, { allowMultipleLeftJoins: true });
128
- expect(query.tables).toMatchObject([
129
- { alias: "a", table: "authors", join: "primary" },
130
- { alias: "b", table: "books", join: "outer" },
131
- { alias: "c", table: "comments", join: "outer" },
132
- ]);
133
- expect(query.condition).toMatchObject({
134
- op: "or",
135
- conditions: [
136
- { kind: "column", alias: "b", column: "id" },
137
- { kind: "column", alias: "c", column: "id" },
138
- ],
139
- });
140
- });
141
- it("does not rewrite collection joins when selected aliases must remain in the outer query", () => {
142
- const query = {
143
- selects: ["b.id::text as id", "array_agg(br.rating::text) as review_ratings"],
144
- tables: [
145
- { alias: "a", table: "authors", join: "primary" },
146
- {
147
- alias: "b",
148
- table: "books",
149
- join: "outer",
150
- col1: "a.id",
151
- col2: "b.author_id",
152
- collection: { parentAlias: "a", rootAlias: "b", kind: "o2m" },
153
- },
154
- {
155
- alias: "br",
156
- table: "book_reviews",
157
- join: "outer",
158
- col1: "b.id",
159
- col2: "br.book_id",
160
- collection: { parentAlias: "b", rootAlias: "br", kind: "o2m" },
161
- },
162
- ],
163
- condition: {
164
- kind: "exp",
165
- op: "and",
166
- conditions: [
167
- {
168
- kind: "column",
169
- alias: "br",
170
- column: "rating",
171
- dbType: "int",
172
- cond: { kind: "not-null" },
173
- },
174
- ],
175
- },
176
- groupBys: [{ alias: "b", column: "id" }],
177
- orderBys: [],
178
- };
179
- (0, QueryParser_collectionJoins_1.optimizeCollectionJoins)(query);
180
- expect(query.tables).toMatchObject([
181
- { alias: "a", table: "authors", join: "primary" },
182
- { alias: "b", table: "books", join: "outer" },
183
- { alias: "br", table: "book_reviews", join: "outer" },
184
- ]);
185
- expect(JSON.stringify(query.condition).includes('"kind":"exists"')).toEqual(false);
186
- });
187
- it("does not rewrite nested collection joins referenced by raw aggregate selects", () => {
188
- const query = {
189
- selects: ["a.id::text as id", { sql: "array_agg(br.rating::text) as review_ratings", bindings: [], aliases: [] }],
190
- tables: [
191
- { alias: "a", table: "authors", join: "primary" },
192
- {
193
- alias: "b",
194
- table: "books",
195
- join: "outer",
196
- col1: "a.id",
197
- col2: "b.author_id",
198
- collection: { parentAlias: "a", rootAlias: "b", kind: "o2m" },
199
- },
200
- {
201
- alias: "br",
202
- table: "book_reviews",
203
- join: "outer",
204
- col1: "b.id",
205
- col2: "br.book_id",
206
- collection: { parentAlias: "b", rootAlias: "br", kind: "o2m" },
207
- },
208
- ],
209
- condition: {
210
- kind: "exp",
211
- op: "and",
212
- conditions: [
213
- {
214
- kind: "column",
215
- alias: "br",
216
- column: "rating",
217
- dbType: "int",
218
- cond: { kind: "not-null" },
219
- },
220
- ],
221
- },
222
- groupBys: [{ alias: "a", column: "id" }],
223
- orderBys: [{ alias: "a", column: "id", order: "ASC" }],
224
- };
225
- (0, QueryParser_collectionJoins_1.optimizeCollectionJoins)(query);
226
- // I.e. even if the raw select's `aliases` metadata is empty, `array_agg(br.rating)` keeps `br` in the
227
- // outer query; moving `br` under EXISTS would leave the aggregate with a dangling FROM reference.
228
- expect(query.tables).toMatchObject([
229
- { alias: "a", table: "authors", join: "primary" },
230
- { alias: "b", table: "books", join: "outer" },
231
- { alias: "br", table: "book_reviews", join: "outer" },
232
- ]);
233
- expect(JSON.stringify(query.condition).includes('"kind":"exists"')).toEqual(false);
234
- });
235
- it("does not rewrite m2m target joins referenced by raw aggregate selects", () => {
236
- const query = {
237
- selects: ["a.id::text as id", { sql: "array_agg(t.name::text) as tag_names", bindings: [], aliases: [] }],
238
- tables: [
239
- { alias: "a", table: "authors", join: "primary" },
240
- {
241
- alias: "att",
242
- table: "authors_to_tags",
243
- join: "outer",
244
- col1: "a.id",
245
- col2: "att.author_id",
246
- collection: { parentAlias: "a", rootAlias: "att", kind: "m2m" },
247
- },
248
- {
249
- alias: "t",
250
- table: "tags",
251
- join: "outer",
252
- col1: "att.tag_id",
253
- col2: "t.id",
254
- collection: { parentAlias: "att", rootAlias: "att", kind: "m2m" },
255
- },
256
- ],
257
- condition: {
258
- kind: "exp",
259
- op: "and",
260
- conditions: [
261
- {
262
- kind: "column",
263
- alias: "t",
264
- column: "name",
265
- dbType: "text",
266
- cond: { kind: "not-null" },
267
- },
268
- ],
269
- },
270
- groupBys: [{ alias: "a", column: "id" }],
271
- orderBys: [{ alias: "a", column: "id", order: "ASC" }],
272
- };
273
- (0, QueryParser_collectionJoins_1.optimizeCollectionJoins)(query);
274
- // I.e. `t` is not the m2m collection root, but `array_agg(t.name)` still requires the `att -> t` join chain to
275
- // stay in the outer query.
276
- expect(query.tables).toMatchObject([
277
- { alias: "a", table: "authors", join: "primary" },
278
- { alias: "att", table: "authors_to_tags", join: "outer" },
279
- { alias: "t", table: "tags", join: "outer" },
280
- ]);
281
- expect(JSON.stringify(query.condition).includes('"kind":"exists"')).toEqual(false);
282
- });
283
- it("keeps non-parent correlation aliases required by collection EXISTS", () => {
284
- const query = {
285
- selects: ["pp.*"],
286
- tables: [
287
- { alias: "pp", table: "plan_packages", join: "primary" },
288
- {
289
- alias: "pp_b0",
290
- table: "ready_plans",
291
- join: "outer",
292
- col1: "pp.id",
293
- col2: "pp_b0.id",
294
- distinct: false,
295
- },
296
- {
297
- alias: "_pp_b0_version",
298
- table: "ready_plan_versions",
299
- join: "outer",
300
- col1: "pp_b0.id",
301
- col2: "_pp_b0_version.identity_id",
302
- },
303
- {
304
- alias: "_pp_version",
305
- table: "plan_package_versions",
306
- join: "outer",
307
- col1: "_pp_b0_version.id",
308
- col2: "_pp_version.id",
309
- },
310
- {
311
- alias: "rpm",
312
- table: "ready_plan_version_to_markets",
313
- join: "outer",
314
- col1: "_pp_version.id",
315
- col2: "rpm.ready_plan_version_id",
316
- collection: { parentAlias: "pp", rootAlias: "rpm", kind: "m2m" },
317
- },
318
- ],
319
- condition: {
320
- kind: "exp",
321
- op: "and",
322
- conditions: [{ kind: "column", alias: "rpm", column: "market_id", dbType: "int", cond: { kind: "in", value: [2] } }],
323
- },
324
- orderBys: [{ alias: "pp", column: "id", order: "ASC" }],
325
- };
326
- (0, QueryParser_collectionJoins_1.optimizeCollectionJoins)(query);
327
- // I.e. the collection metadata points at parent `pp`, but the actual EXISTS correlation uses `_pp_version`.
328
- // Pruning must keep the whole `pp_b0 -> _pp_b0_version -> _pp_version` dependency chain in the outer query.
329
- expect(query.tables).toMatchObject([
330
- { alias: "pp", table: "plan_packages", join: "primary" },
331
- { alias: "pp_b0", table: "ready_plans", join: "outer" },
332
- { alias: "_pp_b0_version", table: "ready_plan_versions", join: "outer" },
333
- { alias: "_pp_version", table: "plan_package_versions", join: "outer" },
334
- ]);
335
- expect(query.condition).toMatchObject({
336
- kind: "exp",
337
- op: "and",
338
- conditions: [
339
- {
340
- kind: "exists",
341
- outerAliases: ["_pp_version"],
342
- subquery: {
343
- tables: [{ alias: "rpm", table: "ready_plan_version_to_markets", join: "primary" }],
344
- condition: {
345
- op: "and",
346
- conditions: [
347
- // I.e. `_pp_version` must be tracked as the outer alias, not just the declared collection parent `pp`.
348
- { kind: "raw", aliases: ["rpm", "_pp_version"], condition: "_pp_version.id = rpm.ready_plan_version_id" },
349
- { kind: "column", alias: "rpm", column: "market_id", cond: { kind: "in", value: [2] } },
350
- ],
351
- },
352
- },
353
- },
354
- ],
355
- });
356
- });
357
- it("rewrites collection branches inside mixed ordinary and collection ORs", () => {
358
- const query = {
359
- selects: ["a.*"],
360
- tables: [
361
- { alias: "a", table: "authors", join: "primary" },
362
- { alias: "p", table: "publishers", join: "outer", col1: "a.publisher_id", col2: "p.id" },
363
- {
364
- alias: "b",
365
- table: "books",
366
- join: "outer",
367
- col1: "a.id",
368
- col2: "b.author_id",
369
- collection: { parentAlias: "a", rootAlias: "b", kind: "o2m" },
370
- },
371
- {
372
- alias: "c",
373
- table: "comments",
374
- join: "outer",
375
- col1: "a.id",
376
- col2: "c.parent_author_id",
377
- collection: { parentAlias: "a", rootAlias: "c", kind: "o2m" },
378
- },
379
- ],
380
- condition: {
381
- kind: "exp",
382
- op: "or",
383
- conditions: [
384
- { kind: "column", alias: "p", column: "name", dbType: "text", cond: { kind: "ilike", value: "%foo%" } },
385
- { kind: "column", alias: "b", column: "title", dbType: "text", cond: { kind: "ilike", value: "%foo%" } },
386
- { kind: "column", alias: "c", column: "text", dbType: "text", cond: { kind: "ilike", value: "%foo%" } },
387
- ],
388
- },
389
- orderBys: [{ alias: "a", column: "id", order: "ASC" }],
390
- };
391
- (0, QueryParser_collectionJoins_1.optimizeCollectionJoins)(query);
392
- // I.e. the ordinary `p` branch stays joined, while independent collection branches become scoped EXISTS clauses.
393
- expect(query.tables).toMatchObject([
394
- { alias: "a", table: "authors", join: "primary" },
395
- { alias: "p", table: "publishers", join: "outer" },
396
- ]);
397
- expect(query.condition).toMatchObject({
398
- kind: "exp",
399
- op: "or",
400
- conditions: [
401
- { kind: "column", alias: "p", column: "name", cond: { kind: "ilike", value: "%foo%" } },
402
- {
403
- kind: "exists",
404
- subquery: {
405
- tables: [{ alias: "b", table: "books", join: "primary" }],
406
- condition: {
407
- op: "and",
408
- conditions: [
409
- { kind: "raw", condition: "a.id = b.author_id" },
410
- { kind: "column", alias: "b", column: "title", cond: { kind: "ilike", value: "%foo%" } },
411
- ],
412
- },
413
- },
414
- },
415
- {
416
- kind: "exists",
417
- subquery: {
418
- tables: [{ alias: "c", table: "comments", join: "primary" }],
419
- condition: {
420
- op: "and",
421
- conditions: [
422
- { kind: "raw", condition: "a.id = c.parent_author_id" },
423
- { kind: "column", alias: "c", column: "text", cond: { kind: "ilike", value: "%foo%" } },
424
- ],
425
- },
426
- },
427
- },
428
- ],
429
- });
430
- });
431
- it("preserves optional joins under collection EXISTS for nullable OR branches", () => {
432
- const query = {
433
- selects: ["a.*"],
434
- tables: [
435
- { alias: "a", table: "authors", join: "primary" },
436
- {
437
- alias: "b",
438
- table: "books",
439
- join: "outer",
440
- col1: "a.id",
441
- col2: "b.author_id",
442
- collection: { parentAlias: "a", rootAlias: "b", kind: "o2m" },
443
- },
444
- { alias: "br", table: "book_reviews", join: "outer", col1: "b.id", col2: "br.book_id" },
445
- { alias: "c", table: "comments", join: "outer", col1: "b.id", col2: "c.parent_book_id" },
446
- ],
447
- condition: {
448
- kind: "exp",
449
- op: "and",
450
- conditions: [
451
- {
452
- kind: "exp",
453
- op: "or",
454
- conditions: [
455
- { kind: "column", alias: "br", column: "rating", dbType: "int", cond: { kind: "eq", value: 5 } },
456
- { kind: "column", alias: "c", column: "text", dbType: "text", cond: { kind: "eq", value: "match" } },
457
- ],
458
- },
459
- ],
460
- },
461
- orderBys: [],
462
- };
463
- (0, QueryParser_collectionJoins_1.optimizeCollectionJoins)(query);
464
- // I.e. an OR across optional descendants must be evaluated after LEFT JOINs, not after INNER JOINs that require
465
- // every nullable branch to exist before any branch can match.
466
- // I.e. only the parent table remains in the outer query; `b`/`br`/`c` moved under EXISTS.
467
- expect(query.tables).toMatchObject([{ alias: "a", table: "authors", join: "primary" }]);
468
- expect(query.condition).toMatchObject({
469
- kind: "exp",
470
- op: "and",
471
- conditions: [
472
- {
473
- kind: "exists",
474
- subquery: {
475
- tables: [
476
- // I.e. `b` is the collection root and becomes the EXISTS subquery's FROM table.
477
- { alias: "b", table: "books", join: "primary" },
478
- // I.e. `br` must stay nullable so the `c.text = match` OR branch can match without a review row.
479
- { alias: "br", table: "book_reviews", join: "outer", distinct: false },
480
- // I.e. `c` must stay nullable so the `br.rating = 5` OR branch can match without a comment row.
481
- { alias: "c", table: "comments", join: "outer", distinct: false },
482
- ],
483
- condition: {
484
- op: "and",
485
- conditions: [
486
- // I.e. this correlation is required after moving `b` out of the outer query.
487
- { kind: "raw", condition: "a.id = b.author_id" },
488
- {
489
- kind: "exp",
490
- op: "or",
491
- conditions: [
492
- // I.e. these branch aliases must remain in one OR under the LEFT JOINs, not become required joins.
493
- { kind: "column", alias: "br", column: "rating", cond: { kind: "eq", value: 5 } },
494
- { kind: "column", alias: "c", column: "text", cond: { kind: "eq", value: "match" } },
495
- ],
496
- },
497
- ],
498
- },
499
- },
500
- },
501
- ],
502
- });
503
- });
504
- it("splits same-root anti-join ORs into NOT EXISTS OR EXISTS", () => {
505
- const query = {
506
- selects: ["a.*"],
507
- tables: [
508
- { alias: "a", table: "authors", join: "primary" },
509
- {
510
- alias: "b",
511
- table: "books",
512
- join: "outer",
513
- col1: "a.id",
514
- col2: "b.author_id",
515
- collection: { parentAlias: "a", rootAlias: "b", kind: "o2m" },
516
- },
517
- {
518
- alias: "br",
519
- table: "book_reviews",
520
- join: "outer",
521
- col1: "b.id",
522
- col2: "br.book_id",
523
- collection: { parentAlias: "b", rootAlias: "br", kind: "o2m" },
524
- },
525
- ],
526
- condition: {
527
- kind: "exp",
528
- op: "or",
529
- conditions: [
530
- { kind: "column", alias: "b", column: "id", dbType: "int", cond: { kind: "is-null" } },
531
- { kind: "column", alias: "br", column: "rating", dbType: "int", cond: { kind: "eq", value: 5 } },
532
- ],
533
- },
534
- orderBys: [],
535
- };
536
- (0, QueryParser_collectionJoins_1.optimizeCollectionJoins)(query);
537
- // I.e. the anti-join branch must become `NOT EXISTS (books)`, while the positive review branch can become its
538
- // own correlated `EXISTS`; keeping `b.id IS NULL` inside an `EXISTS (books ...)` would make it impossible.
539
- expect(query.tables).toMatchObject([{ alias: "a", table: "authors", join: "primary" }]);
540
- expect(query.condition).toMatchObject({
541
- kind: "exp",
542
- op: "or",
543
- conditions: [
544
- {
545
- kind: "exists",
546
- negate: true,
547
- subquery: {
548
- tables: [{ alias: "b", table: "books", join: "primary" }],
549
- condition: { op: "and", conditions: [{ kind: "raw", condition: "a.id = b.author_id" }] },
550
- },
551
- },
552
- {
553
- kind: "exists",
554
- negate: false,
555
- subquery: {
556
- tables: [{ alias: "b", table: "books", join: "primary" }],
557
- condition: {
558
- op: "and",
559
- conditions: [
560
- { kind: "raw", condition: "a.id = b.author_id" },
561
- {
562
- kind: "exists",
563
- negate: false,
564
- subquery: { tables: [{ alias: "br", table: "book_reviews", join: "primary" }] },
565
- },
566
- ],
567
- },
568
- },
569
- },
570
- ],
571
- });
572
- });
573
- it("splits same-root id IS NULL OR id IN list into NOT EXISTS OR EXISTS", () => {
574
- const query = {
575
- selects: ["a.*"],
576
- tables: [
577
- { alias: "a", table: "authors", join: "primary" },
578
- {
579
- alias: "b",
580
- table: "books",
581
- join: "outer",
582
- col1: "a.id",
583
- col2: "b.author_id",
584
- collection: { parentAlias: "a", rootAlias: "b", kind: "o2m" },
585
- },
586
- ],
587
- condition: {
588
- kind: "exp",
589
- op: "or",
590
- conditions: [
591
- { kind: "column", alias: "b", column: "id", dbType: "int", cond: { kind: "is-null" } },
592
- { kind: "column", alias: "b", column: "id", dbType: "int", cond: { kind: "in", value: [1, 2] } },
593
- ],
594
- },
595
- orderBys: [],
596
- };
597
- (0, QueryParser_collectionJoins_1.optimizeCollectionJoins)(query);
598
- // I.e. `b.id IS NULL OR b.id IN (...)` means "no books OR one of these books"; the null branch must not be
599
- // evaluated inside an `EXISTS (books ...)`, where `b.id IS NULL` can never match a real child row.
600
- expect(query.tables).toMatchObject([{ alias: "a", table: "authors", join: "primary" }]);
601
- expect(query.condition).toMatchObject({
602
- kind: "exp",
603
- op: "or",
604
- conditions: [
605
- {
606
- kind: "exists",
607
- negate: true,
608
- subquery: {
609
- tables: [{ alias: "b", table: "books", join: "primary" }],
610
- condition: { op: "and", conditions: [{ kind: "raw", condition: "a.id = b.author_id" }] },
611
- },
612
- },
613
- {
614
- kind: "exists",
615
- negate: false,
616
- subquery: {
617
- tables: [{ alias: "b", table: "books", join: "primary" }],
618
- condition: {
619
- op: "and",
620
- conditions: [
621
- { kind: "raw", condition: "a.id = b.author_id" },
622
- { kind: "column", alias: "b", column: "id", cond: { kind: "in", value: [1, 2] } },
623
- ],
624
- },
625
- },
626
- },
627
- ],
628
- });
629
- });
630
- it("splits m2m target id IS NULL OR id IN list into NOT EXISTS OR EXISTS", () => {
631
- const query = {
632
- selects: ["a.*"],
633
- tables: [
634
- { alias: "a", table: "authors", join: "primary" },
635
- {
636
- alias: "att",
637
- table: "authors_to_tags",
638
- join: "outer",
639
- col1: "a.id",
640
- col2: "att.author_id",
641
- collection: { parentAlias: "a", rootAlias: "att", kind: "m2m" },
642
- },
643
- {
644
- alias: "t",
645
- table: "tags",
646
- join: "outer",
647
- col1: "att.tag_id",
648
- col2: "t.id",
649
- collection: { parentAlias: "att", rootAlias: "att", kind: "m2m" },
650
- },
651
- ],
652
- condition: {
653
- kind: "exp",
654
- op: "or",
655
- conditions: [
656
- { kind: "column", alias: "t", column: "id", dbType: "int", cond: { kind: "is-null" } },
657
- { kind: "column", alias: "t", column: "id", dbType: "int", cond: { kind: "in", value: [1, 2] } },
658
- ],
659
- },
660
- orderBys: [],
661
- };
662
- (0, QueryParser_collectionJoins_1.optimizeCollectionJoins)(query);
663
- // I.e. m2m target `t.id IS NULL` means no matching membership row, so it must split against root `att`.
664
- expect(query.tables).toMatchObject([{ alias: "a", table: "authors", join: "primary" }]);
665
- expect(query.condition).toMatchObject({
666
- kind: "exp",
667
- op: "or",
668
- conditions: [
669
- {
670
- kind: "exists",
671
- negate: true,
672
- subquery: {
673
- tables: [{ alias: "att", table: "authors_to_tags", join: "primary" }],
674
- condition: { op: "and", conditions: [{ kind: "raw", condition: "a.id = att.author_id" }] },
675
- },
676
- },
677
- {
678
- kind: "exists",
679
- negate: false,
680
- subquery: {
681
- tables: [
682
- { alias: "att", table: "authors_to_tags", join: "primary" },
683
- { alias: "t", table: "tags", join: "outer", distinct: false },
684
- ],
685
- condition: {
686
- op: "and",
687
- conditions: [
688
- { kind: "raw", condition: "a.id = att.author_id" },
689
- { kind: "column", alias: "t", column: "id", cond: { kind: "in", value: [1, 2] } },
690
- ],
691
- },
692
- },
693
- },
694
- ],
695
- });
696
- });
697
- it("does not split same-row positive branches into unrelated EXISTS clauses", () => {
698
- const query = {
699
- selects: ["a.*"],
700
- tables: [
701
- { alias: "a", table: "authors", join: "primary" },
702
- {
703
- alias: "b",
704
- table: "books",
705
- join: "outer",
706
- col1: "a.id",
707
- col2: "b.author_id",
708
- collection: { parentAlias: "a", rootAlias: "b", kind: "o2m" },
709
- },
710
- {
711
- alias: "br",
712
- table: "book_reviews",
713
- join: "outer",
714
- col1: "b.id",
715
- col2: "br.book_id",
716
- collection: { parentAlias: "b", rootAlias: "br", kind: "o2m" },
717
- },
718
- ],
719
- condition: {
720
- kind: "exp",
721
- op: "or",
722
- conditions: [
723
- { kind: "column", alias: "b", column: "id", dbType: "int", cond: { kind: "is-null" } },
724
- {
725
- kind: "exp",
726
- op: "and",
727
- conditions: [
728
- { kind: "column", alias: "b", column: "title", dbType: "text", cond: { kind: "eq", value: "b1" } },
729
- { kind: "column", alias: "br", column: "rating", dbType: "int", cond: { kind: "eq", value: 5 } },
730
- ],
731
- },
732
- ],
733
- },
734
- orderBys: [],
735
- };
736
- (0, QueryParser_collectionJoins_1.optimizeCollectionJoins)(query);
737
- // I.e. the positive branch must stay one `EXISTS (books WHERE b.title = ... AND EXISTS reviews ...)`, not split
738
- // into independent `EXISTS (books title = ...) AND EXISTS (reviews rating = ...)` clauses that can match different rows.
739
- expect(query.tables).toMatchObject([{ alias: "a", table: "authors", join: "primary" }]);
740
- expect(query.condition).toMatchObject({
741
- kind: "exp",
742
- op: "or",
743
- conditions: [
744
- { kind: "exists", negate: true, subquery: { tables: [{ alias: "b", join: "primary" }] } },
745
- {
746
- kind: "exists",
747
- negate: false,
748
- subquery: {
749
- tables: [{ alias: "b", table: "books", join: "primary" }],
750
- condition: {
751
- op: "and",
752
- conditions: [
753
- { kind: "raw", condition: "a.id = b.author_id" },
754
- {
755
- kind: "exp",
756
- op: "and",
757
- conditions: [{ kind: "column", alias: "b", column: "title", cond: { kind: "eq", value: "b1" } }],
758
- },
759
- {
760
- kind: "exists",
761
- negate: false,
762
- subquery: { tables: [{ alias: "br", table: "book_reviews", join: "primary" }] },
763
- },
764
- ],
765
- },
766
- },
767
- },
768
- ],
769
- });
770
- });
771
- });
772
- //# sourceMappingURL=QueryParser.collectionJoins.test.js.map