mythix-orm 1.11.6 → 1.11.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -9
- package/lib/connection/connection-base.js +147 -9
- package/lib/connection/literals/average-literal.js +67 -0
- package/lib/connection/literals/count-literal.js +80 -0
- package/lib/connection/literals/distinct-literal.js +71 -0
- package/lib/connection/literals/field-literal.js +54 -0
- package/lib/connection/literals/literal-base.d.ts +1 -0
- package/lib/connection/literals/literal-base.js +137 -2
- package/lib/connection/literals/literal-field-base.js +50 -0
- package/lib/connection/literals/literal.js +15 -0
- package/lib/connection/literals/max-literal.js +67 -0
- package/lib/connection/literals/min-literal.js +67 -0
- package/lib/connection/literals/sum-literal.js +67 -0
- package/lib/field.js +1 -1
- package/lib/model.js +54 -2
- package/lib/query-engine/field-scope.js +401 -9
- package/lib/query-engine/model-scope.js +572 -13
- package/lib/query-engine/query-engine-base.js +590 -30
- package/lib/query-engine/query-engine.d.ts +13 -2
- package/lib/query-engine/query-engine.js +525 -18
- package/lib/types/helpers/default-helpers.js +124 -0
- package/lib/types/type.js +297 -3
- package/package.json +1 -1
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!
|
|
@@ -280,6 +280,39 @@ class ConnectionBase extends EventEmitter {
|
|
|
280
280
|
return new QueryGeneratorBase(this);
|
|
281
281
|
}
|
|
282
282
|
|
|
283
|
+
/// An `Object.assign` type of operation... with a twist.
|
|
284
|
+
///
|
|
285
|
+
/// `stackAssign` works kinda like `Object.assign`. It has
|
|
286
|
+
/// the same interface, and accomplishes the same result.
|
|
287
|
+
/// What it does differently however is that it uses
|
|
288
|
+
/// `Object.create` on the first argument to create a new
|
|
289
|
+
/// object, using the first argument as a prototype. It then
|
|
290
|
+
/// merges all remaining `object` arguments into this newly
|
|
291
|
+
/// created object.
|
|
292
|
+
///
|
|
293
|
+
/// This is used quite heavily in the underlying Mythix ORM engine.
|
|
294
|
+
/// It's purpose is to modify `options` arguments as they pass through
|
|
295
|
+
/// the engine. For example, a `destroy` operation might want to inform
|
|
296
|
+
/// the projection engine that we don't want any field aliases... and
|
|
297
|
+
/// so it will `stackAssign` the `options`, setting `noProjectionAliases: true`
|
|
298
|
+
/// for the "stacked options" object. Javascript--being the prototypical language
|
|
299
|
+
/// that it is--will *behave* like the objects in question have been
|
|
300
|
+
/// passed through `Object.assign`, because all the original `options` to
|
|
301
|
+
/// any operation are still accessible in the prototype, but may have been
|
|
302
|
+
/// overridden like in our example of a `destroy` operation. This allows the
|
|
303
|
+
/// engine to easily and quickly override options without mutating the original
|
|
304
|
+
/// `options` object provided, and still be able to access provided options,
|
|
305
|
+
/// even if they are not enumerable.
|
|
306
|
+
///
|
|
307
|
+
/// Arguments:
|
|
308
|
+
/// obj: object
|
|
309
|
+
/// The object to set as the prototype of the newly created object,
|
|
310
|
+
/// using `Object.create` on it.
|
|
311
|
+
/// ...args: Array<object>
|
|
312
|
+
/// The other objects to merge into this object, using `Object.assign`.
|
|
313
|
+
///
|
|
314
|
+
/// Return: object
|
|
315
|
+
/// The newly "stacked" and merged object.
|
|
283
316
|
stackAssign(obj, ..._args) {
|
|
284
317
|
let newObj = Object.create(obj || {});
|
|
285
318
|
let args = _args.filter(Boolean);
|
|
@@ -347,12 +380,14 @@ class ConnectionBase extends EventEmitter {
|
|
|
347
380
|
}
|
|
348
381
|
|
|
349
382
|
/// 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
|
|
383
|
+
/// from the database. The connection
|
|
354
384
|
/// driver itself might specify a default order for
|
|
355
|
-
/// each table.
|
|
385
|
+
/// each table, if one isn't specified by the user.
|
|
386
|
+
///
|
|
387
|
+
/// Note:
|
|
388
|
+
/// To specify a default order for each model, use
|
|
389
|
+
/// the <see>Model.static defaultScope</see> method
|
|
390
|
+
/// instead.
|
|
356
391
|
///
|
|
357
392
|
/// Arguments:
|
|
358
393
|
/// Model: class <see>Model</see>
|
|
@@ -408,6 +443,35 @@ class ConnectionBase extends EventEmitter {
|
|
|
408
443
|
return true;
|
|
409
444
|
}
|
|
410
445
|
|
|
446
|
+
/// A convenience method to get from "model cache".
|
|
447
|
+
///
|
|
448
|
+
/// Model Cache is a simple system to cache
|
|
449
|
+
/// random results from model methods. This is used
|
|
450
|
+
/// for things that should never change, for example
|
|
451
|
+
/// the models fields, the models name, the table
|
|
452
|
+
/// name for the model, etc... Some of these values
|
|
453
|
+
/// are initially computed, and then cached using this
|
|
454
|
+
/// system so operations later on return much quicker.
|
|
455
|
+
///
|
|
456
|
+
/// Note:
|
|
457
|
+
/// The underlying cache system uses the `Map` type,
|
|
458
|
+
/// so any value can be used as a cache key.
|
|
459
|
+
///
|
|
460
|
+
/// Note:
|
|
461
|
+
/// This cache is never cleared or marked as stale, so
|
|
462
|
+
/// if using dynamic cache keys, make sure that you
|
|
463
|
+
/// properly remove them later to prevent memory leaks.
|
|
464
|
+
///
|
|
465
|
+
/// Arguments:
|
|
466
|
+
/// Model: class <see>Model</see>
|
|
467
|
+
/// The model class we a caching for.
|
|
468
|
+
/// key: any
|
|
469
|
+
/// The key to use for our cache.
|
|
470
|
+
/// defaultValue?: any
|
|
471
|
+
/// The default value to return if no cache entry was found.
|
|
472
|
+
///
|
|
473
|
+
/// Return: any
|
|
474
|
+
/// Any value found in the cache.
|
|
411
475
|
_getFromModelCache(Model, key, defaultValue) {
|
|
412
476
|
let cache = this._modelCache.get(Model);
|
|
413
477
|
if (!cache)
|
|
@@ -420,6 +484,35 @@ class ConnectionBase extends EventEmitter {
|
|
|
420
484
|
return value;
|
|
421
485
|
}
|
|
422
486
|
|
|
487
|
+
/// A convenience method to set to the "model cache".
|
|
488
|
+
///
|
|
489
|
+
/// Model Cache is a simple system to cache
|
|
490
|
+
/// random results from model methods. This is used
|
|
491
|
+
/// for things that should never change, for example
|
|
492
|
+
/// the models fields, the models name, the table
|
|
493
|
+
/// name for the model, etc... Some of these values
|
|
494
|
+
/// are initially computed, and then cached using this
|
|
495
|
+
/// system so operations later on return much quicker.
|
|
496
|
+
///
|
|
497
|
+
/// Note:
|
|
498
|
+
/// The underlying cache system uses the `Map` type,
|
|
499
|
+
/// so any value can be used as a cache key.
|
|
500
|
+
///
|
|
501
|
+
/// Note:
|
|
502
|
+
/// This cache is never cleared or marked as stale, so
|
|
503
|
+
/// if using dynamic cache keys, make sure that you
|
|
504
|
+
/// properly remove them later to prevent memory leaks.
|
|
505
|
+
///
|
|
506
|
+
/// Arguments:
|
|
507
|
+
/// Model: class <see>Model</see>
|
|
508
|
+
/// The model class we a caching for.
|
|
509
|
+
/// key: any
|
|
510
|
+
/// The key to use for our cache.
|
|
511
|
+
/// value: any
|
|
512
|
+
/// The value to cache.
|
|
513
|
+
///
|
|
514
|
+
/// Return: any
|
|
515
|
+
/// The `value` provided.
|
|
423
516
|
_setToModelCache(Model, key, value) {
|
|
424
517
|
let cache = this._modelCache.get(Model);
|
|
425
518
|
if (!cache) {
|
|
@@ -493,6 +586,51 @@ class ConnectionBase extends EventEmitter {
|
|
|
493
586
|
return queryEngine;
|
|
494
587
|
}
|
|
495
588
|
|
|
589
|
+
/// Finalize a query before using it for database operations.
|
|
590
|
+
///
|
|
591
|
+
/// `finalizeQuery` is called on **every** query immediately
|
|
592
|
+
/// before it is used for a database operation. Its only purpose
|
|
593
|
+
/// is to potentially modify the query before the database operation
|
|
594
|
+
/// occurs. This can be extremely useful for things like "row level permissions",
|
|
595
|
+
/// or ensuring that a certain type of query always has certain conditions.
|
|
596
|
+
///
|
|
597
|
+
/// Because it is asynchronous by design, it is possible to finalize the
|
|
598
|
+
/// query using other asynchronous operations; for example validating
|
|
599
|
+
/// authentication tokens, or fetching user roles from the database.
|
|
600
|
+
///
|
|
601
|
+
/// It works by walking the provided query, and calling <see>Model.static finalizeQuery</see>
|
|
602
|
+
/// on every model it encounters that is used in the query. It will also recursively
|
|
603
|
+
/// call itself for every new query it encounters that is part of the query,
|
|
604
|
+
/// for example sub-queries. In this way, you can take on extra conditions to any
|
|
605
|
+
/// part of a query, throw a "Forbidden" exception if the user is disallowed from querying
|
|
606
|
+
/// certain data, or whatever you want.
|
|
607
|
+
///
|
|
608
|
+
/// Note:
|
|
609
|
+
/// "With great power comes great responsibility." Use `finalizeQuery` intelligently. It can
|
|
610
|
+
/// cause a noticeable performance hit, and can really make things hard to debug and
|
|
611
|
+
/// understand if you don't clearly document.
|
|
612
|
+
///
|
|
613
|
+
/// Note:
|
|
614
|
+
/// `'create'` isn't actually currently supported, since no queries are
|
|
615
|
+
/// ever used in an `INSERT` operation. It is reserved for future use.
|
|
616
|
+
///
|
|
617
|
+
/// Arguments:
|
|
618
|
+
/// crudOperation: 'create' | 'read' | 'update' | 'delete'
|
|
619
|
+
/// The Mythix ORM reports what "type" of operation is being executed
|
|
620
|
+
/// using this argument. This is used so one can know if the operation
|
|
621
|
+
/// that is about to be executed is a `read`, `update`, or `delete` operation.
|
|
622
|
+
/// query: <see>QueryEngine</see>
|
|
623
|
+
/// The query to operate upon. This will be walked, calling <see>Model.static finalizeQuery</see>
|
|
624
|
+
/// for each unique model encountered, and also recursively walking any sub-queries.
|
|
625
|
+
/// options?: object
|
|
626
|
+
/// Random options for the operation. These are not used by this method, but instead are
|
|
627
|
+
/// the `options` provided to the database operation when it was requested, and are also
|
|
628
|
+
/// available for use for any user needs.
|
|
629
|
+
///
|
|
630
|
+
/// Return: <see>QueryEngine</see>
|
|
631
|
+
/// The query provided, possibly altered.
|
|
632
|
+
///
|
|
633
|
+
/// See: Model.static finalizeQuery
|
|
496
634
|
async finalizeQuery(crudOperation, queryEngine, options) {
|
|
497
635
|
if (!QueryEngine.isQuery(queryEngine))
|
|
498
636
|
return queryEngine;
|
|
@@ -1382,10 +1520,10 @@ class ConnectionBase extends EventEmitter {
|
|
|
1382
1520
|
/// will be database specific. The database driver connection
|
|
1383
1521
|
/// is free to override this method.
|
|
1384
1522
|
///
|
|
1385
|
-
/// This method will convert
|
|
1386
|
-
/// <see>CountLiteral</see>,
|
|
1387
|
-
///
|
|
1388
|
-
/// <see>MinLiteral</see>,
|
|
1523
|
+
/// This method will convert an <see>AverageLiteral</see>,
|
|
1524
|
+
/// <see>CountLiteral</see>, <see>DistinctLiteral</see>,
|
|
1525
|
+
/// <see>FieldLiteral</see>, <see>MaxLiteral</see>,
|
|
1526
|
+
/// <see>MinLiteral</see>, <see>SumLiteral</see>, or a
|
|
1389
1527
|
/// <see>Literal</see> to a string. If the provided literal
|
|
1390
1528
|
/// is not one of these types, than an exception will be thrown.
|
|
1391
1529
|
///
|
|
@@ -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} {}`;
|
|
@@ -2,7 +2,78 @@
|
|
|
2
2
|
|
|
3
3
|
const LiteralFieldBase = require('./literal-field-base');
|
|
4
4
|
|
|
5
|
+
/// Define a "distinct" 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 "distinct" operation across a single
|
|
11
|
+
/// column, or entire rows. Distinct is a little different than
|
|
12
|
+
/// most other literals. Whereas most other literals are simply
|
|
13
|
+
/// used as "values"--either identifiers, methods, or values--this
|
|
14
|
+
/// `DistinctLiteral` defines an entire state for a query. It can modify
|
|
15
|
+
/// the projection, the order, or modify the query in other ways. On
|
|
16
|
+
/// some database drivers, it may cause the engine to take an entirely
|
|
17
|
+
/// different path to fetch the data requested. `DistinctLiteral` requires
|
|
18
|
+
/// a field, or another literal. It may or may not use this field in
|
|
19
|
+
/// underlying database operations. However, to remain
|
|
20
|
+
/// consistent in the interface and across databases, it is required.
|
|
21
|
+
/// There are some cases in which a `DistinctLiteral` may not alter how
|
|
22
|
+
/// a query is carried out. One of these is if it is used as an argument to another
|
|
23
|
+
/// literal. For example, if one were to use a `DistinctLiteral` inside a
|
|
24
|
+
/// `CountLiteral`, then it would count distinctly across rows, not modify how the
|
|
25
|
+
/// query is carried out: `new CountLiteral(new DistinctLiteral('User:id'))`.
|
|
26
|
+
///
|
|
27
|
+
/// There are two primary ways to access literals in Mythix ORM. The
|
|
28
|
+
/// first is to simply import them. The second way literals can be
|
|
29
|
+
/// accessed is via the connection class itself. All Mythix ORM connection
|
|
30
|
+
/// classes export all literals on the `static Literals` attribute of
|
|
31
|
+
/// the class. So for example, you could access literals like `SQLiteConnection.Literals.DistinctLiteral`.
|
|
32
|
+
///
|
|
33
|
+
/// All built-in Mythix ORM literals--except `Literal` and `LiteralBase`--accept a field
|
|
34
|
+
/// as their first argument. This field can be a fully qualified field name, an actual
|
|
35
|
+
/// <see>Field</see> instance, or another literal. The second argument to all literal constructors
|
|
36
|
+
/// is an `options` object, that generally contains connection-specific (and operation-specific) options...
|
|
37
|
+
/// however, there are common options that can be supplied, such as `as: string;` which allows you to
|
|
38
|
+
/// define an alias for the defined field, and `noProjectionAliases: boolean;`, which allows you to disable
|
|
39
|
+
/// the column alias entirely.
|
|
40
|
+
///
|
|
41
|
+
/// Note:
|
|
42
|
+
/// The `DistinctLiteral` is rarely used directly. Normally you would want to
|
|
43
|
+
/// call `query.DISTINCT` instead, which internally uses this literal.
|
|
44
|
+
///
|
|
45
|
+
/// Example:
|
|
46
|
+
/// const { Literals } = require('mythix-orm');
|
|
47
|
+
/// const { SQLiteConnection } = require('mythix-orm-sqlite');
|
|
48
|
+
/// let literal1 = new Literals.DistinctLiteral('User:firstName');
|
|
49
|
+
/// let literal2 = new SQLiteConnection.Literals.DistinctLiteral('User:firstName');
|
|
50
|
+
///
|
|
51
|
+
/// See: LiteralFieldBase
|
|
52
|
+
///
|
|
53
|
+
/// See: LiteralBase
|
|
5
54
|
class DistinctLiteral extends LiteralFieldBase {
|
|
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. `'CountLiteral {}'`.
|
|
61
|
+
///
|
|
62
|
+
/// Note:
|
|
63
|
+
/// Ultimately, for most connections, this will end up calling
|
|
64
|
+
/// <see>QueryGenerator._distinctLiteralToString</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.
|
|
6
77
|
toString(connection, options) {
|
|
7
78
|
if (!connection)
|
|
8
79
|
return `${this.constructor.name} {}`;
|
|
@@ -2,7 +2,61 @@
|
|
|
2
2
|
|
|
3
3
|
const LiteralFieldBase = require('./literal-field-base');
|
|
4
4
|
|
|
5
|
+
/// Define a "field" 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 "field" in the underlying database.
|
|
11
|
+
/// It could for example be used in a projection, an `ORDER`,
|
|
12
|
+
/// or a `GROUP BY` clause.
|
|
13
|
+
///
|
|
14
|
+
/// There are two primary ways to access literals in Mythix ORM. The
|
|
15
|
+
/// first is to simply import them. The second way literals can be
|
|
16
|
+
/// accessed is via the connection class itself. All Mythix ORM connection
|
|
17
|
+
/// classes export all literals on the `static Literals` attribute of
|
|
18
|
+
/// the class. So for example, you could access literals like `SQLiteConnection.Literals.FieldLiteral`.
|
|
19
|
+
///
|
|
20
|
+
/// All built-in Mythix ORM literals--except `Literal` and `LiteralBase`--accept a field
|
|
21
|
+
/// as their first argument. This field can be a fully qualified field name, an actual
|
|
22
|
+
/// <see>Field</see> instance, or another literal. The second argument to all literal constructors
|
|
23
|
+
/// is an `options` object, that generally contains connection-specific (and operation-specific) options...
|
|
24
|
+
/// however, there are common options that can be supplied, such as `as: string;` which allows you to
|
|
25
|
+
/// define an alias for the defined field, and `noProjectionAliases: boolean;`, which allows you to disable
|
|
26
|
+
/// the column alias entirely.
|
|
27
|
+
///
|
|
28
|
+
/// Example:
|
|
29
|
+
/// const { Literals } = require('mythix-orm');
|
|
30
|
+
/// const { SQLiteConnection } = require('mythix-orm-sqlite');
|
|
31
|
+
/// let literal1 = new Literals.FieldLiteral('User:age');
|
|
32
|
+
/// let literal2 = new SQLiteConnection.Literals.FieldLiteral('User:age');
|
|
33
|
+
///
|
|
34
|
+
/// See: LiteralFieldBase
|
|
35
|
+
///
|
|
36
|
+
/// See: LiteralBase
|
|
5
37
|
class FieldLiteral extends LiteralFieldBase {
|
|
38
|
+
/// Convert this literal to a string to be used in a database query.
|
|
39
|
+
///
|
|
40
|
+
/// This method proxies the conversion of this literal to the connection
|
|
41
|
+
/// by calling <see>Connection.literalToString</see>. If no connection
|
|
42
|
+
/// is provided when this is called, then the literal will be converted
|
|
43
|
+
/// to a string representing it for debugging, i.e. `'FieldLiteral {}'`.
|
|
44
|
+
///
|
|
45
|
+
/// Note:
|
|
46
|
+
/// Ultimately, for most connections, this will end up calling
|
|
47
|
+
/// <see>QueryGenerator._fieldLiteralToString</see>.
|
|
48
|
+
///
|
|
49
|
+
/// Arguments:
|
|
50
|
+
/// connection?: <see>Connection</see>
|
|
51
|
+
/// The connection to use to stringify this literal. If none is provided,
|
|
52
|
+
/// then a string representing this object will be returned instead.
|
|
53
|
+
/// options?: object
|
|
54
|
+
/// A connection and operation specific set of options that can be provided.
|
|
55
|
+
/// This might for example be `{ as: 'name' }` to provided a field alias, or
|
|
56
|
+
/// `{ isProjection: true }` to define that this is being stringified for use
|
|
57
|
+
/// as a field in the query projection. Normally the end-user won't care about
|
|
58
|
+
/// any literal options, except `as`, which is commonly used to give your literal
|
|
59
|
+
/// an alias.
|
|
6
60
|
toString(connection, options) {
|
|
7
61
|
if (!connection)
|
|
8
62
|
return `${this.constructor.name} {}`;
|
|
@@ -9,6 +9,7 @@ declare class LiteralBase {
|
|
|
9
9
|
public static isLiteralClass(value: any): boolean;
|
|
10
10
|
public static isLiteral(value: any): boolean;
|
|
11
11
|
public static isLiteralType(value: any): boolean;
|
|
12
|
+
public static isAggregate(): boolean;
|
|
12
13
|
|
|
13
14
|
public constructor(literal: any, options?: GenericObject);
|
|
14
15
|
public fullyQualifiedNameToDefinition(fullyQualifiedName: LiteralBase | string | Field): LiteralBase | FullyQualifiedFieldDefinition;
|