mythix-orm 1.11.6 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -9
- package/lib/connection/connection-base.js +173 -39
- package/lib/connection/literals/average-literal.js +67 -0
- package/lib/connection/literals/count-literal.js +80 -0
- package/lib/connection/literals/distinct-literal.js +71 -0
- package/lib/connection/literals/field-literal.js +54 -0
- package/lib/connection/literals/literal-base.d.ts +1 -0
- package/lib/connection/literals/literal-base.js +137 -2
- package/lib/connection/literals/literal-field-base.js +50 -0
- package/lib/connection/literals/literal.js +15 -0
- package/lib/connection/literals/max-literal.js +67 -0
- package/lib/connection/literals/min-literal.js +67 -0
- package/lib/connection/literals/sum-literal.js +67 -0
- package/lib/connection/query-generator-base.js +273 -0
- package/lib/field.js +1 -1
- package/lib/model.js +54 -2
- package/lib/proxy-class/proxy-class.js +156 -21
- package/lib/query-engine/field-scope.js +401 -9
- package/lib/query-engine/model-scope.js +572 -13
- package/lib/query-engine/query-engine-base.js +590 -30
- package/lib/query-engine/query-engine.d.ts +13 -2
- package/lib/query-engine/query-engine.js +525 -18
- package/lib/types/helpers/default-helpers.js +124 -0
- package/lib/types/type.js +297 -3
- package/lib/utils/async-store.js +80 -3
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -1,15 +1,106 @@
|
|
|
1
1
|
# mythix-orm
|
|
2
2
|
|
|
3
|
-
ORM
|
|
3
|
+
Mythix ORM aims to replace Sequelize and the few other terrible solutions that the poor destitute Node community has to work with. Mythix ORM has been designed to replace all current ORMs for Node, with a focus on what is lacking in the community, namely good engineering, good documentation, and ease of use.
|
|
4
4
|
|
|
5
|
-
Mythix
|
|
6
|
-
|
|
7
|
-
What to expect while you are waiting:
|
|
8
|
-
1. Advanced, seamless, and powerful (yet simple) query engine that is easy to use, and works across database drivers, even for No-SQL databases. Here is a simple example to fetch users and their roles: `let users = await User.where.id.EQ(Role.where.userID).firstName.EQ('Mythix').lastName.EQ('ORM').Roles.name.EQ('superuser').PROJECT('User', 'Role').all();`
|
|
5
|
+
Mythix ORMs feature set includes:
|
|
6
|
+
1. An advanced, seamless, and powerful (yet simple) query engine that is easy to use, and works across database drivers, even for No-SQL databases.
|
|
9
7
|
2. Powerful model classes and helpers that don't violate good design patterns, stay out of your face, and have no undocumented auto-magic built in. The model system is also designed to work seamlessly across different databases, including No-SQL databases.
|
|
10
8
|
3. Simple, clean, and slim... Mythix ORM isn't intended to be a sledge hammer, nor a 'batteries included' framework. Instead, it is designed to be a useful tool, and was designed to be easily extended. It can be used for large enterprise applications, or it can be used as a simple slim layer to interact with different databases in a human-friendly way.
|
|
11
|
-
4.
|
|
12
|
-
5.
|
|
13
|
-
6.
|
|
9
|
+
4. A modular design. Instead of being a large bloated library that attempts to handle every database and every type of operation, it instead only provides exactly what you need. Mythix ORM is itself just a base connection, a query engine, and a model and type system. That is all. To interact with databases you can choose between any number of drivers for Mythix ORM (coming soon!), and can use community-built plugins for adding features (or simply write your own!).
|
|
10
|
+
5. A deliberate design to be extended and added onto. Easily modify the Query Engine to add more features, create your own database driver, modify how models behave, or add your own custom data types. The sky is the limit!
|
|
11
|
+
6. Complete feature parity (and soon greater functionality) then all existing ORMs for Node. Model validation, hooks, model attributes and data types, model relations, support for multiple databases, an advanced query engine, transactions, transactions inside transactions, useful utility methods, an extensible type system, virtual types, an extensible query generator, support for older Node versions, support for multiple connections and multiplex connections (at the same time), and more!
|
|
12
|
+
|
|
13
|
+
Mythix ORM is still in its very early stages, and is looking for users! It is stable, and currently has native support for SQLite and PostgreSQL. A mongo driver will be added next, and after that MySQL. If you want to help then drop me a line! All help is welcome.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm i --save mythix-orm mythix-orm-sqlite
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Documentation
|
|
22
|
+
|
|
23
|
+
Check out the [WIKI](https://github.com/th317erd/mythix-orm/wiki) for documentation.
|
|
24
|
+
|
|
25
|
+
## Getting started
|
|
26
|
+
|
|
27
|
+
Just start creating models!
|
|
28
|
+
|
|
29
|
+
```javascript
|
|
30
|
+
const { Model, Types } = require('mythix-orm');
|
|
31
|
+
const SQLiteConnection = require('mythix-orm-sqlite');
|
|
32
|
+
|
|
33
|
+
class User extends Model {
|
|
34
|
+
static fields = {
|
|
35
|
+
id: {
|
|
36
|
+
type: Types.XID(),
|
|
37
|
+
defaultValue: Types.XID.Defaults.XID,
|
|
38
|
+
allowNull: false,
|
|
39
|
+
primaryKey: true,
|
|
40
|
+
},
|
|
41
|
+
email: {
|
|
42
|
+
type: Types.STRING(128),
|
|
43
|
+
allowNull: false,
|
|
44
|
+
index: true,
|
|
45
|
+
unique: true,
|
|
46
|
+
},
|
|
47
|
+
firstName: {
|
|
48
|
+
type: Types.STRING(64),
|
|
49
|
+
allowNull: false,
|
|
50
|
+
index: true,
|
|
51
|
+
},
|
|
52
|
+
lastName: {
|
|
53
|
+
type: Types.STRING(64),
|
|
54
|
+
allowNull: false,
|
|
55
|
+
index: true,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Entry point
|
|
61
|
+
(async function() {
|
|
62
|
+
// Define a connection, and "bind" our models to it
|
|
63
|
+
let connection = new SQLiteConnection({
|
|
64
|
+
models: [
|
|
65
|
+
User,
|
|
66
|
+
],
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Fire up our connection
|
|
70
|
+
await connection.start();
|
|
71
|
+
|
|
72
|
+
// Create our tables needed for our User
|
|
73
|
+
// model in SQLite
|
|
74
|
+
await connection.createTables([ User ]);
|
|
75
|
+
|
|
76
|
+
// Now we can store and load a user
|
|
77
|
+
let user = new User({
|
|
78
|
+
email: 'test@example.com',
|
|
79
|
+
firstName: 'Test',
|
|
80
|
+
lastName: 'User',
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Store user
|
|
84
|
+
await user.save();
|
|
85
|
+
|
|
86
|
+
// Reload user by querying on the
|
|
87
|
+
// user's email address
|
|
88
|
+
user = await User.where.email.EQ('test@example.com').first();
|
|
89
|
+
|
|
90
|
+
// Serialize to JSON
|
|
91
|
+
console.log('My user: ', JSON.stringify(user, undefined, 2));
|
|
92
|
+
|
|
93
|
+
// Shutdown our connection
|
|
94
|
+
await connection.stop();
|
|
95
|
+
})();
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Notes
|
|
99
|
+
|
|
100
|
+
1. The [WIKI](https://github.com/th317erd/mythix-orm/wiki) is still being worked on. Most of the documentation is complete, but there is still a lot more to write. Documentation is the main focus right now. There is a lot more to write. If you have any questions, feel free to drop a line, or open an issue! We will be happy to answer any questions. We aren't "done" until our documentation is pristine.
|
|
101
|
+
2. Right now there are only database drivers for [SQLite](https://www.npmjs.com/package/mythix-orm-sqlite) and [PostgreSQL](https://www.npmjs.com/package/mythix-orm-postgresql). More are planned, with a Mongo driver likely to land next, followed by MySQL. Help wanted!
|
|
102
|
+
3. Check out the [Mythix](https://www.npmjs.com/package/mythix) web-app framework. It is also still in active development, and the documentation is poor (to say the least), but it is up and coming, and will soon have fantastic documentation, and even though still in active development is fully functional. To get started try `npx mythix-cli create 'Test App'`
|
|
103
|
+
|
|
104
|
+
## Goals
|
|
14
105
|
|
|
15
|
-
|
|
106
|
+
The `Mythix` suite of technologies are being developed to give a rock-solid full-stack to build web-apps on Node. I got tired of the piecemeal garbage that currently exist in the Node ecosystem for building apps. My end goal is to have `Mythix` technologies take the Node community by storm, providing top-notch technologies for developers to create amazing things. Get involved with me, and let's change the world for the better!
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
const { DateTime } = require('luxon');
|
|
4
4
|
const EventEmitter = require('events');
|
|
5
5
|
const Nife = require('nife');
|
|
6
|
-
const SqlString = require('sqlstring');
|
|
7
6
|
const { QueryEngine } = require('../query-engine');
|
|
8
7
|
const Utils = require('../utils');
|
|
9
8
|
const { Model: ModelBase } = require('../model');
|
|
@@ -230,6 +229,8 @@ class ConnectionBase extends EventEmitter {
|
|
|
230
229
|
|
|
231
230
|
if (!options.queryGenerator)
|
|
232
231
|
options.queryGenerator = this.createQueryGenerator(options);
|
|
232
|
+
else
|
|
233
|
+
options.queryGenerator.setConnection(this);
|
|
233
234
|
|
|
234
235
|
Object.defineProperties(this, {
|
|
235
236
|
'dialect': {
|
|
@@ -280,6 +281,39 @@ class ConnectionBase extends EventEmitter {
|
|
|
280
281
|
return new QueryGeneratorBase(this);
|
|
281
282
|
}
|
|
282
283
|
|
|
284
|
+
/// An `Object.assign` type of operation... with a twist.
|
|
285
|
+
///
|
|
286
|
+
/// `stackAssign` works kinda like `Object.assign`. It has
|
|
287
|
+
/// the same interface, and accomplishes the same result.
|
|
288
|
+
/// What it does differently however is that it uses
|
|
289
|
+
/// `Object.create` on the first argument to create a new
|
|
290
|
+
/// object, using the first argument as a prototype. It then
|
|
291
|
+
/// merges all remaining `object` arguments into this newly
|
|
292
|
+
/// created object.
|
|
293
|
+
///
|
|
294
|
+
/// This is used quite heavily in the underlying Mythix ORM engine.
|
|
295
|
+
/// It's purpose is to modify `options` arguments as they pass through
|
|
296
|
+
/// the engine. For example, a `destroy` operation might want to inform
|
|
297
|
+
/// the projection engine that we don't want any field aliases... and
|
|
298
|
+
/// so it will `stackAssign` the `options`, setting `noProjectionAliases: true`
|
|
299
|
+
/// for the "stacked options" object. Javascript--being the prototypical language
|
|
300
|
+
/// that it is--will *behave* like the objects in question have been
|
|
301
|
+
/// passed through `Object.assign`, because all the original `options` to
|
|
302
|
+
/// any operation are still accessible in the prototype, but may have been
|
|
303
|
+
/// overridden like in our example of a `destroy` operation. This allows the
|
|
304
|
+
/// engine to easily and quickly override options without mutating the original
|
|
305
|
+
/// `options` object provided, and still be able to access provided options,
|
|
306
|
+
/// even if they are not enumerable.
|
|
307
|
+
///
|
|
308
|
+
/// Arguments:
|
|
309
|
+
/// obj: object
|
|
310
|
+
/// The object to set as the prototype of the newly created object,
|
|
311
|
+
/// using `Object.create` on it.
|
|
312
|
+
/// ...args: Array<object>
|
|
313
|
+
/// The other objects to merge into this object, using `Object.assign`.
|
|
314
|
+
///
|
|
315
|
+
/// Return: object
|
|
316
|
+
/// The newly "stacked" and merged object.
|
|
283
317
|
stackAssign(obj, ..._args) {
|
|
284
318
|
let newObj = Object.create(obj || {});
|
|
285
319
|
let args = _args.filter(Boolean);
|
|
@@ -347,12 +381,14 @@ class ConnectionBase extends EventEmitter {
|
|
|
347
381
|
}
|
|
348
382
|
|
|
349
383
|
/// Get the default order for selecting rows
|
|
350
|
-
/// from the database.
|
|
351
|
-
/// Model's <see name="Model.defaultOrder">Model.static defaultOrder</see> method
|
|
352
|
-
/// first to see if the model specifies a default order
|
|
353
|
-
/// for itself. If it doesn't, then the connection
|
|
384
|
+
/// from the database. The connection
|
|
354
385
|
/// driver itself might specify a default order for
|
|
355
|
-
/// each table.
|
|
386
|
+
/// each table, if one isn't specified by the user.
|
|
387
|
+
///
|
|
388
|
+
/// Note:
|
|
389
|
+
/// To specify a default order for each model, use
|
|
390
|
+
/// the <see>Model.static defaultScope</see> method
|
|
391
|
+
/// instead.
|
|
356
392
|
///
|
|
357
393
|
/// Arguments:
|
|
358
394
|
/// Model: class <see>Model</see>
|
|
@@ -408,6 +444,35 @@ class ConnectionBase extends EventEmitter {
|
|
|
408
444
|
return true;
|
|
409
445
|
}
|
|
410
446
|
|
|
447
|
+
/// A convenience method to get from "model cache".
|
|
448
|
+
///
|
|
449
|
+
/// Model Cache is a simple system to cache
|
|
450
|
+
/// random results from model methods. This is used
|
|
451
|
+
/// for things that should never change, for example
|
|
452
|
+
/// the models fields, the models name, the table
|
|
453
|
+
/// name for the model, etc... Some of these values
|
|
454
|
+
/// are initially computed, and then cached using this
|
|
455
|
+
/// system so operations later on return much quicker.
|
|
456
|
+
///
|
|
457
|
+
/// Note:
|
|
458
|
+
/// The underlying cache system uses the `Map` type,
|
|
459
|
+
/// so any value can be used as a cache key.
|
|
460
|
+
///
|
|
461
|
+
/// Note:
|
|
462
|
+
/// This cache is never cleared or marked as stale, so
|
|
463
|
+
/// if using dynamic cache keys, make sure that you
|
|
464
|
+
/// properly remove them later to prevent memory leaks.
|
|
465
|
+
///
|
|
466
|
+
/// Arguments:
|
|
467
|
+
/// Model: class <see>Model</see>
|
|
468
|
+
/// The model class we a caching for.
|
|
469
|
+
/// key: any
|
|
470
|
+
/// The key to use for our cache.
|
|
471
|
+
/// defaultValue?: any
|
|
472
|
+
/// The default value to return if no cache entry was found.
|
|
473
|
+
///
|
|
474
|
+
/// Return: any
|
|
475
|
+
/// Any value found in the cache.
|
|
411
476
|
_getFromModelCache(Model, key, defaultValue) {
|
|
412
477
|
let cache = this._modelCache.get(Model);
|
|
413
478
|
if (!cache)
|
|
@@ -420,6 +485,35 @@ class ConnectionBase extends EventEmitter {
|
|
|
420
485
|
return value;
|
|
421
486
|
}
|
|
422
487
|
|
|
488
|
+
/// A convenience method to set to the "model cache".
|
|
489
|
+
///
|
|
490
|
+
/// Model Cache is a simple system to cache
|
|
491
|
+
/// random results from model methods. This is used
|
|
492
|
+
/// for things that should never change, for example
|
|
493
|
+
/// the models fields, the models name, the table
|
|
494
|
+
/// name for the model, etc... Some of these values
|
|
495
|
+
/// are initially computed, and then cached using this
|
|
496
|
+
/// system so operations later on return much quicker.
|
|
497
|
+
///
|
|
498
|
+
/// Note:
|
|
499
|
+
/// The underlying cache system uses the `Map` type,
|
|
500
|
+
/// so any value can be used as a cache key.
|
|
501
|
+
///
|
|
502
|
+
/// Note:
|
|
503
|
+
/// This cache is never cleared or marked as stale, so
|
|
504
|
+
/// if using dynamic cache keys, make sure that you
|
|
505
|
+
/// properly remove them later to prevent memory leaks.
|
|
506
|
+
///
|
|
507
|
+
/// Arguments:
|
|
508
|
+
/// Model: class <see>Model</see>
|
|
509
|
+
/// The model class we a caching for.
|
|
510
|
+
/// key: any
|
|
511
|
+
/// The key to use for our cache.
|
|
512
|
+
/// value: any
|
|
513
|
+
/// The value to cache.
|
|
514
|
+
///
|
|
515
|
+
/// Return: any
|
|
516
|
+
/// The `value` provided.
|
|
423
517
|
_setToModelCache(Model, key, value) {
|
|
424
518
|
let cache = this._modelCache.get(Model);
|
|
425
519
|
if (!cache) {
|
|
@@ -493,6 +587,51 @@ class ConnectionBase extends EventEmitter {
|
|
|
493
587
|
return queryEngine;
|
|
494
588
|
}
|
|
495
589
|
|
|
590
|
+
/// Finalize a query before using it for database operations.
|
|
591
|
+
///
|
|
592
|
+
/// `finalizeQuery` is called on **every** query immediately
|
|
593
|
+
/// before it is used for a database operation. Its only purpose
|
|
594
|
+
/// is to potentially modify the query before the database operation
|
|
595
|
+
/// occurs. This can be extremely useful for things like "row level permissions",
|
|
596
|
+
/// or ensuring that a certain type of query always has certain conditions.
|
|
597
|
+
///
|
|
598
|
+
/// Because it is asynchronous by design, it is possible to finalize the
|
|
599
|
+
/// query using other asynchronous operations; for example validating
|
|
600
|
+
/// authentication tokens, or fetching user roles from the database.
|
|
601
|
+
///
|
|
602
|
+
/// It works by walking the provided query, and calling <see>Model.static finalizeQuery</see>
|
|
603
|
+
/// on every model it encounters that is used in the query. It will also recursively
|
|
604
|
+
/// call itself for every new query it encounters that is part of the query,
|
|
605
|
+
/// for example sub-queries. In this way, you can take on extra conditions to any
|
|
606
|
+
/// part of a query, throw a "Forbidden" exception if the user is disallowed from querying
|
|
607
|
+
/// certain data, or whatever you want.
|
|
608
|
+
///
|
|
609
|
+
/// Note:
|
|
610
|
+
/// "With great power comes great responsibility." Use `finalizeQuery` intelligently. It can
|
|
611
|
+
/// cause a noticeable performance hit, and can really make things hard to debug and
|
|
612
|
+
/// understand if you don't clearly document.
|
|
613
|
+
///
|
|
614
|
+
/// Note:
|
|
615
|
+
/// `'create'` isn't actually currently supported, since no queries are
|
|
616
|
+
/// ever used in an `INSERT` operation. It is reserved for future use.
|
|
617
|
+
///
|
|
618
|
+
/// Arguments:
|
|
619
|
+
/// crudOperation: 'create' | 'read' | 'update' | 'delete'
|
|
620
|
+
/// The Mythix ORM reports what "type" of operation is being executed
|
|
621
|
+
/// using this argument. This is used so one can know if the operation
|
|
622
|
+
/// that is about to be executed is a `read`, `update`, or `delete` operation.
|
|
623
|
+
/// query: <see>QueryEngine</see>
|
|
624
|
+
/// The query to operate upon. This will be walked, calling <see>Model.static finalizeQuery</see>
|
|
625
|
+
/// for each unique model encountered, and also recursively walking any sub-queries.
|
|
626
|
+
/// options?: object
|
|
627
|
+
/// Random options for the operation. These are not used by this method, but instead are
|
|
628
|
+
/// the `options` provided to the database operation when it was requested, and are also
|
|
629
|
+
/// available for use for any user needs.
|
|
630
|
+
///
|
|
631
|
+
/// Return: <see>QueryEngine</see>
|
|
632
|
+
/// The query provided, possibly altered.
|
|
633
|
+
///
|
|
634
|
+
/// See: Model.static finalizeQuery
|
|
496
635
|
async finalizeQuery(crudOperation, queryEngine, options) {
|
|
497
636
|
if (!QueryEngine.isQuery(queryEngine))
|
|
498
637
|
return queryEngine;
|
|
@@ -613,7 +752,7 @@ class ConnectionBase extends EventEmitter {
|
|
|
613
752
|
/// it was created.
|
|
614
753
|
///
|
|
615
754
|
/// Arguments:
|
|
616
|
-
///
|
|
755
|
+
/// models: Array<class <see>Model</see>> | { [key: string]: class <see>Model</see> }
|
|
617
756
|
/// The model classes to register with this connection. If no models are bound, then
|
|
618
757
|
/// they will simply exist in the model pool for this connection. If bound, then
|
|
619
758
|
/// this connection will bind itself to every model being registered.
|
|
@@ -623,13 +762,14 @@ class ConnectionBase extends EventEmitter {
|
|
|
623
762
|
/// provided to the connection when it was created. If you specify either of these
|
|
624
763
|
/// options they simply override the connection's default.
|
|
625
764
|
///
|
|
626
|
-
/// Return: class <see>Model</see>
|
|
765
|
+
/// Return: { [key: string]: class <see>Model</see> }
|
|
627
766
|
/// The registered model classes, **which may have changed during registration**.
|
|
628
767
|
/// It is not uncommon for the connection driver itself to modify the model
|
|
629
768
|
/// classes, or to return a new model classes that inherit from your model classes.
|
|
630
769
|
/// The classes that are returned should be the classes that you use for this connection,
|
|
631
770
|
/// and will be the same classes returned by a call to <see>Connection.getModel</see>,
|
|
632
|
-
/// or <see>Connection.getModels</see>.
|
|
771
|
+
/// or <see>Connection.getModels</see>. An object is returned, where each key is
|
|
772
|
+
/// a model name, and each value is a model class.
|
|
633
773
|
registerModels(models, options) {
|
|
634
774
|
if (!models)
|
|
635
775
|
return;
|
|
@@ -916,7 +1056,14 @@ class ConnectionBase extends EventEmitter {
|
|
|
916
1056
|
/// Return the <see>QueryGenerator</see> for this connection,
|
|
917
1057
|
/// or return `null` if none is defined for this connection.
|
|
918
1058
|
getQueryGenerator() {
|
|
919
|
-
|
|
1059
|
+
let queryGenerator = this.queryGenerator;
|
|
1060
|
+
if (queryGenerator) {
|
|
1061
|
+
let connection = queryGenerator.getConnection();
|
|
1062
|
+
if (!connection)
|
|
1063
|
+
queryGenerator.setConnection(this);
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
return queryGenerator;
|
|
920
1067
|
}
|
|
921
1068
|
|
|
922
1069
|
/// Set the <see>QueryGenerator</see> instance for this
|
|
@@ -940,15 +1087,10 @@ class ConnectionBase extends EventEmitter {
|
|
|
940
1087
|
}
|
|
941
1088
|
|
|
942
1089
|
/// The low-level DB interface for escaping a
|
|
943
|
-
/// value. By default this function
|
|
944
|
-
///
|
|
945
|
-
///
|
|
946
|
-
///
|
|
947
|
-
/// using should be used instead of this. This is
|
|
948
|
-
/// a "default implementation" that is meant as a
|
|
949
|
-
/// fallback when a connection doesn't provide its
|
|
950
|
-
/// own, but each connection should provide its own
|
|
951
|
-
/// when it is able.
|
|
1090
|
+
/// value. By default this function simply returns
|
|
1091
|
+
/// the value it is provided. It is up to the
|
|
1092
|
+
/// database driver itself to provide a proper
|
|
1093
|
+
/// implementation of this method.
|
|
952
1094
|
///
|
|
953
1095
|
/// Note:
|
|
954
1096
|
/// This method escapes "values" that are given in
|
|
@@ -957,8 +1099,7 @@ class ConnectionBase extends EventEmitter {
|
|
|
957
1099
|
/// instead.
|
|
958
1100
|
///
|
|
959
1101
|
/// Return: string
|
|
960
|
-
/// The value provided
|
|
961
|
-
/// underlying database driver.
|
|
1102
|
+
/// The value provided.
|
|
962
1103
|
///
|
|
963
1104
|
/// Arguments:
|
|
964
1105
|
/// value: any
|
|
@@ -966,10 +1107,7 @@ class ConnectionBase extends EventEmitter {
|
|
|
966
1107
|
/// a string, or anything else that can be provided to your
|
|
967
1108
|
/// specific database.
|
|
968
1109
|
_escape(value) {
|
|
969
|
-
|
|
970
|
-
return `'${value.replace(/'/g, '\'\'')}'`;
|
|
971
|
-
|
|
972
|
-
return SqlString.escape(value);
|
|
1110
|
+
return value;
|
|
973
1111
|
}
|
|
974
1112
|
|
|
975
1113
|
/// Unlike <see>ConnectionBase._escape</see> --which is
|
|
@@ -1060,22 +1198,18 @@ class ConnectionBase extends EventEmitter {
|
|
|
1060
1198
|
/// provides as a "fallback" to database drivers that don't
|
|
1061
1199
|
/// supply their own.
|
|
1062
1200
|
///
|
|
1063
|
-
///
|
|
1064
|
-
///
|
|
1065
|
-
///
|
|
1066
|
-
/// `escapeId` method, finally re-joining the parts with a period `.` character.
|
|
1067
|
-
///
|
|
1068
|
-
/// The extra processing is to allow for already escaped identifiers to not be double-escaped.
|
|
1201
|
+
/// This method simply returns the value provided. It is
|
|
1202
|
+
/// expected that each database driver will properly overload
|
|
1203
|
+
/// this method to provide the correct escaping for identifiers.
|
|
1069
1204
|
///
|
|
1070
1205
|
/// Return: string
|
|
1071
|
-
/// The provided identifier
|
|
1206
|
+
/// The provided identifier.
|
|
1072
1207
|
///
|
|
1073
1208
|
/// Arguments:
|
|
1074
1209
|
/// value: string
|
|
1075
1210
|
/// The identifier to escape.
|
|
1076
1211
|
_escapeID(value) {
|
|
1077
|
-
|
|
1078
|
-
return parts.map((part) => SqlString.escapeId(part).replace(/^`/, '"').replace(/`$/, '"')).join('.');
|
|
1212
|
+
return value;
|
|
1079
1213
|
}
|
|
1080
1214
|
|
|
1081
1215
|
/// This method is very similar to <see>ConnectionBase._escapeID</see>,
|
|
@@ -1382,10 +1516,10 @@ class ConnectionBase extends EventEmitter {
|
|
|
1382
1516
|
/// will be database specific. The database driver connection
|
|
1383
1517
|
/// is free to override this method.
|
|
1384
1518
|
///
|
|
1385
|
-
/// This method will convert
|
|
1386
|
-
/// <see>CountLiteral</see>,
|
|
1387
|
-
///
|
|
1388
|
-
/// <see>MinLiteral</see>,
|
|
1519
|
+
/// This method will convert an <see>AverageLiteral</see>,
|
|
1520
|
+
/// <see>CountLiteral</see>, <see>DistinctLiteral</see>,
|
|
1521
|
+
/// <see>FieldLiteral</see>, <see>MaxLiteral</see>,
|
|
1522
|
+
/// <see>MinLiteral</see>, <see>SumLiteral</see>, or a
|
|
1389
1523
|
/// <see>Literal</see> to a string. If the provided literal
|
|
1390
1524
|
/// is not one of these types, than an exception will be thrown.
|
|
1391
1525
|
///
|
|
@@ -2651,7 +2785,7 @@ class ConnectionBase extends EventEmitter {
|
|
|
2651
2785
|
/// Create a table/bucket using the provided model class.
|
|
2652
2786
|
///
|
|
2653
2787
|
/// The provided `options` are database specific,
|
|
2654
|
-
/// but might contain things like `
|
|
2788
|
+
/// but might contain things like `ifNotExists`, for
|
|
2655
2789
|
/// example.
|
|
2656
2790
|
///
|
|
2657
2791
|
/// Return: any
|
|
@@ -2,11 +2,78 @@
|
|
|
2
2
|
|
|
3
3
|
const LiteralFieldBase = require('./literal-field-base');
|
|
4
4
|
|
|
5
|
+
/// Define an "average" literal for the underlying database.
|
|
6
|
+
///
|
|
7
|
+
/// Literals are special types in Mythix ORM that are used to
|
|
8
|
+
/// define "literal values" for the underlying database.
|
|
9
|
+
///
|
|
10
|
+
/// This literal defines an "average" operation across a single
|
|
11
|
+
/// column. It is used by <see>Connection.average</see> to get
|
|
12
|
+
/// the average across all rows for a single column in the underlying
|
|
13
|
+
/// database. When serialized using the <see>QueryGenerator</see>
|
|
14
|
+
/// for the connection, it will turn into a database method that
|
|
15
|
+
/// is appropriate for the underlying database. For example, with
|
|
16
|
+
/// SQL type databases this would turn into `AVG(column)`. This is
|
|
17
|
+
/// often used by the projection engine, to project it as a column
|
|
18
|
+
/// to be selected. For example `SELECT AVG(column) ...`. It can
|
|
19
|
+
/// be used in other places in the query however, such as `ORDER`,
|
|
20
|
+
/// `GROUP BY`, and `HAVING` clauses.
|
|
21
|
+
///
|
|
22
|
+
/// There are two primary ways to access literals in Mythix ORM. The
|
|
23
|
+
/// first is to simply import them. The second way literals can be
|
|
24
|
+
/// accessed is via the connection class itself. All Mythix ORM connection
|
|
25
|
+
/// classes export all literals on the `static Literals` attribute of
|
|
26
|
+
/// the class. So for example, you could access literals like `SQLiteConnection.Literals.AverageLiteral`.
|
|
27
|
+
///
|
|
28
|
+
/// All built-in Mythix ORM literals--except `Literal` and `LiteralBase`--accept a field
|
|
29
|
+
/// as their first argument. This field can be a fully qualified field name, an actual
|
|
30
|
+
/// <see>Field</see> instance, or another literal. The second argument to all literal constructors
|
|
31
|
+
/// is an `options` object, that generally contains connection-specific (and operation-specific) options...
|
|
32
|
+
/// however, there are common options that can be supplied, such as `as: string;` which allows you to
|
|
33
|
+
/// define an alias for the defined field, and `noProjectionAliases: boolean;`, which allows you to disable
|
|
34
|
+
/// the column alias entirely.
|
|
35
|
+
///
|
|
36
|
+
/// Example:
|
|
37
|
+
/// const { Literals } = require('mythix-orm');
|
|
38
|
+
/// const { SQLiteConnection } = require('mythix-orm-sqlite');
|
|
39
|
+
/// let literal1 = new Literals.AverageLiteral('User:age');
|
|
40
|
+
/// let literal2 = new SQLiteConnection.Literals.AverageLiteral('User:age');
|
|
41
|
+
///
|
|
42
|
+
/// See: LiteralFieldBase
|
|
43
|
+
///
|
|
44
|
+
/// See: LiteralBase
|
|
5
45
|
class AverageLiteral extends LiteralFieldBase {
|
|
46
|
+
/// Return `true`, letting the caller know that
|
|
47
|
+
/// this is an "aggregating literal".
|
|
48
|
+
///
|
|
49
|
+
/// Return: boolean
|
|
50
|
+
/// Return `true`, informing the caller that this literal is used for aggregate operations.
|
|
6
51
|
static isAggregate() {
|
|
7
52
|
return true;
|
|
8
53
|
}
|
|
9
54
|
|
|
55
|
+
/// Convert this literal to a string to be used in a database query.
|
|
56
|
+
///
|
|
57
|
+
/// This method proxies the conversion of this literal to the connection
|
|
58
|
+
/// by calling <see>Connection.literalToString</see>. If no connection
|
|
59
|
+
/// is provided when this is called, then the literal will be converted
|
|
60
|
+
/// to a string representing it for debugging, i.e. `'AverageLiteral {}'`.
|
|
61
|
+
///
|
|
62
|
+
/// Note:
|
|
63
|
+
/// Ultimately, for most connections, this will end up calling
|
|
64
|
+
/// <see>QueryGenerator._averageLiteralToString</see>.
|
|
65
|
+
///
|
|
66
|
+
/// Arguments:
|
|
67
|
+
/// connection?: <see>Connection</see>
|
|
68
|
+
/// The connection to use to stringify this literal. If none is provided,
|
|
69
|
+
/// then a string representing this object will be returned instead.
|
|
70
|
+
/// options?: object
|
|
71
|
+
/// A connection and operation specific set of options that can be provided.
|
|
72
|
+
/// This might for example be `{ as: 'name' }` to provided a field alias, or
|
|
73
|
+
/// `{ isProjection: true }` to define that this is being stringified for use
|
|
74
|
+
/// as a field in the query projection. Normally the end-user won't care about
|
|
75
|
+
/// any literal options, except `as`, which is commonly used to give your literal
|
|
76
|
+
/// an alias.
|
|
10
77
|
toString(connection, options) {
|
|
11
78
|
if (!connection)
|
|
12
79
|
return `${this.constructor.name} {}`;
|
|
@@ -2,15 +2,95 @@
|
|
|
2
2
|
|
|
3
3
|
const LiteralFieldBase = require('./literal-field-base');
|
|
4
4
|
|
|
5
|
+
/// Define a "count" literal for the underlying database.
|
|
6
|
+
///
|
|
7
|
+
/// Literals are special types in Mythix ORM that are used to
|
|
8
|
+
/// define "literal values" for the underlying database.
|
|
9
|
+
///
|
|
10
|
+
/// This literal defines a "count" operation across all matching
|
|
11
|
+
/// rows. It is used by <see>Connection.count</see> to get
|
|
12
|
+
/// the number of matching rows for a query. When serialized using
|
|
13
|
+
/// the <see>QueryGenerator</see> for the connection, it will turn
|
|
14
|
+
/// into a database method that is appropriate for the underlying database.
|
|
15
|
+
/// For example, with SQL type databases this would turn into `COUNT(column)`,
|
|
16
|
+
/// our `COUNT(*)`. This is often used by the projection engine, to project
|
|
17
|
+
/// it as a column to be selected. For example `SELECT COUNT(column) AS count ...`.
|
|
18
|
+
/// It can be used in other places in the query however, such as `ORDER`,
|
|
19
|
+
/// `GROUP BY`, and `HAVING` clauses.
|
|
20
|
+
///
|
|
21
|
+
/// Note:
|
|
22
|
+
/// If no field is provided to `CountLiteral`
|
|
23
|
+
/// then all fields (`*`) is assumed.
|
|
24
|
+
///
|
|
25
|
+
/// Note:
|
|
26
|
+
/// It is common to use the `{ as: 'count' }` option to give the count
|
|
27
|
+
/// literal an alias (name).
|
|
28
|
+
///
|
|
29
|
+
/// There are two primary ways to access literals in Mythix ORM. The
|
|
30
|
+
/// first is to simply import them. The second way literals can be
|
|
31
|
+
/// accessed is via the connection class itself. All Mythix ORM connection
|
|
32
|
+
/// classes export all literals on the `static Literals` attribute of
|
|
33
|
+
/// the class. So for example, you could access literals like `SQLiteConnection.Literals.CountLiteral`.
|
|
34
|
+
///
|
|
35
|
+
/// All built-in Mythix ORM literals--except `Literal` and `LiteralBase`--accept a field
|
|
36
|
+
/// as their first argument. This field can be a fully qualified field name, an actual
|
|
37
|
+
/// <see>Field</see> instance, or another literal. The second argument to all literal constructors
|
|
38
|
+
/// is an `options` object, that generally contains connection-specific (and operation-specific) options...
|
|
39
|
+
/// however, there are common options that can be supplied, such as `as: string;` which allows you to
|
|
40
|
+
/// define an alias for the defined field, and `noProjectionAliases: boolean;`, which allows you to disable
|
|
41
|
+
/// the column alias entirely.
|
|
42
|
+
///
|
|
43
|
+
/// Example:
|
|
44
|
+
/// const { Literals } = require('mythix-orm');
|
|
45
|
+
/// const { SQLiteConnection } = require('mythix-orm-sqlite');
|
|
46
|
+
/// let literal1 = new Literals.CountLiteral('*', { as: 'count' });
|
|
47
|
+
/// let literal2 = new SQLiteConnection.CountLiteral.CountLiteral('*', { as: 'count' });
|
|
48
|
+
///
|
|
49
|
+
/// See: LiteralFieldBase
|
|
50
|
+
///
|
|
51
|
+
/// See: LiteralBase
|
|
5
52
|
class CountLiteral extends LiteralFieldBase {
|
|
53
|
+
/// Return `false`, informing the engine that
|
|
54
|
+
/// a field is not required for this literal type.
|
|
55
|
+
///
|
|
56
|
+
/// Return: boolean
|
|
57
|
+
/// Return `false`, informing the caller that this literal
|
|
58
|
+
/// does not require a field.
|
|
6
59
|
static isFieldRequired() {
|
|
7
60
|
return false;
|
|
8
61
|
}
|
|
9
62
|
|
|
63
|
+
/// Return `true`, letting the caller know that
|
|
64
|
+
/// this is an "aggregating literal".
|
|
65
|
+
///
|
|
66
|
+
/// Return: boolean
|
|
67
|
+
/// Return `true`, informing the caller that this literal is used for aggregate operations.
|
|
10
68
|
static isAggregate() {
|
|
11
69
|
return true;
|
|
12
70
|
}
|
|
13
71
|
|
|
72
|
+
/// Convert this literal to a string to be used in a database query.
|
|
73
|
+
///
|
|
74
|
+
/// This method proxies the conversion of this literal to the connection
|
|
75
|
+
/// by calling <see>Connection.literalToString</see>. If no connection
|
|
76
|
+
/// is provided when this is called, then the literal will be converted
|
|
77
|
+
/// to a string representing it for debugging, i.e. `'CountLiteral {}'`.
|
|
78
|
+
///
|
|
79
|
+
/// Note:
|
|
80
|
+
/// Ultimately, for most connections, this will end up calling
|
|
81
|
+
/// <see>QueryGenerator._countLiteralToString</see>.
|
|
82
|
+
///
|
|
83
|
+
/// Arguments:
|
|
84
|
+
/// connection?: <see>Connection</see>
|
|
85
|
+
/// The connection to use to stringify this literal. If none is provided,
|
|
86
|
+
/// then a string representing this object will be returned instead.
|
|
87
|
+
/// options?: object
|
|
88
|
+
/// A connection and operation specific set of options that can be provided.
|
|
89
|
+
/// This might for example be `{ as: 'name' }` to provided a field alias, or
|
|
90
|
+
/// `{ isProjection: true }` to define that this is being stringified for use
|
|
91
|
+
/// as a field in the query projection. Normally the end-user won't care about
|
|
92
|
+
/// any literal options, except `as`, which is commonly used to give your literal
|
|
93
|
+
/// an alias.
|
|
14
94
|
toString(connection, options) {
|
|
15
95
|
if (!connection)
|
|
16
96
|
return `${this.constructor.name} {}`;
|