uql-orm 0.80.0 → 0.82.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 +3 -3
- package/dist/browser/querier/httpQuerier.d.ts +2 -2
- package/dist/browser/querier/httpQuerier.js +2 -1
- package/dist/browser/type/clientQuerier.d.ts +2 -2
- package/dist/browser/uql-browser.min.js +2 -2
- package/dist/browser/uql-browser.min.js.map +9 -8
- package/dist/bunSql/bunSql.util.js +2 -1
- package/dist/dialect/abstractSqlDialect.d.ts +15 -5
- package/dist/dialect/abstractSqlDialect.js +109 -40
- package/dist/dialect/operators.d.ts +7 -1
- package/dist/dialect/operators.js +13 -1
- package/dist/dialect/vectorSqlDialect.d.ts +2 -0
- package/dist/dialect/vectorSqlDialect.js +4 -0
- package/dist/entity/metadata/definition.d.ts +1 -2
- package/dist/entity/metadata/definition.js +37 -39
- package/dist/http/handler.js +5 -4
- package/dist/http/query.d.ts +1 -1
- package/dist/http/query.js +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/migrate/acquireQuerierForMigrations.js +2 -1
- package/dist/migrate/assertCliConfig.js +7 -6
- package/dist/migrate/bin.js +0 -0
- package/dist/migrate/builder/expressions.d.ts +2 -0
- package/dist/migrate/builder/expressions.js +26 -1
- package/dist/migrate/cli-config.js +5 -4
- package/dist/migrate/cli.js +1 -1
- package/dist/migrate/codegen/entityCodeGenerator.js +2 -2
- package/dist/migrate/codegen/indexDecoratorSource.d.ts +3 -2
- package/dist/migrate/codegen/indexDecoratorSource.js +5 -23
- package/dist/migrate/ddl/indexDdl.js +4 -3
- package/dist/migrate/ddl/mssqlTableDdl.d.ts +4 -4
- package/dist/migrate/ddl/mssqlTableDdl.js +20 -14
- package/dist/migrate/ddl/mysqlIndexDdl.d.ts +2 -2
- package/dist/migrate/ddl/mysqlIndexDdl.js +12 -10
- package/dist/migrate/ddl/pgIndexDdl.d.ts +2 -1
- package/dist/migrate/ddl/pgIndexDdl.js +10 -7
- package/dist/migrate/ddl/sqliteIndexDdl.js +2 -1
- package/dist/migrate/ddl/tableDdl.d.ts +3 -2
- package/dist/migrate/ddl/tableDdl.js +11 -8
- package/dist/migrate/drift/driftDetector.d.ts +4 -5
- package/dist/migrate/drift/driftDetector.js +21 -21
- package/dist/migrate/generator/definitionToNode.d.ts +1 -1
- package/dist/migrate/generator/definitionToNode.js +9 -20
- package/dist/migrate/generator/mongoCommand.js +2 -1
- package/dist/migrate/generator/mongoSchemaGenerator.d.ts +1 -1
- package/dist/migrate/generator/mongoSchemaGenerator.js +17 -24
- package/dist/migrate/index.d.ts +2 -1
- package/dist/migrate/index.js +1 -0
- package/dist/migrate/indexPredicate.js +2 -1
- package/dist/migrate/introspection/abstractSqlSchemaIntrospector.d.ts +5 -7
- package/dist/migrate/introspection/abstractSqlSchemaIntrospector.js +13 -19
- package/dist/migrate/introspection/baseSqlIntrospector.js +7 -18
- package/dist/migrate/introspection/mongoIntrospector.d.ts +1 -1
- package/dist/migrate/introspection/mongoIntrospector.js +5 -4
- package/dist/migrate/introspection/mssqlIntrospector.js +2 -1
- package/dist/migrate/introspection/mysqlIntrospector.d.ts +15 -5
- package/dist/migrate/introspection/mysqlIntrospector.js +32 -4
- package/dist/migrate/introspection/postgresIntrospector.d.ts +29 -21
- package/dist/migrate/introspection/postgresIntrospector.js +63 -46
- package/dist/migrate/introspection/sqliteIntrospector.js +11 -9
- package/dist/migrate/migrationTarget.js +2 -1
- package/dist/migrate/migrator.d.ts +5 -0
- package/dist/migrate/migrator.js +35 -45
- package/dist/migrate/schemaChange.d.ts +18 -0
- package/dist/migrate/schemaChange.js +37 -0
- package/dist/migrate/schemaGenerator.d.ts +13 -14
- package/dist/migrate/schemaGenerator.js +88 -181
- package/dist/migrate/triggerSql.d.ts +1 -1
- package/dist/migrate/triggerSql.js +77 -61
- package/dist/mongo/mongoDialect.d.ts +1 -3
- package/dist/mongo/mongoDialect.js +9 -14
- package/dist/mongo/mongodbQuerier.js +3 -7
- package/dist/querier/abstractQuerier.d.ts +9 -4
- package/dist/querier/abstractQuerier.js +26 -19
- package/dist/querier/abstractQuerierPool.d.ts +3 -3
- package/dist/querier/abstractSqlQuerier.d.ts +2 -2
- package/dist/querier/abstractSqlQuerier.js +1 -1
- package/dist/querier/abstractSqlQuerierPool.d.ts +2 -2
- package/dist/querier/queryError.d.ts +2 -2
- package/dist/schema/indexDifferences.d.ts +22 -6
- package/dist/schema/indexDifferences.js +23 -8
- package/dist/schema/matchByKey.d.ts +10 -0
- package/dist/schema/matchByKey.js +18 -0
- package/dist/schema/schemaAST.d.ts +6 -2
- package/dist/schema/schemaAST.js +7 -3
- package/dist/schema/schemaASTBuilder.d.ts +2 -0
- package/dist/schema/schemaASTBuilder.js +17 -11
- package/dist/schema/schemaASTDiffer.d.ts +2 -3
- package/dist/schema/schemaASTDiffer.js +15 -36
- package/dist/schema/types.d.ts +14 -15
- package/dist/type/dialect.d.ts +23 -1
- package/dist/type/entity.d.ts +15 -11
- package/dist/type/logger.d.ts +2 -2
- package/dist/type/migration.d.ts +32 -50
- package/dist/type/querier.d.ts +3 -3
- package/dist/type/query.d.ts +3 -13
- package/dist/type/queryAggregate.d.ts +4 -10
- package/dist/type/queryRaw.d.ts +17 -3
- package/dist/type/queryRaw.js +2 -1
- package/dist/type/queryWhere.d.ts +7 -7
- package/dist/type/universalQuerier.d.ts +3 -3
- package/dist/type/vector.d.ts +2 -1
- package/dist/type/vector.js +2 -1
- package/dist/util/ddlExpression.util.d.ts +5 -1
- package/dist/util/ddlExpression.util.js +6 -2
- package/dist/util/dialect.util.d.ts +13 -5
- package/dist/util/dialect.util.js +28 -20
- package/dist/util/field.util.d.ts +4 -4
- package/dist/util/field.util.js +10 -2
- package/dist/util/hook.util.d.ts +1 -1
- package/dist/util/hook.util.js +8 -1
- package/dist/util/index.d.ts +1 -0
- package/dist/util/index.js +1 -0
- package/dist/util/logger.d.ts +3 -3
- package/dist/util/object.util.js +3 -2
- package/dist/util/raw.d.ts +6 -7
- package/dist/util/raw.js +10 -12
- package/dist/util/sqlLiteral.js +3 -2
- package/dist/util/triggerWrite.d.ts +15 -0
- package/dist/util/triggerWrite.js +20 -0
- package/package.json +1 -1
- package/skills/uql-orm/SKILL.md +3 -3
package/dist/util/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from './ddlExpression.util.js';
|
|
|
7
7
|
export * from './logger.js';
|
|
8
8
|
export * from './object.util.js';
|
|
9
9
|
export * from './raw.js';
|
|
10
|
+
export * from './triggerWrite.js';
|
|
10
11
|
export * from './rowKey.util.js';
|
|
11
12
|
export * from './relationQuery.util.js';
|
|
12
13
|
export * from './sql.util.js';
|
package/dist/util/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export * from './ddlExpression.util.js';
|
|
|
7
7
|
export * from './logger.js';
|
|
8
8
|
export * from './object.util.js';
|
|
9
9
|
export * from './raw.js';
|
|
10
|
+
export * from './triggerWrite.js';
|
|
10
11
|
export * from './rowKey.util.js';
|
|
11
12
|
export * from './relationQuery.util.js';
|
|
12
13
|
export * from './sql.util.js';
|
package/dist/util/logger.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ import type { Logger, LoggingOptions } from '../type/logger.js';
|
|
|
3
3
|
* Default implementation of the Logger interface using console methods.
|
|
4
4
|
*/
|
|
5
5
|
export declare class DefaultLogger implements Logger {
|
|
6
|
-
logQuery(query: string, values?: unknown[], duration?: number): void;
|
|
7
|
-
logSlowQuery(query: string, values?: unknown[], duration?: number): void;
|
|
6
|
+
logQuery(query: string, values?: readonly unknown[], duration?: number): void;
|
|
7
|
+
logSlowQuery(query: string, values?: readonly unknown[], duration?: number): void;
|
|
8
8
|
logWarn(message: string): void;
|
|
9
9
|
logError(message: string, error?: unknown): void;
|
|
10
10
|
logInfo(message: string): void;
|
|
@@ -37,7 +37,7 @@ export declare class LoggerWrapper implements Logger {
|
|
|
37
37
|
constructor(options?: LoggingOptions, config?: LoggerWrapperConfig);
|
|
38
38
|
/** Whether `logQuery` would ever actually surface bound values, given the configured levels/slowQuery/logValues. */
|
|
39
39
|
willLogValues(): boolean;
|
|
40
|
-
logQuery(query: string, values?: unknown[], duration?: number): void;
|
|
40
|
+
logQuery(query: string, values?: readonly unknown[], duration?: number): void;
|
|
41
41
|
logWarn(message: string): void;
|
|
42
42
|
logError(message: string, error?: unknown): void;
|
|
43
43
|
logInfo(message: string): void;
|
package/dist/util/object.util.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { UqlUsageError } from './uqlError.js';
|
|
1
2
|
export function throwPendingTransaction() {
|
|
2
|
-
throw
|
|
3
|
+
throw new UqlUsageError('pending transaction');
|
|
3
4
|
}
|
|
4
5
|
export function throwNoPendingTransaction() {
|
|
5
|
-
throw
|
|
6
|
+
throw new UqlUsageError('not a pending transaction');
|
|
6
7
|
}
|
|
7
8
|
export function clone(value) {
|
|
8
9
|
if (typeof value !== 'object' || value === null) {
|
package/dist/util/raw.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type EntitySql, type EntityWhere, type EntityWhereMeta, QueryRaw, type QueryRawFn, type ComputedRefs, type RefMap, type TriggerRowName, type Type } from '../type/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Raw SQL, where an interpolated value binds, a `refs` field renders its column, and a `raw` renders
|
|
4
4
|
* in place: `raw`GREATEST(0, ${user.credits} - ${amount})``. A callback writes whatever it writes, so
|
|
@@ -27,10 +27,9 @@ export declare function entitySql<E>(sql: EntitySql<E>): QueryRaw;
|
|
|
27
27
|
/** A definition's predicate, its callback resolved the way {@link entitySql} resolves one. */
|
|
28
28
|
export declare function entityWhere<E>(where: EntityWhere<E>): EntityWhereMeta<E>;
|
|
29
29
|
/**
|
|
30
|
-
* The fields of `
|
|
31
|
-
* against the incoming row, `OLD."col"` against the outgoing one.
|
|
32
|
-
*
|
|
30
|
+
* The fields of `entity` as the row a trigger body reads them off, qualified by the side it names:
|
|
31
|
+
* `NEW."col"` against the incoming row, `OLD."col"` against the outgoing one. Bound to the entity, as
|
|
32
|
+
* {@link refs} are, so each names its own column wherever it renders, a write to another table included.
|
|
33
|
+
* Columns only: a relation's aggregate is a subquery, and a trigger fires on one row, not over a table.
|
|
33
34
|
*/
|
|
34
|
-
export declare function rowRefs<E>(qualifier: TriggerRowName): RefMap<E>;
|
|
35
|
-
/** One field of a trigger's row, for code that names it by its key rather than off {@link rowRefs}. */
|
|
36
|
-
export declare function rowColumn(qualifier: TriggerRowName, key: string): ColumnRef;
|
|
35
|
+
export declare function rowRefs<E>(entity: Type<E>, qualifier: TriggerRowName): RefMap<E>;
|
package/dist/util/raw.js
CHANGED
|
@@ -2,6 +2,7 @@ import { getMeta } from '../entity/metadata/definition.js';
|
|
|
2
2
|
import { ColumnRef, QueryRaw, RAW_TEXT, RelationAggregate, } from '../type/index.js';
|
|
3
3
|
import { aggregateOf, isInlinedExpression } from './field.util.js';
|
|
4
4
|
import { entityName, hasKeys } from './object.util.js';
|
|
5
|
+
import { UqlUsageError } from './uqlError.js';
|
|
5
6
|
export function raw(value, ...rest) {
|
|
6
7
|
if (!isTemplateStrings(value)) {
|
|
7
8
|
return new QueryRaw(value);
|
|
@@ -78,22 +79,19 @@ function rowsOf(q) {
|
|
|
78
79
|
function relationAggregate(spec) {
|
|
79
80
|
return new RelationAggregate(spec, (opts) => {
|
|
80
81
|
if (!opts.entity) {
|
|
81
|
-
throw new
|
|
82
|
+
throw new UqlUsageError(`'${spec.relation}' was read off a definition's refs, so it renders only inside its entity's SQL`);
|
|
82
83
|
}
|
|
83
84
|
opts.dialect.appendRelationAggregate(opts.ctx, opts.entity, spec, opts.prefix);
|
|
84
85
|
});
|
|
85
86
|
}
|
|
86
87
|
/**
|
|
87
|
-
* The fields of `
|
|
88
|
-
* against the incoming row, `OLD."col"` against the outgoing one.
|
|
89
|
-
*
|
|
88
|
+
* The fields of `entity` as the row a trigger body reads them off, qualified by the side it names:
|
|
89
|
+
* `NEW."col"` against the incoming row, `OLD."col"` against the outgoing one. Bound to the entity, as
|
|
90
|
+
* {@link refs} are, so each names its own column wherever it renders, a write to another table included.
|
|
91
|
+
* Columns only: a relation's aggregate is a subquery, and a trigger fires on one row, not over a table.
|
|
90
92
|
*/
|
|
91
|
-
export function rowRefs(qualifier) {
|
|
92
|
-
return new Proxy({}, { get: (_, key) =>
|
|
93
|
-
}
|
|
94
|
-
/** One field of a trigger's row, for code that names it by its key rather than off {@link rowRefs}. */
|
|
95
|
-
export function rowColumn(qualifier, key) {
|
|
96
|
-
return columnRef(undefined, key, qualifier);
|
|
93
|
+
export function rowRefs(entity, qualifier) {
|
|
94
|
+
return new Proxy({}, { get: (_, key) => columnRef(entity, String(key), qualifier) });
|
|
97
95
|
}
|
|
98
96
|
/**
|
|
99
97
|
* One field as SQL, against its own entity or, read off a definition, the entity rendering it. A
|
|
@@ -103,7 +101,7 @@ function columnRef(entity, key, qualifier) {
|
|
|
103
101
|
return new ColumnRef(key, (opts) => {
|
|
104
102
|
const owner = entity ?? opts.entity;
|
|
105
103
|
if (!owner) {
|
|
106
|
-
throw new
|
|
104
|
+
throw new UqlUsageError(`'${key}' was read off a definition's refs, so it renders only inside its entity's SQL`);
|
|
107
105
|
}
|
|
108
106
|
renderColumn(getMeta(owner), key, { ...opts, entity: owner }, qualifier);
|
|
109
107
|
});
|
|
@@ -119,7 +117,7 @@ function renderColumn(meta, key, opts, qualifier) {
|
|
|
119
117
|
if (field && isInlinedExpression(field)) {
|
|
120
118
|
// A relation aggregate is a subquery correlated to a table in scope, and a trigger's row is not one.
|
|
121
119
|
if (qualifier !== undefined && aggregateOf(field)) {
|
|
122
|
-
throw new
|
|
120
|
+
throw new UqlUsageError(`'${entityName(meta)}.${key}' reads a relation, which a trigger's row cannot: it fires on one row, ` +
|
|
123
121
|
'with no table in scope to correlate a subquery to. Name the columns it is derived from instead.');
|
|
124
122
|
}
|
|
125
123
|
scope.ctx.append('(');
|
package/dist/util/sqlLiteral.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// SQL literal escaping for `Dialect.escape`: ANSI quote doubling, or MySQL's backslashes. UQL binds
|
|
2
2
|
// values instead, so this is the hand-written-SQL hatch, and inline MySQL literals break under
|
|
3
3
|
// `NO_BACKSLASH_ESCAPES` or a GBK-like charset: prefer bound parameters. Postgres arrays are separate.
|
|
4
|
+
import { UqlUsageError } from './uqlError.js';
|
|
4
5
|
const SINGLE_QUOTE = /'/g;
|
|
5
6
|
/** Doubles every single quote in `val`, the ANSI escaping shared by string literals and JSON path keys. */
|
|
6
7
|
export function escapeSingleQuotes(val) {
|
|
@@ -73,7 +74,7 @@ function createEscaper(escapeString) {
|
|
|
73
74
|
if ('toSqlString' in value && typeof value.toSqlString === 'function') {
|
|
74
75
|
return String(value.toSqlString());
|
|
75
76
|
}
|
|
76
|
-
throw new
|
|
77
|
+
throw new UqlUsageError('escapeSqlLiteral: plain objects are not supported; use bound parameters or JSON.stringify + a string column.');
|
|
77
78
|
};
|
|
78
79
|
const escapeValue = (value) => {
|
|
79
80
|
if (value === undefined || value === null) {
|
|
@@ -92,7 +93,7 @@ function createEscaper(escapeString) {
|
|
|
92
93
|
return escapeObject(value);
|
|
93
94
|
default:
|
|
94
95
|
// A symbol or a function, or a future JS type: none of them may silently become SQL.
|
|
95
|
-
throw new
|
|
96
|
+
throw new UqlUsageError(`escapeSqlLiteral: unsupported value type '${typeof value}'; use bound parameters.`);
|
|
96
97
|
}
|
|
97
98
|
};
|
|
98
99
|
return escapeValue;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { EntityPredicate, QueryRaw, Type, UpdatePayload, WritableKey, WriteRow } from '../type/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* A row inserted by a trigger's body, into any table: `insertInto(PostAudit, { postId: newRow.id })`.
|
|
4
|
+
* Each value is a literal or SQL, a row's ref most often, and every engine renders it, SQL Server's
|
|
5
|
+
* set-based trigger included, where it inserts one row for each the statement touched.
|
|
6
|
+
*/
|
|
7
|
+
export declare function insertInto<E extends object>(entity: Type<E>, row: WriteRow<E>): QueryRaw;
|
|
8
|
+
/** The rows `q.$where` names updated by a trigger's body: `updateTable(Post, { $where: { id: newRow.postId } }, set)`. */
|
|
9
|
+
export declare function updateTable<E extends object>(entity: Type<E>, q: {
|
|
10
|
+
readonly $where: EntityPredicate<E>;
|
|
11
|
+
}, set: UpdatePayload<E, QueryRaw, WritableKey<E>, never>): QueryRaw;
|
|
12
|
+
/** The rows `q.$where` names deleted by a trigger's body, outright: a soft delete is an `updateTable`. */
|
|
13
|
+
export declare function deleteFrom<E extends object>(entity: Type<E>, q: {
|
|
14
|
+
readonly $where: EntityPredicate<E>;
|
|
15
|
+
}): QueryRaw;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { raw } from './raw.js';
|
|
2
|
+
/**
|
|
3
|
+
* A row inserted by a trigger's body, into any table: `insertInto(PostAudit, { postId: newRow.id })`.
|
|
4
|
+
* Each value is a literal or SQL, a row's ref most often, and every engine renders it, SQL Server's
|
|
5
|
+
* set-based trigger included, where it inserts one row for each the statement touched.
|
|
6
|
+
*/
|
|
7
|
+
export function insertInto(entity, row) {
|
|
8
|
+
return written({ kind: 'insert', entity, row });
|
|
9
|
+
}
|
|
10
|
+
/** The rows `q.$where` names updated by a trigger's body: `updateTable(Post, { $where: { id: newRow.postId } }, set)`. */
|
|
11
|
+
export function updateTable(entity, q, set) {
|
|
12
|
+
return written({ kind: 'update', entity, set, where: q.$where });
|
|
13
|
+
}
|
|
14
|
+
/** The rows `q.$where` names deleted by a trigger's body, outright: a soft delete is an `updateTable`. */
|
|
15
|
+
export function deleteFrom(entity, q) {
|
|
16
|
+
return written({ kind: 'delete', entity, where: q.$where });
|
|
17
|
+
}
|
|
18
|
+
function written(write) {
|
|
19
|
+
return raw(({ ctx, dialect, rows }) => dialect.triggerWrite(ctx, write, rows));
|
|
20
|
+
}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"homepage": "https://uql-orm.dev",
|
|
4
4
|
"description": "The JSON-native TypeScript ORM for Bun, Browsers, Edge, Deno, Node, Workers. Supports PostgreSQL, PGlite, MySQL, MariaDB, SQLite, CockroachDB, SQL Server, Turso, Neon, Cloudflare D1 and MongoDB. Queries are plain JSON, typed to the leaf.",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.82.0",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"engines": {
|
|
9
9
|
"node": ">=24"
|
package/skills/uql-orm/SKILL.md
CHANGED
|
@@ -84,7 +84,7 @@ export class Post {
|
|
|
84
84
|
an update must carry the version it read (a compile error otherwise), and one against a row someone else moved on throws `UqlOptimisticLockError` (kind `optimisticLock`, HTTP 409). Its updates name one row by its id; save and upsert are refused.
|
|
85
85
|
- `@Field({ computed })` is a value the database produces, on a `readonly` property: SQL over the row, ``(u) => raw`${u.first} || ' ' || ${u.last}` ``, or a relation aggregate, `(order) => order.items.count()`.
|
|
86
86
|
`stored: true` makes the SQL a generated column; `stored: ['insert', 'update']` makes it a stamp, a trigger writing it on those events whoever writes the row (``computed: raw`CURRENT_TIMESTAMP` ``), where `onUpdate` covers only uql's own writes.
|
|
87
|
-
- `@Trigger({ on: 'afterUpdate', of: (post) => [post.status], where: { $old: { status: 'draft' } }, run })` is a trigger the database fires; `where` holds a `$where` predicate per row it names, or SQL off the rows. `run`
|
|
87
|
+
- `@Trigger({ on: 'afterUpdate', of: (post) => [post.status], where: { $old: { status: 'draft' } }, run })` is a trigger the database fires (`defineEntity`'s `triggers` or `defineTrigger` without decorators); `where` holds a `$where` predicate per row it names, or SQL off the rows. `run` takes `(newRow, oldRow)`, each only where the event has it (no `oldRow` on insert, no `newRow` on delete), and returns the body: `insertInto(Audit, { postId: newRow.id })`, `updateTable(Audit, { $where: { postId: newRow.id } }, { status: newRow.status })` or `deleteFrom(Audit, { $where: { postId: oldRow.id } })`, typed by the entity written and rendered on every engine (no `onInsert`/`onUpdate` fills, so an insert names each field uql fills on insert unless its column has a `defaultValue`; `$where` reads the entity's own fields; no entity filters, security ones included, so a soft-delete entity is hard-deleted; an update or delete naming no rows is refused; no `$inc`/`$mul`/`$push` on SQL Server), several joined in one `raw`. Anything else is `raw` SQL over the refs, one body for every engine or `{ postgres, mssql, ... }` where they differ (SQL Server fires per statement, reading `inserted`/`deleted` as tables, with no `before*` and no `where`). MongoDB has none, and refuses a write to an entity declaring one.
|
|
88
88
|
- `defineEntity` defines the same entity without decorators: https://uql-orm.dev/entities/imperative.md
|
|
89
89
|
|
|
90
90
|
## Queries
|
|
@@ -123,7 +123,7 @@ const users = await pool.findMany(User, {
|
|
|
123
123
|
- Methods: `findMany`, `findOne`, `findOneById`, `findManyAndCount`, `findManyStream`, `count`, `exists`,
|
|
124
124
|
`aggregate`, `insertOne`, `insertMany`, `updateOneById`, `updateMany`, `saveOne`, `saveMany`, `upsertOne`,
|
|
125
125
|
`upsertMany`, `deleteOneById`, `deleteMany`. Each takes the entity class first.
|
|
126
|
-
- `updateMany` and `deleteMany` naming no rows - no `$where
|
|
126
|
+
- `updateMany` and `deleteMany` naming no rows - no `$where` holding a value (an `undefined` or an empty group holds none), no `$limit` - throw; `{ unfiltered: true }` means the whole table.
|
|
127
127
|
- An update takes `{ stock: { $inc: -1 } }` to add, or `$mul` to multiply, in the statement, a NULL counting as 0,
|
|
128
128
|
so a guard in `$where` (`stock: { $gte: 1 }`) makes a decrement race-safe. JSON fields take `$set`, `$unset`,
|
|
129
129
|
`$push`, `$pull`.
|
|
@@ -133,7 +133,7 @@ const users = await pool.findMany(User, {
|
|
|
133
133
|
- `queryErrorKind(err)` names any failure the same on every engine - `uniqueViolation`, `foreignKeyViolation`,
|
|
134
134
|
`notNullViolation`, `checkViolation`, `optimisticLock`, `retryable`, `usage` - so catch by kind rather than by
|
|
135
135
|
a driver's code or an `instanceof`.
|
|
136
|
-
- `raw()` embeds SQL anywhere a value or field goes; `pool.all(sql, values)` runs a raw `SELECT`.
|
|
136
|
+
- `raw()` embeds SQL anywhere a value or field goes; `pool.all(sql, values)` runs a raw `SELECT`. A field read off `refs(Entity)` carries its type: on its own as a value it fits only a field of that type.
|
|
137
137
|
|
|
138
138
|
## Connections and transactions
|
|
139
139
|
|