mythix-orm 1.8.2 → 1.8.3
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/lib/connection/connection-base.js +2236 -6
- package/lib/connection/query-generator-base.js +3 -0
- package/lib/model.js +17 -3
- package/lib/query-engine/query-engine-base.js +4 -4
- package/lib/types/concrete/date-type.js +2 -2
- package/lib/types/concrete/datetime-type.js +2 -2
- package/lib/types/concrete/foreign-key-type.js +2 -2
- package/lib/types/type.js +1 -1
- package/lib/types/virtual/model-type.js +151 -0
- package/lib/types/virtual/models-type.js +147 -0
- package/lib/types/virtual/relational-type-base.js +0 -10
- package/lib/utils/model-utils.js +44 -0
- package/lib/utils/query-utils.js +2 -2
- package/package.json +1 -1
|
@@ -15,15 +15,73 @@ const LiteralBase = Literals.LiteralBase;
|
|
|
15
15
|
|
|
16
16
|
/// ConnectionBase is the base class that
|
|
17
17
|
/// all connection classes should inherit from.
|
|
18
|
+
/// It provides common functionality to all
|
|
19
|
+
/// connections, and converts literals and
|
|
20
|
+
/// types into their native database representation.
|
|
21
|
+
///
|
|
22
|
+
/// A "connection" in Mythix ORM is essentially
|
|
23
|
+
/// the "application" for the ORM. It stores all
|
|
24
|
+
/// models used by the connection, stores and defines
|
|
25
|
+
/// the query generator (if any), converts literals
|
|
26
|
+
/// and types, and also provides the query engine.
|
|
27
|
+
///
|
|
28
|
+
/// Multiple connections can be used at the same time
|
|
29
|
+
/// in Mythix ORM. It is also planned that someday
|
|
30
|
+
/// Mythix ORM (or the community) will provide a
|
|
31
|
+
/// multiplex connection, to mix multiple connections
|
|
32
|
+
/// into a single connection for the entire application.
|
|
33
|
+
///
|
|
34
|
+
/// For now you can use multiple connections at once.
|
|
35
|
+
/// Just know that you should read and fully understand
|
|
36
|
+
/// [Connection Binding](./ConnectionBinding) if you plan
|
|
37
|
+
/// on using more than one connection for your application.
|
|
38
|
+
///
|
|
39
|
+
/// ConnectionBase is also an [Event Emitter](https://nodejs.org/docs/latest-v16.x/api/events.html),
|
|
40
|
+
/// so you can bind events to a connection instance with `.on`, and unbind
|
|
41
|
+
/// with `.off`. Events are connection specific, but common events that
|
|
42
|
+
/// can be bound to are:
|
|
43
|
+
///
|
|
44
|
+
/// 1. `connect` - Commonly fired when a connection is successfully established
|
|
45
|
+
/// 2. `acquire` - Commonly fired when a connection is acquired from a connection pool
|
|
46
|
+
/// 3. `error` - Commonly fired when a database level error occurs
|
|
47
|
+
/// 4. `disconnect` - Commonly fired when a connection is disconnected
|
|
48
|
+
///
|
|
49
|
+
/// *This is just an example of common connection driver events.
|
|
50
|
+
/// Please see documentation for your specific database connection for the proper events.*
|
|
51
|
+
///
|
|
52
|
+
/// Properties:
|
|
53
|
+
/// static Literals: Literals
|
|
54
|
+
/// All default Mythix ORM literal classes,
|
|
55
|
+
/// provided for convenient access.
|
|
56
|
+
/// static dialect: string
|
|
57
|
+
/// The dialect of the database, i.e. `'sqlite'`, or `'postgresql'`.
|
|
58
|
+
/// dialect: string
|
|
59
|
+
/// The dialect of the database, i.e. `'sqlite'`, or `'postgresql'`.
|
|
60
|
+
/// static _isMythixConnection: boolean
|
|
61
|
+
/// Helper for type checking methods. Should always be `true`.
|
|
18
62
|
///
|
|
19
63
|
/// Alias: Connection
|
|
20
64
|
class ConnectionBase extends EventEmitter {
|
|
21
65
|
static Literals = Literals;
|
|
22
66
|
|
|
67
|
+
static DefaultQueryGenerator = QueryGeneratorBase;
|
|
68
|
+
|
|
23
69
|
static dialect = 'none';
|
|
24
70
|
|
|
25
71
|
static _isMythixConnection = true;
|
|
26
72
|
|
|
73
|
+
/// Use this method to check if a class
|
|
74
|
+
/// is a Mythix ORM connection. It will return
|
|
75
|
+
/// `true` if the provided value is a class
|
|
76
|
+
/// that inherits from <see>ConnectionBase</see>, or
|
|
77
|
+
/// if the provided value has an attribute
|
|
78
|
+
/// named `_isMythixConnection` that is truthy.
|
|
79
|
+
///
|
|
80
|
+
/// Return: boolean
|
|
81
|
+
///
|
|
82
|
+
/// Arguments:
|
|
83
|
+
/// value: Function
|
|
84
|
+
/// Value to check.
|
|
27
85
|
static isConnectionClass(value) {
|
|
28
86
|
if (!value)
|
|
29
87
|
return false;
|
|
@@ -37,6 +95,22 @@ class ConnectionBase extends EventEmitter {
|
|
|
37
95
|
return false;
|
|
38
96
|
}
|
|
39
97
|
|
|
98
|
+
/// Check to see if the provided value is
|
|
99
|
+
/// an *instance* of a Mythix ORM <see>ConnectionBase</see>.
|
|
100
|
+
/// Unlike <see>ConnectionBase.static isConnectionClass</see>, which
|
|
101
|
+
/// checks if a *class* is a <see>ConnectionBase</see>, this will check
|
|
102
|
+
/// to see if an *instance* is an instance of a
|
|
103
|
+
/// Mythix ORM <see>ConnectionBase</see>. It will return
|
|
104
|
+
/// `true` if the provided value is an `instanceof`
|
|
105
|
+
/// <see>ConnectionBase</see>, or if the value's `constructor`
|
|
106
|
+
/// property has a truthy `_isMythixConnection` property
|
|
107
|
+
/// (`value.constructor._isMythixConnection`)
|
|
108
|
+
///
|
|
109
|
+
/// Return: boolean
|
|
110
|
+
///
|
|
111
|
+
/// Arguments:
|
|
112
|
+
/// value: any
|
|
113
|
+
/// Value to check
|
|
40
114
|
static isConnection(value) {
|
|
41
115
|
if (!value)
|
|
42
116
|
return false;
|
|
@@ -50,20 +124,72 @@ class ConnectionBase extends EventEmitter {
|
|
|
50
124
|
return false;
|
|
51
125
|
}
|
|
52
126
|
|
|
127
|
+
/// Fetch a literal class by its name.
|
|
128
|
+
///
|
|
129
|
+
/// The following is a table that displays
|
|
130
|
+
/// the `name` argument that can be provided,
|
|
131
|
+
/// and the resulting Literal class that would
|
|
132
|
+
/// be returned for that name.
|
|
133
|
+
/// | `name` | Resulting literal class |
|
|
134
|
+
/// | --------------- | --------------------------- |
|
|
135
|
+
/// | `'Average'` | <see>AverageLiteral</see> |
|
|
136
|
+
/// | `'Base'` | <see>LiteralBase</see> |
|
|
137
|
+
/// | `'Count'` | <see>CountLiteral</see> |
|
|
138
|
+
/// | `'Distinct'` | <see>DistinctLiteral</see> |
|
|
139
|
+
/// | `'Field'` | <see>FieldLiteral</see> |
|
|
140
|
+
/// | `'FieldBase'` | <see>LiteralFieldBase</see> |
|
|
141
|
+
/// | `'Literal'` | <see>Literal</see> |
|
|
142
|
+
/// | `'Max'` | <see>MaxLiteral</see> |
|
|
143
|
+
/// | `'Min'` | <see>MinLiteral</see> |
|
|
144
|
+
/// | `'Sum'` | <see>SumLiteral</see> |
|
|
145
|
+
///
|
|
146
|
+
/// Arguments:
|
|
147
|
+
/// name: string
|
|
148
|
+
/// The name of the literal class to return.
|
|
149
|
+
///
|
|
150
|
+
/// Return: class <see>LiteralBase</see>
|
|
151
|
+
/// Return the literal class requested.
|
|
53
152
|
static getLiteralClassByName(_name) {
|
|
54
153
|
if (!_name)
|
|
55
154
|
return;
|
|
56
155
|
|
|
57
|
-
let
|
|
156
|
+
let Klass = Literals[_name];
|
|
157
|
+
if (Klass)
|
|
158
|
+
return Klass;
|
|
58
159
|
|
|
160
|
+
let name = Nife.capitalize(_name.toLowerCase());
|
|
59
161
|
if (name === 'Literal')
|
|
60
162
|
return Literals.Literal;
|
|
163
|
+
if (name === 'FieldBase')
|
|
164
|
+
return Literals.LiteralFieldBase;
|
|
61
165
|
else if (name === 'Base')
|
|
62
166
|
return Literals.LiteralBase;
|
|
63
167
|
|
|
64
168
|
return Literals[`${name}Literal`];
|
|
65
169
|
}
|
|
66
170
|
|
|
171
|
+
/// Create the literal specified by name.
|
|
172
|
+
///
|
|
173
|
+
/// Whereas <see>ConnectionBase.static getLiteralClassByName</see> will
|
|
174
|
+
/// simply return the literal class specified, this will create
|
|
175
|
+
/// the specified literal, with the provided arguments.
|
|
176
|
+
///
|
|
177
|
+
/// Please see <see>ConnectionBase.static getLiteralClassByName</see> for
|
|
178
|
+
/// possible names that can be provided as the `name` argument.
|
|
179
|
+
///
|
|
180
|
+
/// See: ConnectionBase.static getLiteralClassByName
|
|
181
|
+
///
|
|
182
|
+
/// Arguments:
|
|
183
|
+
/// name: string
|
|
184
|
+
/// The name of the literal to create. See
|
|
185
|
+
/// <see>ConnectionBase.static getLiteralClassByName</see> for
|
|
186
|
+
/// possible values.
|
|
187
|
+
/// ...args: Array<any>
|
|
188
|
+
/// Arguments to provide to the literal constructor.
|
|
189
|
+
///
|
|
190
|
+
/// Return: <see>LiteralBase</see>
|
|
191
|
+
/// Return an instance the literal requested,
|
|
192
|
+
/// using the arguments specified.
|
|
67
193
|
static Literal(name, ...args) {
|
|
68
194
|
const LiteralClass = this.getLiteralClassByName(name);
|
|
69
195
|
if (!LiteralClass)
|
|
@@ -73,6 +199,26 @@ class ConnectionBase extends EventEmitter {
|
|
|
73
199
|
return literal;
|
|
74
200
|
}
|
|
75
201
|
|
|
202
|
+
/// Create a connection.
|
|
203
|
+
///
|
|
204
|
+
/// The `options` argument is generally connection
|
|
205
|
+
/// specific. However, there are a few generic options,
|
|
206
|
+
/// which you will find listed in the table below:
|
|
207
|
+
/// | Option | Type | Default Value | Description |
|
|
208
|
+
/// | ------------- | ---- | ------------- | ----------- |
|
|
209
|
+
/// | `bindModels` | `boolean` | `true` | If `true`, then bind the provided `models` to this connection. Models are bound to a connection by setting a static `_mythixBoundConnection` property on each model class to this connection instance. |
|
|
210
|
+
/// | `forceConnectionBinding` | `boolean` | `false` | Normally attempting to bind a connection to a model more than once will result in an exception being thrown. However, if you set this property to `true`, then Mythix ORM will rebind the connection without complaint, even if a connection is already bound to your models. Make sure you know what you are doing if you use this option. |
|
|
211
|
+
/// | `models` | `Array` or `Object` of <see>Models</see> | `undefined` | Models to provide to this connection. This can be either an array of <see>Models</see>, or an Object where each value is a <see>Model</see> |
|
|
212
|
+
/// | `QueryEngine` | class <see>QueryEngine</see> | <see>QueryEngine</see> | The QueryEngine class to use for this connection and all this connection's models. You can provide your own class if you wish to add onto the query interface. |
|
|
213
|
+
/// | `queryGenerator` | <see>QueryGenerator</see> | *Connection specific* | The query generator for this connection. If a <see>QueryGenerator</see> instance is provided (the correct one for the connection you are using), then this provided query generator will be used. If one isn't provided, then the connection will create its own query generator that is specific to the connection type. |
|
|
214
|
+
///
|
|
215
|
+
/// Arguments:
|
|
216
|
+
/// options: object
|
|
217
|
+
/// Connection specific options to supply to your connection. These
|
|
218
|
+
/// will commonly include things like a hostname to connect to, a
|
|
219
|
+
/// user name and password, and any connection specific parameters.
|
|
220
|
+
///
|
|
221
|
+
/// Return: <see>Connection</see>
|
|
76
222
|
constructor(_options) {
|
|
77
223
|
super();
|
|
78
224
|
|
|
@@ -124,6 +270,36 @@ class ConnectionBase extends EventEmitter {
|
|
|
124
270
|
this.registerModels(options.models);
|
|
125
271
|
}
|
|
126
272
|
|
|
273
|
+
/// This method is an internal method that parses
|
|
274
|
+
/// the "lock mode" options passed to a call to
|
|
275
|
+
/// <see>Connection.transaction</see>.
|
|
276
|
+
///
|
|
277
|
+
/// These might be different depending on the connection driver
|
|
278
|
+
/// you are using. Please refer to the documentation
|
|
279
|
+
/// for your connection driver for more details.
|
|
280
|
+
///
|
|
281
|
+
/// Arguments:
|
|
282
|
+
/// options: any
|
|
283
|
+
/// Possibly connection specific lock options for a
|
|
284
|
+
/// connection's <see>Connection.transaction</see> method.
|
|
285
|
+
/// Generally this will either be a `true` value, a Model name
|
|
286
|
+
/// (for which table to lock), or a complete lock options object,
|
|
287
|
+
/// which generally will look something like:
|
|
288
|
+
/// `{ lock: boolean; modelName: string; read: boolean; write: boolean }`
|
|
289
|
+
/// <br>
|
|
290
|
+
/// <br>`lock` - If `true`, then lock the transaction
|
|
291
|
+
/// <br>`modelName` - The name of the table(s) to lock
|
|
292
|
+
/// <br>`read` - If `true`, then lock for reads
|
|
293
|
+
/// <br>`write` - If `true`, then lock for writes
|
|
294
|
+
///
|
|
295
|
+
/// Return: object
|
|
296
|
+
/// Return the lock options for a transaction. These might change
|
|
297
|
+
/// based on the connection driver you are using, but will generally
|
|
298
|
+
/// look like `{ lock: boolean; modelName: string; read: boolean; write: boolean }`.
|
|
299
|
+
/// 1. `lock` - If `true`, then lock the transaction
|
|
300
|
+
/// 2. `modelName` - The name of the table(s) to lock
|
|
301
|
+
/// 3. `read` - If `true`, then lock for reads
|
|
302
|
+
/// 4. `write` - If `true`, then lock for writes
|
|
127
303
|
getLockMode(options) {
|
|
128
304
|
if (!options)
|
|
129
305
|
return { lock: false, read: false, write: false };
|
|
@@ -150,6 +326,25 @@ class ConnectionBase extends EventEmitter {
|
|
|
150
326
|
}
|
|
151
327
|
}
|
|
152
328
|
|
|
329
|
+
/// Get the default order for selecting rows
|
|
330
|
+
/// from the database. This will call the
|
|
331
|
+
/// Model's <see name="Model.defaultOrder">Model.static defaultOrder</see> method
|
|
332
|
+
/// first to see if the model specifies a default order
|
|
333
|
+
/// for itself. If it doesn't, then the connection
|
|
334
|
+
/// driver itself might specify a default order for
|
|
335
|
+
/// each table.
|
|
336
|
+
///
|
|
337
|
+
/// Arguments:
|
|
338
|
+
/// Model: class <see>Model</see>
|
|
339
|
+
/// The model/table to fetch the default order for.
|
|
340
|
+
/// options: object
|
|
341
|
+
/// Operation specific options (i.e. options for a "select" call)
|
|
342
|
+
///
|
|
343
|
+
/// Return: Array<string>
|
|
344
|
+
/// An array of fully qualified field names for this model should
|
|
345
|
+
/// be returned by this method. An empty array, `null`, or `undefined`
|
|
346
|
+
/// are also valid return values (in which case no order will be
|
|
347
|
+
/// applied to the given operation).
|
|
153
348
|
getDefaultOrder(Model, options) {
|
|
154
349
|
let order = Model.defaultOrder(options);
|
|
155
350
|
if (!order)
|
|
@@ -172,10 +367,30 @@ class ConnectionBase extends EventEmitter {
|
|
|
172
367
|
return order.map((value) => ((value.indexOf(':') < 0) ? `${modelName}:${value}` : value));
|
|
173
368
|
}
|
|
174
369
|
|
|
370
|
+
/// This method is called (and often provided)
|
|
371
|
+
/// by the underlying database driver to see
|
|
372
|
+
/// if a `LIMIT` clause is allowed to appear in
|
|
373
|
+
/// a given context/operation.
|
|
374
|
+
///
|
|
375
|
+
/// Arguments:
|
|
376
|
+
/// options: object
|
|
377
|
+
/// Driver specific options for the context.
|
|
378
|
+
///
|
|
379
|
+
/// Return: boolean
|
|
175
380
|
isLimitSupportedInContext(options) {
|
|
176
381
|
return true;
|
|
177
382
|
}
|
|
178
383
|
|
|
384
|
+
/// This method is called (and often provided)
|
|
385
|
+
/// by the underlying database driver to see
|
|
386
|
+
/// if an `ORDER BY` clause is allowed to appear in
|
|
387
|
+
/// a given context/operation.
|
|
388
|
+
///
|
|
389
|
+
/// Arguments:
|
|
390
|
+
/// options: object
|
|
391
|
+
/// Driver specific options for the context.
|
|
392
|
+
///
|
|
393
|
+
/// Return: boolean
|
|
179
394
|
isOrderSupportedInContext(_options) {
|
|
180
395
|
let options = _options || {};
|
|
181
396
|
if (options.isSubQuery) {
|
|
@@ -213,14 +428,52 @@ class ConnectionBase extends EventEmitter {
|
|
|
213
428
|
return value;
|
|
214
429
|
}
|
|
215
430
|
|
|
431
|
+
/// Get the options for this connection.
|
|
432
|
+
///
|
|
433
|
+
/// These will be the options provided to
|
|
434
|
+
/// the connection during creation, plus any
|
|
435
|
+
/// other options the connection driver itself
|
|
436
|
+
/// internally sets.
|
|
437
|
+
///
|
|
438
|
+
/// Return: object
|
|
439
|
+
/// The options for this connection.
|
|
216
440
|
getOptions() {
|
|
217
441
|
return this._options;
|
|
218
442
|
}
|
|
219
443
|
|
|
444
|
+
/// Check to see if `start` has already been called
|
|
445
|
+
/// on this connection. This is used to know if a
|
|
446
|
+
/// connection is "active" or not.
|
|
447
|
+
///
|
|
448
|
+
/// Return: boolean
|
|
220
449
|
isStarted() {
|
|
221
450
|
return true;
|
|
222
451
|
}
|
|
223
452
|
|
|
453
|
+
/// This will take something that can
|
|
454
|
+
/// be turned into a query and turn it
|
|
455
|
+
/// into a query.
|
|
456
|
+
///
|
|
457
|
+
/// If a <see>QueryEngine</see> instance
|
|
458
|
+
/// is provided, it will simply be returned.
|
|
459
|
+
///
|
|
460
|
+
/// If a Model is provided, then `Model.where`
|
|
461
|
+
/// will be returned, returning a <see>QueryEngine</see>
|
|
462
|
+
/// for the model provided.
|
|
463
|
+
///
|
|
464
|
+
/// In the future this may also accept other possible
|
|
465
|
+
/// values that could be turned into a query.
|
|
466
|
+
///
|
|
467
|
+
/// This is often internally called by methods of the connection
|
|
468
|
+
/// on a given argument provided by the user, which could validly
|
|
469
|
+
/// be either a model or a query. <see>Connection.destroyModels</see>
|
|
470
|
+
/// is one example of this.
|
|
471
|
+
///
|
|
472
|
+
/// Arguments:
|
|
473
|
+
/// value: any
|
|
474
|
+
/// The value to attempt to turn into a <see>QueryEngine</see>.
|
|
475
|
+
///
|
|
476
|
+
/// Return: <see>QueryEngine</see> | undefined
|
|
224
477
|
toQueryEngine(_queryEngine) {
|
|
225
478
|
let queryEngine = _queryEngine;
|
|
226
479
|
if (!queryEngine)
|
|
@@ -236,6 +489,37 @@ class ConnectionBase extends EventEmitter {
|
|
|
236
489
|
return queryEngine;
|
|
237
490
|
}
|
|
238
491
|
|
|
492
|
+
/// Register the provided model class.
|
|
493
|
+
///
|
|
494
|
+
/// This will register the provided model class with this
|
|
495
|
+
/// connection. The model must not already be bound to
|
|
496
|
+
/// another connection, or you must specify the `option`
|
|
497
|
+
/// `{ forceConnectionBinding: true }` if it is. You
|
|
498
|
+
/// can specify the `option` of `{ bindModels: false }`
|
|
499
|
+
/// if you don't wish to bind this model to this connection.
|
|
500
|
+
///
|
|
501
|
+
/// Any `options` provided are optional, and will override
|
|
502
|
+
/// the same options provided to the connection itself when
|
|
503
|
+
/// it was created.
|
|
504
|
+
///
|
|
505
|
+
/// Arguments:
|
|
506
|
+
/// Model: class <see>Model</see>
|
|
507
|
+
/// The model class to register with this connection. If not bound, then it
|
|
508
|
+
/// will simply exist in the model pool for this connection. If bound, then
|
|
509
|
+
/// this connection will bind itself to the model being registered.
|
|
510
|
+
/// options?: object
|
|
511
|
+
/// Options looks like `{ forceConnectionBinding: boolean; bindModels: boolean; }`.
|
|
512
|
+
/// This is an optional argument. Both options will default to the same options
|
|
513
|
+
/// provided to the connection when it was created. If you specify either of these
|
|
514
|
+
/// options they simply override the connection's default.
|
|
515
|
+
///
|
|
516
|
+
/// Return: class <see>Model</see>
|
|
517
|
+
/// The registered model class, **which may have changed during registration**.
|
|
518
|
+
/// It is not uncommon for the connection driver itself to modify the model
|
|
519
|
+
/// class, or to return a new model class that inherits from your model class.
|
|
520
|
+
/// The class that is returned should be the class that you use for this connection,
|
|
521
|
+
/// and will be the same class returned by a call to <see>Connection.getModel</see>,
|
|
522
|
+
/// or <see>Connection.getModels</see>.
|
|
239
523
|
registerModel(_Model, options) {
|
|
240
524
|
let Model = _Model.bindConnection(this, options);
|
|
241
525
|
|
|
@@ -244,6 +528,37 @@ class ConnectionBase extends EventEmitter {
|
|
|
244
528
|
return Model;
|
|
245
529
|
}
|
|
246
530
|
|
|
531
|
+
/// Register multiple models at the same time.
|
|
532
|
+
///
|
|
533
|
+
/// This will register the provided models with this
|
|
534
|
+
/// connection. The models provided must not already be bound to
|
|
535
|
+
/// another connection, or you must specify the `option`
|
|
536
|
+
/// `{ forceConnectionBinding: true }` if any of them are. You
|
|
537
|
+
/// can specify the `option` of `{ bindModels: false }`
|
|
538
|
+
/// if you don't wish to bind these models to this connection.
|
|
539
|
+
///
|
|
540
|
+
/// Any `options` provided are optional, and will override
|
|
541
|
+
/// the same options provided to the connection itself when
|
|
542
|
+
/// it was created.
|
|
543
|
+
///
|
|
544
|
+
/// Arguments:
|
|
545
|
+
/// Model: Array<class <see>Model</see>> | { [key: string]: class <see>Model</see> }
|
|
546
|
+
/// The model classes to register with this connection. If no models are bound, then
|
|
547
|
+
/// they will simply exist in the model pool for this connection. If bound, then
|
|
548
|
+
/// this connection will bind itself to every model being registered.
|
|
549
|
+
/// options?: object
|
|
550
|
+
/// Options looks like `{ forceConnectionBinding: boolean; bindModels: boolean; }`.
|
|
551
|
+
/// This is an optional argument. Both options will default to the same options
|
|
552
|
+
/// provided to the connection when it was created. If you specify either of these
|
|
553
|
+
/// options they simply override the connection's default.
|
|
554
|
+
///
|
|
555
|
+
/// Return: class <see>Model</see>
|
|
556
|
+
/// The registered model classes, **which may have changed during registration**.
|
|
557
|
+
/// It is not uncommon for the connection driver itself to modify the model
|
|
558
|
+
/// classes, or to return a new model classes that inherit from your model classes.
|
|
559
|
+
/// The classes that are returned should be the classes that you use for this connection,
|
|
560
|
+
/// and will be the same classes returned by a call to <see>Connection.getModel</see>,
|
|
561
|
+
/// or <see>Connection.getModels</see>.
|
|
247
562
|
registerModels(models, options) {
|
|
248
563
|
if (!models)
|
|
249
564
|
return;
|
|
@@ -310,6 +625,30 @@ class ConnectionBase extends EventEmitter {
|
|
|
310
625
|
return Utils.setContextValue(key, value);
|
|
311
626
|
}
|
|
312
627
|
|
|
628
|
+
/// This builds a "connection context" to provide to
|
|
629
|
+
/// the [AsyncLocalStorage](https://nodejs.org/docs/latest-v16.x/api/async_context.html) context
|
|
630
|
+
/// of a <see>Connection.createContext</see> call.
|
|
631
|
+
///
|
|
632
|
+
/// By default, this will set a `connection` property on the context,
|
|
633
|
+
/// which will be the value of this connection instance. It also sets
|
|
634
|
+
/// a `connection` property on the sub-contexts for each model. This
|
|
635
|
+
/// is because models might have different connections, and so need
|
|
636
|
+
/// a context per-model to work properly.
|
|
637
|
+
///
|
|
638
|
+
/// "How could a model have different connections?" you ask? Well, it
|
|
639
|
+
/// probably won't. But being as this is an [AsyncLocalStorage](https://nodejs.org/docs/latest-v16.x/api/async_context.html)
|
|
640
|
+
/// context, it provides the connection to **every** model inside the context.
|
|
641
|
+
/// Your application might be using other models that aren't part of this connection,
|
|
642
|
+
/// and we wouldn't want those to get the wrong connection for those models.
|
|
643
|
+
///
|
|
644
|
+
/// Arguments:
|
|
645
|
+
/// connection?: <see>Connection</see> = this
|
|
646
|
+
/// The connection to create the context for. This can be provided, and
|
|
647
|
+
/// is used in place of `this` instance, for example, in the case of transactions.
|
|
648
|
+
/// Transactions generally are the "same" *connection*, but not the same *instance*.
|
|
649
|
+
///
|
|
650
|
+
/// Return: Map<any, any>
|
|
651
|
+
/// The new context that will be used for <see>Connection.createContext</see>.
|
|
313
652
|
buildConnectionContext(_connection) {
|
|
314
653
|
let connection = _connection || this;
|
|
315
654
|
let models = connection._models;
|
|
@@ -329,38 +668,118 @@ class ConnectionBase extends EventEmitter {
|
|
|
329
668
|
return newContext;
|
|
330
669
|
}
|
|
331
670
|
|
|
671
|
+
/// Create a connection context to serve all code
|
|
672
|
+
/// running inside it this connection.
|
|
673
|
+
///
|
|
674
|
+
/// This uses [AsyncLocalStorage](https://nodejs.org/docs/latest-v16.x/api/async_context.html)
|
|
675
|
+
/// to create a context that is passed through the entire call stack of the callback. In this
|
|
676
|
+
/// way, a connection can be provided to every model and every operation within the call.
|
|
677
|
+
///
|
|
678
|
+
/// Arguments:
|
|
679
|
+
/// callback: async Function
|
|
680
|
+
/// The method to provide the context to. Every call inside this call stack
|
|
681
|
+
/// will be provided the connection.
|
|
682
|
+
/// connection?: <see>Connection</see> = this
|
|
683
|
+
/// The connection to provide. Generally this will just be `this` connection instance,
|
|
684
|
+
/// however, it can be specified, and is for example inside transactions.
|
|
685
|
+
/// thisArg?: any = this
|
|
686
|
+
/// The `this` value to provide to the given `callback`.
|
|
687
|
+
///
|
|
688
|
+
/// Return: any
|
|
689
|
+
/// The return value of the given `callback`.
|
|
332
690
|
async createContext(callback, _connection, thisArg) {
|
|
333
691
|
let connection = _connection || this;
|
|
334
692
|
let context = this.buildConnectionContext(connection);
|
|
335
693
|
|
|
336
694
|
return await Utils.runInContext(context, async () => {
|
|
337
|
-
return await callback.call(thisArg, connection);
|
|
695
|
+
return await callback.call(thisArg || this, connection);
|
|
338
696
|
});
|
|
339
697
|
}
|
|
340
698
|
|
|
699
|
+
/// Find a specific field across all registered models.
|
|
700
|
+
///
|
|
701
|
+
/// This method is similar to [Array.find](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find),
|
|
702
|
+
/// except that the arguments to this `finder` method are those provided by
|
|
703
|
+
/// <see name="Model.iterateFields">Model.static iterateFields</see>. If this `finder` method
|
|
704
|
+
/// returns a truthy value for a given field, then that is the field that will be returned.
|
|
705
|
+
///
|
|
706
|
+
/// Note:
|
|
707
|
+
/// This will search for the field across all models registered to the connection.
|
|
708
|
+
/// To find a specific field for a known model use <see>Connection.getField</see> instead.
|
|
709
|
+
///
|
|
710
|
+
/// Arguments:
|
|
711
|
+
/// finder: Function
|
|
712
|
+
/// A function to assist in finding the specified field. The signature for this
|
|
713
|
+
/// function must match that used by <see name="Model.iterateFields">Model.static iterateFields</see>.
|
|
714
|
+
///
|
|
715
|
+
/// Return: Field | undefined
|
|
716
|
+
/// The field found, if any.
|
|
341
717
|
findModelField(finder) {
|
|
342
718
|
let modelMap = this.getModels();
|
|
343
719
|
let modelNames = Object.keys(modelMap);
|
|
344
|
-
let results = [];
|
|
345
720
|
|
|
346
721
|
for (let i = 0, il = modelNames.length; i < il; i++) {
|
|
347
722
|
let modelName = modelNames[i];
|
|
348
723
|
let Model = modelMap[modelName];
|
|
724
|
+
let value = Model.iterateFields(finder, null, false, true);
|
|
349
725
|
|
|
350
|
-
|
|
726
|
+
if (value)
|
|
727
|
+
return value;
|
|
351
728
|
}
|
|
352
|
-
|
|
353
|
-
return results;
|
|
354
729
|
}
|
|
355
730
|
|
|
731
|
+
/// This is simply a convenience method that
|
|
732
|
+
/// calls <see>ModelUtils.parseQualifiedName</see>.
|
|
733
|
+
///
|
|
734
|
+
/// See: ModelUtils.parseQualifiedName
|
|
735
|
+
///
|
|
736
|
+
/// Arguments:
|
|
737
|
+
/// fieldName: string
|
|
738
|
+
/// The field name, fully qualified field name, or model name to parse.
|
|
739
|
+
/// See <see>ModelUtils.parseQualifiedName</see> for more information.
|
|
740
|
+
///
|
|
741
|
+
/// Return: object
|
|
742
|
+
/// The result. See <see>ModelUtils.parseQualifiedName</see> for more information.
|
|
356
743
|
parseQualifiedName(str) {
|
|
357
744
|
return Utils.parseQualifiedName(str);
|
|
358
745
|
}
|
|
359
746
|
|
|
747
|
+
/// Get all models known to this connection.
|
|
748
|
+
/// Models are returned as a raw `Object`, and
|
|
749
|
+
/// so can be destructured. The keys of the returned
|
|
750
|
+
/// object are the model's names.
|
|
751
|
+
///
|
|
752
|
+
/// Models can be registered to a connection with the
|
|
753
|
+
/// <see>ConnectionBase.registerModel</see> or
|
|
754
|
+
/// <see>ConnectionBase.registerModels</see> methods.
|
|
755
|
+
///
|
|
756
|
+
/// Return: object
|
|
757
|
+
/// An object of all models known to the connection, where
|
|
758
|
+
/// each key is a model name, and each property value is
|
|
759
|
+
/// the model's class.
|
|
360
760
|
getModels() {
|
|
361
761
|
return this._models;
|
|
362
762
|
}
|
|
363
763
|
|
|
764
|
+
/// Retrieve a single model by its name.
|
|
765
|
+
/// The model must be registered with this
|
|
766
|
+
/// connection to be found.
|
|
767
|
+
///
|
|
768
|
+
/// Models can be registered to a connection with the
|
|
769
|
+
/// <see>ConnectionBase.registerModel</see> or
|
|
770
|
+
/// <see>ConnectionBase.registerModels</see> methods.
|
|
771
|
+
///
|
|
772
|
+
/// This method is "fully qualified aware", meaning you
|
|
773
|
+
/// can pass a fully qualified name, such as "User:id"
|
|
774
|
+
/// and it will fetch the "User" model.
|
|
775
|
+
///
|
|
776
|
+
/// Return: class <see>Model</see>
|
|
777
|
+
/// The model class found by the model's name, or
|
|
778
|
+
/// `undefined` if no model is found.
|
|
779
|
+
///
|
|
780
|
+
/// Arguments:
|
|
781
|
+
/// modelName: string
|
|
782
|
+
/// The model's name, or a fully qualified field name.
|
|
364
783
|
getModel(modelName) {
|
|
365
784
|
if (typeof modelName === 'symbol')
|
|
366
785
|
return;
|
|
@@ -369,6 +788,20 @@ class ConnectionBase extends EventEmitter {
|
|
|
369
788
|
return this._models[def.modelName];
|
|
370
789
|
}
|
|
371
790
|
|
|
791
|
+
/// Get a field by its fully qualified name,
|
|
792
|
+
/// or by a fieldName + a modelName.
|
|
793
|
+
///
|
|
794
|
+
/// Return: <see>Field</see>
|
|
795
|
+
/// The field found, or `undefined` if the specified field is
|
|
796
|
+
/// not found.
|
|
797
|
+
///
|
|
798
|
+
/// Arguments:
|
|
799
|
+
/// fieldName: string
|
|
800
|
+
/// Fully qualified field name. If a fully qualified field name
|
|
801
|
+
/// isn't provided, then you *must* provide the `modelName` argument.
|
|
802
|
+
/// modelName?: string
|
|
803
|
+
/// The name of the model that the field exists on. This argument is
|
|
804
|
+
/// optional if the provided `fieldName` is a fully qualified name.
|
|
372
805
|
getField(fieldName, modelName) {
|
|
373
806
|
let def = this.parseQualifiedName(fieldName);
|
|
374
807
|
if (def.modelName == null)
|
|
@@ -381,19 +814,86 @@ class ConnectionBase extends EventEmitter {
|
|
|
381
814
|
return Model.getField(def.fieldNames[0]);
|
|
382
815
|
}
|
|
383
816
|
|
|
817
|
+
/// Return the <see>QueryEngine</see> class used
|
|
818
|
+
/// for this connection, all its models, and all
|
|
819
|
+
/// query operations. By default this is just the
|
|
820
|
+
/// built-in <see>QueryEngine</see> that Mythix ORM
|
|
821
|
+
/// provides. You can create your own, and provide
|
|
822
|
+
/// it as the `QueryEngine` option to the connection
|
|
823
|
+
/// when you create the connection.
|
|
824
|
+
///
|
|
825
|
+
/// Return: class <see>QueryEngine</see>
|
|
826
|
+
/// The QueryEngine to use for this connection, all
|
|
827
|
+
/// its models, and all query operations for this
|
|
828
|
+
/// connection.
|
|
384
829
|
getQueryEngineClass() {
|
|
385
830
|
let options = this.getOptions();
|
|
386
831
|
return options.QueryEngine;
|
|
387
832
|
}
|
|
388
833
|
|
|
834
|
+
/// Get the <see>QueryGenerator</see> instance
|
|
835
|
+
/// for this connection, if it has one.
|
|
836
|
+
///
|
|
837
|
+
/// All connection drivers may not have a query generator.
|
|
838
|
+
/// The query generator is the class that takes care of
|
|
839
|
+
/// generating queries for the underlying database (i.e. SQL).
|
|
840
|
+
/// If a query generator exists on a connection, it is very
|
|
841
|
+
/// likely to be unique to the connection (i.e. PostgreSQL and MySQL
|
|
842
|
+
/// have different query generators).
|
|
843
|
+
///
|
|
844
|
+
/// Return: <see>QueryGenerator</see> | null
|
|
845
|
+
/// Return the <see>QueryGenerator</see> for this connection,
|
|
846
|
+
/// or return `null` if none is defined for this connection.
|
|
389
847
|
getQueryGenerator() {
|
|
390
848
|
return this.queryGenerator;
|
|
391
849
|
}
|
|
392
850
|
|
|
851
|
+
/// Set the <see>QueryGenerator</see> instance for this
|
|
852
|
+
/// connection. This is rarely used as the <see>QueryGenerator</see>
|
|
853
|
+
/// is often supplied as connection options when creating
|
|
854
|
+
/// the connection (as the `queryGenerator` option). However,
|
|
855
|
+
/// it can be set to a new instance at any time with this
|
|
856
|
+
/// method.
|
|
857
|
+
///
|
|
858
|
+
/// Return: undefined
|
|
859
|
+
///
|
|
860
|
+
/// Arguments:
|
|
861
|
+
/// queryGenerator: <see>QueryGenerator</see> | null
|
|
862
|
+
/// The new <see>QueryGenerator</see> instance to use
|
|
863
|
+
/// for generating underlying database queries. Set
|
|
864
|
+
/// to `null` to specify no query generator (note:
|
|
865
|
+
/// this might break whatever connection you are using
|
|
866
|
+
/// as most connections require their query generator).
|
|
393
867
|
setQueryGenerator(queryGenerator) {
|
|
394
868
|
this.queryGenerator = queryGenerator;
|
|
395
869
|
}
|
|
396
870
|
|
|
871
|
+
/// The low-level DB interface for escaping a
|
|
872
|
+
/// value. By default this function uses the
|
|
873
|
+
/// [sqlstring](https://www.npmjs.com/package/sqlstring)
|
|
874
|
+
/// module to escape values. However, the `escape`
|
|
875
|
+
/// method for whatever database the connection is
|
|
876
|
+
/// using should be used instead of this. This is
|
|
877
|
+
/// a "default implementation" that is meant as a
|
|
878
|
+
/// fallback when a connection doesn't provide its
|
|
879
|
+
/// own, but each connection should provide its own
|
|
880
|
+
/// when it is able.
|
|
881
|
+
///
|
|
882
|
+
/// Note:
|
|
883
|
+
/// This method escapes "values" that are given in
|
|
884
|
+
/// the underlying query language of the database.
|
|
885
|
+
/// To escape identifiers, use the <see>ConnectionBase._escapeID</see>
|
|
886
|
+
/// instead.
|
|
887
|
+
///
|
|
888
|
+
/// Return: string
|
|
889
|
+
/// The value provided, escaped for the specific
|
|
890
|
+
/// underlying database driver.
|
|
891
|
+
///
|
|
892
|
+
/// Arguments:
|
|
893
|
+
/// value: any
|
|
894
|
+
/// The value to escape. This could be a number, a boolean,
|
|
895
|
+
/// a string, or anything else that can be provided to your
|
|
896
|
+
/// specific database.
|
|
397
897
|
_escape(value) {
|
|
398
898
|
if (Nife.instanceOf(value, 'string'))
|
|
399
899
|
return `'${value.replace(/'/g, '\'\'')}'`;
|
|
@@ -401,6 +901,64 @@ class ConnectionBase extends EventEmitter {
|
|
|
401
901
|
return SqlString.escape(value);
|
|
402
902
|
}
|
|
403
903
|
|
|
904
|
+
/// Unlike <see>ConnectionBase._escape</see> --which is
|
|
905
|
+
/// a low-level interface for the database-- this method
|
|
906
|
+
/// will escape specific values in specific ways needed
|
|
907
|
+
/// by Mythix ORM. Said another way, whereas <see>ConnectionBase._escape</see>
|
|
908
|
+
/// is a "low level database method", this is a "high level
|
|
909
|
+
/// Mythix ORM" method.
|
|
910
|
+
///
|
|
911
|
+
/// If this method is provided a literal, then it will convert
|
|
912
|
+
/// the literal into a string, and return the resulting string.
|
|
913
|
+
/// This is the purpose of the `options` argument. The `options`
|
|
914
|
+
/// argument will be passed to the literal's `toString` method.
|
|
915
|
+
///
|
|
916
|
+
/// For any non-literal value, it is first passed through the
|
|
917
|
+
/// field's `serialize` method, for example `value = field.type.serialize(value, thisConnection);`.
|
|
918
|
+
/// This generally won't modify the incoming value, but it might,
|
|
919
|
+
/// for example, with DATE, or DATETIME types, that are modified
|
|
920
|
+
/// to match an acceptable format for the underlying database.
|
|
921
|
+
///
|
|
922
|
+
/// If this method is provided a boolean, then it will return
|
|
923
|
+
/// an upper-cased version of the boolean as a string, i.e. `true` will be returned
|
|
924
|
+
/// as `'TRUE'`, and `false` will be returned as `'FALSE'`.
|
|
925
|
+
///
|
|
926
|
+
/// If this method is provided a BigInt, then it will convert the
|
|
927
|
+
/// bigint into a string representation of the number, i.e. 42n will
|
|
928
|
+
/// be returned as `'42'`.
|
|
929
|
+
///
|
|
930
|
+
/// If this method is provided an `Array` value, then the array
|
|
931
|
+
/// is processed by the connection-specific `prepareArrayValuesForSQL`
|
|
932
|
+
/// method. By default, this method will complete the following operations
|
|
933
|
+
/// on the provided array:
|
|
934
|
+
///
|
|
935
|
+
/// 1. It will flatten the provided array into a 1D array
|
|
936
|
+
/// 2. It will filter the array, such that it removes `undefined`, and any value that isn't a <see>LiteralBase</see>, a `null`, a `string`, a `boolean`, a `number`, or a `bigint`
|
|
937
|
+
/// 3. It will further filter out duplicate values from the array, such that the processed array only contains unique values
|
|
938
|
+
///
|
|
939
|
+
/// After the array is processed with the `prepareArrayValuesForSQL` method,
|
|
940
|
+
/// it will then be mapped such that each value is passed through this
|
|
941
|
+
/// `escape` method, and then all remaining values in the array will be
|
|
942
|
+
/// joined with a `,` character between each element. The idea here is that
|
|
943
|
+
/// if you are providing an array to the underlying database, it is usually
|
|
944
|
+
/// for an `IN` or `NOT IN` operator, so the result will generally be used for
|
|
945
|
+
/// one of these. Keep in mind however that each connection driver might escape
|
|
946
|
+
/// values (including arrays) differently.
|
|
947
|
+
///
|
|
948
|
+
/// All other provided values are simply handed off to <see>ConnectionBase._escape</see>.
|
|
949
|
+
///
|
|
950
|
+
/// Return: string
|
|
951
|
+
/// The escaped value, as a string.
|
|
952
|
+
///
|
|
953
|
+
/// Arguments:
|
|
954
|
+
/// field: <see>Field</see>
|
|
955
|
+
/// The field this value is coming from.
|
|
956
|
+
/// value: any
|
|
957
|
+
/// The value to escape.
|
|
958
|
+
/// options?: object
|
|
959
|
+
/// The options to provide to a Literal's `toString`
|
|
960
|
+
/// method. This `options` object is only ever used
|
|
961
|
+
/// if the provided `value` is a Literal.
|
|
404
962
|
escape(field, _value, options) {
|
|
405
963
|
var value = _value;
|
|
406
964
|
if (LiteralBase.isLiteral(value))
|
|
@@ -425,11 +983,49 @@ class ConnectionBase extends EventEmitter {
|
|
|
425
983
|
return this._escape(value);
|
|
426
984
|
}
|
|
427
985
|
|
|
986
|
+
/// Low-level database method for escaping an identifier.
|
|
987
|
+
/// Each database driver should provide its own version of
|
|
988
|
+
/// this method. This is the "default" method Mythix ORM
|
|
989
|
+
/// provides as a "fallback" to database drivers that don't
|
|
990
|
+
/// supply their own.
|
|
991
|
+
///
|
|
992
|
+
/// It works by first stripping all quotes (single `'`, double `"`, and backtick `` ` ``)
|
|
993
|
+
/// from the provided `value`. After this, it will split on the period (dot) character
|
|
994
|
+
/// `.`, and then will map each resulting part through [sqlstring](https://www.npmjs.com/package/sqlstring)
|
|
995
|
+
/// `escapeId` method, finally re-joining the parts with a period `.` character.
|
|
996
|
+
///
|
|
997
|
+
/// The extra processing is to allow for already escaped identifiers to not be double-escaped.
|
|
998
|
+
///
|
|
999
|
+
/// Return: string
|
|
1000
|
+
/// The provided identifier, escaped for the underlying database.
|
|
1001
|
+
///
|
|
1002
|
+
/// Arguments:
|
|
1003
|
+
/// value: string
|
|
1004
|
+
/// The identifier to escape.
|
|
428
1005
|
_escapeID(value) {
|
|
429
1006
|
let parts = value.replace(/['"`]/g, '').split(/\.+/g);
|
|
430
1007
|
return parts.map((part) => SqlString.escapeId(part).replace(/^`/, '"').replace(/`$/, '"')).join('.');
|
|
431
1008
|
}
|
|
432
1009
|
|
|
1010
|
+
/// This method is very similar to <see>ConnectionBase._escapeID</see>,
|
|
1011
|
+
/// except that instead of being a "low level database method" that the
|
|
1012
|
+
/// database driver itself provides, this is the "Mythix ORM" implementation
|
|
1013
|
+
/// of escaping identifiers. The only difference from <see>ConnectionBase._escapeID</see>
|
|
1014
|
+
/// is that if the provided value is a Literal, it will be converted to a
|
|
1015
|
+
/// string and returned *without* being escaped. Literals are never modified,
|
|
1016
|
+
/// and are always provided to the underlying database exactly as they were defined.
|
|
1017
|
+
///
|
|
1018
|
+
/// Return: string
|
|
1019
|
+
/// The escaped identifier, or if `value` is a Literal, the Literal
|
|
1020
|
+
/// converted to a string.
|
|
1021
|
+
///
|
|
1022
|
+
/// Arguments:
|
|
1023
|
+
/// value: string
|
|
1024
|
+
/// The identifier to escape. If this is a Literal instead of a string,
|
|
1025
|
+
/// then the Literal will be converted to a string and returned.
|
|
1026
|
+
/// options?: object
|
|
1027
|
+
/// The options to pass to `Literal.toString`. This options object is only
|
|
1028
|
+
/// used if the provided `value` is a Literal instance.
|
|
433
1029
|
escapeID(value, options) {
|
|
434
1030
|
if (LiteralBase.isLiteral(value))
|
|
435
1031
|
return value.toString(this.connection, options);
|
|
@@ -437,6 +1033,34 @@ class ConnectionBase extends EventEmitter {
|
|
|
437
1033
|
return this._escapeID(value);
|
|
438
1034
|
}
|
|
439
1035
|
|
|
1036
|
+
/// Convert the provided <see>AverageLiteral</see> to a string
|
|
1037
|
+
/// for the underlying database driver. The conversion
|
|
1038
|
+
/// will be database specific. The database driver connection
|
|
1039
|
+
/// is free to override this method.
|
|
1040
|
+
///
|
|
1041
|
+
/// Note:
|
|
1042
|
+
/// This method is a proxy method for <see>QueryGenerator._averageLiteralToString</see>.
|
|
1043
|
+
/// If the connection has no instance of a `queryGenerator` available to it,
|
|
1044
|
+
/// then this method will simply return `undefined`.
|
|
1045
|
+
///
|
|
1046
|
+
/// Note:
|
|
1047
|
+
/// Generally speaking, Literal "options" are literal (and connection) specific. They often aren't
|
|
1048
|
+
/// needed or used directly by the user, but instead are used by the underlying
|
|
1049
|
+
/// connection itself, to define context specific options. For example, the underlying
|
|
1050
|
+
/// connection might have an option to tell a literal that it is the "DEFAULT" value
|
|
1051
|
+
/// of a field, instead of just a raw value to inject in the generated query stream,
|
|
1052
|
+
/// and this might change the output of the literal when converted to a string.
|
|
1053
|
+
///
|
|
1054
|
+
/// Return: string
|
|
1055
|
+
/// The provided <see>AverageLiteral</see> converted to
|
|
1056
|
+
/// a string for the underlying database driver.
|
|
1057
|
+
///
|
|
1058
|
+
/// Arguments:
|
|
1059
|
+
/// literal: <see>AverageLiteral</see>
|
|
1060
|
+
/// The literal to convert to a string for the database.
|
|
1061
|
+
/// options?: object
|
|
1062
|
+
/// Optional options to pass to the <see>QueryGenerator._averageLiteralToString</see>
|
|
1063
|
+
/// method.
|
|
440
1064
|
_averageLiteralToString(literal, options) {
|
|
441
1065
|
if (!literal || !LiteralBase.isLiteral(literal))
|
|
442
1066
|
return;
|
|
@@ -448,6 +1072,34 @@ class ConnectionBase extends EventEmitter {
|
|
|
448
1072
|
return queryGenerator._averageLiteralToString(literal, options);
|
|
449
1073
|
}
|
|
450
1074
|
|
|
1075
|
+
/// Convert the provided <see>CountLiteral</see> to a string
|
|
1076
|
+
/// for the underlying database driver. The conversion
|
|
1077
|
+
/// will be database specific. The database driver connection
|
|
1078
|
+
/// is free to override this method.
|
|
1079
|
+
///
|
|
1080
|
+
/// Note:
|
|
1081
|
+
/// This method is a proxy method for <see>QueryGenerator._countLiteralToString</see>.
|
|
1082
|
+
/// If the connection has no instance of a `queryGenerator` available to it,
|
|
1083
|
+
/// then this method will simply return `undefined`.
|
|
1084
|
+
///
|
|
1085
|
+
/// Note:
|
|
1086
|
+
/// Generally speaking, Literal "options" are literal (and connection) specific. They often aren't
|
|
1087
|
+
/// needed or used directly by the user, but instead are used by the underlying
|
|
1088
|
+
/// connection itself, to define context specific options. For example, the underlying
|
|
1089
|
+
/// connection might have an option to tell a literal that it is the "DEFAULT" value
|
|
1090
|
+
/// of a field, instead of just a raw value to inject in the generated query stream,
|
|
1091
|
+
/// and this might change the output of the literal when converted to a string.
|
|
1092
|
+
///
|
|
1093
|
+
/// Return: string
|
|
1094
|
+
/// The provided <see>CountLiteral</see> converted to
|
|
1095
|
+
/// a string for the underlying database driver.
|
|
1096
|
+
///
|
|
1097
|
+
/// Arguments:
|
|
1098
|
+
/// literal: <see>CountLiteral</see>
|
|
1099
|
+
/// The literal to convert to a string for the database.
|
|
1100
|
+
/// options?: object
|
|
1101
|
+
/// Optional options to pass to the <see>QueryGenerator._countLiteralToString</see>
|
|
1102
|
+
/// method.
|
|
451
1103
|
_countLiteralToString(literal, options) {
|
|
452
1104
|
if (!literal || !LiteralBase.isLiteral(literal))
|
|
453
1105
|
return;
|
|
@@ -459,6 +1111,34 @@ class ConnectionBase extends EventEmitter {
|
|
|
459
1111
|
return queryGenerator._countLiteralToString(literal, options);
|
|
460
1112
|
}
|
|
461
1113
|
|
|
1114
|
+
/// Convert the provided <see>DistinctLiteral</see> to a string
|
|
1115
|
+
/// for the underlying database driver. The conversion
|
|
1116
|
+
/// will be database specific. The database driver connection
|
|
1117
|
+
/// is free to override this method.
|
|
1118
|
+
///
|
|
1119
|
+
/// Note:
|
|
1120
|
+
/// This method is a proxy method for <see>QueryGenerator._distinctLiteralToString</see>.
|
|
1121
|
+
/// If the connection has no instance of a `queryGenerator` available to it,
|
|
1122
|
+
/// then this method will simply return `undefined`.
|
|
1123
|
+
///
|
|
1124
|
+
/// Note:
|
|
1125
|
+
/// Generally speaking, Literal "options" are literal (and connection) specific. They often aren't
|
|
1126
|
+
/// needed or used directly by the user, but instead are used by the underlying
|
|
1127
|
+
/// connection itself, to define context specific options. For example, the underlying
|
|
1128
|
+
/// connection might have an option to tell a literal that it is the "DEFAULT" value
|
|
1129
|
+
/// of a field, instead of just a raw value to inject in the generated query stream,
|
|
1130
|
+
/// and this might change the output of the literal when converted to a string.
|
|
1131
|
+
///
|
|
1132
|
+
/// Return: string
|
|
1133
|
+
/// The provided <see>DistinctLiteral</see> converted to
|
|
1134
|
+
/// a string for the underlying database driver.
|
|
1135
|
+
///
|
|
1136
|
+
/// Arguments:
|
|
1137
|
+
/// literal: <see>DistinctLiteral</see>
|
|
1138
|
+
/// The literal to convert to a string for the database.
|
|
1139
|
+
/// options?: object
|
|
1140
|
+
/// Optional options to pass to the <see>QueryGenerator._distinctLiteralToString</see>
|
|
1141
|
+
/// method.
|
|
462
1142
|
_distinctLiteralToString(literal, options) {
|
|
463
1143
|
if (!literal || !LiteralBase.isLiteral(literal))
|
|
464
1144
|
return;
|
|
@@ -470,6 +1150,34 @@ class ConnectionBase extends EventEmitter {
|
|
|
470
1150
|
return queryGenerator._distinctLiteralToString(literal, options);
|
|
471
1151
|
}
|
|
472
1152
|
|
|
1153
|
+
/// Convert the provided <see>FieldLiteral</see> to a string
|
|
1154
|
+
/// for the underlying database driver. The conversion
|
|
1155
|
+
/// will be database specific. The database driver connection
|
|
1156
|
+
/// is free to override this method.
|
|
1157
|
+
///
|
|
1158
|
+
/// Note:
|
|
1159
|
+
/// This method is a proxy method for <see>QueryGenerator._fieldLiteralToString</see>.
|
|
1160
|
+
/// If the connection has no instance of a `queryGenerator` available to it,
|
|
1161
|
+
/// then this method will simply return `undefined`.
|
|
1162
|
+
///
|
|
1163
|
+
/// Note:
|
|
1164
|
+
/// Generally speaking, Literal "options" are literal (and connection) specific. They often aren't
|
|
1165
|
+
/// needed or used directly by the user, but instead are used by the underlying
|
|
1166
|
+
/// connection itself, to define context specific options. For example, the underlying
|
|
1167
|
+
/// connection might have an option to tell a literal that it is the "DEFAULT" value
|
|
1168
|
+
/// of a field, instead of just a raw value to inject in the generated query stream,
|
|
1169
|
+
/// and this might change the output of the literal when converted to a string.
|
|
1170
|
+
///
|
|
1171
|
+
/// Return: string
|
|
1172
|
+
/// The provided <see>FieldLiteral</see> converted to
|
|
1173
|
+
/// a string for the underlying database driver.
|
|
1174
|
+
///
|
|
1175
|
+
/// Arguments:
|
|
1176
|
+
/// literal: <see>FieldLiteral</see>
|
|
1177
|
+
/// The literal to convert to a string for the database.
|
|
1178
|
+
/// options?: object
|
|
1179
|
+
/// Optional options to pass to the <see>QueryGenerator._fieldLiteralToString</see>
|
|
1180
|
+
/// method.
|
|
473
1181
|
_fieldLiteralToString(literal, options) {
|
|
474
1182
|
if (!literal || !LiteralBase.isLiteral(literal))
|
|
475
1183
|
return;
|
|
@@ -481,6 +1189,34 @@ class ConnectionBase extends EventEmitter {
|
|
|
481
1189
|
return queryGenerator._fieldLiteralToString(literal, options);
|
|
482
1190
|
}
|
|
483
1191
|
|
|
1192
|
+
/// Convert the provided <see>MaxLiteral</see> to a string
|
|
1193
|
+
/// for the underlying database driver. The conversion
|
|
1194
|
+
/// will be database specific. The database driver connection
|
|
1195
|
+
/// is free to override this method.
|
|
1196
|
+
///
|
|
1197
|
+
/// Note:
|
|
1198
|
+
/// This method is a proxy method for <see>QueryGenerator._maxLiteralToString</see>.
|
|
1199
|
+
/// If the connection has no instance of a `queryGenerator` available to it,
|
|
1200
|
+
/// then this method will simply return `undefined`.
|
|
1201
|
+
///
|
|
1202
|
+
/// Note:
|
|
1203
|
+
/// Generally speaking, Literal "options" are literal (and connection) specific. They often aren't
|
|
1204
|
+
/// needed or used directly by the user, but instead are used by the underlying
|
|
1205
|
+
/// connection itself, to define context specific options. For example, the underlying
|
|
1206
|
+
/// connection might have an option to tell a literal that it is the "DEFAULT" value
|
|
1207
|
+
/// of a field, instead of just a raw value to inject in the generated query stream,
|
|
1208
|
+
/// and this might change the output of the literal when converted to a string.
|
|
1209
|
+
///
|
|
1210
|
+
/// Return: string
|
|
1211
|
+
/// The provided <see>MaxLiteral</see> converted to
|
|
1212
|
+
/// a string for the underlying database driver.
|
|
1213
|
+
///
|
|
1214
|
+
/// Arguments:
|
|
1215
|
+
/// literal: <see>MaxLiteral</see>
|
|
1216
|
+
/// The literal to convert to a string for the database.
|
|
1217
|
+
/// options?: object
|
|
1218
|
+
/// Optional options to pass to the <see>QueryGenerator._maxLiteralToString</see>
|
|
1219
|
+
/// method.
|
|
484
1220
|
_maxLiteralToString(literal, options) {
|
|
485
1221
|
if (!literal || !LiteralBase.isLiteral(literal))
|
|
486
1222
|
return;
|
|
@@ -492,6 +1228,34 @@ class ConnectionBase extends EventEmitter {
|
|
|
492
1228
|
return queryGenerator._maxLiteralToString(literal, options);
|
|
493
1229
|
}
|
|
494
1230
|
|
|
1231
|
+
/// Convert the provided <see>MinLiteral</see> to a string
|
|
1232
|
+
/// for the underlying database driver. The conversion
|
|
1233
|
+
/// will be database specific. The database driver connection
|
|
1234
|
+
/// is free to override this method.
|
|
1235
|
+
///
|
|
1236
|
+
/// Note:
|
|
1237
|
+
/// This method is a proxy method for <see>QueryGenerator._minLiteralToString</see>.
|
|
1238
|
+
/// If the connection has no instance of a `queryGenerator` available to it,
|
|
1239
|
+
/// then this method will simply return `undefined`.
|
|
1240
|
+
///
|
|
1241
|
+
/// Note:
|
|
1242
|
+
/// Generally speaking, Literal "options" are literal (and connection) specific. They often aren't
|
|
1243
|
+
/// needed or used directly by the user, but instead are used by the underlying
|
|
1244
|
+
/// connection itself, to define context specific options. For example, the underlying
|
|
1245
|
+
/// connection might have an option to tell a literal that it is the "DEFAULT" value
|
|
1246
|
+
/// of a field, instead of just a raw value to inject in the generated query stream,
|
|
1247
|
+
/// and this might change the output of the literal when converted to a string.
|
|
1248
|
+
///
|
|
1249
|
+
/// Return: string
|
|
1250
|
+
/// The provided <see>MinLiteral</see> converted to
|
|
1251
|
+
/// a string for the underlying database driver.
|
|
1252
|
+
///
|
|
1253
|
+
/// Arguments:
|
|
1254
|
+
/// literal: <see>MinLiteral</see>
|
|
1255
|
+
/// The literal to convert to a string for the database.
|
|
1256
|
+
/// options?: object
|
|
1257
|
+
/// Optional options to pass to the <see>QueryGenerator._minLiteralToString</see>
|
|
1258
|
+
/// method.
|
|
495
1259
|
_minLiteralToString(literal, options) {
|
|
496
1260
|
if (!literal || !LiteralBase.isLiteral(literal))
|
|
497
1261
|
return;
|
|
@@ -503,6 +1267,34 @@ class ConnectionBase extends EventEmitter {
|
|
|
503
1267
|
return queryGenerator._minLiteralToString(literal, options);
|
|
504
1268
|
}
|
|
505
1269
|
|
|
1270
|
+
/// Convert the provided <see>SumLiteral</see> to a string
|
|
1271
|
+
/// for the underlying database driver. The conversion
|
|
1272
|
+
/// will be database specific. The database driver connection
|
|
1273
|
+
/// is free to override this method.
|
|
1274
|
+
///
|
|
1275
|
+
/// Note:
|
|
1276
|
+
/// This method is a proxy method for <see>QueryGenerator._sumLiteralToString</see>.
|
|
1277
|
+
/// If the connection has no instance of a `queryGenerator` available to it,
|
|
1278
|
+
/// then this method will simply return `undefined`.
|
|
1279
|
+
///
|
|
1280
|
+
/// Note:
|
|
1281
|
+
/// Generally speaking, Literal "options" are literal (and connection) specific. They often aren't
|
|
1282
|
+
/// needed or used directly by the user, but instead are used by the underlying
|
|
1283
|
+
/// connection itself, to define context specific options. For example, the underlying
|
|
1284
|
+
/// connection might have an option to tell a literal that it is the "DEFAULT" value
|
|
1285
|
+
/// of a field, instead of just a raw value to inject in the generated query stream,
|
|
1286
|
+
/// and this might change the output of the literal when converted to a string.
|
|
1287
|
+
///
|
|
1288
|
+
/// Return: string
|
|
1289
|
+
/// The provided <see>SumLiteral</see> converted to
|
|
1290
|
+
/// a string for the underlying database driver.
|
|
1291
|
+
///
|
|
1292
|
+
/// Arguments:
|
|
1293
|
+
/// literal: <see>SumLiteral</see>
|
|
1294
|
+
/// The literal to convert to a string for the database.
|
|
1295
|
+
/// options?: object
|
|
1296
|
+
/// Optional options to pass to the <see>QueryGenerator._sumLiteralToString</see>
|
|
1297
|
+
/// method.
|
|
506
1298
|
_sumLiteralToString(literal, options) {
|
|
507
1299
|
if (!literal || !LiteralBase.isLiteral(literal))
|
|
508
1300
|
return;
|
|
@@ -514,6 +1306,35 @@ class ConnectionBase extends EventEmitter {
|
|
|
514
1306
|
return queryGenerator._sumLiteralToString(literal, options);
|
|
515
1307
|
}
|
|
516
1308
|
|
|
1309
|
+
/// Convert the provided Literal to a string
|
|
1310
|
+
/// for the underlying database driver. The conversion
|
|
1311
|
+
/// will be database specific. The database driver connection
|
|
1312
|
+
/// is free to override this method.
|
|
1313
|
+
///
|
|
1314
|
+
/// This method will convert a <see>AverageLiteral</see>, a
|
|
1315
|
+
/// <see>CountLiteral</see>, a <see>DistinctLiteral</see>,
|
|
1316
|
+
/// a <see>FieldLiteral</see>, a <see>MaxLiteral</see>, a
|
|
1317
|
+
/// <see>MinLiteral</see>, a <see>SumLiteral</see>, or a
|
|
1318
|
+
/// <see>Literal</see> to a string. If the provided literal
|
|
1319
|
+
/// is not one of these types, than an exception will be thrown.
|
|
1320
|
+
///
|
|
1321
|
+
/// If you want to add custom literals to your application, then
|
|
1322
|
+
/// you will need to overload this method, and handle those custom
|
|
1323
|
+
/// literals manually (or simply stick to using <see>Literal</see>).
|
|
1324
|
+
///
|
|
1325
|
+
/// Return: string
|
|
1326
|
+
/// The provided literal, converted to a string for the underlying
|
|
1327
|
+
/// database driver.
|
|
1328
|
+
///
|
|
1329
|
+
/// Arguments:
|
|
1330
|
+
/// literal: <see>LiteralBase</see>
|
|
1331
|
+
/// The literal to convert.
|
|
1332
|
+
/// options?: object
|
|
1333
|
+
/// Optional options that can be passed to the literal conversion
|
|
1334
|
+
/// method. These are generally not provided by the user, but rather
|
|
1335
|
+
/// are often provided by the connection itself, for context-specific
|
|
1336
|
+
/// literal conversions. These options can and will changed based on
|
|
1337
|
+
/// the literal being converted, and the underlying connection.
|
|
517
1338
|
literalToString(literal, options) {
|
|
518
1339
|
if (Literals.AverageLiteral.isLiteralType(literal))
|
|
519
1340
|
return this._averageLiteralToString(literal, options);
|
|
@@ -535,86 +1356,308 @@ class ConnectionBase extends EventEmitter {
|
|
|
535
1356
|
throw new Error(`${this.constructor.name}::literalToString: Unsupported literal ${literal}.`);
|
|
536
1357
|
}
|
|
537
1358
|
|
|
1359
|
+
/// Convert a "BIGINT" field type to a type
|
|
1360
|
+
/// acceptable by the underlying database driver.
|
|
1361
|
+
///
|
|
1362
|
+
/// For most SQL connections this would be `BIGINT`,
|
|
1363
|
+
/// however, it may be different based on what database you are using.
|
|
1364
|
+
///
|
|
1365
|
+
/// Return: string
|
|
1366
|
+
/// The field type needed by the underlying database driver.
|
|
1367
|
+
///
|
|
1368
|
+
/// Arguments:
|
|
1369
|
+
/// type: <see>Type</see>
|
|
1370
|
+
/// The field type to convert to use in the underlying database.
|
|
538
1371
|
// eslint-disable-next-line no-unused-vars
|
|
539
1372
|
_bigintTypeToString(type) {
|
|
540
1373
|
return 'BIGINT';
|
|
541
1374
|
}
|
|
542
1375
|
|
|
1376
|
+
/// Convert a "BLOB" field type to a type
|
|
1377
|
+
/// acceptable by the underlying database driver.
|
|
1378
|
+
///
|
|
1379
|
+
/// For most SQL connections this would be `BLOB`,
|
|
1380
|
+
/// however, it may be different based on what database you are using.
|
|
1381
|
+
///
|
|
1382
|
+
/// Return: string
|
|
1383
|
+
/// The field type needed by the underlying database driver.
|
|
1384
|
+
///
|
|
1385
|
+
/// Arguments:
|
|
1386
|
+
/// type: <see>Type</see>
|
|
1387
|
+
/// The field type to convert to use in the underlying database.
|
|
543
1388
|
// eslint-disable-next-line no-unused-vars
|
|
544
1389
|
_blobTypeToString(type) {
|
|
545
1390
|
return 'BLOB';
|
|
546
1391
|
}
|
|
547
1392
|
|
|
1393
|
+
/// Convert a "BOOLEAN" field type to a type
|
|
1394
|
+
/// acceptable by the underlying database driver.
|
|
1395
|
+
///
|
|
1396
|
+
/// For most SQL connections this would be `BOOLEAN`,
|
|
1397
|
+
/// however, it may be different based on what database you are using.
|
|
1398
|
+
///
|
|
1399
|
+
/// Return: string
|
|
1400
|
+
/// The field type needed by the underlying database driver.
|
|
1401
|
+
///
|
|
1402
|
+
/// Arguments:
|
|
1403
|
+
/// type: <see>Type</see>
|
|
1404
|
+
/// The field type to convert to use in the underlying database.
|
|
548
1405
|
// eslint-disable-next-line no-unused-vars
|
|
549
1406
|
_booleanTypeToString(type) {
|
|
550
1407
|
return 'BOOLEAN';
|
|
551
1408
|
}
|
|
552
1409
|
|
|
1410
|
+
/// Convert a "CHAR" field type to a type
|
|
1411
|
+
/// acceptable by the underlying database driver.
|
|
1412
|
+
///
|
|
1413
|
+
/// For most SQL connections this would be `CHAR`,
|
|
1414
|
+
/// however, it may be different based on what database you are using.
|
|
1415
|
+
///
|
|
1416
|
+
/// Return: string
|
|
1417
|
+
/// The field type needed by the underlying database driver.
|
|
1418
|
+
///
|
|
1419
|
+
/// Arguments:
|
|
1420
|
+
/// type: <see>Type</see>
|
|
1421
|
+
/// The field type to convert to use in the underlying database.
|
|
553
1422
|
// eslint-disable-next-line no-unused-vars
|
|
554
1423
|
_charTypeToString(type) {
|
|
555
1424
|
return 'CHAR';
|
|
556
1425
|
}
|
|
557
1426
|
|
|
1427
|
+
/// Convert a "DATE" field type to a type
|
|
1428
|
+
/// acceptable by the underlying database driver.
|
|
1429
|
+
///
|
|
1430
|
+
/// For most SQL connections this would be `BIGINT`,
|
|
1431
|
+
/// however, it may be different based on what database you are using.
|
|
1432
|
+
///
|
|
1433
|
+
/// Note:
|
|
1434
|
+
/// Mythix ORM always stores DATE and DATETIME types as a timestamp
|
|
1435
|
+
/// (in milliseconds from the UNIX Epoch) whenever it is able to.
|
|
1436
|
+
/// This is why the default type for most connection drivers is
|
|
1437
|
+
/// `BIGINT`. Another common type for this conversion is `TIMESTAMP`.
|
|
1438
|
+
///
|
|
1439
|
+
/// Return: string
|
|
1440
|
+
/// The field type needed by the underlying database driver.
|
|
1441
|
+
///
|
|
1442
|
+
/// Arguments:
|
|
1443
|
+
/// type: <see>Type</see>
|
|
1444
|
+
/// The field type to convert to use in the underlying database.
|
|
558
1445
|
// eslint-disable-next-line no-unused-vars
|
|
559
1446
|
_dateTypeToString(type) {
|
|
560
1447
|
return 'TIMESTAMP';
|
|
561
1448
|
}
|
|
562
1449
|
|
|
1450
|
+
/// Convert a "DATETIME" field type to a type
|
|
1451
|
+
/// acceptable by the underlying database driver.
|
|
1452
|
+
///
|
|
1453
|
+
/// For most SQL connections this would be `BIGINT`,
|
|
1454
|
+
/// however, it may be different based on what database you are using.
|
|
1455
|
+
///
|
|
1456
|
+
/// Note:
|
|
1457
|
+
/// Mythix ORM always stores DATE and DATETIME types as a timestamp
|
|
1458
|
+
/// (in milliseconds from the UNIX Epoch) whenever it is able to.
|
|
1459
|
+
/// This is why the default type for most connection drivers is
|
|
1460
|
+
/// `BIGINT`. Another common type for this conversion is `TIMESTAMP`.
|
|
1461
|
+
///
|
|
1462
|
+
/// Return: string
|
|
1463
|
+
/// The field type needed by the underlying database driver.
|
|
1464
|
+
///
|
|
1465
|
+
/// Arguments:
|
|
1466
|
+
/// type: <see>Type</see>
|
|
1467
|
+
/// The field type to convert to use in the underlying database.
|
|
563
1468
|
// eslint-disable-next-line no-unused-vars
|
|
564
1469
|
_datetimeTypeToString(type) {
|
|
565
1470
|
return 'TIMESTAMP';
|
|
566
1471
|
}
|
|
567
1472
|
|
|
1473
|
+
/// Convert a "NUMERIC" field type to a type
|
|
1474
|
+
/// acceptable by the underlying database driver.
|
|
1475
|
+
///
|
|
1476
|
+
/// For most SQL connections this would be `NUMERIC`, `DECIMAL`,
|
|
1477
|
+
/// or `NUMBER`, however, it may be different based on what database
|
|
1478
|
+
/// you are using.
|
|
1479
|
+
///
|
|
1480
|
+
/// Return: string
|
|
1481
|
+
/// The field type needed by the underlying database driver.
|
|
1482
|
+
///
|
|
1483
|
+
/// Arguments:
|
|
1484
|
+
/// type: <see>Type</see>
|
|
1485
|
+
/// The field type to convert to use in the underlying database.
|
|
568
1486
|
// eslint-disable-next-line no-unused-vars
|
|
569
1487
|
_numericTypeToString(type) {
|
|
570
1488
|
return `NUMERIC(${type.precision}, ${type.scale})`;
|
|
571
1489
|
}
|
|
572
1490
|
|
|
1491
|
+
/// Convert a "REAL" field type to a type
|
|
1492
|
+
/// acceptable by the underlying database driver.
|
|
1493
|
+
///
|
|
1494
|
+
/// For most SQL connections this would be `FLOAT`,
|
|
1495
|
+
/// however, it may be different based on what database you are using.
|
|
1496
|
+
///
|
|
1497
|
+
/// Return: string
|
|
1498
|
+
/// The field type needed by the underlying database driver.
|
|
1499
|
+
///
|
|
1500
|
+
/// Arguments:
|
|
1501
|
+
/// type: <see>Type</see>
|
|
1502
|
+
/// The field type to convert to use in the underlying database.
|
|
573
1503
|
// eslint-disable-next-line no-unused-vars
|
|
574
1504
|
_realTypeToString(type) {
|
|
575
1505
|
return 'FLOAT';
|
|
576
1506
|
}
|
|
577
1507
|
|
|
1508
|
+
/// Convert a "INTEGER" field type to a type
|
|
1509
|
+
/// acceptable by the underlying database driver.
|
|
1510
|
+
///
|
|
1511
|
+
/// For most SQL connections this would be `INTEGER`,
|
|
1512
|
+
/// however, it may be different based on what database you are using.
|
|
1513
|
+
///
|
|
1514
|
+
/// Return: string
|
|
1515
|
+
/// The field type needed by the underlying database driver.
|
|
1516
|
+
///
|
|
1517
|
+
/// Arguments:
|
|
1518
|
+
/// type: <see>Type</see>
|
|
1519
|
+
/// The field type to convert to use in the underlying database.
|
|
578
1520
|
// eslint-disable-next-line no-unused-vars
|
|
579
1521
|
_integerTypeToString(type) {
|
|
580
1522
|
return 'INTEGER';
|
|
581
1523
|
}
|
|
582
1524
|
|
|
1525
|
+
/// Convert a "STRING" field type to a type
|
|
1526
|
+
/// acceptable by the underlying database driver.
|
|
1527
|
+
///
|
|
1528
|
+
/// For most SQL connections this would be `VARCHAR`,
|
|
1529
|
+
/// however, it may be different based on what database you are using.
|
|
1530
|
+
///
|
|
1531
|
+
/// Return: string
|
|
1532
|
+
/// The field type needed by the underlying database driver.
|
|
1533
|
+
///
|
|
1534
|
+
/// Arguments:
|
|
1535
|
+
/// type: <see>Type</see>
|
|
1536
|
+
/// The field type to convert to use in the underlying database.
|
|
583
1537
|
// eslint-disable-next-line no-unused-vars
|
|
584
1538
|
_stringTypeToString(type) {
|
|
585
1539
|
return `VARCHAR(${type.length})`;
|
|
586
1540
|
}
|
|
587
1541
|
|
|
1542
|
+
/// Convert a "TEXT" field type to a type
|
|
1543
|
+
/// acceptable by the underlying database driver.
|
|
1544
|
+
///
|
|
1545
|
+
/// For most SQL connections this would be `TEXT`,
|
|
1546
|
+
/// however, it may be different based on what database you are using.
|
|
1547
|
+
///
|
|
1548
|
+
/// Return: string
|
|
1549
|
+
/// The field type needed by the underlying database driver.
|
|
1550
|
+
///
|
|
1551
|
+
/// Arguments:
|
|
1552
|
+
/// type: <see>Type</see>
|
|
1553
|
+
/// The field type to convert to use in the underlying database.
|
|
588
1554
|
// eslint-disable-next-line no-unused-vars
|
|
589
1555
|
_textTypeToString(type) {
|
|
590
1556
|
return 'TEXT';
|
|
591
1557
|
}
|
|
592
1558
|
|
|
1559
|
+
/// Convert a "UUIDV1" field type to a type
|
|
1560
|
+
/// acceptable by the underlying database driver.
|
|
1561
|
+
///
|
|
1562
|
+
/// For most SQL connections this would be `VARCHAR`,
|
|
1563
|
+
/// however, it may be different based on what database you are using.
|
|
1564
|
+
///
|
|
1565
|
+
/// Return: string
|
|
1566
|
+
/// The field type needed by the underlying database driver.
|
|
1567
|
+
///
|
|
1568
|
+
/// Arguments:
|
|
1569
|
+
/// type: <see>Type</see>
|
|
1570
|
+
/// The field type to convert to use in the underlying database.
|
|
593
1571
|
// eslint-disable-next-line no-unused-vars
|
|
594
1572
|
_uuidV1TypeToString(type) {
|
|
595
1573
|
return `VARCHAR(${type.getTotalLength()})`;
|
|
596
1574
|
}
|
|
597
1575
|
|
|
1576
|
+
/// Convert a "UUIDV3" field type to a type
|
|
1577
|
+
/// acceptable by the underlying database driver.
|
|
1578
|
+
///
|
|
1579
|
+
/// For most SQL connections this would be `VARCHAR`,
|
|
1580
|
+
/// however, it may be different based on what database you are using.
|
|
1581
|
+
///
|
|
1582
|
+
/// Return: string
|
|
1583
|
+
/// The field type needed by the underlying database driver.
|
|
1584
|
+
///
|
|
1585
|
+
/// Arguments:
|
|
1586
|
+
/// type: <see>Type</see>
|
|
1587
|
+
/// The field type to convert to use in the underlying database.
|
|
598
1588
|
// eslint-disable-next-line no-unused-vars
|
|
599
1589
|
_uuidV3TypeToString(type) {
|
|
600
1590
|
return `VARCHAR(${type.getTotalLength()})`;
|
|
601
1591
|
}
|
|
602
1592
|
|
|
1593
|
+
/// Convert a "UUIDV4" field type to a type
|
|
1594
|
+
/// acceptable by the underlying database driver.
|
|
1595
|
+
///
|
|
1596
|
+
/// For most SQL connections this would be `VARCHAR`,
|
|
1597
|
+
/// however, it may be different based on what database you are using.
|
|
1598
|
+
///
|
|
1599
|
+
/// Return: string
|
|
1600
|
+
/// The field type needed by the underlying database driver.
|
|
1601
|
+
///
|
|
1602
|
+
/// Arguments:
|
|
1603
|
+
/// type: <see>Type</see>
|
|
1604
|
+
/// The field type to convert to use in the underlying database.
|
|
603
1605
|
// eslint-disable-next-line no-unused-vars
|
|
604
1606
|
_uuidV4TypeToString(type) {
|
|
605
1607
|
return `VARCHAR(${type.getTotalLength()})`;
|
|
606
1608
|
}
|
|
607
1609
|
|
|
1610
|
+
/// Convert a "UUIDV5" field type to a type
|
|
1611
|
+
/// acceptable by the underlying database driver.
|
|
1612
|
+
///
|
|
1613
|
+
/// For most SQL connections this would be `VARCHAR`,
|
|
1614
|
+
/// however, it may be different based on what database you are using.
|
|
1615
|
+
///
|
|
1616
|
+
/// Return: string
|
|
1617
|
+
/// The field type needed by the underlying database driver.
|
|
1618
|
+
///
|
|
1619
|
+
/// Arguments:
|
|
1620
|
+
/// type: <see>Type</see>
|
|
1621
|
+
/// The field type to convert to use in the underlying database.
|
|
608
1622
|
// eslint-disable-next-line no-unused-vars
|
|
609
1623
|
_uuidV5TypeToString(type) {
|
|
610
1624
|
return `VARCHAR(${type.getTotalLength()})`;
|
|
611
1625
|
}
|
|
612
1626
|
|
|
1627
|
+
/// Convert a "XID" field type to a type
|
|
1628
|
+
/// acceptable by the underlying database driver.
|
|
1629
|
+
///
|
|
1630
|
+
/// For most SQL connections this would be `VARCHAR`,
|
|
1631
|
+
/// however, it may be different based on what database you are using.
|
|
1632
|
+
///
|
|
1633
|
+
/// Return: string
|
|
1634
|
+
/// The field type needed by the underlying database driver.
|
|
1635
|
+
///
|
|
1636
|
+
/// Arguments:
|
|
1637
|
+
/// type: <see>Type</see>
|
|
1638
|
+
/// The field type to convert to use in the underlying database.
|
|
613
1639
|
// eslint-disable-next-line no-unused-vars
|
|
614
1640
|
_xidTypeToString(type) {
|
|
615
1641
|
return `VARCHAR(${type.getTotalLength()})`;
|
|
616
1642
|
}
|
|
617
1643
|
|
|
1644
|
+
/// Convert any field type to the type needed for the underlying
|
|
1645
|
+
/// database driver. Only built-in Mythix ORM fields are supported.
|
|
1646
|
+
/// If a custom field type that is not supported is provided then
|
|
1647
|
+
/// an exception will be thrown.
|
|
1648
|
+
///
|
|
1649
|
+
/// If you need to support a custom field type, simply subclass the
|
|
1650
|
+
/// connection you are using, and overload this method to handle
|
|
1651
|
+
/// your custom field types.
|
|
1652
|
+
///
|
|
1653
|
+
/// Return: string
|
|
1654
|
+
/// The field type needed by the underlying database driver.
|
|
1655
|
+
///
|
|
1656
|
+
/// Arguments:
|
|
1657
|
+
/// type: <see>Type</see>
|
|
1658
|
+
/// The field type to convert to use in the underlying database.
|
|
1659
|
+
/// options?: object
|
|
1660
|
+
/// Optional options to pass to the underlying conversion method.
|
|
618
1661
|
typeToString(type, options) {
|
|
619
1662
|
if (Types.BigIntType.isSameType(type))
|
|
620
1663
|
return this._bigintTypeToString(type, options);
|
|
@@ -652,6 +1695,37 @@ class ConnectionBase extends EventEmitter {
|
|
|
652
1695
|
throw new Error(`${this.constructor.name}::typeToString: Unsupported type ${type}.`);
|
|
653
1696
|
}
|
|
654
1697
|
|
|
1698
|
+
/// Convert a given "time" type object to
|
|
1699
|
+
/// the value needed by the underlying database.
|
|
1700
|
+
///
|
|
1701
|
+
/// By default this method will take a
|
|
1702
|
+
/// Luxon `DateTime` instance, or a `Date` instance,
|
|
1703
|
+
/// and convert it to the value needed by the
|
|
1704
|
+
/// underlying field in the database. This is
|
|
1705
|
+
/// generally a `BIGINT`, or `TIMESTAMP` value,
|
|
1706
|
+
/// as Mythix ORM will always try to store dates
|
|
1707
|
+
/// and times as millisecond timestamps
|
|
1708
|
+
/// (number of milliseconds since the UNIX Epoch).
|
|
1709
|
+
///
|
|
1710
|
+
/// If a `number`, `bigint`, or a `string` type is
|
|
1711
|
+
/// provided, then Mythix ORM will use Luxon to try
|
|
1712
|
+
/// and parse the provided value. If the value is parsed
|
|
1713
|
+
/// correctly, it will then be converted to the proper
|
|
1714
|
+
/// value as needed by the underlying field in the database.
|
|
1715
|
+
///
|
|
1716
|
+
/// Return: any
|
|
1717
|
+
/// Return the value needed by the underlying database field.
|
|
1718
|
+
/// Generally this will be a `bigint` type that is returned,
|
|
1719
|
+
/// but may be something different depending on the field and
|
|
1720
|
+
/// the database itself.
|
|
1721
|
+
///
|
|
1722
|
+
/// Arguments:
|
|
1723
|
+
/// value: any
|
|
1724
|
+
/// The incoming date/time type to convert to the proper
|
|
1725
|
+
/// database value for the underlying field.
|
|
1726
|
+
/// type: <see>Type</see>
|
|
1727
|
+
/// The field type that this conversion is for. This will
|
|
1728
|
+
/// generally be a `DATE` or `DATETIME` type.
|
|
655
1729
|
convertDateToDBTime(value, type) {
|
|
656
1730
|
if (Nife.instanceOf(value, 'number'))
|
|
657
1731
|
return value;
|
|
@@ -667,6 +1741,35 @@ class ConnectionBase extends EventEmitter {
|
|
|
667
1741
|
return value;
|
|
668
1742
|
}
|
|
669
1743
|
|
|
1744
|
+
/// This method will ensure all provided "models"
|
|
1745
|
+
/// are instances of the provided model class.
|
|
1746
|
+
///
|
|
1747
|
+
/// This method is used by the `insert`, `upsert`, and `update`
|
|
1748
|
+
/// methods of the connection to ensure every model
|
|
1749
|
+
/// provided by the user is an actual model instance.
|
|
1750
|
+
///
|
|
1751
|
+
/// For example, it is perfectly valid to create a model
|
|
1752
|
+
/// like `await Model.create({ ...attributes })`. As you
|
|
1753
|
+
/// can see, the provided "model" is actually just a raw
|
|
1754
|
+
/// object. Nearly any call in Mythix ORM will accept a
|
|
1755
|
+
/// raw object in-place of a model instance, and this
|
|
1756
|
+
/// method is used to ensure all provided "models" are
|
|
1757
|
+
/// actually model instances.
|
|
1758
|
+
///
|
|
1759
|
+
/// Return: Array<Model>
|
|
1760
|
+
/// Return all provided models, converted to model instances.
|
|
1761
|
+
/// Any provided model that is already a model instance will
|
|
1762
|
+
/// not be modified, and instead will simply be returned.
|
|
1763
|
+
///
|
|
1764
|
+
/// Arguments:
|
|
1765
|
+
/// Model: class <see>Model</see>
|
|
1766
|
+
/// The model class to use for instantiating models.
|
|
1767
|
+
/// models: object | <see>Model</see> | Array<Model | object>
|
|
1768
|
+
/// The models to convert to model instances (if needed).
|
|
1769
|
+
/// options: object
|
|
1770
|
+
/// Options for the operation. This options object is used
|
|
1771
|
+
/// to pass the `startIndex` and `endIndex` (or `batchSize`)
|
|
1772
|
+
/// as provided by the user when calling `insert`, `upsert`, or `update`.
|
|
670
1773
|
ensureAllModelsAreInstances(Model, _models, options) {
|
|
671
1774
|
if (!_models)
|
|
672
1775
|
return [];
|
|
@@ -696,6 +1799,38 @@ class ConnectionBase extends EventEmitter {
|
|
|
696
1799
|
return instantiatedModels;
|
|
697
1800
|
}
|
|
698
1801
|
|
|
1802
|
+
/// This method will prepare all provided models for
|
|
1803
|
+
/// an `insert`, `upsert`, or `update` operation.
|
|
1804
|
+
///
|
|
1805
|
+
/// What it does is ensure every provided model is a model
|
|
1806
|
+
/// instance, checks if the model is persisted, and if each
|
|
1807
|
+
/// model has dirty fields.
|
|
1808
|
+
///
|
|
1809
|
+
/// Models that are persisted and not dirty will be filtered out,
|
|
1810
|
+
/// so that proceeding operations will "ignore" them entirely.
|
|
1811
|
+
///
|
|
1812
|
+
/// All dirty fields across all models are combined into a unified
|
|
1813
|
+
/// list of dirty fields. This unified list is then used for the list
|
|
1814
|
+
/// of columns in an `insert`, `upsert`, or `updateAll` operation.
|
|
1815
|
+
///
|
|
1816
|
+
/// Return: PreparedModels
|
|
1817
|
+
/// Return an object with the shape `{ models: Array<Model>, dirtyFields: Array<Field>, dirtyModels: Array<Model> }`
|
|
1818
|
+
/// which is known to Mythix ORM as "prepared models". Mythix ORM can understand
|
|
1819
|
+
/// "prepared models" verses simple "models" in most contexts. PreparedModels are often
|
|
1820
|
+
/// passed around after first receiving models from the user, so as not to "prepare" them
|
|
1821
|
+
/// more than once.
|
|
1822
|
+
///
|
|
1823
|
+
/// Arguments:
|
|
1824
|
+
/// Model: class <see>Model</see>
|
|
1825
|
+
/// The model class to use for preparing the provided models. All models
|
|
1826
|
+
/// provided must be of this model type.
|
|
1827
|
+
/// models: object | <see>Model</see> | Array<Model | object>
|
|
1828
|
+
/// The models to prepare. Any model that is a "raw object" will
|
|
1829
|
+
/// be instantiated into the Model class provided.
|
|
1830
|
+
/// options: object
|
|
1831
|
+
/// Options for the operation. These include `startIndex`, `endIndex`
|
|
1832
|
+
/// (or `batchSize`) for batch operations, and `skipPersisted`, `isUpdateOperation`,
|
|
1833
|
+
/// or `isInsertOperation` for other context-specific operations.
|
|
699
1834
|
prepareAllModelsForOperation(Model, _models, _options) {
|
|
700
1835
|
if (!_models)
|
|
701
1836
|
return {};
|
|
@@ -775,6 +1910,32 @@ class ConnectionBase extends EventEmitter {
|
|
|
775
1910
|
return finalResult;
|
|
776
1911
|
}
|
|
777
1912
|
|
|
1913
|
+
/// Recursively walk all provided models and split models into a map
|
|
1914
|
+
/// of model name and model instances.
|
|
1915
|
+
///
|
|
1916
|
+
/// This method is used to split apart provided models by the user.
|
|
1917
|
+
/// For example, it is fully valid to provide "sub models" during most persisting
|
|
1918
|
+
/// operations, such as `new User({ primaryRole: new Role({ name: 'admin' }) })`.
|
|
1919
|
+
///
|
|
1920
|
+
/// This method would find the sub model "Role" in the above example, and split
|
|
1921
|
+
/// it out to be processed separately in the persisting operation.
|
|
1922
|
+
///
|
|
1923
|
+
/// Return: Map<string, Set<Model>>
|
|
1924
|
+
/// Return a map of all models found, where the model name is the key for the
|
|
1925
|
+
/// `Map`, and each model instance is added to the `Set` for that key.
|
|
1926
|
+
/// Using the above example, the return value would be: `new Map({ User: new Set([ user ]), Role: new Set([ role ]) })`.
|
|
1927
|
+
///
|
|
1928
|
+
/// Arguments:
|
|
1929
|
+
/// Model: class <see>Model</see>
|
|
1930
|
+
/// The model class of the primary model being scanned. The primary model could
|
|
1931
|
+
/// also be called the "root model". In our example above the primary model is `User`.
|
|
1932
|
+
/// primaryModel: <see>Model</see>
|
|
1933
|
+
/// The model instance to scan for "sub models". In the example above this would be
|
|
1934
|
+
/// `User` (though `Role` itself will also be passed through this method to check if
|
|
1935
|
+
/// it also has any sub models).
|
|
1936
|
+
/// _relationMap?: Map<string, Set<Model>>
|
|
1937
|
+
/// This argument is provided internally while recursing, and should **not** be provided
|
|
1938
|
+
/// unless you know exactly what you are doing.
|
|
778
1939
|
splitModelAndSubModels(Model, primaryModel, _relationMap) {
|
|
779
1940
|
const addModelInstance = (modelName, self) => {
|
|
780
1941
|
let relatedModels = relationMap.get(modelName);
|
|
@@ -832,6 +1993,56 @@ class ConnectionBase extends EventEmitter {
|
|
|
832
1993
|
return relationMap;
|
|
833
1994
|
}
|
|
834
1995
|
|
|
1996
|
+
/// Recursively prepare all models for a persisting operation
|
|
1997
|
+
/// while also splitting each model out into its own separate
|
|
1998
|
+
/// list, and finally sorting the models based on insertion order.
|
|
1999
|
+
///
|
|
2000
|
+
/// This method will use <see>ConnectionBase.splitModelAndSubModels</see>
|
|
2001
|
+
/// to split provided models out into their own separate space. See this
|
|
2002
|
+
/// method for a better explanation of what this means.
|
|
2003
|
+
///
|
|
2004
|
+
/// It will also assign any foreign key values across models that it is able to.
|
|
2005
|
+
/// For example, in the example provided in the documentation for <see>ConnectionBase.splitModelAndSubModels</see>,
|
|
2006
|
+
/// we had `new User({ primaryRole: new Role({ name: 'admin' }) })`, where the `Role`
|
|
2007
|
+
/// model is being persisted (as a child of `User`) at the same time the `User` is being
|
|
2008
|
+
/// persisted. If `Role` has a generated id, such as one of the `UUID` or `XID` types,
|
|
2009
|
+
/// then in our example here the `primaryRoleID` of the `User` could be set before `User`
|
|
2010
|
+
/// is persisted, saving an extra query to the database to update this foreign key after
|
|
2011
|
+
/// `Role` is persisted. In short, this method will also assign any foreign key values
|
|
2012
|
+
/// that it already has before persisting any models.
|
|
2013
|
+
///
|
|
2014
|
+
/// Finally, after it has "prepared" the models, and split all models into their own
|
|
2015
|
+
/// space, it will sort the resulting `Map` such that the models are in the correct
|
|
2016
|
+
/// order for insertion. In the example we have been using, if `User` has a `primaryRoleID`
|
|
2017
|
+
/// that is a foreign key, then it might require a non-null value before the `User`
|
|
2018
|
+
/// model can be persisted. Because of this, it is important that the `Role` model
|
|
2019
|
+
/// is stored first, so that we have the value we need for this `primaryRoleID` foreign key.
|
|
2020
|
+
/// This is why the models are sorted in what is known as "creation order", or "insertion order".
|
|
2021
|
+
/// This order is defined by the foreign keys themselves. Mythix ORM will walk all foreign keys
|
|
2022
|
+
/// involved in the operation, and decide based on these what the "creation order" should be.
|
|
2023
|
+
/// If you have two models that both have foreign keys pointing to each other, then the sort
|
|
2024
|
+
/// order is undefined. If this is the case, the work-around is to simply manually persist
|
|
2025
|
+
/// your models in the correct order (i.e. save `Role` first, and then supply the foreign key
|
|
2026
|
+
/// to `User` yourself from the result).
|
|
2027
|
+
///
|
|
2028
|
+
/// Return: Map<string, Set<Model>>
|
|
2029
|
+
/// The models processed, and put into their own named `Set`. The keys for
|
|
2030
|
+
/// the `Map` are the names of the models themselves.
|
|
2031
|
+
///
|
|
2032
|
+
/// Arguments:
|
|
2033
|
+
/// Model: class <see>Model</see>
|
|
2034
|
+
/// The model class of the primary model being persisted. The primary model could
|
|
2035
|
+
/// also be called the "root model". In our example above the primary model is `User`.
|
|
2036
|
+
/// models: object | <see>Model</see> | Array<Model | object>
|
|
2037
|
+
/// The models to prepare. Any model that is a "raw object" will
|
|
2038
|
+
/// be instantiated into the Model class provided. Any "sub models" will be
|
|
2039
|
+
/// split into their own space in the resulting `Map`.
|
|
2040
|
+
/// options?: object
|
|
2041
|
+
/// Optional options to supply to this operation. This options object
|
|
2042
|
+
/// isn't used by Mythix ORM, but is provided in case any driver specific
|
|
2043
|
+
/// connection needs them when overloading this model. These options come
|
|
2044
|
+
/// from the options provided to a database operation, such as the options
|
|
2045
|
+
/// provided to an `insert`, `upsert`, or `update` call.
|
|
835
2046
|
// eslint-disable-next-line no-unused-vars
|
|
836
2047
|
prepareAllModelsAndSubModelsForOperation(Model, models, _options) {
|
|
837
2048
|
let primaryModelRelationMap = new Map();
|
|
@@ -908,6 +2119,60 @@ class ConnectionBase extends EventEmitter {
|
|
|
908
2119
|
return sortedGroupedModelMap;
|
|
909
2120
|
}
|
|
910
2121
|
|
|
2122
|
+
/// This is a low-level "helper" method that is used by all
|
|
2123
|
+
/// "bulk operations", such as `insert`, `upsert`, `update`,
|
|
2124
|
+
/// or `destroyModels`. It prepares all provided models for operation,
|
|
2125
|
+
/// splits out sub-models provided, skips already persisted models,
|
|
2126
|
+
/// and also calls the model hooks `onBeforeSave`, `onAfterSave`, etc...
|
|
2127
|
+
/// This method will also always operate in batches, as defined by the
|
|
2128
|
+
/// `batchSize` option (default is `500` if not provided).
|
|
2129
|
+
///
|
|
2130
|
+
/// Lastly, when it is all done running the "batch operation" on all models,
|
|
2131
|
+
/// it will update any foreign keys on each model, and if any model has again
|
|
2132
|
+
/// been marked dirty from this update it will finally persist those updated
|
|
2133
|
+
/// models.
|
|
2134
|
+
///
|
|
2135
|
+
/// When it is fully complete, this method will return all "primary" models supplied
|
|
2136
|
+
/// to the method (i.e. if saving `User` models, then all supplied users will be returned
|
|
2137
|
+
/// and if any sub models were involved those won't be returned). The "primary model" is
|
|
2138
|
+
/// the model whose model class was specified as the `Model` argument on invocation of this
|
|
2139
|
+
/// method, and should match the type of the input `models`.
|
|
2140
|
+
///
|
|
2141
|
+
/// Return: Array<Model>
|
|
2142
|
+
/// Return all input models, converted to model instances, and updated. How they
|
|
2143
|
+
/// are updated depends on the operation being performed.
|
|
2144
|
+
///
|
|
2145
|
+
/// Arguments:
|
|
2146
|
+
/// Model: class <see>Model</see>
|
|
2147
|
+
/// The model class for the input models being provided.
|
|
2148
|
+
/// models: Array<Model>
|
|
2149
|
+
/// The models to bulk operate on. All of them must be instances of the class
|
|
2150
|
+
/// provided as the `Model` argument.
|
|
2151
|
+
/// options?: object
|
|
2152
|
+
/// Options to supply to the method. Refer to the following table for a list of
|
|
2153
|
+
/// possible options.
|
|
2154
|
+
/// | Option | Type | Default Value | Description |
|
|
2155
|
+
/// | ------ | ---- | ------------- | ----------- |
|
|
2156
|
+
/// | `batchSize` | `number` | `500` | The number of models for each batch |
|
|
2157
|
+
/// | `isInsertOperation` | `boolean` | `false` | `true` if this is an insert operation. If this is an insert operation, then dirty models will be collected post-insert, and re-saved if any are re-marked dirty after foreign key updates. |
|
|
2158
|
+
/// | `isDeleteOperation` | `boolean` | `false` | `true` if this is a delete operation. If this is a delete operation, then model preparation and splitting is skipped, and the models are processed directly. |
|
|
2159
|
+
/// beforeCallback?: (Model: typeof <see>Model</see>, batchModelInstances: Array<Model>, options: object, queryGenerator: <see>QueryGenerator</see>) => Promise<void>
|
|
2160
|
+
/// Callback that is called for each batch of models, before the current operation (i.e. insert) operates on them.
|
|
2161
|
+
/// It is generally in this callback that `onBefore*` model hooks are called.
|
|
2162
|
+
/// callback: (Model: typeof <see>Model</see>, preparedModels: <see name="PreparedModels">ConnectionBase.prepareAllModelsForOperation</see>, options: object, queryGenerator: <see>QueryGenerator</see>) => Promise<void>
|
|
2163
|
+
/// Callback to call to process each batch of models. The models are in "prepared model" format, meaning they
|
|
2164
|
+
/// are supplied as an object with `models`, `dirtyFields`, and `dirtyModels` properties.
|
|
2165
|
+
/// afterCallback?: (Model: typeof <see>Model</see>, models: Array<Model>, options: object, queryGenerator: <see>QueryGenerator</see>) => Promise<void>
|
|
2166
|
+
/// Callback that is called for each entire model set (not in batches). For example, if you bulk insert
|
|
2167
|
+
/// 1000 users, and your `batchSize` is `100`, then this will be called once, with all
|
|
2168
|
+
/// 1000 processed users, not 10 times with 100 users each. It is generally in this callback
|
|
2169
|
+
/// that `onAfter*` model hooks are called.
|
|
2170
|
+
/// afterOperationCallback?: (Model: typeof <see>Model</see>, dirtyModels: Set<Model>, options: object, queryGenerator: <see>QueryGenerator</see>) => Promise<void>
|
|
2171
|
+
/// Callback that is called after the entire operation completes successfully. This will only be called
|
|
2172
|
+
/// if `dirtyModels` is not empty. This method generally will re-save any models that got dirty during
|
|
2173
|
+
/// the operation... for example, when foreign keys have been updated on the models being processed.
|
|
2174
|
+
/// Models won't be added to the `dirtyModels` set if they are marked dirty in `onAfter*` model hooks,
|
|
2175
|
+
/// but only if the foreign key update process marked the model as dirty.
|
|
911
2176
|
async bulkModelOperation(Model, _models, _options, beforeCallback, callback, afterCallback, afterOperationCallback) {
|
|
912
2177
|
let models = _models;
|
|
913
2178
|
if (!models)
|
|
@@ -1057,6 +2322,26 @@ class ConnectionBase extends EventEmitter {
|
|
|
1057
2322
|
return (inputIsArray || !primaryResult) ? primaryResult : primaryResult[0];
|
|
1058
2323
|
}
|
|
1059
2324
|
|
|
2325
|
+
/// Mark all models provided as "persisted".
|
|
2326
|
+
///
|
|
2327
|
+
/// Every Mythix ORM model instance has a non-enumerable property `_persisted`.
|
|
2328
|
+
/// If this is `true`, then Mythix ORM will treat the model as persisted.
|
|
2329
|
+
///
|
|
2330
|
+
/// This method iterates all provided models, and marks each as persisted
|
|
2331
|
+
/// by setting this `_persisted` property to `true`.
|
|
2332
|
+
/// For each model iterated, this method checks if the instance property
|
|
2333
|
+
/// `_mythixModelInstance` is `true`. If this is not the case, then that
|
|
2334
|
+
/// instance (whatever it is) will be silently skipped.
|
|
2335
|
+
///
|
|
2336
|
+
/// Return: undefined
|
|
2337
|
+
/// This method modifies `models` directly, and returns nothing.
|
|
2338
|
+
///
|
|
2339
|
+
/// Arguments:
|
|
2340
|
+
/// models: Array<Model> | <see name="PreparedModels">ConnectionBase.prepareAllModelsForOperation</see>
|
|
2341
|
+
/// Models to mark as persisted.
|
|
2342
|
+
/// value:
|
|
2343
|
+
/// If `true`, models will be marked as persisted. If `false`, models will be marked
|
|
2344
|
+
/// as not-persisted.
|
|
1060
2345
|
setPersisted(_models, value) {
|
|
1061
2346
|
let models = _models;
|
|
1062
2347
|
if (models._mythixPreparedModels)
|
|
@@ -1074,14 +2359,83 @@ class ConnectionBase extends EventEmitter {
|
|
|
1074
2359
|
}
|
|
1075
2360
|
}
|
|
1076
2361
|
|
|
2362
|
+
/// Start this connection.
|
|
2363
|
+
///
|
|
2364
|
+
/// The default implementation will throw an exception.
|
|
2365
|
+
///
|
|
2366
|
+
/// Every connection is expected to overload this
|
|
2367
|
+
/// and provide connection specific startup code
|
|
2368
|
+
/// (such as connecting to the database).
|
|
2369
|
+
///
|
|
2370
|
+
/// Return: Promise<void>
|
|
1077
2371
|
async start() {
|
|
1078
2372
|
throw new Error(`${this.constructor.name}::start: Child class is required to implement "start".`);
|
|
1079
2373
|
}
|
|
1080
2374
|
|
|
2375
|
+
/// Stop (shutdown) this connection.
|
|
2376
|
+
///
|
|
2377
|
+
/// The default implementation will throw an exception.
|
|
2378
|
+
///
|
|
2379
|
+
/// Every connection is expected to overload this
|
|
2380
|
+
/// and provide connection specific shutdown code
|
|
2381
|
+
/// (such as disconnecting from the database).
|
|
2382
|
+
///
|
|
2383
|
+
/// Return: Promise<void>
|
|
1081
2384
|
async stop() {
|
|
1082
2385
|
this.removeAllListeners();
|
|
1083
2386
|
}
|
|
1084
2387
|
|
|
2388
|
+
/// Run model hooks by name.
|
|
2389
|
+
///
|
|
2390
|
+
/// This method will run the hooks for a model instance.
|
|
2391
|
+
/// `operationHookName` will be one of `onBeforeCreate`, `onBeforeUpdate`,
|
|
2392
|
+
/// `onAfterCreate`, or `onAfterUpdate`.
|
|
2393
|
+
///
|
|
2394
|
+
/// `operationHookName` will be one of `onBeforeSave`, or `onAfterSave`.
|
|
2395
|
+
/// The idea is that any of the `onBefore*` operations will always be
|
|
2396
|
+
/// followed by an `onBeforeSave`, whereas the `onAfter*` operations
|
|
2397
|
+
/// are all followed by an `onAfterSave`.
|
|
2398
|
+
///
|
|
2399
|
+
/// Note:
|
|
2400
|
+
/// Hooks for models are run serially for a given model, but all model
|
|
2401
|
+
/// hooks are run in parallel across all models.
|
|
2402
|
+
///
|
|
2403
|
+
/// Note:
|
|
2404
|
+
/// The `onValidate` hook is called from the `onBeforeSave` hook itself.
|
|
2405
|
+
/// This is so that the user can decide if model validations should be
|
|
2406
|
+
/// ran or not (simply by calling `this.onValidate` themselves... or not).
|
|
2407
|
+
/// **If you overload the `onBeforeSave` method, make certain you call
|
|
2408
|
+
/// `super.onBeforeSave.apply(this, arguments)` (or `this.onValidate.apply(this, arguments)`
|
|
2409
|
+
/// directly), because if you don't
|
|
2410
|
+
/// your model validations will be skipped.**
|
|
2411
|
+
///
|
|
2412
|
+
/// Return: Promise<Array<any>>
|
|
2413
|
+
/// The result of all model hooks. Mythix ORM ignores the return value
|
|
2414
|
+
/// from model hooks, but it collects them and returns them for the user.
|
|
2415
|
+
///
|
|
2416
|
+
/// Arguments:
|
|
2417
|
+
/// Model: class <see>Model</see>
|
|
2418
|
+
/// The model class we are running hooks for. All `models` provided should
|
|
2419
|
+
/// be instances of this class.
|
|
2420
|
+
/// models: Array<<see>Model</see>>
|
|
2421
|
+
/// All model instances to run hooks on. These should all be instances of the
|
|
2422
|
+
/// provided `Model` class.
|
|
2423
|
+
/// operationHookName: `'onBeforeCreate'` | `'onBeforeUpdate'` | `'onAfterCreate'` | `'onAfterUpdate'`
|
|
2424
|
+
/// The hook to call (if not skipped by the `skipHooks` option).
|
|
2425
|
+
/// saveHookName: `'onBeforeSave'` | `'onAfterSave'`
|
|
2426
|
+
/// The name of the save hook to call after the operation hook
|
|
2427
|
+
/// has completed (if not skipped by the `skipHooks` option).
|
|
2428
|
+
/// options: object
|
|
2429
|
+
/// Options for the operation being completed. For example, if this is an
|
|
2430
|
+
/// `insert` operation, then these "options" will be the options for the
|
|
2431
|
+
/// `insert` operation. One other useful option that can be supplied here
|
|
2432
|
+
/// is the `skipHooks: boolean | { [key: 'onBeforeCreate' | 'onBeforeUpdate' | 'onAfterCreate' | 'onAfterUpdate' | 'onBeforeSave' | 'onAfterSave' ]: boolean; }` option.
|
|
2433
|
+
/// If this is `true`, then all hooks will be bypassed (not called).
|
|
2434
|
+
/// If this is an object, then each key should be a hook name, and if it has
|
|
2435
|
+
/// a `true` value, then that specific hook will be bypassed (not called).
|
|
2436
|
+
///
|
|
2437
|
+
/// This allows the caller of an operation such as `insert`, or `update` to
|
|
2438
|
+
/// request that specific hooks not be called.
|
|
1085
2439
|
async runSaveHooks(Model, models, operationHookName, saveHookName, _options) {
|
|
1086
2440
|
const throwError = (error) => {
|
|
1087
2441
|
throw error;
|
|
@@ -1125,10 +2479,68 @@ class ConnectionBase extends EventEmitter {
|
|
|
1125
2479
|
await Promise.all(promises);
|
|
1126
2480
|
}
|
|
1127
2481
|
|
|
2482
|
+
/// Drop a table/bucket from the database.
|
|
2483
|
+
///
|
|
2484
|
+
/// This uses the provided `Model` class to
|
|
2485
|
+
/// find the table/bucket name to drop, and then
|
|
2486
|
+
/// will drop it from the underlying database.
|
|
2487
|
+
///
|
|
2488
|
+
/// The `options` argument is database specific,
|
|
2489
|
+
/// but might contain options such as `ifExists`,
|
|
2490
|
+
/// or `cascade`, for example.
|
|
2491
|
+
///
|
|
2492
|
+
/// Return: any
|
|
2493
|
+
/// A database specific return value for the drop table
|
|
2494
|
+
/// operation.
|
|
2495
|
+
///
|
|
2496
|
+
/// Arguments:
|
|
2497
|
+
/// Model: class <see>Model</see>
|
|
2498
|
+
/// The model to drop from the database. The method <see name="Model.getTableName">Model.static getTableName</see>
|
|
2499
|
+
/// is called on the model class to figure out what table/bucket to
|
|
2500
|
+
/// drop from the database.
|
|
2501
|
+
/// options?: object
|
|
2502
|
+
/// Database specific operations for dropping the table/bucket. Please
|
|
2503
|
+
/// refer to the documentation of the driver you are using for further
|
|
2504
|
+
/// information.
|
|
2505
|
+
// eslint-disable-next-line no-unused-vars
|
|
1128
2506
|
async dropTable(Model, options) {
|
|
1129
2507
|
throw new Error(`${this.constructor.name}::dropTable: This operation is not supported for this connection type.`);
|
|
1130
2508
|
}
|
|
1131
2509
|
|
|
2510
|
+
/// Drop all specified tables/buckets from the database.
|
|
2511
|
+
///
|
|
2512
|
+
/// This uses the provided `Models` classes to
|
|
2513
|
+
/// find the table/bucket names to drop, and then
|
|
2514
|
+
/// will drop all of them from the underlying database.
|
|
2515
|
+
///
|
|
2516
|
+
/// The `options` argument is database specific,
|
|
2517
|
+
/// but might contain options such as `ifExists`,
|
|
2518
|
+
/// or `cascade`, for example.
|
|
2519
|
+
///
|
|
2520
|
+
/// The model classes provided are first sorted in
|
|
2521
|
+
/// "creation order" using the <see>Utils.sortModelNamesByCreationOrder</see>
|
|
2522
|
+
/// method, and then the tables/buckets are dropped in the
|
|
2523
|
+
/// reverse order. This is to ensure that any foreign key
|
|
2524
|
+
/// constraints in play will play nicely with the operation
|
|
2525
|
+
/// and not throw errors.
|
|
2526
|
+
///
|
|
2527
|
+
/// This method simply calls <see>ConnectionBase.dropTable</see> for every
|
|
2528
|
+
/// model provided--after sorting the models based on their
|
|
2529
|
+
/// foreign keys.
|
|
2530
|
+
///
|
|
2531
|
+
/// Return: any
|
|
2532
|
+
/// A database specific return value for the drop tables
|
|
2533
|
+
/// operation.
|
|
2534
|
+
///
|
|
2535
|
+
/// Arguments:
|
|
2536
|
+
/// Models: Array<class <see>Model</see>>
|
|
2537
|
+
/// All the models to drop from the database. The method <see name="Model.getTableName">Model.static getTableName</see>
|
|
2538
|
+
/// is called on each model class to figure out what table/bucket to
|
|
2539
|
+
/// drop from the database.
|
|
2540
|
+
/// options?: object
|
|
2541
|
+
/// Database specific operations for dropping the table/bucket. Please
|
|
2542
|
+
/// refer to the documentation of the driver you are using for further
|
|
2543
|
+
/// information.
|
|
1132
2544
|
async dropTables(_Models, options) {
|
|
1133
2545
|
if (!_Models)
|
|
1134
2546
|
return;
|
|
@@ -1165,10 +2577,67 @@ class ConnectionBase extends EventEmitter {
|
|
|
1165
2577
|
return results;
|
|
1166
2578
|
}
|
|
1167
2579
|
|
|
2580
|
+
/// Create a table/bucket using the provided model class.
|
|
2581
|
+
///
|
|
2582
|
+
/// The provided `options` are database specific,
|
|
2583
|
+
/// but might contain things like `ifExists`, for
|
|
2584
|
+
/// example.
|
|
2585
|
+
///
|
|
2586
|
+
/// Return: any
|
|
2587
|
+
/// A connection specific return value for the operation.
|
|
2588
|
+
///
|
|
2589
|
+
/// Arguments:
|
|
2590
|
+
/// Model: class <see>Model</see>
|
|
2591
|
+
/// The model class used to create the table/bucket. The <see name="Model.getTableName">Model.static getTableName</see>
|
|
2592
|
+
/// method will be called to get the table/bucket name to create. Then
|
|
2593
|
+
/// the `static fields` property on the model class is used to create the
|
|
2594
|
+
/// columns/fields for the table/bucket. Only "concrete" fields are created
|
|
2595
|
+
/// in the underlying database. Any "virtual" or "relational" fields will
|
|
2596
|
+
/// be skipped.
|
|
2597
|
+
/// options?: object
|
|
2598
|
+
/// Database specific operations for creating the table/bucket. Please
|
|
2599
|
+
/// refer to the documentation of the driver you are using for further
|
|
2600
|
+
/// information.
|
|
1168
2601
|
async createTable(Model, options) {
|
|
1169
2602
|
throw new Error(`${this.constructor.name}::createTable: This operation is not supported for this connection type.`);
|
|
1170
2603
|
}
|
|
1171
2604
|
|
|
2605
|
+
/// Create all specified tables/buckets in the database.
|
|
2606
|
+
///
|
|
2607
|
+
/// This uses the provided `Models` classes to
|
|
2608
|
+
/// create the tables/buckets specified.
|
|
2609
|
+
///
|
|
2610
|
+
/// The `options` argument is database specific,
|
|
2611
|
+
/// but might contain options such as `ifNotExists`,
|
|
2612
|
+
/// for example.
|
|
2613
|
+
///
|
|
2614
|
+
/// The model classes provided are first sorted in
|
|
2615
|
+
/// "creation order" using the <see>Utils.sortModelNamesByCreationOrder</see>
|
|
2616
|
+
/// method, and then the tables/buckets are created in the
|
|
2617
|
+
/// that order. This is to ensure that any foreign key
|
|
2618
|
+
/// constraints in play will play nicely with the operation
|
|
2619
|
+
/// and not throw errors.
|
|
2620
|
+
///
|
|
2621
|
+
/// This method simply calls <see>ConnectionBase.createTable</see> for every
|
|
2622
|
+
/// model provided--after sorting the models based on their
|
|
2623
|
+
/// foreign keys.
|
|
2624
|
+
///
|
|
2625
|
+
/// Return: any
|
|
2626
|
+
/// A database specific return value for the create tables
|
|
2627
|
+
/// operation.
|
|
2628
|
+
///
|
|
2629
|
+
/// Arguments:
|
|
2630
|
+
/// Models: Array<class <see>Model</see>>
|
|
2631
|
+
/// The model classes used to create the tables/buckets. The <see name="Model.getTableName">Model.static getTableName</see>
|
|
2632
|
+
/// method will be called for each model to get the table/bucket name to create. Then
|
|
2633
|
+
/// the `static fields` property on each model class is used to create the
|
|
2634
|
+
/// columns/fields for the table/bucket. Only "concrete" fields are created
|
|
2635
|
+
/// in the underlying database. Any "virtual" or "relational" fields will
|
|
2636
|
+
/// be skipped.
|
|
2637
|
+
/// options?: object
|
|
2638
|
+
/// Database specific operations for dropping the table/bucket. Please
|
|
2639
|
+
/// refer to the documentation of the driver you are using for further
|
|
2640
|
+
/// information.
|
|
1172
2641
|
async createTables(_Models, options) {
|
|
1173
2642
|
if (!_Models)
|
|
1174
2643
|
return;
|
|
@@ -1220,125 +2689,886 @@ class ConnectionBase extends EventEmitter {
|
|
|
1220
2689
|
|
|
1221
2690
|
// Alter operations
|
|
1222
2691
|
|
|
2692
|
+
/// Alter a table/bucket based on the provided attributes for
|
|
2693
|
+
/// the model.
|
|
2694
|
+
///
|
|
2695
|
+
/// For SQL based drivers this might run a statement like the following
|
|
2696
|
+
/// `ALTER TABLE "users" RENAME TO "old_users";`
|
|
2697
|
+
///
|
|
2698
|
+
/// Please refer to the documentation of the database driver
|
|
2699
|
+
/// you are using for more information.
|
|
2700
|
+
///
|
|
2701
|
+
/// Return: Promise<void>
|
|
2702
|
+
///
|
|
2703
|
+
/// Arguments:
|
|
2704
|
+
/// Model: class <see>Model</see>
|
|
2705
|
+
/// The model to alter. This is used to alter the underlying
|
|
2706
|
+
/// table/bucket in the database.
|
|
2707
|
+
/// newAttributes: object
|
|
2708
|
+
/// The attributes to alter. Please refer to the documentation
|
|
2709
|
+
/// of the database driver you are using for more information.
|
|
1223
2710
|
async alterTable(Model, newModelAttributes, options) {
|
|
1224
2711
|
throw new Error(`${this.constructor.name}::renameTable: This operation is not supported for this connection type.`);
|
|
1225
2712
|
}
|
|
1226
2713
|
|
|
2714
|
+
/// Drop the specified column/field from the database.
|
|
2715
|
+
///
|
|
2716
|
+
/// The table/bucket to drop the field from is known
|
|
2717
|
+
/// by the `Model` property (model class) on the field
|
|
2718
|
+
/// itself.
|
|
2719
|
+
///
|
|
2720
|
+
/// The provided `options` are specific to the database
|
|
2721
|
+
/// you are using.
|
|
2722
|
+
/// Please refer to the documentation of the database driver
|
|
2723
|
+
/// you are using for more information.
|
|
2724
|
+
///
|
|
2725
|
+
/// Return: any
|
|
2726
|
+
/// A database specific return value for the operation completed.
|
|
2727
|
+
///
|
|
2728
|
+
/// Arguments:
|
|
2729
|
+
/// Field: <see>Field</see>
|
|
2730
|
+
/// The column/field to drop from the database.
|
|
2731
|
+
/// options?: object
|
|
2732
|
+
/// Database specific option for the operation. Please refer to the
|
|
2733
|
+
/// documentation of the database driver you are using for more information.
|
|
1227
2734
|
async dropColumn(Field, options) {
|
|
1228
2735
|
throw new Error(`${this.constructor.name}::dropColumn: This operation is not supported for this connection type.`);
|
|
1229
2736
|
}
|
|
1230
2737
|
|
|
2738
|
+
/// Alter the specified column/field in the database.
|
|
2739
|
+
///
|
|
2740
|
+
/// This will take the two fields, `Field` and `NewField`,
|
|
2741
|
+
/// and will compare them. It will generate multiple alter
|
|
2742
|
+
/// table statements internally, and will alter the column/field
|
|
2743
|
+
/// based on the differences it detects between the two fields.
|
|
2744
|
+
///
|
|
2745
|
+
/// If `NewField` is provided as a raw object, then it will be
|
|
2746
|
+
/// converted into a <see>Field</see>.
|
|
2747
|
+
///
|
|
2748
|
+
/// This method will check for the following differences between
|
|
2749
|
+
/// the two fields, in this order:
|
|
2750
|
+
/// 1. `allowNull`
|
|
2751
|
+
/// 2. `type`
|
|
2752
|
+
/// 3. `defaultValue`
|
|
2753
|
+
/// 4. `primaryKey`
|
|
2754
|
+
/// 5. `unique`
|
|
2755
|
+
/// 6. `index` (will calculate index differences, and do the minimum work required)
|
|
2756
|
+
/// 7. `columnName`
|
|
2757
|
+
///
|
|
2758
|
+
/// Return: Promise<void>
|
|
2759
|
+
///
|
|
2760
|
+
/// Arguments:
|
|
2761
|
+
/// Field: <see>Field</see>
|
|
2762
|
+
/// The current column/field (as it is in the database) that we are changing.
|
|
2763
|
+
/// NewField: <see>Field</see> | object
|
|
2764
|
+
/// The new field properties to compare. Only the provided properties will be compared.
|
|
2765
|
+
/// For example, if you only supply a `defaultValue` property, then only that will be
|
|
2766
|
+
/// altered (if it differs from `Field`).
|
|
2767
|
+
/// options?: object
|
|
2768
|
+
/// Operation specific options. These will change depending on the database
|
|
2769
|
+
/// driver you are using. Please refer to the documentation for your specific
|
|
2770
|
+
/// driver for more information.
|
|
1231
2771
|
async alterColumn(Field, newFieldAttributes, options) {
|
|
1232
2772
|
throw new Error(`${this.constructor.name}::alterColumn: This operation is not supported for this connection type.`);
|
|
1233
2773
|
}
|
|
1234
2774
|
|
|
2775
|
+
/// Add the column/field specified to the database.
|
|
2776
|
+
///
|
|
2777
|
+
/// The table/bucket to add the field to is fetched from the
|
|
2778
|
+
/// `Model` property on the supplied field.
|
|
2779
|
+
///
|
|
2780
|
+
/// Return: Promise<void>
|
|
2781
|
+
///
|
|
2782
|
+
/// Arguments:
|
|
2783
|
+
/// Field: <see>Field</see>
|
|
2784
|
+
/// The new field to add to the underlying database.
|
|
2785
|
+
/// options?: object
|
|
2786
|
+
/// Operation specific options. These will change depending on the database
|
|
2787
|
+
/// driver you are using. Please refer to the documentation for your specific
|
|
2788
|
+
/// driver for more information.
|
|
1235
2789
|
async addColumn(Field, options) {
|
|
1236
2790
|
throw new Error(`${this.constructor.name}::addColumn: This operation is not supported for this connection type.`);
|
|
1237
2791
|
}
|
|
1238
2792
|
|
|
2793
|
+
/// Create an index (or combo index) in the database.
|
|
2794
|
+
///
|
|
2795
|
+
/// This will create a new index for the field(s) specified.
|
|
2796
|
+
/// The `indexFields` argument must be an array of field names
|
|
2797
|
+
/// as strings. It can contain more than one field. If it does
|
|
2798
|
+
/// contain more than one field, then a combo index will be created
|
|
2799
|
+
/// for all specified fields (if the database you are using supports
|
|
2800
|
+
/// combined indexes).
|
|
2801
|
+
///
|
|
2802
|
+
/// All the provided field names must exist on the provided `Model`.
|
|
2803
|
+
/// If they don't, then an exception will be thrown. The field names
|
|
2804
|
+
/// can be fully qualified, but they don't need to be. If they are
|
|
2805
|
+
/// fully qualified, then they must all still be owned by the provided
|
|
2806
|
+
/// `Model`. You can not for example use a fully qualified field name
|
|
2807
|
+
/// from another model.
|
|
2808
|
+
///
|
|
2809
|
+
/// Combo indexes are created by combining two or more fields to create
|
|
2810
|
+
/// the index. For example, you could create a combo index for Users
|
|
2811
|
+
/// like `[ 'firstName', 'lastName', 'email' ]` if it is common for your
|
|
2812
|
+
/// application to query on all three of these fields at once.
|
|
2813
|
+
///
|
|
2814
|
+
/// If you just want to index a single column/field, simply provide only
|
|
2815
|
+
/// one field name, i.e. `[ 'firstName' ]`.
|
|
2816
|
+
///
|
|
2817
|
+
/// Return: Promise<void>
|
|
2818
|
+
///
|
|
2819
|
+
/// Arguments:
|
|
2820
|
+
/// Model: class <see>Model</see>
|
|
2821
|
+
/// The model that owns the specified fields.
|
|
2822
|
+
/// indexFields: Array<string>
|
|
2823
|
+
/// The field names to use to create the index. One field name
|
|
2824
|
+
/// is valid if you only wish to index a single field. These are
|
|
2825
|
+
/// used to generate the index name, along with which fields to
|
|
2826
|
+
/// index.
|
|
2827
|
+
/// options?: object
|
|
2828
|
+
/// Operation specific options. These will change depending on the database
|
|
2829
|
+
/// driver you are using. Please refer to the documentation for your specific
|
|
2830
|
+
/// driver for more information.
|
|
1239
2831
|
async addIndex(Model, indexFields, options) {
|
|
1240
2832
|
throw new Error(`${this.constructor.name}::addIndex: This operation is not supported for this connection type.`);
|
|
1241
2833
|
}
|
|
1242
2834
|
|
|
2835
|
+
/// Drop the index from the database based on the specified fields.
|
|
2836
|
+
///
|
|
2837
|
+
/// This is the exact inverse of <see>ConnectionBase.addIndex</see>,
|
|
2838
|
+
/// and it functions nearly identically, except that it will drop
|
|
2839
|
+
/// the specified index instead of creating it.
|
|
2840
|
+
///
|
|
2841
|
+
/// Return: Promise<void>
|
|
2842
|
+
///
|
|
2843
|
+
/// Arguments:
|
|
2844
|
+
/// Model: class <see>Model</see>
|
|
2845
|
+
/// The model that owns the specified fields.
|
|
2846
|
+
/// indexFields: Array<string>
|
|
2847
|
+
/// The field names to used to drop the index. These are used
|
|
2848
|
+
/// to generate the index name, which will then be dropped.
|
|
2849
|
+
/// options?: object
|
|
2850
|
+
/// Operation specific options. These will change depending on the database
|
|
2851
|
+
/// driver you are using. Please refer to the documentation for your specific
|
|
2852
|
+
/// driver for more information.
|
|
1243
2853
|
async dropIndex(Model, indexFields, options) {
|
|
1244
2854
|
throw new Error(`${this.constructor.name}::addIndex: This operation is not supported for this connection type.`);
|
|
1245
2855
|
}
|
|
1246
2856
|
|
|
2857
|
+
/// Insert the specified models into the specified
|
|
2858
|
+
/// table/bucket (based on the provided `Model`).
|
|
2859
|
+
///
|
|
2860
|
+
/// This will insert one or more models into the database.
|
|
2861
|
+
/// Like nearly all such Mythix ORM methods, bulk operations are supported
|
|
2862
|
+
/// out-of-the-box. You can provide a single model to `models`,
|
|
2863
|
+
/// or you can provide an array of models.
|
|
2864
|
+
///
|
|
2865
|
+
/// The provided "models" can be either an object, an array of
|
|
2866
|
+
/// objects, a model instance, or an array of model instances,
|
|
2867
|
+
/// or a mix of both. Mythix ORM will ensure any provided raw
|
|
2868
|
+
/// objects are first converted into model instances using the
|
|
2869
|
+
/// provided `Model` before it inserts anything.
|
|
2870
|
+
///
|
|
2871
|
+
/// You can also supply "sub models", and those will also be
|
|
2872
|
+
/// inserted in the correct order (and any foreign keys will
|
|
2873
|
+
/// also be updated for you). For example, if you have a `User`
|
|
2874
|
+
/// model that has a virtual `Type.Model` `primaryRole` field,
|
|
2875
|
+
/// then you can supply a new `Role` model upon insertion and
|
|
2876
|
+
/// Mythix ORM will handle this properly for you. For example:
|
|
2877
|
+
/// `await connection.insert(User, new User({ primaryRole: new Role({ ... }) }))`.
|
|
2878
|
+
/// This type of sub model save also works on through-tables.
|
|
2879
|
+
/// If `primaryRole` was targeting a `Role` model, but through
|
|
2880
|
+
/// another table(s), then Mythix ORM will also create the through-table
|
|
2881
|
+
/// relationships (if it is able to).
|
|
2882
|
+
///
|
|
2883
|
+
/// This **will not work** for `Types.Models` (multi-relations).
|
|
2884
|
+
/// Mythix ORM doesn't know what you intend for multi-relations
|
|
2885
|
+
/// (overwrite the set? add to the set? what?) so it will deliberately
|
|
2886
|
+
/// skip multi-relational fields. "sub models on insert" only work for
|
|
2887
|
+
/// single-relation fields defined with `Types.Model`. For multi-relation
|
|
2888
|
+
/// fields you must manually work through the relation yourself. For example,
|
|
2889
|
+
/// if our user instead had a `Types.Models` `roles` field (plural), then you
|
|
2890
|
+
/// would instead need to:
|
|
2891
|
+
///
|
|
2892
|
+
/// Example:
|
|
2893
|
+
/// let user = await connection.insert(User, new User({ ... }));
|
|
2894
|
+
/// let role = await connection.insert(Role, { ... }); // model instance is not required
|
|
2895
|
+
/// await user.addToRoles(role);
|
|
2896
|
+
///
|
|
2897
|
+
///
|
|
2898
|
+
/// Return: Promise<Array<Model> | Model>
|
|
2899
|
+
/// If you provide an array of models, then an array of models will be
|
|
2900
|
+
/// returned. If you provide only a single model, then a single
|
|
2901
|
+
/// model will be returned. If you provided "sub models" then those
|
|
2902
|
+
/// will be returned as "related models" on the primary model. For example,
|
|
2903
|
+
/// using the above `User` example, the newly created `Role` model that was
|
|
2904
|
+
/// stored for the `primaryRole` would be available on the returned `User`
|
|
2905
|
+
/// model as `user.Roles[0]`, or you could also access it via the field you
|
|
2906
|
+
/// set it on `user.primaryRole`.
|
|
2907
|
+
///
|
|
2908
|
+
/// Arguments:
|
|
2909
|
+
/// Model: class <see>Model</see>
|
|
2910
|
+
/// The model class used for the operation. This defines what
|
|
2911
|
+
/// table/bucket to insert the specified models into.
|
|
2912
|
+
/// models: Array<Model | object> | object | <see>Model</see>
|
|
2913
|
+
/// The model(s) to insert into the database. If raw objects are provided,
|
|
2914
|
+
/// then the properties of each object must match the required attributes
|
|
2915
|
+
/// for the model class.
|
|
2916
|
+
/// options?: object
|
|
2917
|
+
/// Most of these options are database/driver specific. However, the following
|
|
2918
|
+
/// options are common across all database drivers:
|
|
2919
|
+
/// | Option | Type | Default Value | Description |
|
|
2920
|
+
/// | ------------- | ---- | ------------- | ----------- |
|
|
2921
|
+
/// | `skipHooks` | `boolean` | `object` | `undefined` | Skip specific hooks. See <see>ConnectionBase.runSaveHooks</see> for more information. |
|
|
2922
|
+
/// | `batchSize` | `number` | `500` | The size of each batch during a multi-model insert operation. |
|
|
1247
2923
|
// eslint-disable-next-line no-unused-vars
|
|
1248
2924
|
async insert(Model, models, _options) {
|
|
1249
2925
|
throw new Error(`${this.constructor.name}::insert: This operation is not supported for this connection type.`);
|
|
1250
2926
|
}
|
|
1251
2927
|
|
|
2928
|
+
/// Insert or update (upsert) models into the database.
|
|
2929
|
+
///
|
|
2930
|
+
/// This method is only supported by some databases. Database
|
|
2931
|
+
/// drivers that don't support `upsert` natively may attempt to emulate
|
|
2932
|
+
/// the operation (at the cost of speed).
|
|
2933
|
+
///
|
|
2934
|
+
/// This method should function identically to <see>ConnectionBase.insert</see>,
|
|
2935
|
+
/// with the exception that it should update rows that already exist in the database
|
|
2936
|
+
/// instead of inserting new rows.
|
|
2937
|
+
///
|
|
2938
|
+
/// See: ConnectionBase.insert
|
|
2939
|
+
///
|
|
2940
|
+
/// Return: Promise<Array<Model> | Model>
|
|
2941
|
+
/// If you provide an array of models, then an array of models will be
|
|
2942
|
+
/// returned. If you provide only a single model, then a single
|
|
2943
|
+
/// model will be returned. If you provided "sub models" then those
|
|
2944
|
+
/// will be returned as "related models" on the primary model. For example,
|
|
2945
|
+
/// using the above `User` example, the newly created `Role` model that was
|
|
2946
|
+
/// stored for the `primaryRole` would be available on the returned `User`
|
|
2947
|
+
/// model as `user.Roles[0]`, or you could also access it via the field you
|
|
2948
|
+
/// set it on `user.primaryRole`.
|
|
2949
|
+
///
|
|
2950
|
+
/// Arguments:
|
|
2951
|
+
/// Model: class <see>Model</see>
|
|
2952
|
+
/// The model class used for the operation. This defines what
|
|
2953
|
+
/// table/bucket to insert the specified models into.
|
|
2954
|
+
/// models: Array<Model | object> | object | <see>Model</see>
|
|
2955
|
+
/// The model(s) to insert into the database. If raw objects are provided,
|
|
2956
|
+
/// then the properties of each object must match the required attributes
|
|
2957
|
+
/// for the model class.
|
|
2958
|
+
/// options?: object
|
|
2959
|
+
/// Most of these options are database/driver specific. However, the following
|
|
2960
|
+
/// options are common across all database drivers:
|
|
2961
|
+
/// | Option | Type | Default Value | Description |
|
|
2962
|
+
/// | ------------- | ---- | ------------- | ----------- |
|
|
2963
|
+
/// | `skipHooks` | `boolean` | `object` | `undefined` | Skip specific hooks. See <see>ConnectionBase.runSaveHooks</see> for more information. |
|
|
2964
|
+
/// | `batchSize` | `number` | `500` | The size of each batch during a multi-model upsert operation. |
|
|
1252
2965
|
// eslint-disable-next-line no-unused-vars
|
|
1253
2966
|
async upsert(Model, models, _options) {
|
|
1254
2967
|
throw new Error(`${this.constructor.name}::upsert: This operation is not supported for this connection type.`);
|
|
1255
2968
|
}
|
|
1256
2969
|
|
|
2970
|
+
/// Update the specified models in the database.
|
|
2971
|
+
///
|
|
2972
|
+
/// Many databases don't have good (or even decent) support
|
|
2973
|
+
/// for bulk updates, so unfortunately this method is fairly
|
|
2974
|
+
/// slow, and will usually make a query to the database for each
|
|
2975
|
+
/// model updated.
|
|
2976
|
+
///
|
|
2977
|
+
/// If you want to update many models at the same time (using the same
|
|
2978
|
+
/// attributes across all models), then consider using the <see>ConnectionBase.updateAll</see>
|
|
2979
|
+
/// method instead.
|
|
2980
|
+
///
|
|
2981
|
+
/// Note:
|
|
2982
|
+
/// Models will only be updated if they are dirty. Also, only the
|
|
2983
|
+
/// dirty attributes for each model will be updated (some attributes
|
|
2984
|
+
/// are always dirty, for example `updatedAt` fields are forced to
|
|
2985
|
+
/// always be dirty based on the configuration of their `defaultValue`).
|
|
2986
|
+
///
|
|
2987
|
+
/// Return: Promise<Array<Model> | Model>
|
|
2988
|
+
/// If you provide an array of models, then an array of models will be
|
|
2989
|
+
/// returned. If you provide only a single model, then a single
|
|
2990
|
+
/// model will be returned.
|
|
2991
|
+
///
|
|
2992
|
+
/// Arguments:
|
|
2993
|
+
/// Model: class <see>Model</see>
|
|
2994
|
+
/// The model class used for the operation. This defines what
|
|
2995
|
+
/// table/bucket to update.
|
|
2996
|
+
/// models: Array<Model | object> | object | <see>Model</see>
|
|
2997
|
+
/// The model(s) to update in the database. If raw objects are provided,
|
|
2998
|
+
/// then the properties of each object must match the required attributes
|
|
2999
|
+
/// for the model class.
|
|
3000
|
+
/// options?: object
|
|
3001
|
+
/// Most of these options are database/driver specific. However, the following
|
|
3002
|
+
/// options are common across all database drivers:
|
|
3003
|
+
/// | Option | Type | Default Value | Description |
|
|
3004
|
+
/// | ------------- | ---- | ------------- | ----------- |
|
|
3005
|
+
/// | `skipHooks` | `boolean` | `object` | `undefined` | Skip specific hooks. See <see>ConnectionBase.runSaveHooks</see> for more information. |
|
|
3006
|
+
/// | `batchSize` | `number` | `500` | The size of each batch during a multi-model update operation. |
|
|
1257
3007
|
// eslint-disable-next-line no-unused-vars
|
|
1258
3008
|
async update(Model, models, _options) {
|
|
1259
3009
|
throw new Error(`${this.constructor.name}::update: This operation is not supported for this connection type.`);
|
|
1260
3010
|
}
|
|
1261
3011
|
|
|
3012
|
+
/// Update multiple models at the same time (bulk update).
|
|
3013
|
+
///
|
|
3014
|
+
/// This will update multiple models at the same time
|
|
3015
|
+
/// using the provided `query` to select which models to update.
|
|
3016
|
+
/// All matching rows will set the provided `attributes` upon them.
|
|
3017
|
+
///
|
|
3018
|
+
/// The provided `attributes` can be a model instance, or
|
|
3019
|
+
/// a raw object. If a raw object is provided, then they
|
|
3020
|
+
/// will be converted into a model instance using the provided
|
|
3021
|
+
/// `Model` class. This also means that you can *only* bulk update
|
|
3022
|
+
/// columns/fields that exist on the model itself (i.e. you might have
|
|
3023
|
+
/// other columns in your table not related to this model, and
|
|
3024
|
+
/// those can **not** be updated using this method).
|
|
3025
|
+
///
|
|
3026
|
+
/// Note:
|
|
3027
|
+
/// As always with Mythix ORM, you will **never** supply
|
|
3028
|
+
/// raw column names as the `attributes`. You must always
|
|
3029
|
+
/// provide model field names in Mythix ORM.
|
|
3030
|
+
///
|
|
3031
|
+
/// Note:
|
|
3032
|
+
/// This will be an update operation across all matching rows,
|
|
3033
|
+
/// using the data provided. This method is really only useful
|
|
3034
|
+
/// when you want to update multiple rows to the **same values**.
|
|
3035
|
+
/// If you need to update each row to different values per-row,
|
|
3036
|
+
/// then use the <see>ConnectionBase.update</see> method instead.
|
|
3037
|
+
///
|
|
3038
|
+
/// Return: Promise<any>
|
|
3039
|
+
/// A database specific result from the `UPDATE` statement.
|
|
3040
|
+
/// In the future all "database specific" results will be
|
|
3041
|
+
/// abstracted away. So in the future, this will likely return
|
|
3042
|
+
/// the number of rows updated as a `number` (**HELP WANTED**).
|
|
3043
|
+
///
|
|
3044
|
+
/// Arguments:
|
|
3045
|
+
/// query: <see>QueryEngine</see>
|
|
3046
|
+
/// The query used to select which models/rows to update.
|
|
3047
|
+
/// The "root model" of the query is the table/bucket that
|
|
3048
|
+
/// will be updated.
|
|
3049
|
+
/// attributes: object | Model
|
|
3050
|
+
/// The attributes to set across all updated rows.
|
|
3051
|
+
/// options?: object
|
|
3052
|
+
/// Operation specific options. These will change depending on the database
|
|
3053
|
+
/// driver you are using. Please refer to the documentation for your specific
|
|
3054
|
+
/// driver for more information.
|
|
1262
3055
|
// eslint-disable-next-line no-unused-vars
|
|
1263
3056
|
async updateAll(_queryEngine, model, _options) {
|
|
1264
3057
|
throw new Error(`${this.constructor.name}::updateAll: This operation is not supported for this connection type.`);
|
|
1265
3058
|
}
|
|
1266
3059
|
|
|
3060
|
+
/// Destroy the provided models.
|
|
3061
|
+
///
|
|
3062
|
+
/// This method will bulk-iterate the specified
|
|
3063
|
+
/// models and will destroy each one. A primary key field
|
|
3064
|
+
/// is required for every model, or this method will throw
|
|
3065
|
+
/// an exception.
|
|
3066
|
+
///
|
|
3067
|
+
/// The `skipHooks` option (see <see>ConnectionBase.runSaveHooks</see>) won't
|
|
3068
|
+
/// do anything here, because Mythix ORM doesn't have any `on*Destroy` hooks.
|
|
3069
|
+
/// Mythix ORM doesn't have any destroy hooks for performance reasons.
|
|
3070
|
+
/// However, the `batchSize` option is still useful for this method.
|
|
3071
|
+
///
|
|
3072
|
+
/// Note:
|
|
3073
|
+
/// **WARNING!!!**: If you supply `null` or `undefined` as the `models`
|
|
3074
|
+
/// argument then this method will silently return. If you also supply
|
|
3075
|
+
/// the option `{ truncate: true }` then the entire table will be truncated.
|
|
3076
|
+
/// This option is an "opt-in", to make sure you don't truncate an entire
|
|
3077
|
+
/// table on accident.
|
|
3078
|
+
///
|
|
3079
|
+
/// Note:
|
|
3080
|
+
/// Some databases (i.e. SQLite) don't support a `TRUNCATE` statement,
|
|
3081
|
+
/// and so will deliberately call this method with `null` for the `models`
|
|
3082
|
+
/// argument for `truncate` operations. When doing so they will also
|
|
3083
|
+
/// deliberately supply the `{ truncate: true }` option.
|
|
3084
|
+
///
|
|
3085
|
+
/// Return: Promise<Array<Model> | Model>
|
|
3086
|
+
/// If you provide an array of models, then an array of models will be
|
|
3087
|
+
/// returned. If you provide only a single model, then a single
|
|
3088
|
+
/// model will be returned.
|
|
3089
|
+
///
|
|
3090
|
+
/// Arguments:
|
|
3091
|
+
/// Model: class <see>Model</see>
|
|
3092
|
+
/// The model class used for the operation. This defines what
|
|
3093
|
+
/// table/bucket to delete from.
|
|
3094
|
+
/// models: Array<Model | object> | object | <see>Model</see>
|
|
3095
|
+
/// The model(s) to delete from the database. If raw objects are provided,
|
|
3096
|
+
/// then they must contain a `primaryKey` for each model. If any of the
|
|
3097
|
+
/// models provided don't contain a `primaryKey` field, then an exception
|
|
3098
|
+
/// will be thrown. If you have a table/bucket that has no primary key column,
|
|
3099
|
+
/// then you will need to destroy rows manually yourself using a manual query
|
|
3100
|
+
/// with <see>ConnectionBase.query</see>, or by using the <see>ConnectionBase.destroy</see> method.
|
|
3101
|
+
/// options?: object
|
|
3102
|
+
/// Most of these options are database/driver specific. However, the following
|
|
3103
|
+
/// options are common across all database drivers (`skipHooks` is not supported in this context):
|
|
3104
|
+
/// | Option | Type | Default Value | Description |
|
|
3105
|
+
/// | ------------- | ---- | ------------- | ----------- |
|
|
3106
|
+
/// | `batchSize` | `number` | `500` | The size of each batch during a multi-model destroy operation. |
|
|
1267
3107
|
// eslint-disable-next-line no-unused-vars
|
|
1268
3108
|
async destroyModels(Model, _models, _options) {
|
|
1269
3109
|
throw new Error(`${this.constructor.name}::destroyModels: This operation is not supported for this connection type.`);
|
|
1270
3110
|
}
|
|
1271
3111
|
|
|
3112
|
+
/// Destroy multiple models by query, or by the
|
|
3113
|
+
/// provided models themselves. If models are provided,
|
|
3114
|
+
/// then each model must have a valid primary key field,
|
|
3115
|
+
/// or an exception will be thrown.
|
|
3116
|
+
///
|
|
3117
|
+
/// If models are provided as the second argument, then
|
|
3118
|
+
/// it is required that the first argument be a <see>Model</see>
|
|
3119
|
+
/// class. In this case, this method simply calls
|
|
3120
|
+
/// <see>ConnectionBase.destroyModels</see> to complete the operation.
|
|
3121
|
+
///
|
|
3122
|
+
/// If the first argument is a <see>QueryEngine</see> instance,
|
|
3123
|
+
/// then rows will be deleted from the database using the provided query.
|
|
3124
|
+
/// In this case, it is expected that the second argument
|
|
3125
|
+
/// will be the "options" for this operation instead of an array of models.
|
|
3126
|
+
///
|
|
3127
|
+
/// Return: Promise<Array<Models> | Model | number>
|
|
3128
|
+
/// Return the models deleted (if models were provided),
|
|
3129
|
+
/// or the number of rows deleted (if a query was provided).
|
|
3130
|
+
///
|
|
3131
|
+
/// Arguments:
|
|
3132
|
+
/// queryOrModel: class <see>Model</see> | <see>QueryEngine</see>
|
|
3133
|
+
/// A <see>QueryEngine</see> instance to specify which models to
|
|
3134
|
+
/// delete via a query, or a <see>Model</see> class if models are
|
|
3135
|
+
/// being provided to be deleted.
|
|
3136
|
+
/// modelsOrOptions: Array<Model> | Model | object
|
|
3137
|
+
/// If a <see>QueryEngine</see> instance is provided as the first argument
|
|
3138
|
+
/// then this is expected to be the "options" for the operation. If however
|
|
3139
|
+
/// a <see>Model</see> class is provided as the first argument, then this
|
|
3140
|
+
/// should be a <see>Model</see> instance, or an array of <see>Model</see> instances.
|
|
3141
|
+
/// options?: object | undefined
|
|
3142
|
+
/// Most of these options are database/driver specific.
|
|
3143
|
+
/// The `batchSize` option is ignored if a <see>QueryEngine</see> instance is provided as the
|
|
3144
|
+
/// first argument to the call. If a <see>Model</see> class is provided as the first argument to
|
|
3145
|
+
/// the call, then this `options` object will be at argument index `1` instead (the second argument, `modelsOrOptions`).
|
|
3146
|
+
/// The following options are common across all database drivers
|
|
3147
|
+
/// (`skipHooks` is not supported in this context):
|
|
3148
|
+
/// | Option | Type | Default Value | Description |
|
|
3149
|
+
/// | ------------- | ---- | ------------- | ----------- |
|
|
3150
|
+
/// | `batchSize` | `number` | `500` | The size of each batch during a multi-model destroy operation. |
|
|
1272
3151
|
// eslint-disable-next-line no-unused-vars
|
|
1273
3152
|
async destroy(_queryEngineOrModel, modelsOrOptions, _options) {
|
|
1274
3153
|
throw new Error(`${this.constructor.name}::destroy: This operation is not supported for this connection type.`);
|
|
1275
3154
|
}
|
|
1276
3155
|
|
|
3156
|
+
/// Select data from the underlying database.
|
|
3157
|
+
///
|
|
3158
|
+
/// To select data from the database you will use this method,
|
|
3159
|
+
/// providing a `query` as a <see>QueryEngine</see> instance.
|
|
3160
|
+
/// The provided query will be used to generate the underlying
|
|
3161
|
+
/// request to the database, will collect the response, and return
|
|
3162
|
+
/// the results to the caller.
|
|
3163
|
+
///
|
|
3164
|
+
/// This method is an async generator method, and is designed for
|
|
3165
|
+
/// "streaming" results from the database, one "row" at a time. Many
|
|
3166
|
+
/// methods that call this method (such as <see>QueryEngine.all</see>)
|
|
3167
|
+
/// collect all the results from the async generator to return an array
|
|
3168
|
+
/// of results to the caller. This is because it is often tedious to
|
|
3169
|
+
/// collect the results yourself from the async generator, and often the
|
|
3170
|
+
/// caller simply wants a small amount of data from the database.
|
|
3171
|
+
/// However, if you intend to fetch large amounts of data from your database,
|
|
3172
|
+
/// it is a good idea to call this method directly, and iterate the results
|
|
3173
|
+
/// of the async generator manually. All methods that in-turn call this
|
|
3174
|
+
/// method (such as <see>QueryEngine.all</see>) will generally have a
|
|
3175
|
+
/// `{ stream: true }` option that can be provided, causing the method to
|
|
3176
|
+
/// return the async generator, instead of the collected results.
|
|
3177
|
+
///
|
|
3178
|
+
///
|
|
3179
|
+
/// Return: AsyncGenerator<Model>
|
|
3180
|
+
///
|
|
3181
|
+
/// Arguments:
|
|
3182
|
+
/// query: <see>QueryEngine</see>
|
|
3183
|
+
/// The query to run against the underlying database. This is generated
|
|
3184
|
+
/// from a <see>QueryEngine</see> interface. The result of this <see>QueryEngine</see>
|
|
3185
|
+
/// instance will then be converted to a query, or generated code to
|
|
3186
|
+
/// interact with the underlying database.
|
|
3187
|
+
/// options?: object
|
|
3188
|
+
/// Operation specific options. These will change depending on the database
|
|
3189
|
+
/// driver you are using. Please refer to the documentation for your specific
|
|
3190
|
+
/// driver for more information.
|
|
1277
3191
|
// eslint-disable-next-line no-unused-vars, require-yield
|
|
1278
3192
|
async *select(_queryEngine, _options) {
|
|
1279
3193
|
throw new Error(`${this.constructor.name}::select: This operation is not supported for this connection type.`);
|
|
1280
3194
|
}
|
|
1281
3195
|
|
|
3196
|
+
/// Aggregate data across rows.
|
|
3197
|
+
///
|
|
3198
|
+
/// Though this method can be called directly, it is generally called from
|
|
3199
|
+
/// one of <see>ConnectionBase.average</see>, <see>ConnectionBase.sum</see>,
|
|
3200
|
+
/// <see>ConnectionBase.count</see>, <see>ConnectionBase.min</see>,
|
|
3201
|
+
/// or <see>ConnectionBase.max</see>, or one of the other aggregate methods
|
|
3202
|
+
/// provided by the connection.
|
|
3203
|
+
///
|
|
3204
|
+
/// It takes a `query` which is used to generate a query for the underlying
|
|
3205
|
+
/// database, and sets the query `PROJECTION` to the aggregate `literal` provided.
|
|
3206
|
+
/// For example, a `sum` method call would call this method with a `SumLiteral`,
|
|
3207
|
+
/// which would change the `query` projection to the expanded result of the
|
|
3208
|
+
/// `SumLiteral`, returning the "sum" of all column values targeted by the literal field.
|
|
3209
|
+
/// The results will then be collected, and always returned as a `number` primitive
|
|
3210
|
+
/// to the caller.
|
|
3211
|
+
///
|
|
3212
|
+
/// Return: Promise<number>
|
|
3213
|
+
/// The result of the aggregate operation, as a number.
|
|
3214
|
+
///
|
|
3215
|
+
/// Arguments:
|
|
3216
|
+
/// query: <see>QueryEngine</see>
|
|
3217
|
+
/// The query used to select which rows to aggregate across.
|
|
3218
|
+
/// literal: <see>LiteralBase</see>
|
|
3219
|
+
/// A literal, used as the aggregate function. For example, if a
|
|
3220
|
+
/// <see>CountLiteral</see> is provided, then the count of all rows
|
|
3221
|
+
/// matching the provided query will be the result.
|
|
3222
|
+
/// options?: object
|
|
3223
|
+
/// Operation specific options. These will change depending on the database
|
|
3224
|
+
/// driver you are using. Please refer to the documentation for your specific
|
|
3225
|
+
/// driver for more information.
|
|
1282
3226
|
// eslint-disable-next-line no-unused-vars
|
|
1283
3227
|
async aggregate(_queryEngine, _literal, options) {
|
|
1284
3228
|
throw new Error(`${this.constructor.name}::aggregate: This operation is not supported for this connection type.`);
|
|
1285
3229
|
}
|
|
1286
3230
|
|
|
3231
|
+
/// Get the average for a single column, spanning all matching rows.
|
|
3232
|
+
///
|
|
3233
|
+
/// This will return the average of all values in a column,
|
|
3234
|
+
/// across all matching rows, as a `number` primitive.
|
|
3235
|
+
///
|
|
3236
|
+
/// Return: Promise<number>
|
|
3237
|
+
/// The average of all matching columns.
|
|
3238
|
+
///
|
|
3239
|
+
/// Arguments:
|
|
3240
|
+
/// query: <see>QueryEngine</see>
|
|
3241
|
+
/// The query used to select which rows are used to calculate the average.
|
|
3242
|
+
/// field: <see>Field</see> | string
|
|
3243
|
+
/// A field instance, or a fully qualified field name, used as the target
|
|
3244
|
+
/// column in the underlying database to calculate an average across all matching values.
|
|
3245
|
+
/// options?: object
|
|
3246
|
+
/// Operation specific options. These will change depending on the database
|
|
3247
|
+
/// driver you are using. Please refer to the documentation for your specific
|
|
3248
|
+
/// driver for more information.
|
|
1287
3249
|
// eslint-disable-next-line no-unused-vars
|
|
1288
3250
|
async average(_queryEngine, _field, options) {
|
|
1289
3251
|
throw new Error(`${this.constructor.name}::average: This operation is not supported for this connection type.`);
|
|
1290
3252
|
}
|
|
1291
3253
|
|
|
3254
|
+
/// Get the number of rows matching the query.
|
|
3255
|
+
///
|
|
3256
|
+
/// This will return the number of rows matching
|
|
3257
|
+
/// the provided query, as a `number` primitive.
|
|
3258
|
+
///
|
|
3259
|
+
/// Note:
|
|
3260
|
+
/// In most databases, if the `field` argument is not
|
|
3261
|
+
/// specified, then the count operation will be across
|
|
3262
|
+
/// all table columns (`COUNT(*)`).
|
|
3263
|
+
///
|
|
3264
|
+
/// Return: Promise<number>
|
|
3265
|
+
/// The count (number) of all rows matching the provided query.
|
|
3266
|
+
///
|
|
3267
|
+
/// Arguments:
|
|
3268
|
+
/// query: <see>QueryEngine</see>
|
|
3269
|
+
/// The query used to select which rows to count.
|
|
3270
|
+
/// field: <see>Field</see> | string
|
|
3271
|
+
/// A field instance, or a fully qualified field name, used as the target
|
|
3272
|
+
/// column in the underlying database to count the rows. If not specified,
|
|
3273
|
+
/// then most database drivers will count across all columns (i.e. `COUNT(*)`).
|
|
3274
|
+
/// options?: object
|
|
3275
|
+
/// Operation specific options. These will change depending on the database
|
|
3276
|
+
/// driver you are using. Please refer to the documentation for your specific
|
|
3277
|
+
/// driver for more information.
|
|
1292
3278
|
// eslint-disable-next-line no-unused-vars
|
|
1293
3279
|
async count(_queryEngine, _field, options) {
|
|
1294
3280
|
throw new Error(`${this.constructor.name}::count: This operation is not supported for this connection type.`);
|
|
1295
3281
|
}
|
|
1296
3282
|
|
|
3283
|
+
/// Get the minimum value for a column, spanning all matching rows.
|
|
3284
|
+
///
|
|
3285
|
+
/// This will return the minimum of all values in a column,
|
|
3286
|
+
/// across all matching rows, as a `number` primitive.
|
|
3287
|
+
///
|
|
3288
|
+
/// Return: Promise<number>
|
|
3289
|
+
/// The minimum value found across all matching rows.
|
|
3290
|
+
///
|
|
3291
|
+
/// Arguments:
|
|
3292
|
+
/// query: <see>QueryEngine</see>
|
|
3293
|
+
/// The query used to select which rows are used to calculate the minimum.
|
|
3294
|
+
/// field: <see>Field</see> | string
|
|
3295
|
+
/// A field instance, or a fully qualified field name, used as the target
|
|
3296
|
+
/// column in the underlying database to find the minimum across all matching values.
|
|
3297
|
+
/// options?: object
|
|
3298
|
+
/// Operation specific options. These will change depending on the database
|
|
3299
|
+
/// driver you are using. Please refer to the documentation for your specific
|
|
3300
|
+
/// driver for more information.
|
|
1297
3301
|
// eslint-disable-next-line no-unused-vars
|
|
1298
3302
|
async min(_queryEngine, _field, options) {
|
|
1299
3303
|
throw new Error(`${this.constructor.name}::min: This operation is not supported for this connection type.`);
|
|
1300
3304
|
}
|
|
1301
3305
|
|
|
3306
|
+
/// Get the maximum value for a column, spanning all matching rows.
|
|
3307
|
+
///
|
|
3308
|
+
/// This will return the maximum of all values in a column,
|
|
3309
|
+
/// across all matching rows, as a `number` primitive.
|
|
3310
|
+
///
|
|
3311
|
+
/// Return: Promise<number>
|
|
3312
|
+
/// The maximum value found across all matching rows.
|
|
3313
|
+
///
|
|
3314
|
+
/// Arguments:
|
|
3315
|
+
/// query: <see>QueryEngine</see>
|
|
3316
|
+
/// The query used to select which rows are used to calculate the maximum.
|
|
3317
|
+
/// field: <see>Field</see> | string
|
|
3318
|
+
/// A field instance, or a fully qualified field name, used as the target
|
|
3319
|
+
/// column in the underlying database to find the maximum across all matching values.
|
|
3320
|
+
/// options?: object
|
|
3321
|
+
/// Operation specific options. These will change depending on the database
|
|
3322
|
+
/// driver you are using. Please refer to the documentation for your specific
|
|
3323
|
+
/// driver for more information.
|
|
1302
3324
|
// eslint-disable-next-line no-unused-vars
|
|
1303
3325
|
async max(_queryEngine, _field, options) {
|
|
1304
3326
|
throw new Error(`${this.constructor.name}::max: This operation is not supported for this connection type.`);
|
|
1305
3327
|
}
|
|
1306
3328
|
|
|
3329
|
+
/// Get the sum of all values for a column, spanning all matching rows.
|
|
3330
|
+
///
|
|
3331
|
+
/// This will return the sum of all values in a column,
|
|
3332
|
+
/// across all matching rows, as a `number` primitive.
|
|
3333
|
+
///
|
|
3334
|
+
/// Return: Promise<number>
|
|
3335
|
+
/// The sum of all values found across all matching rows.
|
|
3336
|
+
///
|
|
3337
|
+
/// Arguments:
|
|
3338
|
+
/// query: <see>QueryEngine</see>
|
|
3339
|
+
/// The query used to select which rows are used to calculate the sum.
|
|
3340
|
+
/// field: <see>Field</see> | string
|
|
3341
|
+
/// A field instance, or a fully qualified field name, used as the target
|
|
3342
|
+
/// column in the underlying database to find the sum of all matching values.
|
|
3343
|
+
/// options?: object
|
|
3344
|
+
/// Operation specific options. These will change depending on the database
|
|
3345
|
+
/// driver you are using. Please refer to the documentation for your specific
|
|
3346
|
+
/// driver for more information.
|
|
1307
3347
|
// eslint-disable-next-line no-unused-vars
|
|
1308
3348
|
async sum(_queryEngine, _field, options) {
|
|
1309
3349
|
throw new Error(`${this.constructor.name}::sum: This operation is not supported for this connection type.`);
|
|
1310
3350
|
}
|
|
1311
3351
|
|
|
3352
|
+
/// Pluck only specific columns/fields from the
|
|
3353
|
+
/// underlying database, using the provided `query`.
|
|
3354
|
+
///
|
|
3355
|
+
/// This method will return only the specified `fields`
|
|
3356
|
+
/// from the database--as raw values--from rows matched
|
|
3357
|
+
/// on by the provided query.
|
|
3358
|
+
///
|
|
3359
|
+
/// This method is often much faster than a normal `select` operation,
|
|
3360
|
+
/// in that only the data requested will be transmitted from the database,
|
|
3361
|
+
/// and models won't be constructed and stitched together on load. Use this
|
|
3362
|
+
/// when you just need an "array of values" across certain columns from a table.
|
|
3363
|
+
///
|
|
3364
|
+
/// Return: Array<any> | Array<Array<any>> | Array<object>
|
|
3365
|
+
/// If the provided `fields` argument is an array of fields
|
|
3366
|
+
/// (fully qualified field names, or <see>Field</see> instances),
|
|
3367
|
+
/// then the result will be an array of arrays, where each item
|
|
3368
|
+
/// in the top-level array is a "row", and each sub-array is the
|
|
3369
|
+
/// values for the columns (fields) specified. If a single field
|
|
3370
|
+
/// is specified, then an one dimensional array is returned, where
|
|
3371
|
+
/// each item is the column value for each row fetched.
|
|
3372
|
+
/// For example, if we call `pluck` like: `let result = await connection.pluck(User.where.firstName.EQ('Bob'), 'User:id')`
|
|
3373
|
+
/// then the `result` would look like `[ 'USER_id_1`, `USER_id_2`, ... ]`
|
|
3374
|
+
/// where each value in the array is a user id. If however we call pluck like:
|
|
3375
|
+
/// `let result = await connection.pluck(User.where.firstName.EQ('Bob'), [ 'User:id', 'User:firstName' ])`
|
|
3376
|
+
/// then the `result` would look like `[ [ 'USER_id_1', 'Bob' ], [ 'USER_id_2', 'Bob' ], ... ]`, because
|
|
3377
|
+
/// the provided `fields` is an array, an array of field values will be returned from each row.
|
|
3378
|
+
/// If the `option` `mapToObjects` is `true`, then an array of objects will be returned,
|
|
3379
|
+
/// where each object is a "row", and each property one of the specified fields. Note that
|
|
3380
|
+
/// the properties of each returned object will be the fully qualified field name of each field
|
|
3381
|
+
/// specified. So, for example, specifying a pluck field of `User:id` means that each returned
|
|
3382
|
+
/// object in the array will look like `[ { 'User:id': 'USER_id_1' }, { 'User:id': 'USER_id_2' }, ... ]`.
|
|
3383
|
+
///
|
|
3384
|
+
/// Arguments:
|
|
3385
|
+
/// query: <see>QueryEngine</see>
|
|
3386
|
+
/// The query used to select rows from which columns will be plucked.
|
|
3387
|
+
/// fields: <see>Field</see> | string | Array<Field> | Array<string>
|
|
3388
|
+
/// Which fields to "pluck" from the matching rows. If an array is provided (even if
|
|
3389
|
+
/// it only contains a single field), then an array of arrays will be returned
|
|
3390
|
+
/// as the result. If a single field is provided (not an array), then an array
|
|
3391
|
+
/// of raw plucked column values will be returned instead.
|
|
3392
|
+
/// options?: object
|
|
3393
|
+
/// Operation specified options. These might change based on the database driver you
|
|
3394
|
+
/// are using, so please refer to your specific database driver documentation. One
|
|
3395
|
+
/// option that is common across all drivers is the `mapToObjects` boolean option.
|
|
3396
|
+
/// If `true`, then each row in the returned array will be an object instead of
|
|
3397
|
+
/// raw column values, where the property of each "row object" will be the fully
|
|
3398
|
+
/// qualified names of each field provided as the `fields` argument.
|
|
1312
3399
|
// eslint-disable-next-line no-unused-vars
|
|
1313
3400
|
async pluck(_queryEngine, _fields, _options) {
|
|
1314
3401
|
throw new Error(`${this.constructor.name}::pluck: This operation is not supported for this connection type.`);
|
|
1315
3402
|
}
|
|
1316
3403
|
|
|
3404
|
+
/// Check if any rows match the provided `query`.
|
|
3405
|
+
///
|
|
3406
|
+
/// Return: boolean
|
|
3407
|
+
/// `true` if one or more rows match the provided query, or `false` otherwise.
|
|
3408
|
+
///
|
|
3409
|
+
/// Arguments:
|
|
3410
|
+
/// query: <see>QueryEngine</see>
|
|
3411
|
+
/// The query used to select rows, to check if said rows exist in the database.
|
|
3412
|
+
/// options?: object
|
|
3413
|
+
/// Operation specific options. These will change depending on the database
|
|
3414
|
+
/// driver you are using. Please refer to the documentation for your specific
|
|
3415
|
+
/// driver for more information.
|
|
1317
3416
|
// eslint-disable-next-line no-unused-vars
|
|
1318
3417
|
async exists(queryEngine, options) {
|
|
1319
3418
|
throw new Error(`${this.constructor.name}::exists: This operation is not supported for this connection type.`);
|
|
1320
3419
|
}
|
|
1321
3420
|
|
|
3421
|
+
/// Truncate (erase/clear) the entire table/bucket defined
|
|
3422
|
+
/// by the provided `Model`. All rows/objects from the underlying
|
|
3423
|
+
/// table/bucket will be destroyed, leaving you with an empty
|
|
3424
|
+
/// table/bucket.
|
|
3425
|
+
///
|
|
3426
|
+
/// Return: Promise<void>
|
|
3427
|
+
///
|
|
3428
|
+
/// Arguments:
|
|
3429
|
+
/// Model: class <see>Model</see>
|
|
3430
|
+
/// The model class that defines the underlying table/bucket to wipe clean/erase.
|
|
3431
|
+
/// options?: object
|
|
3432
|
+
/// Operation specific options. These will change depending on the database
|
|
3433
|
+
/// driver you are using. Please refer to the documentation for your specific
|
|
3434
|
+
/// driver for more information.
|
|
1322
3435
|
// eslint-disable-next-line no-unused-vars
|
|
1323
3436
|
async truncate(Model, options) {
|
|
1324
3437
|
throw new Error(`${this.constructor.name}::truncate: This operation is not supported for this connection type.`);
|
|
1325
3438
|
}
|
|
1326
3439
|
|
|
3440
|
+
/// "raw" database/driver specific query interface.
|
|
3441
|
+
///
|
|
3442
|
+
/// For SQL based databases, this would send a direct
|
|
3443
|
+
/// query string to the database. For other drivers, the
|
|
3444
|
+
/// arguments and operations that are executed might change.
|
|
3445
|
+
///
|
|
3446
|
+
/// Use this method to directly interact with the underlying
|
|
3447
|
+
/// database, in its own native query language.
|
|
3448
|
+
///
|
|
3449
|
+
/// The arguments and return value from this method is database/driver
|
|
3450
|
+
/// specific. Any `options` argument the database provides are also
|
|
3451
|
+
/// specific to the underlying database driver. However, one option
|
|
3452
|
+
/// is common across all drivers, and this is the `logger` option. If
|
|
3453
|
+
/// set, it is expected to have a `log` method in the provided `logger`
|
|
3454
|
+
/// object. Oftentimes, this will simply be `{ logger: console }`, but
|
|
3455
|
+
/// you can provided any custom `logger` instance you want, as long as it
|
|
3456
|
+
/// has a `log` method that can be called to log the results of the query.
|
|
3457
|
+
/// Most drivers also support a `{ logger }` option as a connection option
|
|
3458
|
+
/// when the connection is first instantiated, which will provided logging
|
|
3459
|
+
/// to every query that goes through the connection.
|
|
3460
|
+
///
|
|
3461
|
+
/// Return: database specific
|
|
3462
|
+
/// A database/driver specific return value, based on the query provided.
|
|
1327
3463
|
// eslint-disable-next-line no-unused-vars
|
|
1328
3464
|
async query(sql, options) {
|
|
1329
3465
|
throw new Error(`${this.constructor.name}::query: This operation is not supported for this connection type.`);
|
|
1330
3466
|
}
|
|
1331
3467
|
|
|
3468
|
+
/// Initiate a transaction (or snapshot/sub-transaction)
|
|
3469
|
+
/// if the database driver supports transactions.
|
|
3470
|
+
///
|
|
3471
|
+
/// This will initiate a transaction in the underlying database,
|
|
3472
|
+
/// if the database supports it. For SQL type databases this would
|
|
3473
|
+
/// be a `BEGIN/COMMIT/ROLLBACK` block. If this method is called
|
|
3474
|
+
/// when a transaction is already in-progress, then a snapshot/sub-transaction
|
|
3475
|
+
/// will be started instead.
|
|
3476
|
+
///
|
|
3477
|
+
/// This method will start a transaction in the underlying database,
|
|
3478
|
+
/// and call the provided asynchronous callback. If the callback throws
|
|
3479
|
+
/// an error, then the transaction (or snapshot) will be automatically
|
|
3480
|
+
/// rolled-back. There is a single `connection` argument that will be
|
|
3481
|
+
/// provided to the callback function when called. This `connection` argument
|
|
3482
|
+
/// will be the transaction connection itself, which for many database drivers is simply
|
|
3483
|
+
/// the same connection the transaction was started from. At a lower-level,
|
|
3484
|
+
/// Mythix ORM will use an [AsyncLocalStorage](https://nodejs.org/docs/latest-v16.x/api/async_context.html)
|
|
3485
|
+
/// context to provide the transaction connection to all code executed inside
|
|
3486
|
+
/// the callback, so the provided `connection` argument can generally be ignored.
|
|
3487
|
+
/// However, if [AsyncLocalStorage](https://nodejs.org/docs/latest-v16.x/api/async_context.html) isn't
|
|
3488
|
+
/// supported in your environment, or the specific driver you are using requires that you use
|
|
3489
|
+
/// the supplied `connection` argument, then you must use the supplied `connection`
|
|
3490
|
+
/// for all your operations, and provide it as the `{ connection }` option to all Mythix ORM
|
|
3491
|
+
/// calls made inside the callback.
|
|
3492
|
+
///
|
|
3493
|
+
/// Return: Promise<any>
|
|
3494
|
+
/// Return whatever return value is returned from the provided callback.
|
|
3495
|
+
///
|
|
3496
|
+
/// Arguments:
|
|
3497
|
+
/// callback: (connection: <see>Connection</see>) => any
|
|
3498
|
+
/// The async callback to call for the transaction operation. This should return as quickly as
|
|
3499
|
+
/// possible to avoid deadlocks in the underlying database. Whatever value this method
|
|
3500
|
+
/// returns will be the return value from the `transaction` call itself. If an exception is
|
|
3501
|
+
/// thrown in this method, then the transaction will be automatically rolled-back. If no
|
|
3502
|
+
/// exception is thrown from this method, then when done executing, a `COMMIT` will be sent
|
|
3503
|
+
/// to the underlying database automatically for you.
|
|
3504
|
+
/// options?: object
|
|
3505
|
+
/// Optional database specific options to supply for the transaction operation. There are two
|
|
3506
|
+
/// options that are supported across most database drivers, and those are `connection` and `lock`.
|
|
3507
|
+
/// The `connection` option supplies the the connection to initiate the transaction from, which for
|
|
3508
|
+
/// example might be another transaction connection (initiating a sub-transaction). If no `connection`
|
|
3509
|
+
/// option is supplied, then the `connection` this method was called from is used instead. The second
|
|
3510
|
+
/// common option is `lock`, which specifies how/if to lock the table for the transaction.
|
|
3511
|
+
/// See <see>ConnectionBase.getLockMode</see> for your specific driver for more information on this `lock` option.
|
|
1332
3512
|
// eslint-disable-next-line no-unused-vars
|
|
1333
3513
|
async transaction(callback, options) {
|
|
1334
3514
|
throw new Error(`${this.constructor.name}::transaction: This operation is not supported for this connection type.`);
|
|
1335
3515
|
}
|
|
1336
3516
|
|
|
3517
|
+
/// Translate the `defaultValue` as provided by each models field's
|
|
3518
|
+
/// into a `DEFAULT` value for the underlying database.
|
|
3519
|
+
///
|
|
3520
|
+
/// For example, if you were to specify a `defaultValue` for one of your
|
|
3521
|
+
/// models field's, such as `defaultValue: Types.INTEGER.Defaults.AUTOINCREMENT`,
|
|
3522
|
+
/// then this method would return a database specific `autoincrement` default for
|
|
3523
|
+
/// the column defined by your field. For date/time fields, this might be a database
|
|
3524
|
+
/// specific `NOW()` default. For non-database specific "defaults", the default value
|
|
3525
|
+
/// as defined by your `defaultValue` on your fields is simply returned.
|
|
3526
|
+
///
|
|
3527
|
+
/// Return: any
|
|
3528
|
+
/// Your defined field's `defaultValue`, intercepted, and possibly translated to
|
|
3529
|
+
/// a proper value for the underlying database. It is common for many database
|
|
3530
|
+
/// drivers that only date/time and auto-increment default values are intercepted
|
|
3531
|
+
/// and translated. Most other "default values" are simply returned.
|
|
3532
|
+
///
|
|
3533
|
+
/// Arguments:
|
|
3534
|
+
/// type: <see>Type</see>
|
|
3535
|
+
/// The field's `type` instance, as defined by the field itself.
|
|
3536
|
+
/// context: DefaultValueContext
|
|
3537
|
+
/// A `DefaultValueContext` as is normally provided to all `defaultValue` methods
|
|
3538
|
+
/// defined on <see name="fields">Field</see>. See the documentation for the `defaultValue`
|
|
3539
|
+
/// property of <see>Field</see> for more information.
|
|
1337
3540
|
// eslint-disable-next-line no-unused-vars
|
|
1338
3541
|
async getDefaultFieldValue(type, context) {
|
|
1339
3542
|
throw new Error(`${this.constructor.name}::getDefaultFieldValue: This operation is not supported for this connection type.`);
|
|
1340
3543
|
}
|
|
1341
3544
|
|
|
3545
|
+
/// A connection specific "helper" to force "dirty" fields
|
|
3546
|
+
/// for all models.
|
|
3547
|
+
///
|
|
3548
|
+
/// This method, when present on a connection, will assist in
|
|
3549
|
+
/// defining which fields are "dirty" for a model. It is used,
|
|
3550
|
+
/// for example, by `Types.DATETIME.Defaults.NOW.UPDATED` default values.
|
|
3551
|
+
/// In the case presented, DATETIME fields that should always be updated
|
|
3552
|
+
/// are always marked dirty by this method, even though they might
|
|
3553
|
+
/// not actually be "dirty" client-side.
|
|
3554
|
+
///
|
|
3555
|
+
/// If this method returns _any_ value other than `undefined`, then
|
|
3556
|
+
/// the field being operated upon will be marked "dirty" with the value
|
|
3557
|
+
/// returned, even if the field would otherwise not be marked "dirty".
|
|
3558
|
+
///
|
|
3559
|
+
/// Return: any
|
|
3560
|
+
/// If _any_ value is returned that is not `undefined`, then the field
|
|
3561
|
+
/// will be marked "dirty" with the value returned. Return `undefined`
|
|
3562
|
+
/// if you do not wish to mark a specific field as "dirty". Note however
|
|
3563
|
+
/// that the field _might_ actually still be dirty because the user modified
|
|
3564
|
+
/// the field, in which case this method will not even be called for that field.
|
|
3565
|
+
/// In short, this method is only called for fields that are not already marked
|
|
3566
|
+
/// as dirty, and will force a field to be marked dirty if any value other than
|
|
3567
|
+
/// `undefined` is returned.
|
|
3568
|
+
///
|
|
3569
|
+
/// Arguments:
|
|
3570
|
+
/// context: DefaultValueContext
|
|
3571
|
+
/// See <see>Field</see> for documentation on the `DefaultValueContext` interface.
|
|
1342
3572
|
// eslint-disable-next-line no-unused-vars
|
|
1343
3573
|
dirtyFieldHelper(context) {
|
|
1344
3574
|
|