mythix-orm 1.11.6 → 1.11.7
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 +147 -9
- 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/field.js +1 -1
- package/lib/model.js +54 -2
- 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/package.json +1 -1
|
@@ -3,9 +3,46 @@
|
|
|
3
3
|
const ModelUtils = require('../../utils/model-utils');
|
|
4
4
|
const Field = require('../../field');
|
|
5
5
|
|
|
6
|
+
/// `LiteralBase` is the class all other literals inherit from.
|
|
7
|
+
///
|
|
8
|
+
/// Literals are special types in Mythix ORM that are used to
|
|
9
|
+
/// define "literal values" for the underlying database.
|
|
10
|
+
///
|
|
11
|
+
/// This literal--being the top most ancestor of all other literals--
|
|
12
|
+
/// defines common behavior for literals.
|
|
13
|
+
///
|
|
14
|
+
/// See: AverageLiteral
|
|
15
|
+
///
|
|
16
|
+
/// See: CountLiteral
|
|
17
|
+
///
|
|
18
|
+
/// See: DistinctLiteral
|
|
19
|
+
///
|
|
20
|
+
/// See: FieldLiteral
|
|
21
|
+
///
|
|
22
|
+
/// See: Literal
|
|
23
|
+
///
|
|
24
|
+
/// See: MaxLiteral
|
|
25
|
+
///
|
|
26
|
+
/// See: MinLiteral
|
|
27
|
+
///
|
|
28
|
+
/// See: SumLiteral
|
|
29
|
+
///
|
|
6
30
|
class LiteralBase {
|
|
31
|
+
/// Assist with type-checking
|
|
7
32
|
static _isMythixLiteral = true;
|
|
8
33
|
|
|
34
|
+
/// Use this method to check if a class
|
|
35
|
+
/// is a Mythix ORM Literal. It will return
|
|
36
|
+
/// `true` if the provided value is a class
|
|
37
|
+
/// that inherits from <see>LiteralBase</see>, or
|
|
38
|
+
/// if the provided value has an attribute
|
|
39
|
+
/// named `_isMythixLiteral` that is truthy.
|
|
40
|
+
///
|
|
41
|
+
/// Return: boolean
|
|
42
|
+
///
|
|
43
|
+
/// Arguments:
|
|
44
|
+
/// value: Function
|
|
45
|
+
/// Value to check.
|
|
9
46
|
static isLiteralClass(value) {
|
|
10
47
|
if (!value)
|
|
11
48
|
return false;
|
|
@@ -19,6 +56,25 @@ class LiteralBase {
|
|
|
19
56
|
return false;
|
|
20
57
|
}
|
|
21
58
|
|
|
59
|
+
/// Check to see if the provided value is
|
|
60
|
+
/// an *instance* of a Mythix ORM <see>LiteralBase</see>.
|
|
61
|
+
/// Unlike <see>LiteralBase.static isLiteralClass</see>, which
|
|
62
|
+
/// checks if a *class* is a <see>LiteralBase</see>, this will check
|
|
63
|
+
/// to see if an *instance* is an instance of a
|
|
64
|
+
/// Mythix ORM <see>LiteralBase</see>. It will return
|
|
65
|
+
/// `true` if the provided value is an `instanceof`
|
|
66
|
+
/// <see>LiteralBase</see>, or if the value's `constructor`
|
|
67
|
+
/// property has a truthy `_isMythixLiteral` property
|
|
68
|
+
/// (`value.constructor._isMythixLiteral`)
|
|
69
|
+
///
|
|
70
|
+
/// Note:
|
|
71
|
+
/// This method is also a matching instance method.
|
|
72
|
+
///
|
|
73
|
+
/// Return: boolean
|
|
74
|
+
///
|
|
75
|
+
/// Arguments:
|
|
76
|
+
/// value: any
|
|
77
|
+
/// Value to check
|
|
22
78
|
static isLiteral(value) {
|
|
23
79
|
if (!value)
|
|
24
80
|
return false;
|
|
@@ -39,10 +95,49 @@ class LiteralBase {
|
|
|
39
95
|
return this.constructor.isLiteral(value);
|
|
40
96
|
}
|
|
41
97
|
|
|
98
|
+
/// Check to see if the provided value is
|
|
99
|
+
/// an *instance* of *`this`* literal type.
|
|
100
|
+
/// Unlike <see>LiteralBase.static isLiteral</see>, which
|
|
101
|
+
/// checks if an *instance* is any <see>LiteralBase</see>
|
|
102
|
+
/// type, this will check if the provided literal is
|
|
103
|
+
/// exactly *`this`* type of literal. It will return
|
|
104
|
+
/// `true` if the provided value is an `instanceof`
|
|
105
|
+
/// `this` literal class, or if the value's `constructor`
|
|
106
|
+
/// property has a name that is equal to `this` literal's
|
|
107
|
+
/// class name.
|
|
108
|
+
/// (`value.constructor.name === this.name`)
|
|
109
|
+
///
|
|
110
|
+
/// Example:
|
|
111
|
+
/// console.log(CountLiteral.isLiteralType(new AverageLiteral('User:age')))
|
|
112
|
+
/// // false
|
|
113
|
+
///
|
|
114
|
+
/// console.log(CountLiteral.isLiteralType(new CountLiteral('*')))
|
|
115
|
+
/// // true
|
|
116
|
+
///
|
|
117
|
+
/// Note:
|
|
118
|
+
/// This method is also a matching instance method.
|
|
119
|
+
///
|
|
120
|
+
/// Return: boolean
|
|
121
|
+
///
|
|
122
|
+
/// Arguments:
|
|
123
|
+
/// value: any
|
|
124
|
+
/// Value to check
|
|
42
125
|
static isLiteralType(value) {
|
|
126
|
+
if (value && value instanceof this)
|
|
127
|
+
return true;
|
|
128
|
+
|
|
43
129
|
return (this.isLiteral(value) && value.constructor && value.constructor.name === this.name);
|
|
44
130
|
}
|
|
45
131
|
|
|
132
|
+
/// Used internally in the engine to know if
|
|
133
|
+
/// a literal being operated upon is an aggregating
|
|
134
|
+
/// literal or not.
|
|
135
|
+
///
|
|
136
|
+
/// Note:
|
|
137
|
+
/// This method is also a matching instance method.
|
|
138
|
+
///
|
|
139
|
+
/// Return: boolean
|
|
140
|
+
/// Return `true`, informing the caller that this literal is used for aggregate operations.
|
|
46
141
|
static isAggregate() {
|
|
47
142
|
return false;
|
|
48
143
|
}
|
|
@@ -51,6 +146,13 @@ class LiteralBase {
|
|
|
51
146
|
return this.constructor.isAggregate();
|
|
52
147
|
}
|
|
53
148
|
|
|
149
|
+
/// Construct a new literal.
|
|
150
|
+
///
|
|
151
|
+
/// Arguments:
|
|
152
|
+
/// literal: string
|
|
153
|
+
/// The literal value you wish to insert into the query.
|
|
154
|
+
/// options?: object
|
|
155
|
+
/// Literal, connection, and operation specific options.
|
|
54
156
|
constructor(literal, options) {
|
|
55
157
|
Object.defineProperties(this, {
|
|
56
158
|
'literal': {
|
|
@@ -68,6 +170,17 @@ class LiteralBase {
|
|
|
68
170
|
});
|
|
69
171
|
}
|
|
70
172
|
|
|
173
|
+
/// Take the value provided as either a <see>Field</see>
|
|
174
|
+
/// instance, or a fully qualified field name, then return the field
|
|
175
|
+
/// definition for it.
|
|
176
|
+
///
|
|
177
|
+
/// If a literal is provided instead, then simply return the literal
|
|
178
|
+
/// without modifying it.
|
|
179
|
+
///
|
|
180
|
+
/// Note:
|
|
181
|
+
/// This is the inverse operation of <see>LiteralBase.definitionToField</see>
|
|
182
|
+
///
|
|
183
|
+
/// See: ModelUtils.parseQualifiedName
|
|
71
184
|
fullyQualifiedNameToDefinition(fullyQualifiedName) {
|
|
72
185
|
if (LiteralBase.isLiteral(fullyQualifiedName))
|
|
73
186
|
return fullyQualifiedName;
|
|
@@ -91,11 +204,21 @@ class LiteralBase {
|
|
|
91
204
|
return definition;
|
|
92
205
|
}
|
|
93
206
|
|
|
207
|
+
/// Take a field definition and return the actual <see>Field</see>
|
|
208
|
+
/// instance for it.
|
|
209
|
+
///
|
|
210
|
+
/// If a literal is provided... or a value that isn't understood
|
|
211
|
+
/// (such as a string), then it is simply returned unmodified.
|
|
212
|
+
///
|
|
213
|
+
/// Note:
|
|
214
|
+
/// This is the inverse operation of <see>LiteralBase.fullyQualifiedNameToDefinition</see>
|
|
215
|
+
///
|
|
216
|
+
/// See: ModelUtils.parseQualifiedName
|
|
94
217
|
definitionToField(connection, definition) {
|
|
95
218
|
if (LiteralBase.isLiteral(definition))
|
|
96
219
|
return definition;
|
|
97
220
|
|
|
98
|
-
if (!definition.fieldNames)
|
|
221
|
+
if (!definition || !definition.fieldNames)
|
|
99
222
|
return definition;
|
|
100
223
|
|
|
101
224
|
let field = connection.getField(definition.fieldNames[0], definition.modelName);
|
|
@@ -117,10 +240,22 @@ class LiteralBase {
|
|
|
117
240
|
return field;
|
|
118
241
|
}
|
|
119
242
|
|
|
243
|
+
/// Convert the literal value provided to the `constructor`
|
|
244
|
+
/// to a string.
|
|
245
|
+
///
|
|
246
|
+
/// Return: string
|
|
247
|
+
/// The value provided to the `constructor` as a string.
|
|
120
248
|
toString() {
|
|
121
|
-
|
|
249
|
+
if (!this.literal)
|
|
250
|
+
return ('' + this.literal);
|
|
251
|
+
|
|
252
|
+
return this.literal.toString();
|
|
122
253
|
}
|
|
123
254
|
|
|
255
|
+
/// Return the raw value provided to the `constructor`.
|
|
256
|
+
///
|
|
257
|
+
/// Return: any
|
|
258
|
+
/// The raw value provided to the `constructor`.
|
|
124
259
|
valueOf() {
|
|
125
260
|
return this.literal;
|
|
126
261
|
}
|
|
@@ -3,11 +3,42 @@
|
|
|
3
3
|
const Nife = require('nife');
|
|
4
4
|
const LiteralBase = require('./literal-base');
|
|
5
5
|
|
|
6
|
+
/// LiteralFieldBase is the ancestor that all
|
|
7
|
+
/// literals dealing with fields inherit from
|
|
8
|
+
/// (which is nearly all literals). Its primary
|
|
9
|
+
/// function is to enforce being provided fields
|
|
10
|
+
/// when the child literal requires them, and to
|
|
11
|
+
/// fetch those fields when the engine needs them.
|
|
12
|
+
///
|
|
13
|
+
/// See: LiteralBase
|
|
14
|
+
///
|
|
15
|
+
/// See: Literal
|
|
6
16
|
class LiteralFieldBase extends LiteralBase {
|
|
17
|
+
/// This is provided so each child class
|
|
18
|
+
/// can overload it. By default it returns
|
|
19
|
+
/// `true`. However, any literal that inherits
|
|
20
|
+
/// from this literal may override it to instead
|
|
21
|
+
/// return `false`. The <see>CountLiteral</see>
|
|
22
|
+
/// does exactly this for example.
|
|
23
|
+
///
|
|
24
|
+
/// Return: boolean
|
|
25
|
+
/// Returns `true` by default, children can change the return value.
|
|
7
26
|
static isFieldRequired() {
|
|
8
27
|
return true;
|
|
9
28
|
}
|
|
10
29
|
|
|
30
|
+
/// Construct a new field-based literal. The
|
|
31
|
+
/// first argument should be a fully qualified field name,
|
|
32
|
+
/// a <see>Field</see> instance, or another literal.
|
|
33
|
+
///
|
|
34
|
+
/// Arguments:
|
|
35
|
+
/// field: string | <see>Field</see> | <see>LiteralBase</see>
|
|
36
|
+
/// The "field" that this literal is representing. If this is a
|
|
37
|
+
/// string, then it is expected to be a fully qualified field name.
|
|
38
|
+
/// If instead this is a <see>Field</see>, then that defines the
|
|
39
|
+
/// field. Finally, this can also be another literal.
|
|
40
|
+
/// options?: object
|
|
41
|
+
/// Connection, Literal, and operation specific options for this literal.
|
|
11
42
|
constructor(fullyQualifiedName, options) {
|
|
12
43
|
super(undefined, options);
|
|
13
44
|
|
|
@@ -35,6 +66,15 @@ class LiteralFieldBase extends LiteralBase {
|
|
|
35
66
|
});
|
|
36
67
|
}
|
|
37
68
|
|
|
69
|
+
/// Get the fully qualified field name of the field
|
|
70
|
+
/// that this literal is representing.
|
|
71
|
+
///
|
|
72
|
+
/// Return: string
|
|
73
|
+
/// The fully qualified field name of the field this literal
|
|
74
|
+
/// is representing. This would be the same field provided to the
|
|
75
|
+
/// `constructor` when the literal was first created.
|
|
76
|
+
///
|
|
77
|
+
/// See: ModelUtils.parseQualifiedName
|
|
38
78
|
getFullyQualifiedFieldName() {
|
|
39
79
|
let definition = this.definition || {};
|
|
40
80
|
if (!definition.modelName || Nife.isEmpty(definition.fieldNames))
|
|
@@ -43,6 +83,12 @@ class LiteralFieldBase extends LiteralBase {
|
|
|
43
83
|
return `${definition.modelName}:${definition.fieldNames[0]}`;
|
|
44
84
|
}
|
|
45
85
|
|
|
86
|
+
/// Get the field represented by this literal.
|
|
87
|
+
///
|
|
88
|
+
/// Return: <see>Field</see>
|
|
89
|
+
/// The field that this literal is representing. This will
|
|
90
|
+
/// be the field given to the `constructor` when the literal
|
|
91
|
+
/// was first created.
|
|
46
92
|
getField(connection) {
|
|
47
93
|
if (!this.definition)
|
|
48
94
|
return;
|
|
@@ -50,6 +96,10 @@ class LiteralFieldBase extends LiteralBase {
|
|
|
50
96
|
return this.definitionToField(connection, this.definition);
|
|
51
97
|
}
|
|
52
98
|
|
|
99
|
+
/// Return the raw field definition for
|
|
100
|
+
/// the provided field.
|
|
101
|
+
///
|
|
102
|
+
/// See: ModelUtils.parseQualifiedName
|
|
53
103
|
valueOf() {
|
|
54
104
|
return this.definition;
|
|
55
105
|
}
|
|
@@ -2,7 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
const LiteralBase = require('./literal-base');
|
|
4
4
|
|
|
5
|
+
/// This literal type simply defines a pure "literal".
|
|
6
|
+
/// It will represent any "raw" value you want to insert
|
|
7
|
+
/// directly into any query. This can be useful for custom
|
|
8
|
+
/// database operations, math, or anything else you need
|
|
9
|
+
/// in "raw" form in the database.
|
|
10
|
+
///
|
|
11
|
+
/// Note:
|
|
12
|
+
/// **Caution should be taken if using this for values. Values defined by this literal won't ever be escaped.**
|
|
5
13
|
class Literal extends LiteralBase {
|
|
14
|
+
/// Construct a pure vanilla "literal" for the underlying database.
|
|
15
|
+
///
|
|
16
|
+
/// Arguments:
|
|
17
|
+
/// literal: any
|
|
18
|
+
/// The literal value you want to stringify for the underlying database query engine.
|
|
19
|
+
/// options?: object
|
|
20
|
+
/// Connection, literal, and operation specific options.
|
|
6
21
|
constructor(literal, options) {
|
|
7
22
|
super(literal, options);
|
|
8
23
|
}
|
|
@@ -2,11 +2,78 @@
|
|
|
2
2
|
|
|
3
3
|
const LiteralFieldBase = require('./literal-field-base');
|
|
4
4
|
|
|
5
|
+
/// Define an "average" literal for the underlying database.
|
|
6
|
+
///
|
|
7
|
+
/// Literals are special types in Mythix ORM that are used to
|
|
8
|
+
/// define "literal values" for the underlying database.
|
|
9
|
+
///
|
|
10
|
+
/// This literal defines an "average" operation across a single
|
|
11
|
+
/// column. It is used by <see>Connection.average</see> to get
|
|
12
|
+
/// the average across all rows for a single column in the underlying
|
|
13
|
+
/// database. When serialized using the <see>QueryGenerator</see>
|
|
14
|
+
/// for the connection, it will turn into a database method that
|
|
15
|
+
/// is appropriate for the underlying database. For example, with
|
|
16
|
+
/// SQL type databases this would turn into `MAX(column)`. This is
|
|
17
|
+
/// often used by the projection engine, to project it as a column
|
|
18
|
+
/// to be selected. For example `SELECT MAX(column) ...`. It can
|
|
19
|
+
/// be used in other places in the query however, such as `ORDER`,
|
|
20
|
+
/// `GROUP BY`, and `HAVING` clauses.
|
|
21
|
+
///
|
|
22
|
+
/// There are two primary ways to access literals in Mythix ORM. The
|
|
23
|
+
/// first is to simply import them. The second way literals can be
|
|
24
|
+
/// accessed is via the connection class itself. All Mythix ORM connection
|
|
25
|
+
/// classes export all literals on the `static Literals` attribute of
|
|
26
|
+
/// the class. So for example, you could access literals like `SQLiteConnection.Literals.MaxLiteral`.
|
|
27
|
+
///
|
|
28
|
+
/// All built-in Mythix ORM literals--except `Literal` and `LiteralBase`--accept a field
|
|
29
|
+
/// as their first argument. This field can be a fully qualified field name, an actual
|
|
30
|
+
/// <see>Field</see> instance, or another literal. The second argument to all literal constructors
|
|
31
|
+
/// is an `options` object, that generally contains connection-specific (and operation-specific) options...
|
|
32
|
+
/// however, there are common options that can be supplied, such as `as: string;` which allows you to
|
|
33
|
+
/// define an alias for the defined field, and `noProjectionAliases: boolean;`, which allows you to disable
|
|
34
|
+
/// the column alias entirely.
|
|
35
|
+
///
|
|
36
|
+
/// Example:
|
|
37
|
+
/// const { Literals } = require('mythix-orm');
|
|
38
|
+
/// const { SQLiteConnection } = require('mythix-orm-sqlite');
|
|
39
|
+
/// let literal1 = new Literals.MaxLiteral('User:age');
|
|
40
|
+
/// let literal2 = new SQLiteConnection.Literals.MaxLiteral('User:age');
|
|
41
|
+
///
|
|
42
|
+
/// See: LiteralFieldBase
|
|
43
|
+
///
|
|
44
|
+
/// See: LiteralBase
|
|
5
45
|
class MaxLiteral extends LiteralFieldBase {
|
|
46
|
+
/// Return `true`, letting the caller know that
|
|
47
|
+
/// this is an "aggregating literal".
|
|
48
|
+
///
|
|
49
|
+
/// Return: boolean
|
|
50
|
+
/// Return `true`, informing the caller that this literal is used for aggregate operations.
|
|
6
51
|
static isAggregate() {
|
|
7
52
|
return true;
|
|
8
53
|
}
|
|
9
54
|
|
|
55
|
+
/// Convert this literal to a string to be used in a database query.
|
|
56
|
+
///
|
|
57
|
+
/// This method proxies the conversion of this literal to the connection
|
|
58
|
+
/// by calling <see>Connection.literalToString</see>. If no connection
|
|
59
|
+
/// is provided when this is called, then the literal will be converted
|
|
60
|
+
/// to a string representing it for debugging, i.e. `'MaxLiteral {}'`.
|
|
61
|
+
///
|
|
62
|
+
/// Note:
|
|
63
|
+
/// Ultimately, for most connections, this will end up calling
|
|
64
|
+
/// <see>QueryGenerator._maxLiteralToString</see>.
|
|
65
|
+
///
|
|
66
|
+
/// Arguments:
|
|
67
|
+
/// connection?: <see>Connection</see>
|
|
68
|
+
/// The connection to use to stringify this literal. If none is provided,
|
|
69
|
+
/// then a string representing this object will be returned instead.
|
|
70
|
+
/// options?: object
|
|
71
|
+
/// A connection and operation specific set of options that can be provided.
|
|
72
|
+
/// This might for example be `{ as: 'name' }` to provided a field alias, or
|
|
73
|
+
/// `{ isProjection: true }` to define that this is being stringified for use
|
|
74
|
+
/// as a field in the query projection. Normally the end-user won't care about
|
|
75
|
+
/// any literal options, except `as`, which is commonly used to give your literal
|
|
76
|
+
/// an alias.
|
|
10
77
|
toString(connection, options) {
|
|
11
78
|
if (!connection)
|
|
12
79
|
return `${this.constructor.name} {}`;
|
|
@@ -2,11 +2,78 @@
|
|
|
2
2
|
|
|
3
3
|
const LiteralFieldBase = require('./literal-field-base');
|
|
4
4
|
|
|
5
|
+
/// Define an "average" literal for the underlying database.
|
|
6
|
+
///
|
|
7
|
+
/// Literals are special types in Mythix ORM that are used to
|
|
8
|
+
/// define "literal values" for the underlying database.
|
|
9
|
+
///
|
|
10
|
+
/// This literal defines an "average" operation across a single
|
|
11
|
+
/// column. It is used by <see>Connection.average</see> to get
|
|
12
|
+
/// the average across all rows for a single column in the underlying
|
|
13
|
+
/// database. When serialized using the <see>QueryGenerator</see>
|
|
14
|
+
/// for the connection, it will turn into a database method that
|
|
15
|
+
/// is appropriate for the underlying database. For example, with
|
|
16
|
+
/// SQL type databases this would turn into `MIN(column)`. This is
|
|
17
|
+
/// often used by the projection engine, to project it as a column
|
|
18
|
+
/// to be selected. For example `SELECT MIN(column) ...`. It can
|
|
19
|
+
/// be used in other places in the query however, such as `ORDER`,
|
|
20
|
+
/// `GROUP BY`, and `HAVING` clauses.
|
|
21
|
+
///
|
|
22
|
+
/// There are two primary ways to access literals in Mythix ORM. The
|
|
23
|
+
/// first is to simply import them. The second way literals can be
|
|
24
|
+
/// accessed is via the connection class itself. All Mythix ORM connection
|
|
25
|
+
/// classes export all literals on the `static Literals` attribute of
|
|
26
|
+
/// the class. So for example, you could access literals like `SQLiteConnection.Literals.MinLiteral`.
|
|
27
|
+
///
|
|
28
|
+
/// All built-in Mythix ORM literals--except `Literal` and `LiteralBase`--accept a field
|
|
29
|
+
/// as their first argument. This field can be a fully qualified field name, an actual
|
|
30
|
+
/// <see>Field</see> instance, or another literal. The second argument to all literal constructors
|
|
31
|
+
/// is an `options` object, that generally contains connection-specific (and operation-specific) options...
|
|
32
|
+
/// however, there are common options that can be supplied, such as `as: string;` which allows you to
|
|
33
|
+
/// define an alias for the defined field, and `noProjectionAliases: boolean;`, which allows you to disable
|
|
34
|
+
/// the column alias entirely.
|
|
35
|
+
///
|
|
36
|
+
/// Example:
|
|
37
|
+
/// const { Literals } = require('mythix-orm');
|
|
38
|
+
/// const { SQLiteConnection } = require('mythix-orm-sqlite');
|
|
39
|
+
/// let literal1 = new Literals.MinLiteral('User:age');
|
|
40
|
+
/// let literal2 = new SQLiteConnection.Literals.MinLiteral('User:age');
|
|
41
|
+
///
|
|
42
|
+
/// See: LiteralFieldBase
|
|
43
|
+
///
|
|
44
|
+
/// See: LiteralBase
|
|
5
45
|
class MinLiteral extends LiteralFieldBase {
|
|
46
|
+
/// Return `true`, letting the caller know that
|
|
47
|
+
/// this is an "aggregating literal".
|
|
48
|
+
///
|
|
49
|
+
/// Return: boolean
|
|
50
|
+
/// Return `true`, informing the caller that this literal is used for aggregate operations.
|
|
6
51
|
static isAggregate() {
|
|
7
52
|
return true;
|
|
8
53
|
}
|
|
9
54
|
|
|
55
|
+
/// Convert this literal to a string to be used in a database query.
|
|
56
|
+
///
|
|
57
|
+
/// This method proxies the conversion of this literal to the connection
|
|
58
|
+
/// by calling <see>Connection.literalToString</see>. If no connection
|
|
59
|
+
/// is provided when this is called, then the literal will be converted
|
|
60
|
+
/// to a string representing it for debugging, i.e. `'MinLiteral {}'`.
|
|
61
|
+
///
|
|
62
|
+
/// Note:
|
|
63
|
+
/// Ultimately, for most connections, this will end up calling
|
|
64
|
+
/// <see>QueryGenerator._minLiteralToString</see>.
|
|
65
|
+
///
|
|
66
|
+
/// Arguments:
|
|
67
|
+
/// connection?: <see>Connection</see>
|
|
68
|
+
/// The connection to use to stringify this literal. If none is provided,
|
|
69
|
+
/// then a string representing this object will be returned instead.
|
|
70
|
+
/// options?: object
|
|
71
|
+
/// A connection and operation specific set of options that can be provided.
|
|
72
|
+
/// This might for example be `{ as: 'name' }` to provided a field alias, or
|
|
73
|
+
/// `{ isProjection: true }` to define that this is being stringified for use
|
|
74
|
+
/// as a field in the query projection. Normally the end-user won't care about
|
|
75
|
+
/// any literal options, except `as`, which is commonly used to give your literal
|
|
76
|
+
/// an alias.
|
|
10
77
|
toString(connection, options) {
|
|
11
78
|
if (!connection)
|
|
12
79
|
return `${this.constructor.name} {}`;
|
|
@@ -2,11 +2,78 @@
|
|
|
2
2
|
|
|
3
3
|
const LiteralFieldBase = require('./literal-field-base');
|
|
4
4
|
|
|
5
|
+
/// Define an "average" literal for the underlying database.
|
|
6
|
+
///
|
|
7
|
+
/// Literals are special types in Mythix ORM that are used to
|
|
8
|
+
/// define "literal values" for the underlying database.
|
|
9
|
+
///
|
|
10
|
+
/// This literal defines an "average" operation across a single
|
|
11
|
+
/// column. It is used by <see>Connection.average</see> to get
|
|
12
|
+
/// the average across all rows for a single column in the underlying
|
|
13
|
+
/// database. When serialized using the <see>QueryGenerator</see>
|
|
14
|
+
/// for the connection, it will turn into a database method that
|
|
15
|
+
/// is appropriate for the underlying database. For example, with
|
|
16
|
+
/// SQL type databases this would turn into `SUM(column)`. This is
|
|
17
|
+
/// often used by the projection engine, to project it as a column
|
|
18
|
+
/// to be selected. For example `SELECT SUM(column) ...`. It can
|
|
19
|
+
/// be used in other places in the query however, such as `ORDER`,
|
|
20
|
+
/// `GROUP BY`, and `HAVING` clauses.
|
|
21
|
+
///
|
|
22
|
+
/// There are two primary ways to access literals in Mythix ORM. The
|
|
23
|
+
/// first is to simply import them. The second way literals can be
|
|
24
|
+
/// accessed is via the connection class itself. All Mythix ORM connection
|
|
25
|
+
/// classes export all literals on the `static Literals` attribute of
|
|
26
|
+
/// the class. So for example, you could access literals like `SQLiteConnection.Literals.SumLiteral`.
|
|
27
|
+
///
|
|
28
|
+
/// All built-in Mythix ORM literals--except `Literal` and `LiteralBase`--accept a field
|
|
29
|
+
/// as their first argument. This field can be a fully qualified field name, an actual
|
|
30
|
+
/// <see>Field</see> instance, or another literal. The second argument to all literal constructors
|
|
31
|
+
/// is an `options` object, that generally contains connection-specific (and operation-specific) options...
|
|
32
|
+
/// however, there are common options that can be supplied, such as `as: string;` which allows you to
|
|
33
|
+
/// define an alias for the defined field, and `noProjectionAliases: boolean;`, which allows you to disable
|
|
34
|
+
/// the column alias entirely.
|
|
35
|
+
///
|
|
36
|
+
/// Example:
|
|
37
|
+
/// const { Literals } = require('mythix-orm');
|
|
38
|
+
/// const { SQLiteConnection } = require('mythix-orm-sqlite');
|
|
39
|
+
/// let literal1 = new Literals.SumLiteral('User:age');
|
|
40
|
+
/// let literal2 = new SQLiteConnection.Literals.SumLiteral('User:age');
|
|
41
|
+
///
|
|
42
|
+
/// See: LiteralFieldBase
|
|
43
|
+
///
|
|
44
|
+
/// See: LiteralBase
|
|
5
45
|
class SumLiteral extends LiteralFieldBase {
|
|
46
|
+
/// Return `true`, letting the caller know that
|
|
47
|
+
/// this is an "aggregating literal".
|
|
48
|
+
///
|
|
49
|
+
/// Return: boolean
|
|
50
|
+
/// Return `true`, informing the caller that this literal is used for aggregate operations.
|
|
6
51
|
static isAggregate() {
|
|
7
52
|
return true;
|
|
8
53
|
}
|
|
9
54
|
|
|
55
|
+
/// Convert this literal to a string to be used in a database query.
|
|
56
|
+
///
|
|
57
|
+
/// This method proxies the conversion of this literal to the connection
|
|
58
|
+
/// by calling <see>Connection.literalToString</see>. If no connection
|
|
59
|
+
/// is provided when this is called, then the literal will be converted
|
|
60
|
+
/// to a string representing it for debugging, i.e. `'SumLiteral {}'`.
|
|
61
|
+
///
|
|
62
|
+
/// Note:
|
|
63
|
+
/// Ultimately, for most connections, this will end up calling
|
|
64
|
+
/// <see>QueryGenerator._sumLiteralToString</see>.
|
|
65
|
+
///
|
|
66
|
+
/// Arguments:
|
|
67
|
+
/// connection?: <see>Connection</see>
|
|
68
|
+
/// The connection to use to stringify this literal. If none is provided,
|
|
69
|
+
/// then a string representing this object will be returned instead.
|
|
70
|
+
/// options?: object
|
|
71
|
+
/// A connection and operation specific set of options that can be provided.
|
|
72
|
+
/// This might for example be `{ as: 'name' }` to provided a field alias, or
|
|
73
|
+
/// `{ isProjection: true }` to define that this is being stringified for use
|
|
74
|
+
/// as a field in the query projection. Normally the end-user won't care about
|
|
75
|
+
/// any literal options, except `as`, which is commonly used to give your literal
|
|
76
|
+
/// an alias.
|
|
10
77
|
toString(connection, options) {
|
|
11
78
|
if (!connection)
|
|
12
79
|
return `${this.constructor.name} {}`;
|
package/lib/field.js
CHANGED
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
/// it is a function, it will be called when the model is initialized
|
|
134
134
|
/// if no value for the field was provided to the model during instantiation.
|
|
135
135
|
/// As a method, it can have numerous different "flags" set on it, via
|
|
136
|
-
/// the <see>
|
|
136
|
+
/// the <see>Helpers.defaultValueFlags</see> factory. Reference this
|
|
137
137
|
/// methods documentation for a better understanding of what default value
|
|
138
138
|
/// flags are, and what they do.
|
|
139
139
|
/// get: Function(context: GetSetContext)
|
package/lib/model.js
CHANGED
|
@@ -345,7 +345,7 @@ class Model {
|
|
|
345
345
|
/// Just be cautious if you set a `connection` property, as you might overwrite any
|
|
346
346
|
/// connection currently set on the context. Any properties you set here will be available
|
|
347
347
|
/// in any child function calls (inside this context scope), and can be accessed via a
|
|
348
|
-
/// call to <see>Model.getModelContext</see>.
|
|
348
|
+
/// call to <see>Model.static getModelContext</see>.
|
|
349
349
|
///
|
|
350
350
|
/// Note:
|
|
351
351
|
/// An `AsyncLocalStorage` context might not exist when this call is made,
|
|
@@ -381,7 +381,7 @@ class Model {
|
|
|
381
381
|
/// This method will return a connection in the following
|
|
382
382
|
/// order: 1) The provided `connection` argument, if supplied,
|
|
383
383
|
/// 2) The `connection` property on the "model context" from
|
|
384
|
-
/// <see>Model.getModelContext</see> from `AsyncLocalStorage`,
|
|
384
|
+
/// <see>Model.static getModelContext</see> from `AsyncLocalStorage`,
|
|
385
385
|
/// if one is available, and 3) Finally the bound connection, if
|
|
386
386
|
/// available, which is found by searching the `static Model._mythixBoundConnection`
|
|
387
387
|
/// property of the class.
|
|
@@ -677,6 +677,58 @@ class Model {
|
|
|
677
677
|
return this.constructor.defaultScope(queryEngine);
|
|
678
678
|
}
|
|
679
679
|
|
|
680
|
+
/// Finalize a query before using it for database operations.
|
|
681
|
+
///
|
|
682
|
+
/// `finalizeQuery` is called on **every** query immediately
|
|
683
|
+
/// before it is used for a database operation. Its only purpose
|
|
684
|
+
/// is to potentially modify the query before the database operation
|
|
685
|
+
/// occurs. This can be extremely useful for things like "row level permissions",
|
|
686
|
+
/// or ensuring that a certain type of query always has certain conditions.
|
|
687
|
+
///
|
|
688
|
+
/// Because it is asynchronous by design, it is possible to finalize the
|
|
689
|
+
/// query using other asynchronous operations; for example validating
|
|
690
|
+
/// authentication tokens, or fetching user roles from the database.
|
|
691
|
+
///
|
|
692
|
+
/// This is called by <see>Connection.finalizeQuery</see> for each unique
|
|
693
|
+
/// model found in the query.
|
|
694
|
+
///
|
|
695
|
+
/// Interface:
|
|
696
|
+
/// interface FinalizeQueryContext {
|
|
697
|
+
/// type: 'create' | 'read' | 'updated' | 'delete'; // The operation type that is about to happen in the underlying database.
|
|
698
|
+
/// query: QueryEngine; // The query being operated upon. Modify and return this.
|
|
699
|
+
/// queryDepth: number; // The depth we are at while walking the query. Will be 0 for root level, 1 for first sub-query, etc...
|
|
700
|
+
/// operationIndex: number; // The "operation stack" index we are at
|
|
701
|
+
/// operation: object; // The "operation" on the query operation stack we are working on
|
|
702
|
+
/// operations: Array<object>; // The query "operation stack"
|
|
703
|
+
/// parent: object | null; // The parent "operation"
|
|
704
|
+
/// contextKey: string; // The name of the key that this query is a value of for this "operation" object. This is usually "value" for most operations, but it could be something else.
|
|
705
|
+
/// options: object; // The options passed into the operation by the user
|
|
706
|
+
/// }
|
|
707
|
+
///
|
|
708
|
+
///
|
|
709
|
+
/// Note:
|
|
710
|
+
/// "With great power comes great responsibility." Use `finalizeQuery` intelligently. It can
|
|
711
|
+
/// cause a noticeable performance hit, and can really make things hard to debug and
|
|
712
|
+
/// understand if you don't clearly document.
|
|
713
|
+
///
|
|
714
|
+
/// Note:
|
|
715
|
+
/// `'create'` isn't actually currently supported, since no queries are
|
|
716
|
+
/// ever used in an `INSERT` operation. It is reserved for future use.
|
|
717
|
+
///
|
|
718
|
+
/// Arguments:
|
|
719
|
+
/// context: FinalizeQueryContext
|
|
720
|
+
/// All provided values in a single context. You will want to modify `query`
|
|
721
|
+
/// and return it... or if you don't modify it, simply return it. The `contextKey`
|
|
722
|
+
/// might be a little confusing. It is the name of the key the query is a value on.
|
|
723
|
+
/// For example, in an `EQ` operation, this would be "value".
|
|
724
|
+
/// i.e. an `EQ` operation looks something like the following on the operation stack:
|
|
725
|
+
/// `{ operator: 'EQ', value: query }`. The reason it is provided is if you need to
|
|
726
|
+
//// directly get or set a value on the operation frame (`operation`).
|
|
727
|
+
///
|
|
728
|
+
/// Return: <see>QueryEngine</see>
|
|
729
|
+
/// The query provided, possibly altered.
|
|
730
|
+
///
|
|
731
|
+
/// See: Connection.finalizeQuery
|
|
680
732
|
// eslint-disable-next-line no-unused-vars
|
|
681
733
|
static finalizeQuery({ type, query, queryDepth, operationIndex, operation, operations, parent, contextKey, options }) {
|
|
682
734
|
return query;
|