@abedmurrar/objection 0.0.0-stage → 4.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +105 -2
  3. package/lib/index.mjs +6 -0
  4. package/lib/initialize.js +11 -0
  5. package/lib/model/AjvValidator.js +278 -0
  6. package/lib/model/Model.js +772 -0
  7. package/lib/model/ModifierNotFoundError.js +10 -0
  8. package/lib/model/NotFoundError.js +19 -0
  9. package/lib/model/RelationDoesNotExistError.js +11 -0
  10. package/lib/model/ValidationError.js +46 -0
  11. package/lib/model/Validator.js +20 -0
  12. package/lib/model/getModel.js +7 -0
  13. package/lib/model/graph/ModelGraph.js +60 -0
  14. package/lib/model/graph/ModelGraphBuilder.js +188 -0
  15. package/lib/model/graph/ModelGraphEdge.js +40 -0
  16. package/lib/model/graph/ModelGraphNode.js +201 -0
  17. package/lib/model/inheritModel.js +19 -0
  18. package/lib/model/modelBindKnex.js +69 -0
  19. package/lib/model/modelClone.js +102 -0
  20. package/lib/model/modelColPropMap.js +24 -0
  21. package/lib/model/modelConcurrency.js +24 -0
  22. package/lib/model/modelId.js +57 -0
  23. package/lib/model/modelJsonAttributes.js +72 -0
  24. package/lib/model/modelParseRelations.js +83 -0
  25. package/lib/model/modelQueryProps.js +116 -0
  26. package/lib/model/modelSet.js +116 -0
  27. package/lib/model/modelTableMetadata.js +71 -0
  28. package/lib/model/modelToJson.js +157 -0
  29. package/lib/model/modelUtils.js +40 -0
  30. package/lib/model/modelValidate.js +40 -0
  31. package/lib/model/modelValues.js +113 -0
  32. package/lib/model/modelVisitor.js +34 -0
  33. package/lib/objection.js +89 -0
  34. package/lib/queryBuilder/FunctionBuilder.js +291 -0
  35. package/lib/queryBuilder/InternalOptions.js +24 -0
  36. package/lib/queryBuilder/JoinBuilder.js +124 -0
  37. package/lib/queryBuilder/QueryBuilder.js +1136 -0
  38. package/lib/queryBuilder/QueryBuilderBase.js +666 -0
  39. package/lib/queryBuilder/QueryBuilderContext.js +20 -0
  40. package/lib/queryBuilder/QueryBuilderContextBase.js +26 -0
  41. package/lib/queryBuilder/QueryBuilderOperationSupport.js +484 -0
  42. package/lib/queryBuilder/QueryBuilderUserContext.js +25 -0
  43. package/lib/queryBuilder/RawBuilder.js +78 -0
  44. package/lib/queryBuilder/ReferenceBuilder.js +246 -0
  45. package/lib/queryBuilder/RelationExpression.js +373 -0
  46. package/lib/queryBuilder/StaticHookArguments.js +122 -0
  47. package/lib/queryBuilder/ValueBuilder.js +115 -0
  48. package/lib/queryBuilder/expressions.js +121 -0
  49. package/lib/queryBuilder/functions/mysql.js +762 -0
  50. package/lib/queryBuilder/graph/GraphAction.js +54 -0
  51. package/lib/queryBuilder/graph/GraphData.js +12 -0
  52. package/lib/queryBuilder/graph/GraphFetcher.js +155 -0
  53. package/lib/queryBuilder/graph/GraphNodeDbExistence.js +146 -0
  54. package/lib/queryBuilder/graph/GraphOperation.js +21 -0
  55. package/lib/queryBuilder/graph/GraphOptions.js +165 -0
  56. package/lib/queryBuilder/graph/GraphUpsert.js +231 -0
  57. package/lib/queryBuilder/graph/delete/GraphDelete.js +15 -0
  58. package/lib/queryBuilder/graph/delete/GraphDeleteAction.js +56 -0
  59. package/lib/queryBuilder/graph/insert/GraphInsert.js +116 -0
  60. package/lib/queryBuilder/graph/insert/GraphInsertAction.js +183 -0
  61. package/lib/queryBuilder/graph/insert/JoinRowGraphInsertAction.js +70 -0
  62. package/lib/queryBuilder/graph/patch/GraphPatch.js +15 -0
  63. package/lib/queryBuilder/graph/patch/GraphPatchAction.js +205 -0
  64. package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsert.js +26 -0
  65. package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsertAction.js +96 -0
  66. package/lib/queryBuilder/join/JoinResultColumn.js +19 -0
  67. package/lib/queryBuilder/join/JoinResultParser.js +106 -0
  68. package/lib/queryBuilder/join/RelationJoiner.js +258 -0
  69. package/lib/queryBuilder/join/TableNode.js +136 -0
  70. package/lib/queryBuilder/join/TableTree.js +69 -0
  71. package/lib/queryBuilder/join/utils.js +19 -0
  72. package/lib/queryBuilder/operations/DelegateOperation.js +101 -0
  73. package/lib/queryBuilder/operations/DeleteOperation.js +47 -0
  74. package/lib/queryBuilder/operations/FindByIdOperation.js +29 -0
  75. package/lib/queryBuilder/operations/FindByIdsOperation.js +23 -0
  76. package/lib/queryBuilder/operations/FindOperation.js +147 -0
  77. package/lib/queryBuilder/operations/FirstOperation.js +22 -0
  78. package/lib/queryBuilder/operations/FromOperation.js +91 -0
  79. package/lib/queryBuilder/operations/InsertAndFetchOperation.js +38 -0
  80. package/lib/queryBuilder/operations/InsertGraphAndFetchOperation.js +35 -0
  81. package/lib/queryBuilder/operations/InsertGraphOperation.js +87 -0
  82. package/lib/queryBuilder/operations/InsertOperation.js +173 -0
  83. package/lib/queryBuilder/operations/InstanceDeleteOperation.js +37 -0
  84. package/lib/queryBuilder/operations/InstanceFindOperation.js +17 -0
  85. package/lib/queryBuilder/operations/InstanceInsertOperation.js +20 -0
  86. package/lib/queryBuilder/operations/InstanceUpdateOperation.js +45 -0
  87. package/lib/queryBuilder/operations/JoinRelatedOperation.js +83 -0
  88. package/lib/queryBuilder/operations/KnexOperation.js +11 -0
  89. package/lib/queryBuilder/operations/MergeOperation.js +43 -0
  90. package/lib/queryBuilder/operations/ObjectionToKnexConvertingOperation.js +173 -0
  91. package/lib/queryBuilder/operations/OnBuildKnexOperation.js +23 -0
  92. package/lib/queryBuilder/operations/OnBuildOperation.js +23 -0
  93. package/lib/queryBuilder/operations/OnErrorOperation.js +23 -0
  94. package/lib/queryBuilder/operations/QueryBuilderOperation.js +258 -0
  95. package/lib/queryBuilder/operations/RangeOperation.js +37 -0
  96. package/lib/queryBuilder/operations/RelateOperation.js +20 -0
  97. package/lib/queryBuilder/operations/ReturningOperation.js +24 -0
  98. package/lib/queryBuilder/operations/RunAfterOperation.js +23 -0
  99. package/lib/queryBuilder/operations/RunBeforeOperation.js +23 -0
  100. package/lib/queryBuilder/operations/UnrelateOperation.js +18 -0
  101. package/lib/queryBuilder/operations/UpdateAndFetchOperation.js +63 -0
  102. package/lib/queryBuilder/operations/UpdateOperation.js +130 -0
  103. package/lib/queryBuilder/operations/UpsertGraphAndFetchOperation.js +35 -0
  104. package/lib/queryBuilder/operations/UpsertGraphOperation.js +47 -0
  105. package/lib/queryBuilder/operations/WhereCompositeOperation.js +48 -0
  106. package/lib/queryBuilder/operations/WhereInOperation.js +46 -0
  107. package/lib/queryBuilder/operations/eager/EagerOperation.js +46 -0
  108. package/lib/queryBuilder/operations/eager/JoinEagerOperation.js +41 -0
  109. package/lib/queryBuilder/operations/eager/NaiveEagerOperation.js +10 -0
  110. package/lib/queryBuilder/operations/eager/WhereInEagerOperation.js +227 -0
  111. package/lib/queryBuilder/operations/jsonApi/WhereJsonHasOperation.js +29 -0
  112. package/lib/queryBuilder/operations/jsonApi/WhereJsonNotObjectOperation.js +37 -0
  113. package/lib/queryBuilder/operations/jsonApi/WhereJsonOperation.js +30 -0
  114. package/lib/queryBuilder/operations/jsonApi/WhereJsonOverlapsOperation.js +33 -0
  115. package/lib/queryBuilder/operations/jsonApi/mysqlJsonApi.js +155 -0
  116. package/lib/queryBuilder/operations/jsonApi/postgresJsonApi.js +135 -0
  117. package/lib/queryBuilder/operations/select/SelectOperation.js +50 -0
  118. package/lib/queryBuilder/operations/select/Selection.js +112 -0
  119. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeMsSqlOperation.js +84 -0
  120. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeOperation.js +90 -0
  121. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeSqliteOperation.js +95 -0
  122. package/lib/queryBuilder/parsers/jsonFieldExpressionParser.js +787 -0
  123. package/lib/queryBuilder/parsers/relationExpressionParser.js +930 -0
  124. package/lib/queryBuilder/transformations/CompositeQueryTransformation.js +17 -0
  125. package/lib/queryBuilder/transformations/QueryTransformation.js +9 -0
  126. package/lib/queryBuilder/transformations/WrapMysqlModifySubqueryTransformation.js +57 -0
  127. package/lib/queryBuilder/transformations/index.js +9 -0
  128. package/lib/queryBuilder/whereScopes.js +199 -0
  129. package/lib/relations/Relation.js +317 -0
  130. package/lib/relations/RelationDeleteOperation.js +23 -0
  131. package/lib/relations/RelationFindOperation.js +116 -0
  132. package/lib/relations/RelationInsertOperation.js +25 -0
  133. package/lib/relations/RelationOwner.js +199 -0
  134. package/lib/relations/RelationProperty.js +207 -0
  135. package/lib/relations/RelationUpdateOperation.js +23 -0
  136. package/lib/relations/belongsToOne/BelongsToOneDeleteOperation.js +18 -0
  137. package/lib/relations/belongsToOne/BelongsToOneInsertOperation.js +33 -0
  138. package/lib/relations/belongsToOne/BelongsToOneRelateOperation.js +39 -0
  139. package/lib/relations/belongsToOne/BelongsToOneRelation.js +45 -0
  140. package/lib/relations/belongsToOne/BelongsToOneUnrelateOperation.js +46 -0
  141. package/lib/relations/hasMany/HasManyInsertOperation.js +45 -0
  142. package/lib/relations/hasMany/HasManyRelateOperation.js +48 -0
  143. package/lib/relations/hasMany/HasManyRelation.js +41 -0
  144. package/lib/relations/hasMany/HasManyUnrelateOperation.js +26 -0
  145. package/lib/relations/hasOne/HasOneRelation.js +10 -0
  146. package/lib/relations/hasOneThrough/HasOneThroughRelation.js +10 -0
  147. package/lib/relations/manyToMany/ManyToManyModifyMixin.js +82 -0
  148. package/lib/relations/manyToMany/ManyToManyRelation.js +405 -0
  149. package/lib/relations/manyToMany/ManyToManySqliteModifyMixin.js +29 -0
  150. package/lib/relations/manyToMany/delete/ManyToManyDeleteOperation.js +8 -0
  151. package/lib/relations/manyToMany/delete/ManyToManyDeleteOperationBase.js +20 -0
  152. package/lib/relations/manyToMany/delete/ManyToManyDeleteSqliteOperation.js +8 -0
  153. package/lib/relations/manyToMany/find/ManyToManyFindOperation.js +82 -0
  154. package/lib/relations/manyToMany/insert/ManyToManyInsertOperation.js +40 -0
  155. package/lib/relations/manyToMany/relate/ManyToManyRelateOperation.js +64 -0
  156. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperation.js +11 -0
  157. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperationBase.js +27 -0
  158. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateSqliteOperation.js +11 -0
  159. package/lib/relations/manyToMany/update/ManyToManyUpdateOperation.js +8 -0
  160. package/lib/relations/manyToMany/update/ManyToManyUpdateOperationBase.js +65 -0
  161. package/lib/relations/manyToMany/update/ManyToManyUpdateSqliteOperation.js +8 -0
  162. package/lib/transaction.js +66 -0
  163. package/lib/utils/assert.js +19 -0
  164. package/lib/utils/buildUtils.js +19 -0
  165. package/lib/utils/classUtils.js +9 -0
  166. package/lib/utils/cloneDeep.js +365 -0
  167. package/lib/utils/createModifier.js +37 -0
  168. package/lib/utils/deprecate.js +11 -0
  169. package/lib/utils/identifierMapping.js +188 -0
  170. package/lib/utils/internalPropUtils.js +7 -0
  171. package/lib/utils/knexUtils.js +81 -0
  172. package/lib/utils/mixin.js +18 -0
  173. package/lib/utils/mysqlJsonPath.js +70 -0
  174. package/lib/utils/normalizeIds.js +127 -0
  175. package/lib/utils/objectUtils.js +314 -0
  176. package/lib/utils/parseFieldExpression.js +73 -0
  177. package/lib/utils/postgresJsonPath.js +96 -0
  178. package/lib/utils/promiseUtils/after.js +14 -0
  179. package/lib/utils/promiseUtils/afterReturn.js +14 -0
  180. package/lib/utils/promiseUtils/index.js +15 -0
  181. package/lib/utils/promiseUtils/isPromise.js +8 -0
  182. package/lib/utils/promiseUtils/map.js +96 -0
  183. package/lib/utils/promiseUtils/mapAfterAllReturn.js +23 -0
  184. package/lib/utils/promiseUtils/try.js +19 -0
  185. package/lib/utils/resolveModel.js +104 -0
  186. package/lib/utils/tmpColumnUtils.js +7 -0
  187. package/package.json +113 -4
  188. package/typings/objection/index.d.mts +362 -0
  189. package/typings/objection/index.d.ts +4131 -0
  190. package/typings/objection/relation-expression.d.ts +237 -0
@@ -0,0 +1,258 @@
1
+ 'use strict';
2
+ const { uniqBy } = require('../../utils/objectUtils');
3
+ const { Selection } = require('../operations/select/Selection');
4
+ const { createModifier } = require('../../utils/createModifier');
5
+ const { map: mapPromise } = require('../../utils/promiseUtils');
6
+ const { getReadConcurrency } = require('../../model/modelConcurrency');
7
+ const { ValidationErrorType } = require('../../model/ValidationError');
8
+ const { TableTree } = require('./TableTree');
9
+ const { JoinResultParser } = require('./JoinResultParser');
10
+ const { ID_LENGTH_LIMIT } = require('./utils');
11
+ /**
12
+ * Given a relation expression, builds a query using joins to fetch it.
13
+ */
14
+ class RelationJoiner {
15
+ constructor({ modelClass }) {
16
+ this.rootModelClass = modelClass;
17
+ // The relation expression to join.
18
+ this.expression = null;
19
+ // Explicit modifiers for the relation expression.
20
+ this.modifiers = null;
21
+ this.options = defaultOptions();
22
+ this.tableTree = null;
23
+ this.internalSelections = null;
24
+ }
25
+ setExpression(expression) {
26
+ if (!this.expression) {
27
+ this.expression = expression;
28
+ }
29
+ return this;
30
+ }
31
+ setModifiers(modifiers) {
32
+ if (!this.modifiers) {
33
+ this.modifiers = modifiers;
34
+ }
35
+ return this;
36
+ }
37
+ setOptions(options) {
38
+ this.options = Object.assign(this.options, options);
39
+ return this;
40
+ }
41
+ /**
42
+ * Fetches the column information needed for building the select clauses.
43
+ *
44
+ * This must be called before calling `build(builder, true)`. `build(builder, false)`
45
+ * can be called without this since it doesn't build selects.
46
+ */
47
+ fetchColumnInfo(builder) {
48
+ const tableTree = this._getTableTree(builder);
49
+ const allModelClasses = new Set(tableTree.nodes.map((node) => node.modelClass));
50
+ return mapPromise(Array.from(allModelClasses), (modelClass) => modelClass.fetchTableMetadata({ parentBuilder: builder }), {
51
+ concurrency: getReadConcurrency(this.rootModelClass, builder.unsafeKnex()),
52
+ });
53
+ }
54
+ build(builder, buildSelects = true) {
55
+ const rootTableNode = this._getTableTree(builder).rootNode;
56
+ const userSelectQueries = new Map([[rootTableNode, builder]]);
57
+ for (const tableNode of rootTableNode.childNodes) {
58
+ this._buildJoinsForNode({ builder, tableNode, userSelectQueries });
59
+ }
60
+ if (buildSelects) {
61
+ this._buildSelects({ builder, tableNode: rootTableNode, userSelectQueries });
62
+ }
63
+ }
64
+ parseResult(builder, flatRows) {
65
+ const parser = JoinResultParser.create({
66
+ tableTree: this._getTableTree(builder),
67
+ omitColumnAliases: this.internalSelections.map((it) => it.alias),
68
+ });
69
+ return parser.parse(flatRows);
70
+ }
71
+ _getTableTree(builder) {
72
+ if (!this.tableTree) {
73
+ // Create the table tree lazily.
74
+ this.tableTree = TableTree.create({
75
+ rootModelClass: this.rootModelClass,
76
+ rootTableAlias: builder.tableRef(),
77
+ expression: this.expression,
78
+ options: this.options,
79
+ });
80
+ }
81
+ return this.tableTree;
82
+ }
83
+ _buildJoinsForNode({ builder, tableNode, userSelectQueries }) {
84
+ const subqueryToJoin = createSubqueryToJoin({
85
+ builder,
86
+ tableNode,
87
+ modifiers: this.modifiers,
88
+ });
89
+ const userSelectQuery = subqueryToJoin.clone();
90
+ // relation.join applies the relation modifier that can
91
+ // also contain selects.
92
+ userSelectQuery.modify(tableNode.relation.modify);
93
+ // Save the query that contains the user specified selects
94
+ // for later use.
95
+ userSelectQueries.set(tableNode, userSelectQuery);
96
+ tableNode.relation.join(builder, {
97
+ joinOperation: this.options.joinOperation,
98
+ ownerTable: tableNode.parentNode.alias,
99
+ relatedTableAlias: tableNode.alias,
100
+ joinTableAlias: tableNode.getJoinTableAlias(builder),
101
+ relatedJoinSelectQuery: ensureIdAndRelationPropsAreSelected({
102
+ builder: subqueryToJoin,
103
+ tableNode,
104
+ }),
105
+ });
106
+ for (const childNode of tableNode.childNodes) {
107
+ this._buildJoinsForNode({ builder, tableNode: childNode, userSelectQueries });
108
+ }
109
+ }
110
+ _buildSelects({ builder, tableNode, userSelectQueries }) {
111
+ const { selections, internalSelections } = getSelectionsForNode({
112
+ builder,
113
+ tableNode,
114
+ userSelectQueries,
115
+ });
116
+ for (const selection of selections) {
117
+ checkAliasLength(tableNode.modelClass, selection.name);
118
+ }
119
+ // Save the selections that were added internally (not by the user)
120
+ // so that we can later remove the corresponding properties when
121
+ // parsing the result.
122
+ this.internalSelections = internalSelections;
123
+ builder.select(selectionsToStrings(selections));
124
+ }
125
+ }
126
+ function defaultOptions() {
127
+ return {
128
+ joinOperation: 'leftJoin',
129
+ minimize: false,
130
+ separator: ':',
131
+ aliases: {},
132
+ };
133
+ }
134
+ function createSubqueryToJoin({ builder, tableNode, modifiers }) {
135
+ const { relation, expression, modelClass } = tableNode;
136
+ const modifierQuery = modelClass.query().childQueryOf(builder);
137
+ for (const modifierName of expression.node.$modify) {
138
+ const modifier = createModifier({
139
+ modifier: modifierName,
140
+ modelClass,
141
+ modifiers,
142
+ });
143
+ try {
144
+ modifier(modifierQuery);
145
+ }
146
+ catch (err) {
147
+ if (err instanceof modelClass.ModifierNotFoundError) {
148
+ throw modelClass.createValidationError({
149
+ type: ValidationErrorType.RelationExpression,
150
+ message: `could not find modifier "${modifierName}" for relation "${relation.name}"`,
151
+ });
152
+ }
153
+ else {
154
+ throw err;
155
+ }
156
+ }
157
+ }
158
+ return modifierQuery;
159
+ }
160
+ function ensureIdAndRelationPropsAreSelected({ builder, tableNode }) {
161
+ const tableRef = builder.tableRef();
162
+ const cols = [
163
+ ...builder.modelClass().getIdColumnArray(),
164
+ ...tableNode.relation.relatedProp.cols,
165
+ ...tableNode.childNodes.reduce((cols, childNode) => [...cols, ...childNode.relation.ownerProp.cols], []),
166
+ ];
167
+ const selectStrings = uniqBy(cols)
168
+ .filter((col) => !builder.hasSelectionAs(col, col))
169
+ .map((col) => `${tableRef}.${col}`);
170
+ return builder.select(selectStrings);
171
+ }
172
+ function getSelectionsForNode({ builder, tableNode, userSelectQueries }) {
173
+ const userSelectQuery = userSelectQueries.get(tableNode);
174
+ const userSelections = userSelectQuery.findAllSelections();
175
+ const userSelectedAllColumns = isSelectAllSelectionSet(userSelections);
176
+ let selections = [];
177
+ let internalSelections = [];
178
+ if (tableNode.parentNode) {
179
+ selections = mapUserSelectionsFromSubqueryToMainQuery({ userSelections, tableNode });
180
+ if (userSelectedAllColumns && tableNode.relation.isObjectionManyToManyRelation) {
181
+ const extraSelections = getJoinTableExtraSelectionsForNode({ builder, tableNode });
182
+ selections = selections.concat(extraSelections);
183
+ }
184
+ }
185
+ if (userSelectedAllColumns) {
186
+ const allColumnSelections = getAllColumnSelectionsForNode({ builder, tableNode });
187
+ selections = allColumnSelections.concat(selections);
188
+ }
189
+ else {
190
+ const idSelections = getIdSelectionsForNode({ tableNode });
191
+ for (const idSelection of idSelections) {
192
+ if (!userSelectQuery.hasSelectionAs(idSelection.column, idSelection.column)) {
193
+ selections.push(idSelection);
194
+ internalSelections.push(idSelection);
195
+ }
196
+ }
197
+ }
198
+ for (const childNode of tableNode.childNodes) {
199
+ const childResult = getSelectionsForNode({ builder, tableNode: childNode, userSelectQueries });
200
+ selections = selections.concat(childResult.selections);
201
+ internalSelections = internalSelections.concat(childResult.internalSelections);
202
+ }
203
+ return {
204
+ selections,
205
+ internalSelections,
206
+ };
207
+ }
208
+ function mapUserSelectionsFromSubqueryToMainQuery({ userSelections, tableNode }) {
209
+ return userSelections.filter(isNotSelectAll).map((selection) => {
210
+ return new Selection(tableNode.alias, selection.name, tableNode.getColumnAliasForColumn(selection.name));
211
+ });
212
+ }
213
+ function getJoinTableExtraSelectionsForNode({ builder, tableNode }) {
214
+ return tableNode.relation.joinTableExtras.map((extra) => {
215
+ return new Selection(tableNode.getJoinTableAlias(builder), extra.joinTableCol, tableNode.getColumnAliasForColumn(extra.aliasCol));
216
+ });
217
+ }
218
+ function getAllColumnSelectionsForNode({ builder, tableNode }) {
219
+ const table = builder.tableNameFor(tableNode.modelClass);
220
+ const tableMeta = tableNode.modelClass.tableMetadata({ table });
221
+ if (!tableMeta) {
222
+ throw new Error(`table metadata has not been fetched for table '${table}'. Are you trying to call toKnexQuery() for a withGraphJoined query? To make sure the table metadata is fetched see the objection.initialize function.`);
223
+ }
224
+ return tableMeta.columns.map((columnName) => {
225
+ return new Selection(tableNode.alias, columnName, tableNode.getColumnAliasForColumn(columnName));
226
+ });
227
+ }
228
+ function getIdSelectionsForNode({ tableNode }) {
229
+ return tableNode.modelClass.getIdColumnArray().map((columnName) => {
230
+ return new Selection(tableNode.alias, columnName, tableNode.getColumnAliasForColumn(columnName));
231
+ });
232
+ }
233
+ function selectionsToStrings(selections) {
234
+ return selections.map((selection) => {
235
+ const selectStr = `${selection.table}.${selection.column}`;
236
+ return `${selectStr} as ${selection.alias}`;
237
+ });
238
+ }
239
+ function isSelectAll(selection) {
240
+ return selection.column === '*';
241
+ }
242
+ function isNotSelectAll(selection) {
243
+ return selection.column !== '*';
244
+ }
245
+ function isSelectAllSelectionSet(selections) {
246
+ return selections.length === 0 || selections.some(isSelectAll);
247
+ }
248
+ function checkAliasLength(modelClass, alias) {
249
+ if (alias.length > ID_LENGTH_LIMIT) {
250
+ throw modelClass.createValidationError({
251
+ type: ValidationErrorType.RelationExpression,
252
+ message: `identifier ${alias} is over ${ID_LENGTH_LIMIT} characters long and would be truncated by the database engine.`,
253
+ });
254
+ }
255
+ }
256
+ module.exports = {
257
+ RelationJoiner,
258
+ };
@@ -0,0 +1,136 @@
1
+ 'use strict';
2
+ class TableNode {
3
+ constructor({ tableTree, modelClass, expression, parentNode = null, relation = null }) {
4
+ this.tableTree = tableTree;
5
+ this.modelClass = modelClass;
6
+ this.parentNode = parentNode;
7
+ this.relation = relation;
8
+ this.expression = expression;
9
+ this.childNodes = [];
10
+ this.alias = this._calculateAlias();
11
+ this.idGetter = this._createIdGetter();
12
+ }
13
+ static create(args) {
14
+ const node = new TableNode(args);
15
+ if (node.parentNode) {
16
+ node.parentNode.childNodes.push(node);
17
+ }
18
+ return node;
19
+ }
20
+ get options() {
21
+ return this.tableTree.options;
22
+ }
23
+ get relationProperty() {
24
+ return this.expression.node.$name;
25
+ }
26
+ getReferenceForColumn(column) {
27
+ return `${this.alias}.${column}`;
28
+ }
29
+ getColumnAliasForColumn(column) {
30
+ if (this.parentNode) {
31
+ return `${this.alias}${this.options.separator}${column}`;
32
+ }
33
+ else {
34
+ return column;
35
+ }
36
+ }
37
+ getColumnForColumnAlias(columnAlias) {
38
+ const lastSepIndex = columnAlias.lastIndexOf(this.options.separator);
39
+ if (lastSepIndex === -1) {
40
+ return columnAlias;
41
+ }
42
+ else {
43
+ return columnAlias.slice(lastSepIndex + this.options.separator.length);
44
+ }
45
+ }
46
+ getIdFromFlatRow(flatRow) {
47
+ return this.idGetter(flatRow);
48
+ }
49
+ getJoinTableAlias(builder) {
50
+ if (this.relation.isObjectionManyToManyRelation) {
51
+ return (builder.aliasFor(this.relation.joinTableModelClass) ||
52
+ this.modelClass.joinTableAlias(this.alias));
53
+ }
54
+ else {
55
+ return undefined;
56
+ }
57
+ }
58
+ _calculateAlias() {
59
+ if (this.parentNode) {
60
+ const relationName = this.expression.node.$name;
61
+ const alias = this.options.aliases[relationName] || relationName;
62
+ if (this.options.minimize) {
63
+ return `_t${this.tableTree.createNextUid()}`;
64
+ }
65
+ else if (this.parentNode.parentNode) {
66
+ return `${this.parentNode.alias}${this.options.separator}${alias}`;
67
+ }
68
+ else {
69
+ return alias;
70
+ }
71
+ }
72
+ else {
73
+ return this.tableTree.rootTableAlias;
74
+ }
75
+ }
76
+ _createIdGetter() {
77
+ const idColumns = this.modelClass.getIdColumnArray();
78
+ const columnAliases = idColumns.map((column) => this.getColumnAliasForColumn(column));
79
+ if (idColumns.length === 1) {
80
+ return createIdGetter(columnAliases);
81
+ }
82
+ else {
83
+ return createCompositeIdGetter(columnAliases);
84
+ }
85
+ }
86
+ }
87
+ function createIdGetter(columnAliases) {
88
+ const columnAlias = columnAliases[0];
89
+ return (flatRow) => {
90
+ const id = flatRow[columnAlias];
91
+ if (id === null) {
92
+ return null;
93
+ }
94
+ return `${id}`;
95
+ };
96
+ }
97
+ function createCompositeIdGetter(columnAliases) {
98
+ if (columnAliases.length === 2) {
99
+ return createTwoIdGetter(columnAliases);
100
+ }
101
+ else {
102
+ return createMultiIdGetter(columnAliases);
103
+ }
104
+ }
105
+ function createTwoIdGetter(columnAliases) {
106
+ const columnAlias1 = columnAliases[0];
107
+ const columnAlias2 = columnAliases[1];
108
+ return (flatRow) => {
109
+ const id1 = flatRow[columnAlias1];
110
+ const id2 = flatRow[columnAlias2];
111
+ if (id1 === null || id2 === null) {
112
+ return null;
113
+ }
114
+ return `${id1},${id2}`;
115
+ };
116
+ }
117
+ function createMultiIdGetter(columnAliases) {
118
+ return (flatRow) => {
119
+ let idStr = '';
120
+ for (let i = 0, l = columnAliases.length; i < l; ++i) {
121
+ const columnAlias = columnAliases[i];
122
+ const id = flatRow[columnAlias];
123
+ if (id === null) {
124
+ return null;
125
+ }
126
+ idStr += id;
127
+ if (i !== l - 1) {
128
+ idStr += ',';
129
+ }
130
+ }
131
+ return idStr;
132
+ };
133
+ }
134
+ module.exports = {
135
+ TableNode,
136
+ };
@@ -0,0 +1,69 @@
1
+ 'use strict';
2
+ const { forEachChildExpression } = require('./utils');
3
+ const { TableNode } = require('./TableNode');
4
+ class TableTree {
5
+ constructor({ expression, rootModelClass, rootTableAlias, options }) {
6
+ this.options = options;
7
+ this.rootModelClass = rootModelClass;
8
+ this.rootTableAlias = rootTableAlias;
9
+ this.nodes = [];
10
+ this.nodesByAlias = new Map();
11
+ this.uidCounter = 0;
12
+ this._createNodes({ expression, modelClass: rootModelClass });
13
+ }
14
+ static create(args) {
15
+ return new TableTree(args);
16
+ }
17
+ get rootNode() {
18
+ return this.nodes[0];
19
+ }
20
+ getNodeForColumnAlias(columnAlias) {
21
+ const lastSepIndex = columnAlias.lastIndexOf(this.options.separator);
22
+ if (lastSepIndex === -1) {
23
+ return this.rootNode;
24
+ }
25
+ else {
26
+ const tableAlias = columnAlias.slice(0, lastSepIndex);
27
+ return this.nodesByAlias.get(tableAlias);
28
+ }
29
+ }
30
+ createNextUid() {
31
+ return this.uidCounter++;
32
+ }
33
+ _createNodes({ expression, modelClass }) {
34
+ const rootNode = this._createRootNode({ expression, modelClass });
35
+ this._createChildNodes({ expression, modelClass, parentNode: rootNode });
36
+ for (const node of this.nodes) {
37
+ this.nodesByAlias.set(node.alias, node);
38
+ }
39
+ }
40
+ _createRootNode({ expression, modelClass }) {
41
+ const node = TableNode.create({
42
+ tableTree: this,
43
+ modelClass,
44
+ expression,
45
+ });
46
+ this.nodes.push(node);
47
+ return node;
48
+ }
49
+ _createChildNodes({ expression, modelClass, parentNode }) {
50
+ forEachChildExpression(expression, modelClass, (childExpr, relation) => {
51
+ const node = TableNode.create({
52
+ tableTree: this,
53
+ modelClass: relation.relatedModelClass,
54
+ expression: childExpr,
55
+ parentNode,
56
+ relation,
57
+ });
58
+ this.nodes.push(node);
59
+ this._createChildNodes({
60
+ expression: childExpr,
61
+ modelClass: relation.relatedModelClass,
62
+ parentNode: node,
63
+ });
64
+ });
65
+ }
66
+ }
67
+ module.exports = {
68
+ TableTree,
69
+ };
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+ const { ValidationErrorType } = require('../../model/ValidationError');
3
+ const ID_LENGTH_LIMIT = 63;
4
+ const RELATION_RECURSION_LIMIT = 64;
5
+ // Given a relation expression, goes through all first level children.
6
+ function forEachChildExpression(expr, modelClass, callback) {
7
+ if (expr.node.$allRecursive || expr.maxRecursionDepth > RELATION_RECURSION_LIMIT) {
8
+ throw modelClass.createValidationError({
9
+ type: ValidationErrorType.RelationExpression,
10
+ message: `recursion depth of eager expression ${expr.toString()} too big for JoinEagerAlgorithm`,
11
+ });
12
+ }
13
+ expr.forEachChildExpression(modelClass, callback);
14
+ }
15
+ module.exports = {
16
+ ID_LENGTH_LIMIT,
17
+ RELATION_RECURSION_LIMIT,
18
+ forEachChildExpression,
19
+ };
@@ -0,0 +1,101 @@
1
+ 'use strict';
2
+ const { QueryBuilderOperation } = require('./QueryBuilderOperation');
3
+ // Operation that simply delegates all calls to the operation passed
4
+ // to to the constructor in `opt.delegate`.
5
+ class DelegateOperation extends QueryBuilderOperation {
6
+ constructor(name, opt) {
7
+ super(name, opt);
8
+ this.delegate = opt.delegate;
9
+ }
10
+ get modelOptions() {
11
+ return this.delegate.modelOptions;
12
+ }
13
+ is(OperationClass) {
14
+ return super.is(OperationClass) || this.delegate.is(OperationClass);
15
+ }
16
+ onAdd(builder, args) {
17
+ return this.delegate.onAdd(builder, args);
18
+ }
19
+ onBefore1(builder, result) {
20
+ return this.delegate.onBefore1(builder, result);
21
+ }
22
+ hasOnBefore1() {
23
+ return this.onBefore1 !== DelegateOperation.prototype.onBefore1 || this.delegate.hasOnBefore1();
24
+ }
25
+ onBefore2(builder, result) {
26
+ return this.delegate.onBefore2(builder, result);
27
+ }
28
+ hasOnBefore2() {
29
+ return this.onBefore2 !== DelegateOperation.prototype.onBefore2 || this.delegate.hasOnBefore2();
30
+ }
31
+ onBefore3(builder, result) {
32
+ return this.delegate.onBefore3(builder, result);
33
+ }
34
+ hasOnBefore3() {
35
+ return this.onBefore3 !== DelegateOperation.prototype.onBefore3 || this.delegate.hasOnBefore3();
36
+ }
37
+ onBuild(builder) {
38
+ return this.delegate.onBuild(builder);
39
+ }
40
+ hasOnBuild() {
41
+ return this.onBuild !== DelegateOperation.prototype.onBuild || this.delegate.hasOnBuild();
42
+ }
43
+ onBuildKnex(knexBuilder, builder) {
44
+ return this.delegate.onBuildKnex(knexBuilder, builder);
45
+ }
46
+ hasOnBuildKnex() {
47
+ return (this.onBuildKnex !== DelegateOperation.prototype.onBuildKnex || this.delegate.hasOnBuildKnex());
48
+ }
49
+ onRawResult(builder, result) {
50
+ return this.delegate.onRawResult(builder, result);
51
+ }
52
+ hasOnRawResult() {
53
+ return (this.onRawResult !== DelegateOperation.prototype.onRawResult || this.delegate.hasOnRawResult());
54
+ }
55
+ onAfter1(builder, result) {
56
+ return this.delegate.onAfter1(builder, result);
57
+ }
58
+ hasOnAfter1() {
59
+ return this.onAfter1 !== DelegateOperation.prototype.onAfter1 || this.delegate.hasOnAfter1();
60
+ }
61
+ onAfter2(builder, result) {
62
+ return this.delegate.onAfter2(builder, result);
63
+ }
64
+ hasOnAfter2() {
65
+ return this.onAfter2 !== DelegateOperation.prototype.onAfter2 || this.delegate.hasOnAfter2();
66
+ }
67
+ onAfter3(builder, result) {
68
+ return this.delegate.onAfter3(builder, result);
69
+ }
70
+ hasOnAfter3() {
71
+ return this.onAfter3 !== DelegateOperation.prototype.onAfter3 || this.delegate.hasOnAfter3();
72
+ }
73
+ queryExecutor(builder) {
74
+ return this.delegate.queryExecutor(builder);
75
+ }
76
+ hasQueryExecutor() {
77
+ return (this.queryExecutor !== DelegateOperation.prototype.queryExecutor ||
78
+ this.delegate.hasQueryExecutor());
79
+ }
80
+ onError(builder, error) {
81
+ return this.delegate.onError(builder, error);
82
+ }
83
+ hasOnError() {
84
+ return this.onError !== DelegateOperation.prototype.onError || this.delegate.hasOnError();
85
+ }
86
+ toFindOperation(builder) {
87
+ return this.delegate.toFindOperation(builder);
88
+ }
89
+ hasToFindOperation() {
90
+ return (this.hasToFindOperation !== DelegateOperation.prototype.hasToFindOperation ||
91
+ this.delegate.hasToFindOperation());
92
+ }
93
+ clone() {
94
+ const clone = super.clone();
95
+ clone.delegate = this.delegate && this.delegate.clone();
96
+ return clone;
97
+ }
98
+ }
99
+ module.exports = {
100
+ DelegateOperation,
101
+ };
@@ -0,0 +1,47 @@
1
+ 'use strict';
2
+ const { QueryBuilderOperation } = require('./QueryBuilderOperation');
3
+ const { StaticHookArguments, hasStaticHook } = require('../StaticHookArguments');
4
+ class DeleteOperation extends QueryBuilderOperation {
5
+ async onBefore2(builder, result) {
6
+ await callBeforeDelete(builder);
7
+ return result;
8
+ }
9
+ onBuildKnex(knexBuilder) {
10
+ return knexBuilder.delete();
11
+ }
12
+ onAfter2(builder, result) {
13
+ return callAfterDelete(builder, result);
14
+ }
15
+ toFindOperation() {
16
+ return null;
17
+ }
18
+ }
19
+ function callBeforeDelete(builder) {
20
+ return callStaticBeforeDelete(builder);
21
+ }
22
+ function callStaticBeforeDelete(builder) {
23
+ if (!hasStaticHook(builder.modelClass(), 'beforeDelete')) {
24
+ return undefined;
25
+ }
26
+ const args = StaticHookArguments.create({ builder });
27
+ return builder.modelClass().beforeDelete(args);
28
+ }
29
+ function callAfterDelete(builder, result) {
30
+ return callStaticAfterDelete(builder, result);
31
+ }
32
+ async function callStaticAfterDelete(builder, result) {
33
+ if (!hasStaticHook(builder.modelClass(), 'afterDelete')) {
34
+ return result;
35
+ }
36
+ const args = StaticHookArguments.create({ builder, result });
37
+ const maybeResult = await builder.modelClass().afterDelete(args);
38
+ if (maybeResult === undefined) {
39
+ return result;
40
+ }
41
+ else {
42
+ return maybeResult;
43
+ }
44
+ }
45
+ module.exports = {
46
+ DeleteOperation,
47
+ };
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+ const { QueryBuilderOperation } = require('./QueryBuilderOperation');
3
+ const { assertIdNotUndefined } = require('../../utils/assert');
4
+ class FindByIdOperation extends QueryBuilderOperation {
5
+ constructor(name, opt) {
6
+ super(name, opt);
7
+ this.id = this.opt.id;
8
+ }
9
+ onAdd(builder, args) {
10
+ if (this.id === null || this.id === undefined) {
11
+ this.id = args[0];
12
+ }
13
+ return super.onAdd(builder, args);
14
+ }
15
+ onBuild(builder) {
16
+ if (!builder.internalOptions().skipUndefined) {
17
+ assertIdNotUndefined(this.id, `undefined was passed to ${this.name}`);
18
+ }
19
+ builder.whereComposite(builder.fullIdColumn(), this.id);
20
+ }
21
+ clone() {
22
+ const clone = super.clone();
23
+ clone.id = this.id;
24
+ return clone;
25
+ }
26
+ }
27
+ module.exports = {
28
+ FindByIdOperation,
29
+ };
@@ -0,0 +1,23 @@
1
+ 'use strict';
2
+ const { QueryBuilderOperation } = require('./QueryBuilderOperation');
3
+ class FindByIdsOperation extends QueryBuilderOperation {
4
+ constructor(name, opt) {
5
+ super(name, opt);
6
+ this.ids = null;
7
+ }
8
+ onAdd(builder, args) {
9
+ this.ids = args[0];
10
+ return super.onAdd(builder, args);
11
+ }
12
+ onBuild(builder) {
13
+ builder.whereInComposite(builder.fullIdColumn(), this.ids);
14
+ }
15
+ clone() {
16
+ const clone = super.clone();
17
+ clone.ids = this.ids;
18
+ return clone;
19
+ }
20
+ }
21
+ module.exports = {
22
+ FindByIdsOperation,
23
+ };