mythix-orm 1.11.6 → 1.12.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.
- package/README.md +100 -9
- package/lib/connection/connection-base.js +173 -39
- package/lib/connection/literals/average-literal.js +67 -0
- package/lib/connection/literals/count-literal.js +80 -0
- package/lib/connection/literals/distinct-literal.js +71 -0
- package/lib/connection/literals/field-literal.js +54 -0
- package/lib/connection/literals/literal-base.d.ts +1 -0
- package/lib/connection/literals/literal-base.js +137 -2
- package/lib/connection/literals/literal-field-base.js +50 -0
- package/lib/connection/literals/literal.js +15 -0
- package/lib/connection/literals/max-literal.js +67 -0
- package/lib/connection/literals/min-literal.js +67 -0
- package/lib/connection/literals/sum-literal.js +67 -0
- package/lib/connection/query-generator-base.js +273 -0
- package/lib/field.js +1 -1
- package/lib/model.js +54 -2
- package/lib/proxy-class/proxy-class.js +156 -21
- package/lib/query-engine/field-scope.js +401 -9
- package/lib/query-engine/model-scope.js +572 -13
- package/lib/query-engine/query-engine-base.js +590 -30
- package/lib/query-engine/query-engine.d.ts +13 -2
- package/lib/query-engine/query-engine.js +525 -18
- package/lib/types/helpers/default-helpers.js +124 -0
- package/lib/types/type.js +297 -3
- package/lib/utils/async-store.js +80 -3
- package/package.json +1 -2
|
@@ -57,20 +57,80 @@ function wrapAnyAll(func) {
|
|
|
57
57
|
return func;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
/// `FieldScope` is the "field level" of a query.
|
|
61
|
+
/// It manages conditions, such as things like `EQ`, `NEQ`,
|
|
62
|
+
/// `GT`, `LT`, etc...
|
|
63
|
+
///
|
|
64
|
+
/// Any operator completed on this "field scope" will return
|
|
65
|
+
/// the previous `ModelScope` so the user can continue chaining
|
|
66
|
+
/// operations on the query. All operators at this level (except
|
|
67
|
+
/// `NOT`, `AND`, and `OR`) must be called and provided a value.
|
|
68
|
+
///
|
|
69
|
+
/// See: QueryEngineBase
|
|
70
|
+
///
|
|
71
|
+
/// See: QueryEngine
|
|
72
|
+
///
|
|
73
|
+
/// See: ModelScope
|
|
74
|
+
///
|
|
75
|
+
/// Note:
|
|
76
|
+
/// `FieldScope` is a sub-part of the `QueryEngine`, and so is generally referred to
|
|
77
|
+
/// simply as the `QueryEngine` as a whole. This is also the case for <see>QueryEngineBase</see>,
|
|
78
|
+
/// and <see>ModelScope</see>, which also make up the `QueryEngine` as sub-parts,
|
|
79
|
+
/// and so are also often referred to simply as "the query engine".
|
|
60
80
|
class FieldScope extends QueryEngineBase {
|
|
81
|
+
/// Invert the logic of the following operator.
|
|
82
|
+
///
|
|
83
|
+
/// This method does not need to be called.
|
|
84
|
+
///
|
|
85
|
+
/// Unlike `AND` and `OR` operators, this is not a permanent toggle.
|
|
86
|
+
/// As soon as a following operator is encountered, the `NOT` operation
|
|
87
|
+
/// will be "turned off". `NOT` will invert any operation, so for example
|
|
88
|
+
/// if you did a `User.where.id.NOT.EQ('test')` then this is the same as
|
|
89
|
+
/// `User.where.id.NEQ('test')`--selecting everything NOT EQUAL TO `'test'`.
|
|
90
|
+
/// `NOT` can also be used in combination with `EXISTS`, `ANY`, `ALL`, `IN`,
|
|
91
|
+
/// etc... inverting any operator following `NOT`.
|
|
92
|
+
///
|
|
93
|
+
/// Note:
|
|
94
|
+
/// `NOT` is only ever used once, and then it is toggled back off. For example,
|
|
95
|
+
/// if we did: `User.where.id.NOT.EQ('test').AND.lastName.EQ('Smith')`, then
|
|
96
|
+
/// we would have a query where `id != 'test' AND lastName = 'Smith'`. As you
|
|
97
|
+
/// can see, the `NOT` doesn't apply to the second `lastName` operator, as it
|
|
98
|
+
/// was turned off as soon as the first `EQ` operator was encountered on the `id`
|
|
99
|
+
/// field.
|
|
100
|
+
///
|
|
101
|
+
/// SyntaxType: FunctionDeclaration
|
|
61
102
|
NOT = ProxyClass.autoCall(function() {
|
|
62
|
-
this._pushOperationOntoStack({ logical: true, operator: 'NOT', queryProp: 'NOT', not: !this.
|
|
103
|
+
this._pushOperationOntoStack({ logical: true, operator: 'NOT', queryProp: 'NOT', not: !this.getOperationContext().not });
|
|
63
104
|
return this[ProxyClass.PROXY];
|
|
64
105
|
});
|
|
65
106
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
107
|
+
/// This method assists in conversion of provided values to conditions.
|
|
108
|
+
///
|
|
109
|
+
/// For example, if you provide a conditional operator (i.e. `EQ`) with
|
|
110
|
+
/// a model, i.e. `Role.where.userID.EQ(User)`, then this method will
|
|
111
|
+
/// look up the primary key field of the model, and use that to create
|
|
112
|
+
/// a table-join.
|
|
113
|
+
///
|
|
114
|
+
/// If instead you provided a model *instance* as a value, then the primary
|
|
115
|
+
/// key field of that model will be looked up, and the resulting value from
|
|
116
|
+
/// the instance will be used as the value. For example: `Role.where.userID.EQ(userInstance)`
|
|
117
|
+
/// is equivalent to `Role.where.userID.EQ(userInstance.id)`.
|
|
118
|
+
///
|
|
119
|
+
/// Aside from these two exceptions (model classes, and model instances)
|
|
120
|
+
/// this method will simply return the value it was provided.
|
|
121
|
+
///
|
|
122
|
+
/// This method is called on **every** value provided to **every** call
|
|
123
|
+
/// to a conditional operator. It can be overloaded if you want to mutate
|
|
124
|
+
/// specific values going into conditional operations.
|
|
125
|
+
///
|
|
126
|
+
/// Arguments:
|
|
127
|
+
/// value: any
|
|
128
|
+
/// The value being provided to a conditional operator.
|
|
129
|
+
///
|
|
130
|
+
/// Return: any
|
|
131
|
+
/// If `value` is a model class, then return a table-join query with that model. If
|
|
132
|
+
/// `value` is a model instance, then return the value of the model's primary key field.
|
|
133
|
+
/// Otherwise, return the `value` provided.
|
|
74
134
|
_fetchOperatorValue(_value) {
|
|
75
135
|
let value = _value;
|
|
76
136
|
if (!value)
|
|
@@ -98,35 +158,363 @@ class FieldScope extends QueryEngineBase {
|
|
|
98
158
|
return value;
|
|
99
159
|
}
|
|
100
160
|
|
|
161
|
+
/// "equals" condition.
|
|
162
|
+
///
|
|
163
|
+
/// This will check equality with the value(s) provided.
|
|
164
|
+
///
|
|
165
|
+
/// If `null`, `true`, or `false` are provided as a value,
|
|
166
|
+
/// then the underlying database driver will convert it to
|
|
167
|
+
/// the proper query. For example, given a SQL-type database
|
|
168
|
+
/// driver, these values would be generated in the query as
|
|
169
|
+
/// `"table"."column" IS NULL`, `"table"."column" IS TRUE`, or `"table"."column" IS FALSE`.
|
|
170
|
+
///
|
|
171
|
+
/// If an array is provided as the value, then this stops being an "equals",
|
|
172
|
+
/// and instead will turn into an `IN` operator (in SQL-type databases).
|
|
173
|
+
/// For example, given the following query: `User.where.id.EQ([ 1, 2, 3, 4 ])`,
|
|
174
|
+
/// the resulting SQL query would be `... WHERE "users"."id" IN(1,2,3,4)`. If a `null`,
|
|
175
|
+
/// `true`, or `false` value is encountered in the array, then the condition
|
|
176
|
+
/// will be grouped, and these values will be split out and handled separately.
|
|
177
|
+
/// For example: `User.where.id.EQ([ 1, 2, 3, null, true, false ])` would result
|
|
178
|
+
/// in the following SQL: `("users"."id" IS NULL OR "users"."id" IS TRUE OR "users"."id" IS FALSE OR "users"."id" IN(1,2,3))`.
|
|
179
|
+
/// If the array provided is empty, than an exception will be thrown. This is for safety reasons.
|
|
180
|
+
/// For example, if one were to do `User.where.id.EQ([]).destroy()`, then the result
|
|
181
|
+
/// would be `DELETE FROM USERS`... truncating your entire table. This is obviously not
|
|
182
|
+
/// at all ideal... so Mythix ORM will throw an exception if an empty array is encountered,
|
|
183
|
+
/// requiring that the user be explicit.
|
|
184
|
+
///
|
|
185
|
+
/// This condition also has two other variants, `EQ.ALL`, and `EQ.ANY` to check
|
|
186
|
+
/// equality with a sub-query. For example, a `User.where.firstName.EQ.ANY(User.where.age.GTE(18).PROJECT('firstName'))`
|
|
187
|
+
/// would generate the following SQL query: `... WHERE "users"."firstName" = ANY(SELECT "users"."firstName" FROM "users" WHERE "users"."age" >= 18)`,
|
|
188
|
+
/// checking if the users first name matches any of the adult user names in the database.
|
|
189
|
+
/// `ALL` is identical in how it functions, except it uses the `ALL` SQL operator instead of the `ANY` operator.
|
|
190
|
+
/// `ANY` will check to see if any of the resulting rows match, `ALL` (for this conditional only) will also check
|
|
191
|
+
/// if any of the resulting rows of the sub-query match. `ALL` behaves differently than `ANY` for `GT`, `GTE`, `LT`, or `LTE` operators.
|
|
192
|
+
/// For `EQ` and `NEQ` operators, `ANY` and `ALL` behave identically.
|
|
193
|
+
///
|
|
194
|
+
/// If a sub-query is provided as a value, then one of two things will happen:
|
|
195
|
+
/// 1) If the sub-query has no conditions, then a table-join operation will be the result.
|
|
196
|
+
/// 2) If the sub-query has conditions, then a sub-query will be executed using an `IN` operator.
|
|
197
|
+
/// For example, given the following query: `User.where.id.EQ(User.where.firstName.EQ('Bob').PROJECT('id'))`,
|
|
198
|
+
/// the sub-query **does have conditions** (`EQ('Bob')`), so the following SQL query that would be generated
|
|
199
|
+
/// would be `... WHERE "users"."id" IN (SELECT "users"."id" FROM "users" WHERE "users"."firstName" = 'Bob')`.
|
|
200
|
+
/// If instead a sub-query is provided as a value that **does not have conditions**, such as
|
|
201
|
+
/// `User.where.id.EQ(Role.where.userID)`, then this is specifying a table join, joining on the `"roles"` table
|
|
202
|
+
/// where `"users"."id" = "roles"."userID"`.
|
|
203
|
+
///
|
|
204
|
+
/// Note:
|
|
205
|
+
/// Mythix ORM has no `IN` operator built into the query engine by design. It is expected
|
|
206
|
+
/// that you will use `EQ` or `NEQ` in combination with an array to get `IN` and `NOT IN`
|
|
207
|
+
/// functionality.
|
|
208
|
+
///
|
|
209
|
+
/// Arguments:
|
|
210
|
+
/// value: any
|
|
211
|
+
/// The value to check against for equality. If an array is provided, then this operator will
|
|
212
|
+
/// turn into an `IN` operator instead. `null`, `true`, and `false` values are treated separately.
|
|
213
|
+
/// options?: object
|
|
214
|
+
/// Options to supply to the operation. This is not used by Mythix ORM, but is provided should
|
|
215
|
+
/// the user or underlying database driver need options.
|
|
216
|
+
///
|
|
217
|
+
/// Return: <see>ModelScope</see>
|
|
218
|
+
/// Return a <see>ModelScope</see> to allow the user to continue chaining operations on the query.
|
|
219
|
+
///
|
|
220
|
+
/// SyntaxType: FunctionDeclaration
|
|
101
221
|
EQ = wrapAnyAll.call(this, (value, options) => {
|
|
102
222
|
return addOperatorToQuery.call(this, 'EQ', 'NEQ', value, options);
|
|
103
223
|
});
|
|
104
224
|
|
|
225
|
+
/// "not equals" condition.
|
|
226
|
+
///
|
|
227
|
+
/// This will check inverse (not) equality with the value(s) provided.
|
|
228
|
+
///
|
|
229
|
+
/// If `null`, `true`, or `false` are provided as a value,
|
|
230
|
+
/// then the underlying database driver will convert it to
|
|
231
|
+
/// the proper query. For example, given a SQL-type database
|
|
232
|
+
/// driver, these values would be generated in the query as
|
|
233
|
+
/// `"table"."column" IS NOT NULL`, `"table"."column" IS NOT TRUE`, or `"table"."column" IS NOT FALSE`.
|
|
234
|
+
///
|
|
235
|
+
/// If an array is provided as the value, then this stops being a "not equals",
|
|
236
|
+
/// and instead will turn into a `NOT IN` operator (in SQL-type databases).
|
|
237
|
+
/// For example, given the following query: `User.where.id.NEQ([ 1, 2, 3, 4 ])`,
|
|
238
|
+
/// the resulting SQL query would be `... WHERE "users"."id" NOT IN(1,2,3,4)`. If a `null`,
|
|
239
|
+
/// `true`, or `false` value is encountered in the array, then the condition
|
|
240
|
+
/// will be grouped, and these values will be split out and handled separately.
|
|
241
|
+
/// For example: `User.where.id.NEQ([ 1, 2, 3, null, true, false ])` would result
|
|
242
|
+
/// in the following SQL: `("users"."id" IS NOT NULL AND "users"."id" IS NOT TRUE AND "users"."id" IS NOT FALSE AND "users"."id" NOT IN(1,2,3))`.
|
|
243
|
+
/// If the array provided is empty, than an exception will be thrown. This is for safety reasons.
|
|
244
|
+
/// For example, if one were to do `User.where.id.NEQ([]).destroy()`, then the result
|
|
245
|
+
/// would be `DELETE FROM USERS`... truncating your entire table. This is obviously not
|
|
246
|
+
/// at all ideal... so Mythix ORM will throw an exception if an empty array is encountered,
|
|
247
|
+
/// requiring that the user be explicit.
|
|
248
|
+
///
|
|
249
|
+
/// This condition also has two other variants, `NEQ.ALL`, and `NEQ.ANY` to check
|
|
250
|
+
/// equality with a sub-query. For example, a `User.where.firstName.NEQ.ANY(User.where.age.GTE(18).PROJECT('firstName'))`
|
|
251
|
+
/// would generate the following SQL query: `... WHERE "users"."firstName" != ANY(SELECT "users"."firstName" FROM "users" WHERE "users"."age" >= 18)`,
|
|
252
|
+
/// checking if the users first name does not match any of the adult user names in the database.
|
|
253
|
+
/// `ALL` is identical in how it functions, except it uses the `ALL` SQL operator instead of the `ANY` operator.
|
|
254
|
+
/// `ANY` will check to see if any of the resulting rows do not match, `ALL` (for this conditional only) will also check
|
|
255
|
+
/// if any of the resulting rows of the sub-query do not match. `ALL` behaves differently than `ANY` for `GT`, `GTE`, `LT`, or `LTE` operators.
|
|
256
|
+
/// For `EQ` and `NEQ` operators, `ANY` and `ALL` behave identically.
|
|
257
|
+
///
|
|
258
|
+
/// If a sub-query is provided as a value, then one of two things will happen:
|
|
259
|
+
/// 1) If the sub-query has no conditions, then a table-join operation will be the result.
|
|
260
|
+
/// 2) If the sub-query has conditions, then a sub-query will be executed using an `IN` operator.
|
|
261
|
+
/// For example, given the following query: `User.where.id.NEQ(User.where.firstName.EQ('Bob').PROJECT('id'))`,
|
|
262
|
+
/// the sub-query **does have conditions** (`EQ('Bob')`), so the following SQL query that would be generated
|
|
263
|
+
/// would be `... WHERE "users"."id" NOT IN (SELECT "users"."id" FROM "users" WHERE "users"."firstName" = 'Bob')`.
|
|
264
|
+
/// If instead a sub-query is provided as a value that **does not have conditions**, such as
|
|
265
|
+
/// `User.where.id.NEQ(Role.where.userID)`, then this is specifying a table join, joining on the `"roles"` table
|
|
266
|
+
/// where `"users"."id" != "roles"."userID"`.
|
|
267
|
+
///
|
|
268
|
+
/// Note:
|
|
269
|
+
/// Mythix ORM has no `IN` operator built into the query engine by design. It is expected
|
|
270
|
+
/// that you will use `EQ` or `NEQ` in combination with an array to get `IN` and `NOT IN`
|
|
271
|
+
/// functionality.
|
|
272
|
+
///
|
|
273
|
+
/// Arguments:
|
|
274
|
+
/// value: any
|
|
275
|
+
/// The value to check against for inverse (not) equality. If an array is provided, then this operator will
|
|
276
|
+
/// turn into an `NOT IN` operator instead. `null`, `true`, and `false` values are treated separately.
|
|
277
|
+
/// options?: object
|
|
278
|
+
/// Options to supply to the operation. This is not used by Mythix ORM, but is provided should
|
|
279
|
+
/// the user or underlying database driver need options.
|
|
280
|
+
///
|
|
281
|
+
/// Return: <see>ModelScope</see>
|
|
282
|
+
/// Return a <see>ModelScope</see> to allow the user to continue chaining operations on the query.
|
|
283
|
+
///
|
|
284
|
+
/// SyntaxType: FunctionDeclaration
|
|
105
285
|
NEQ = wrapAnyAll.call(this, (value, options) => {
|
|
106
286
|
return addOperatorToQuery.call(this, 'NEQ', 'EQ', value, options);
|
|
107
287
|
});
|
|
108
288
|
|
|
289
|
+
/// "greater than" condition.
|
|
290
|
+
///
|
|
291
|
+
/// This will check if values in the database are greater than the value provided.
|
|
292
|
+
///
|
|
293
|
+
/// This condition also has two other variants, `GT.ALL`, and `GT.ANY` to compare
|
|
294
|
+
/// with a sub-query. For example, a `User.where.age.GT.ANY(User.where.age.GTE(18).PROJECT('age'))`
|
|
295
|
+
/// would generate the following SQL query: `... WHERE "users"."age" > ANY(SELECT "users"."age" FROM "users" WHERE "users"."age" >= 18)`,
|
|
296
|
+
/// checking if the users age is greater than any of the adult aged users in the database.
|
|
297
|
+
/// `ALL` is identical in how it functions, except it uses the `ALL` SQL operator instead of the `ANY` operator.
|
|
298
|
+
/// `ANY` will check to see if any of the resulting rows of the sub-query match the condition. `ALL` will compare all returned rows
|
|
299
|
+
/// from the sub-query, and check to see if the value provided is greater than the *largest value* across all
|
|
300
|
+
/// rows of the sub-query.
|
|
301
|
+
///
|
|
302
|
+
/// If a sub-query is provided as a value, then one of two things will happen:
|
|
303
|
+
/// 1) If the sub-query has no conditions, then a table-join operation will be the result.
|
|
304
|
+
/// 2) If the sub-query has conditions, then any exception will be thrown.
|
|
305
|
+
/// For example, if a sub-query is provided as a value that **does not have conditions**, such as
|
|
306
|
+
/// `User.where.createdAt.GT(Role.where.createdAt)`, then this is specifying a table join, joining on the `"roles"` table
|
|
307
|
+
/// where `"users"."createdAt" > "roles"."createdAt"`.
|
|
308
|
+
///
|
|
309
|
+
/// Note:
|
|
310
|
+
/// If you want to compare "greater than" on a sub-query, use `GT.ANY`, or `GT.ALL`.
|
|
311
|
+
///
|
|
312
|
+
/// Arguments:
|
|
313
|
+
/// value: any
|
|
314
|
+
/// The value to compare against for a "greater than" operation. Providing an array, a `null`, a `true`, or
|
|
315
|
+
/// a `false` value will generally throw an exception... unless this means something to the underlying database driver.
|
|
316
|
+
/// options?: object
|
|
317
|
+
/// Options to supply to the operation. This is not used by Mythix ORM, but is provided should
|
|
318
|
+
/// the user or underlying database driver need options.
|
|
319
|
+
///
|
|
320
|
+
/// Return: <see>ModelScope</see>
|
|
321
|
+
/// Return a <see>ModelScope</see> to allow the user to continue chaining operations on the query.
|
|
322
|
+
///
|
|
323
|
+
/// SyntaxType: FunctionDeclaration
|
|
109
324
|
GT = wrapAnyAll.call(this, (value, options) => {
|
|
110
325
|
return addOperatorToQuery.call(this, 'GT', 'LTE', value, options);
|
|
111
326
|
});
|
|
112
327
|
|
|
328
|
+
/// "greater than or equals to" condition.
|
|
329
|
+
///
|
|
330
|
+
/// This will check if values in the database are greater than or equal to the value provided.
|
|
331
|
+
///
|
|
332
|
+
/// This condition also has two other variants, `GTE.ALL`, and `GTE.ANY` to compare
|
|
333
|
+
/// with a sub-query. For example, a `User.where.age.GTE.ANY(User.where.age.GTE(18).PROJECT('age'))`
|
|
334
|
+
/// would generate the following SQL query: `... WHERE "users"."age" >= ANY(SELECT "users"."age" FROM "users" WHERE "users"."age" >= 18)`,
|
|
335
|
+
/// checking if the users age is greater than or equal to any of the adult aged users in the database.
|
|
336
|
+
/// `ALL` is identical in how it functions, except it uses the `ALL` SQL operator instead of the `ANY` operator.
|
|
337
|
+
/// `ANY` will check to see if any of the resulting rows of the sub-query match the condition. `ALL` will compare all returned rows
|
|
338
|
+
/// from the sub-query, and check to see if the value provided is greater than or equal to the *largest value* across all
|
|
339
|
+
/// rows of the sub-query.
|
|
340
|
+
///
|
|
341
|
+
/// If a sub-query is provided as a value, then one of two things will happen:
|
|
342
|
+
/// 1) If the sub-query has no conditions, then a table-join operation will be the result.
|
|
343
|
+
/// 2) If the sub-query has conditions, then any exception will be thrown.
|
|
344
|
+
/// For example, if a sub-query is provided as a value that **does not have conditions**, such as
|
|
345
|
+
/// `User.where.createdAt.GTE(Role.where.createdAt)`, then this is specifying a table join, joining on the `"roles"` table
|
|
346
|
+
/// where `"users"."createdAt" >= "roles"."createdAt"`.
|
|
347
|
+
///
|
|
348
|
+
/// Note:
|
|
349
|
+
/// If you want to compare "greater than or equal to" on a sub-query, use `GTE.ANY`, or `GTE.ALL`.
|
|
350
|
+
///
|
|
351
|
+
/// Arguments:
|
|
352
|
+
/// value: any
|
|
353
|
+
/// The value to compare against for a "greater than or equal to" operation. Providing an array, a `null`, a `true`, or
|
|
354
|
+
/// a `false` value will generally throw an exception... unless this means something to the underlying database driver.
|
|
355
|
+
/// options?: object
|
|
356
|
+
/// Options to supply to the operation. This is not used by Mythix ORM, but is provided should
|
|
357
|
+
/// the user or underlying database driver need options.
|
|
358
|
+
///
|
|
359
|
+
/// Return: <see>ModelScope</see>
|
|
360
|
+
/// Return a <see>ModelScope</see> to allow the user to continue chaining operations on the query.
|
|
361
|
+
///
|
|
362
|
+
/// SyntaxType: FunctionDeclaration
|
|
113
363
|
GTE = wrapAnyAll.call(this, (value, options) => {
|
|
114
364
|
return addOperatorToQuery.call(this, 'GTE', 'LT', value, options);
|
|
115
365
|
});
|
|
116
366
|
|
|
367
|
+
/// "less than" condition.
|
|
368
|
+
///
|
|
369
|
+
/// This will check if values in the database are less than the value provided.
|
|
370
|
+
///
|
|
371
|
+
/// This condition also has two other variants, `LT.ALL`, and `LT.ANY` to compare
|
|
372
|
+
/// with a sub-query. For example, a `User.where.age.LT.ANY(User.where.age.GTE(18).PROJECT('age'))`
|
|
373
|
+
/// would generate the following SQL query: `... WHERE "users"."age" < ANY(SELECT "users"."age" FROM "users" WHERE "users"."age" >= 18)`,
|
|
374
|
+
/// checking if the users age is less than any of the adult aged users in the database.
|
|
375
|
+
/// `ALL` is identical in how it functions, except it uses the `ALL` SQL operator instead of the `ANY` operator.
|
|
376
|
+
/// `ANY` will check to see if any of the resulting rows of the sub-query match the condition. `ALL` will compare all returned rows
|
|
377
|
+
/// from the sub-query, and check to see if the value provided is less than the *smallest value* across all
|
|
378
|
+
/// rows of the sub-query.
|
|
379
|
+
///
|
|
380
|
+
/// If a sub-query is provided as a value, then one of two things will happen:
|
|
381
|
+
/// 1) If the sub-query has no conditions, then a table-join operation will be the result.
|
|
382
|
+
/// 2) If the sub-query has conditions, then any exception will be thrown.
|
|
383
|
+
/// For example, if a sub-query is provided as a value that **does not have conditions**, such as
|
|
384
|
+
/// `User.where.createdAt.LT(Role.where.createdAt)`, then this is specifying a table join, joining on the `"roles"` table
|
|
385
|
+
/// where `"users"."createdAt" < "roles"."createdAt"`.
|
|
386
|
+
///
|
|
387
|
+
/// Note:
|
|
388
|
+
/// If you want to compare "less than" on a sub-query, use `LT.ANY`, or `LT.ALL`.
|
|
389
|
+
///
|
|
390
|
+
/// Arguments:
|
|
391
|
+
/// value: any
|
|
392
|
+
/// The value to compare against for a "less than" operation. Providing an array, a `null`, a `true`, or
|
|
393
|
+
/// a `false` value will generally throw an exception... unless this means something to the underlying database driver.
|
|
394
|
+
/// options?: object
|
|
395
|
+
/// Options to supply to the operation. This is not used by Mythix ORM, but is provided should
|
|
396
|
+
/// the user or underlying database driver need options.
|
|
397
|
+
///
|
|
398
|
+
/// Return: <see>ModelScope</see>
|
|
399
|
+
/// Return a <see>ModelScope</see> to allow the user to continue chaining operations on the query.
|
|
400
|
+
///
|
|
401
|
+
/// SyntaxType: FunctionDeclaration
|
|
117
402
|
LT = wrapAnyAll.call(this, (value, options) => {
|
|
118
403
|
return addOperatorToQuery.call(this, 'LT', 'GTE', value, options);
|
|
119
404
|
});
|
|
120
405
|
|
|
406
|
+
/// "less than or equals to" condition.
|
|
407
|
+
///
|
|
408
|
+
/// This will check if values in the database are less than or equal to the value provided.
|
|
409
|
+
///
|
|
410
|
+
/// This condition also has two other variants, `LTE.ALL`, and `LTE.ANY` to compare
|
|
411
|
+
/// with a sub-query. For example, a `User.where.age.LTE.ANY(User.where.age.GTE(18).PROJECT('age'))`
|
|
412
|
+
/// would generate the following SQL query: `... WHERE "users"."age" <= ANY(SELECT "users"."age" FROM "users" WHERE "users"."age" >= 18)`,
|
|
413
|
+
/// checking if the users age is less than or equal to any of the adult aged users in the database.
|
|
414
|
+
/// `ALL` is identical in how it functions, except it uses the `ALL` SQL operator instead of the `ANY` operator.
|
|
415
|
+
/// `ANY` will check to see if any of the resulting rows of the sub-query match the condition. `ALL` will compare all returned rows
|
|
416
|
+
/// from the sub-query, and check to see if the value provided is less than or equal to the *smallest value* across all
|
|
417
|
+
/// rows of the sub-query.
|
|
418
|
+
///
|
|
419
|
+
/// If a sub-query is provided as a value, then one of two things will happen:
|
|
420
|
+
/// 1) If the sub-query has no conditions, then a table-join operation will be the result.
|
|
421
|
+
/// 2) If the sub-query has conditions, then any exception will be thrown.
|
|
422
|
+
/// For example, if a sub-query is provided as a value that **does not have conditions**, such as
|
|
423
|
+
/// `User.where.createdAt.LTE(Role.where.createdAt)`, then this is specifying a table join, joining on the `"roles"` table
|
|
424
|
+
/// where `"users"."createdAt" <= "roles"."createdAt"`.
|
|
425
|
+
///
|
|
426
|
+
/// Note:
|
|
427
|
+
/// If you want to compare "less than or equal to" on a sub-query, use `LTE.ANY`, or `LTE.ALL`.
|
|
428
|
+
///
|
|
429
|
+
/// Arguments:
|
|
430
|
+
/// value: any
|
|
431
|
+
/// The value to compare against for a "less than or equal to" operation. Providing an array, a `null`, a `true`, or
|
|
432
|
+
/// a `false` value will generally throw an exception... unless this means something to the underlying database driver.
|
|
433
|
+
/// options?: object
|
|
434
|
+
/// Options to supply to the operation. This is not used by Mythix ORM, but is provided should
|
|
435
|
+
/// the user or underlying database driver need options.
|
|
436
|
+
///
|
|
437
|
+
/// Return: <see>ModelScope</see>
|
|
438
|
+
/// Return a <see>ModelScope</see> to allow the user to continue chaining operations on the query.
|
|
439
|
+
///
|
|
440
|
+
/// SyntaxType: FunctionDeclaration
|
|
121
441
|
LTE = wrapAnyAll.call(this, (value, options) => {
|
|
122
442
|
return addOperatorToQuery.call(this, 'LTE', 'GT', value, options);
|
|
123
443
|
});
|
|
124
444
|
|
|
445
|
+
/// A "like" wildcard condition.
|
|
446
|
+
///
|
|
447
|
+
/// This will check if values in the database are "like" the value provided, using wildcards and pattern matching.
|
|
448
|
+
///
|
|
449
|
+
/// The `LIKE` operator in Mythix ORM follows PostgreSQL design, using `%` for a "zero or more" match, and an `_`
|
|
450
|
+
/// for a "single character" match. All database engines are required to follow this pattern, even if the underlying
|
|
451
|
+
/// database uses a different syntax. If that is the case, then the underlying database driver is required to behave
|
|
452
|
+
/// correctly by translating the value to the input it expects. In short, the interface here in Mythix ORM is unified,
|
|
453
|
+
/// and it is up to the underlying database driver to carry out the operation correctly.
|
|
454
|
+
///
|
|
455
|
+
/// The "escape character" for this operation is always set to a backslash `\` for all database drivers. So if you
|
|
456
|
+
/// need to match against a literal `%` or `_` character, you would do so by using the escape character, i.e. `LIKE('100\\%')`.
|
|
457
|
+
/// Two escape characters are needed, because Javascript also interprets `\` as an escape character, so a double backslash
|
|
458
|
+
/// `'\\'` will "escape" to a single backslash in Javascript.
|
|
459
|
+
///
|
|
460
|
+
/// For all databases, the Mythix ORM `LIKE` is case-insensitive. For databases like PostgreSQL, a standard Mythix ORM `LIKE` operation
|
|
461
|
+
/// is actually carried out as an `ILIKE` operation to follow this convention of case-insensitivity. There is
|
|
462
|
+
/// a boolean `options` that can be supplied to this operator, named `caseSensitive`. If supplied, for example
|
|
463
|
+
/// `LIKE('%something%', { caseSensitive: true })`, then the operation will be case-sensitive... but only if the underlying database
|
|
464
|
+
/// supports case-sensitivity for `LIKE`... and not all databases do. `LIKE` operations in most SQL databases are case-insensitive by default.
|
|
465
|
+
///
|
|
466
|
+
/// Arguments:
|
|
467
|
+
/// value: any
|
|
468
|
+
/// The value to compare against for a "LIKE" operation. Providing any non-string value will
|
|
469
|
+
/// likely throw an exception... unless the underlying database driver supports other pattern
|
|
470
|
+
/// formats (i.e. `RegExp` is supported in Mongo).
|
|
471
|
+
/// options?: object
|
|
472
|
+
/// Options to supply to the operation. The only option supported for this operator is the boolean
|
|
473
|
+
/// option `caseSensitive`. If `true`, then the database driver will attempt to carry out a case-sensitive
|
|
474
|
+
/// operation. If not supported by the database, then the database driver should throw an exception.
|
|
475
|
+
/// If a `RegExp` value is used (for databases that support it), then this option will be ignored.
|
|
476
|
+
///
|
|
477
|
+
/// Return: <see>ModelScope</see>
|
|
478
|
+
/// Return a <see>ModelScope</see> to allow the user to continue chaining operations on the query.
|
|
125
479
|
LIKE(value, options) {
|
|
126
480
|
let caseSensitive = ((options && options.caseSensitive) === true);
|
|
127
481
|
return addOperatorToQuery.call(this, 'LIKE', 'NOT_LIKE', value, { caseSensitive });
|
|
128
482
|
}
|
|
129
483
|
|
|
484
|
+
/// A "not like" wildcard condition.
|
|
485
|
+
///
|
|
486
|
+
/// This will check if values in the database are "not like" the value provided, using wildcards and pattern matching.
|
|
487
|
+
///
|
|
488
|
+
/// The `LIKE` operator in Mythix ORM follows PostgreSQL design, using `%` for a "zero or more" match, and an `_`
|
|
489
|
+
/// for a "single character" match. All database engines are required to follow this pattern, even if the underlying
|
|
490
|
+
/// database uses a different syntax. If that is the case, then the underlying database driver is required to behave
|
|
491
|
+
/// correctly by translating the value to the input it expects. In short, the interface here in Mythix ORM is unified,
|
|
492
|
+
/// and it is up to the underlying database driver to carry out the operation correctly.
|
|
493
|
+
///
|
|
494
|
+
/// The "escape character" for this operation is always set to a backslash `\` for all database drivers. So if you
|
|
495
|
+
/// need to match against a literal `%` or `_` character, you would do so by using the escape character, i.e. `NOT LIKE('100\\%')`.
|
|
496
|
+
/// Two escape characters are needed, because Javascript also interprets `\` as an escape character, so a double backslash
|
|
497
|
+
/// `'\\'` will "escape" to a single backslash in Javascript.
|
|
498
|
+
///
|
|
499
|
+
/// For all databases, the Mythix ORM `NOT_LIKE` is case-insensitive. For databases like PostgreSQL, a standard Mythix ORM `NOT_LIKE` operation
|
|
500
|
+
/// is actually carried out as an `NOT ILIKE` operation to follow this convention of case-insensitivity. There is
|
|
501
|
+
/// a boolean `options` that can be supplied to this operator, named `caseSensitive`. If supplied, for example
|
|
502
|
+
/// `NOT_LIKE('%something%', { caseSensitive: true })`, then the operation will be case-sensitive... but only if the underlying database
|
|
503
|
+
/// supports case-sensitivity for `NOT LIKE`... and not all databases do. `NOT LIKE` operations in most SQL databases are case-insensitive by default.
|
|
504
|
+
///
|
|
505
|
+
/// Arguments:
|
|
506
|
+
/// value: any
|
|
507
|
+
/// The value to compare against for a "NOT LIKE" operation. Providing any non-string value will
|
|
508
|
+
/// likely throw an exception... unless the underlying database driver supports other pattern
|
|
509
|
+
/// formats (i.e. `RegExp` is supported in Mongo).
|
|
510
|
+
/// options?: object
|
|
511
|
+
/// Options to supply to the operation. The only option supported for this operator is the boolean
|
|
512
|
+
/// option `caseSensitive`. If `true`, then the database driver will attempt to carry out a case-sensitive
|
|
513
|
+
/// operation. If not supported by the database, then the database driver should throw an exception.
|
|
514
|
+
/// If a `RegExp` value is used (for databases that support it), then this option will be ignored.
|
|
515
|
+
///
|
|
516
|
+
/// Return: <see>ModelScope</see>
|
|
517
|
+
/// Return a <see>ModelScope</see> to allow the user to continue chaining operations on the query.
|
|
130
518
|
NOT_LIKE(value, options) {
|
|
131
519
|
let caseSensitive = ((options && options.caseSensitive) === true);
|
|
132
520
|
return addOperatorToQuery.call(this, 'NOT_LIKE', 'LIKE', value, { caseSensitive });
|
|
@@ -136,6 +524,10 @@ class FieldScope extends QueryEngineBase {
|
|
|
136
524
|
let lowerScope = this._fetchScope('model');
|
|
137
525
|
return lowerScope[prop];
|
|
138
526
|
}
|
|
527
|
+
|
|
528
|
+
toString(...args) {
|
|
529
|
+
return this.getOperationContext().queryEngineScope.toString(...args);
|
|
530
|
+
}
|
|
139
531
|
}
|
|
140
532
|
|
|
141
533
|
module.exports = FieldScope;
|