uql-orm 0.66.0 → 0.67.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/dist/browser/querier/httpQuerier.js +1 -8
- package/dist/browser/uql-browser.min.js.map +5 -5
- package/dist/bunSql/bunSql.util.d.ts +2 -6
- package/dist/bunSql/bunSql.util.js +2 -6
- package/dist/bunSql/bunSqlQuerier.d.ts +2 -5
- package/dist/bunSql/bunSqlQuerier.js +2 -5
- package/dist/cockroachdb/cockroachDialect.d.ts +4 -13
- package/dist/cockroachdb/cockroachDialect.js +4 -13
- package/dist/context/context.browser.js +2 -10
- package/dist/context/context.d.ts +4 -17
- package/dist/context/context.js +4 -17
- package/dist/dialect/abstractDialect.d.ts +4 -19
- package/dist/dialect/abstractDialect.js +2 -20
- package/dist/dialect/abstractSqlDialect.d.ts +47 -212
- package/dist/dialect/abstractSqlDialect.js +68 -222
- package/dist/dialect/aliases.d.ts +2 -12
- package/dist/dialect/aliases.js +4 -12
- package/dist/dialect/hydrateColumn.d.ts +2 -6
- package/dist/dialect/hydrateColumn.js +3 -13
- package/dist/dialect/jsonArrayElemMatchUtils.d.ts +1 -7
- package/dist/dialect/jsonArrayElemMatchUtils.js +1 -7
- package/dist/dialect/jsonSql.d.ts +6 -27
- package/dist/dialect/jsonSql.js +6 -27
- package/dist/dialect/mergeSqlDialect.d.ts +4 -22
- package/dist/dialect/mergeSqlDialect.js +4 -22
- package/dist/dialect/mysqlLikeSqlDialect.d.ts +11 -37
- package/dist/dialect/mysqlLikeSqlDialect.js +35 -51
- package/dist/dialect/pgLikeSqlDialect.d.ts +8 -22
- package/dist/dialect/pgLikeSqlDialect.js +36 -39
- package/dist/dialect/queryContext.d.ts +4 -22
- package/dist/dialect/queryContext.js +4 -22
- package/dist/dialect/queryJoins.d.ts +3 -12
- package/dist/dialect/queryJoins.js +3 -12
- package/dist/dialect/vectorCast.d.ts +2 -12
- package/dist/dialect/vectorCast.js +3 -19
- package/dist/dialect/vectorSqlDialect.d.ts +8 -38
- package/dist/dialect/vectorSqlDialect.js +7 -38
- package/dist/entity/decorator/bag.d.ts +6 -19
- package/dist/entity/decorator/bag.js +6 -22
- package/dist/entity/decorator/entity.d.ts +2 -7
- package/dist/entity/decorator/entity.js +2 -7
- package/dist/entity/decorator/members.d.ts +7 -30
- package/dist/entity/decorator/members.js +3 -12
- package/dist/entity/metadata/definition.d.ts +2 -18
- package/dist/entity/metadata/definition.js +6 -28
- package/dist/http/handler.d.ts +2 -14
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/libsql/libsqlDialect.d.ts +1 -8
- package/dist/libsql/libsqlDialect.js +1 -8
- package/dist/maria/mariaDialect.d.ts +3 -5
- package/dist/maria/mariaDialect.js +5 -5
- package/dist/maria/mariadbQuerier.js +2 -2
- package/dist/maria/mariadbQuerierPool.js +1 -6
- package/dist/migrate/builder/migrationBuilder.js +3 -19
- package/dist/migrate/builder/splitSqlStatements.d.ts +1 -14
- package/dist/migrate/builder/splitSqlStatements.js +2 -22
- package/dist/migrate/builder/types.d.ts +2 -15
- package/dist/migrate/cli-config.js +2 -11
- package/dist/migrate/cli.js +2 -7
- package/dist/migrate/codegen/entityCodeGenerator.d.ts +0 -15
- package/dist/migrate/codegen/entityCodeGenerator.js +15 -44
- package/dist/migrate/codegen/fieldOptionsSource.d.ts +1 -8
- package/dist/migrate/codegen/fieldOptionsSource.js +3 -22
- package/dist/migrate/ddl/indexDdl.d.ts +2 -5
- package/dist/migrate/ddl/indexDdl.js +2 -5
- package/dist/migrate/ddl/pgIndexDdl.d.ts +3 -13
- package/dist/migrate/ddl/pgIndexDdl.js +3 -13
- package/dist/migrate/generator/definitionToNode.d.ts +2 -9
- package/dist/migrate/generator/definitionToNode.js +3 -17
- package/dist/migrate/generator/indexNodeToSchema.d.ts +2 -3
- package/dist/migrate/generator/indexNodeToSchema.js +2 -3
- package/dist/migrate/generator/mongoCommand.d.ts +1 -8
- package/dist/migrate/generator/mongoSchemaGenerator.d.ts +1 -8
- package/dist/migrate/generator/mongoSchemaGenerator.js +1 -8
- package/dist/migrate/introspection/abstractSqlSchemaIntrospector.d.ts +6 -26
- package/dist/migrate/introspection/abstractSqlSchemaIntrospector.js +9 -41
- package/dist/migrate/introspection/baseSqlIntrospector.js +0 -1
- package/dist/migrate/introspection/mongoIntrospector.d.ts +3 -1
- package/dist/migrate/introspection/mongoIntrospector.js +48 -46
- package/dist/migrate/introspection/mssqlIntrospector.d.ts +4 -4
- package/dist/migrate/introspection/mssqlIntrospector.js +18 -27
- package/dist/migrate/introspection/mysqlIntrospector.d.ts +7 -2
- package/dist/migrate/introspection/mysqlIntrospector.js +16 -14
- package/dist/migrate/introspection/postgresIntrospector.d.ts +24 -9
- package/dist/migrate/introspection/postgresIntrospector.js +68 -59
- package/dist/migrate/introspection/sqliteIntrospector.d.ts +1 -1
- package/dist/migrate/introspection/sqliteIntrospector.js +8 -10
- package/dist/migrate/migrator.d.ts +9 -53
- package/dist/migrate/migrator.js +32 -65
- package/dist/migrate/schemaGenerator.d.ts +16 -66
- package/dist/migrate/schemaGenerator.js +21 -74
- package/dist/mongo/mongoDialect.d.ts +21 -53
- package/dist/mongo/mongoDialect.js +25 -70
- package/dist/mongo/mongodbQuerier.d.ts +5 -8
- package/dist/mongo/mongodbQuerier.js +31 -65
- package/dist/mssql/mssqlDialect.d.ts +8 -34
- package/dist/mssql/mssqlDialect.js +37 -51
- package/dist/mssql/mssqlQuerier.d.ts +37 -4
- package/dist/mssql/mssqlQuerier.js +2 -2
- package/dist/mssql/mssqlWireTypes.d.ts +2 -14
- package/dist/mssql/mssqlWireTypes.js +2 -14
- package/dist/nestjs/uqlModule.js +2 -7
- package/dist/pglite/pgliteQuerier.d.ts +1 -9
- package/dist/pglite/pgliteQuerierPool.d.ts +4 -26
- package/dist/pglite/pgliteQuerierPool.js +3 -18
- package/dist/postgres/abstractPgQuerierPool.d.ts +1 -8
- package/dist/postgres/abstractPgQuerierPool.js +1 -8
- package/dist/postgres/pgNumericTypes.d.ts +3 -26
- package/dist/postgres/pgNumericTypes.js +3 -26
- package/dist/postgres/postgresDialect.d.ts +4 -10
- package/dist/postgres/postgresDialect.js +4 -10
- package/dist/querier/abstractQuerier.d.ts +35 -103
- package/dist/querier/abstractQuerier.js +105 -201
- package/dist/querier/abstractSharedHandleQuerierPool.d.ts +3 -17
- package/dist/querier/abstractSharedHandleQuerierPool.js +3 -17
- package/dist/querier/abstractSqlQuerier.d.ts +15 -36
- package/dist/querier/abstractSqlQuerier.js +49 -131
- package/dist/schema/canonicalType.d.ts +3 -21
- package/dist/schema/canonicalType.js +22 -67
- package/dist/schema/dependencyGraph.d.ts +2 -8
- package/dist/schema/dependencyGraph.js +2 -32
- package/dist/schema/index.d.ts +1 -25
- package/dist/schema/index.js +0 -26
- package/dist/schema/indexColumns.d.ts +1 -8
- package/dist/schema/indexColumns.js +1 -8
- package/dist/schema/indexDifferences.d.ts +7 -40
- package/dist/schema/indexDifferences.js +6 -31
- package/dist/schema/schemaAST.d.ts +8 -175
- package/dist/schema/schemaAST.js +13 -365
- package/dist/schema/schemaASTBuilder.d.ts +2 -24
- package/dist/schema/schemaASTBuilder.js +2 -30
- package/dist/schema/schemaASTDiffer.d.ts +6 -46
- package/dist/schema/schemaASTDiffer.js +8 -56
- package/dist/schema/types.d.ts +5 -61
- package/dist/schema/types.js +3 -6
- package/dist/sqlite/abstractSqliteQuerier.d.ts +1 -8
- package/dist/sqlite/localSqliteQuerierPool.d.ts +1 -7
- package/dist/sqlite/localSqliteQuerierPool.js +1 -7
- package/dist/sqlite/nodeSqliteQuerierPool.d.ts +2 -7
- package/dist/sqlite/nodeSqliteQuerierPool.js +2 -7
- package/dist/sqlite/sqliteDialect.d.ts +5 -20
- package/dist/sqlite/sqliteDialect.js +29 -35
- package/dist/turso/tursoDialect.d.ts +4 -6
- package/dist/turso/tursoDialect.js +4 -6
- package/dist/turso/tursoLocalQuerierPool.d.ts +1 -7
- package/dist/turso/tursoLocalQuerierPool.js +1 -7
- package/dist/turso/tursoQuerierPool.d.ts +2 -6
- package/dist/turso/tursoQuerierPool.js +2 -6
- package/dist/turso/tursoSessionQuerier.d.ts +1 -7
- package/dist/turso/tursoSessionQuerier.js +1 -7
- package/dist/type/dialect.d.ts +42 -94
- package/dist/type/dialect.js +3 -13
- package/dist/type/entity.d.ts +163 -534
- package/dist/type/entity.js +26 -9
- package/dist/type/logger.d.ts +2 -14
- package/dist/type/migration.d.ts +9 -38
- package/dist/type/querier.d.ts +9 -28
- package/dist/type/querierPool.d.ts +4 -26
- package/dist/type/query.d.ts +19 -73
- package/dist/type/query.js +2 -7
- package/dist/type/queryAggregate.d.ts +18 -98
- package/dist/type/queryRaw.d.ts +1 -8
- package/dist/type/queryRaw.js +1 -8
- package/dist/type/queryWhere.d.ts +13 -61
- package/dist/type/universalQuerier.d.ts +18 -105
- package/dist/type/utility.d.ts +12 -24
- package/dist/type/vector.d.ts +8 -38
- package/dist/type/vector.js +1 -1
- package/dist/type/wire.d.ts +2 -5
- package/dist/util/dialect.util.d.ts +9 -27
- package/dist/util/dialect.util.js +10 -27
- package/dist/util/field.util.d.ts +2 -31
- package/dist/util/field.util.js +3 -43
- package/dist/util/fieldOption.util.d.ts +7 -15
- package/dist/util/fieldOption.util.js +1 -1
- package/dist/util/filters.util.d.ts +2 -5
- package/dist/util/filters.util.js +2 -5
- package/dist/util/logger.d.ts +2 -6
- package/dist/util/logger.js +2 -6
- package/dist/util/object.util.d.ts +2 -6
- package/dist/util/object.util.js +1 -5
- package/dist/util/raw.d.ts +3 -23
- package/dist/util/relationQuery.util.d.ts +3 -14
- package/dist/util/relationQuery.util.js +3 -14
- package/dist/util/rowKey.util.d.ts +2 -10
- package/dist/util/rowKey.util.js +2 -10
- package/dist/util/sql.util.d.ts +6 -37
- package/dist/util/sql.util.js +13 -73
- package/dist/util/sqlLiteral.d.ts +2 -13
- package/dist/util/sqlLiteral.js +8 -13
- package/dist/util/string.util.js +0 -2
- package/package.json +4 -4
|
@@ -36,36 +36,15 @@ export declare function jsonElemExists(from: string, conditions: readonly string
|
|
|
36
36
|
*/
|
|
37
37
|
export type JsonAccessMode = 'json' | 'numeric' | 'text';
|
|
38
38
|
/**
|
|
39
|
-
* How a JSON scalar
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* - `numeric` - cast the accessor. Keeps `1` equal to a stored `1.0`, which strict JSON equality
|
|
43
|
-
* would not, and satisfies drivers that send typed parameters (`text = integer` otherwise).
|
|
44
|
-
* - `json` - compare the JSON value against a JSON-encoded parameter. No cast recovers a boolean
|
|
45
|
-
* portably: PostgreSQL raises `text = boolean` and MySQL matches `'true'` against `1`.
|
|
46
|
-
* - `text` - compare as extracted, which is also what the string operators need.
|
|
47
|
-
*
|
|
48
|
-
* Mixed operand types fall back to `text`, since one comparison cannot be two shapes at once.
|
|
39
|
+
* How a JSON scalar compares against `value`, since extraction yields text: `numeric` casts (so `1` equals
|
|
40
|
+
* `1.0`), `json` compares JSON values (the only portable boolean), and `text` compares as extracted,
|
|
41
|
+
* also for mixed operands.
|
|
49
42
|
*/
|
|
50
43
|
export declare function jsonCompareMode(value: unknown): JsonAccessMode;
|
|
51
|
-
/**
|
|
52
|
-
* The mode a *declared* type asks for: {@link jsonCompareMode}'s twin, reading the type instead of an
|
|
53
|
-
* operand. An index over a JSON path is only reachable by a comparison that extracts it the same way,
|
|
54
|
-
* so the two have to answer alike - which is why they are one pair over one vocabulary.
|
|
55
|
-
*
|
|
56
|
-
* Reads the type through `util/field.util`'s own classifier, which the dialects already carry:
|
|
57
|
-
* resolving it through `schema/canonicalType` instead pulls that whole module into every consumer
|
|
58
|
-
* bundle.
|
|
59
|
-
*/
|
|
44
|
+
/** The mode a declared type asks for, {@link jsonCompareMode}'s twin: an index over a path is reached only by a comparison extracting it alike. */
|
|
60
45
|
export declare function jsonTypeMode(type: FieldType): JsonAccessMode;
|
|
61
46
|
/**
|
|
62
|
-
* Whether the operator reads the JSON
|
|
63
|
-
*
|
|
64
|
-
* a way no cast recovers portably: PostgreSQL raises `operator does not exist: text = boolean`,
|
|
65
|
-
* MySQL compares `'true'` to `1` and silently matches nothing, and SQLite's `JSON_EXTRACT` yields
|
|
66
|
-
* `1`. Comparing the JSON value against a JSON-encoded parameter is exact on every dialect.
|
|
67
|
-
*
|
|
68
|
-
* Numbers stay on the text accessor with a numeric cast, which keeps `1` equal to `1.0` - JSON
|
|
69
|
-
* equality would not.
|
|
47
|
+
* Whether the operator reads the JSON value rather than its text: the array operators, and equality
|
|
48
|
+
* against a boolean, which no cast recovers portably from text.
|
|
70
49
|
*/
|
|
71
50
|
export declare function isJsonbOp(op: string, value?: unknown): boolean;
|
package/dist/dialect/jsonSql.js
CHANGED
|
@@ -53,16 +53,9 @@ export function jsonElemExists(from, conditions) {
|
|
|
53
53
|
return `EXISTS (SELECT 1 FROM ${from}${where})`;
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
|
-
* How a JSON scalar
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* - `numeric` - cast the accessor. Keeps `1` equal to a stored `1.0`, which strict JSON equality
|
|
60
|
-
* would not, and satisfies drivers that send typed parameters (`text = integer` otherwise).
|
|
61
|
-
* - `json` - compare the JSON value against a JSON-encoded parameter. No cast recovers a boolean
|
|
62
|
-
* portably: PostgreSQL raises `text = boolean` and MySQL matches `'true'` against `1`.
|
|
63
|
-
* - `text` - compare as extracted, which is also what the string operators need.
|
|
64
|
-
*
|
|
65
|
-
* Mixed operand types fall back to `text`, since one comparison cannot be two shapes at once.
|
|
56
|
+
* How a JSON scalar compares against `value`, since extraction yields text: `numeric` casts (so `1` equals
|
|
57
|
+
* `1.0`), `json` compares JSON values (the only portable boolean), and `text` compares as extracted,
|
|
58
|
+
* also for mixed operands.
|
|
66
59
|
*/
|
|
67
60
|
export function jsonCompareMode(value) {
|
|
68
61
|
const operands = Array.isArray(value) ? value : [value];
|
|
@@ -74,15 +67,7 @@ export function jsonCompareMode(value) {
|
|
|
74
67
|
}
|
|
75
68
|
return operands.every((operand) => typeof operand === 'number') ? 'numeric' : 'text';
|
|
76
69
|
}
|
|
77
|
-
/**
|
|
78
|
-
* The mode a *declared* type asks for: {@link jsonCompareMode}'s twin, reading the type instead of an
|
|
79
|
-
* operand. An index over a JSON path is only reachable by a comparison that extracts it the same way,
|
|
80
|
-
* so the two have to answer alike - which is why they are one pair over one vocabulary.
|
|
81
|
-
*
|
|
82
|
-
* Reads the type through `util/field.util`'s own classifier, which the dialects already carry:
|
|
83
|
-
* resolving it through `schema/canonicalType` instead pulls that whole module into every consumer
|
|
84
|
-
* bundle.
|
|
85
|
-
*/
|
|
70
|
+
/** The mode a declared type asks for, {@link jsonCompareMode}'s twin: an index over a path is reached only by a comparison extracting it alike. */
|
|
86
71
|
export function jsonTypeMode(type) {
|
|
87
72
|
const family = columnFamily(type);
|
|
88
73
|
if (family === 'numeric') {
|
|
@@ -91,14 +76,8 @@ export function jsonTypeMode(type) {
|
|
|
91
76
|
return family === 'boolean' ? 'json' : 'text';
|
|
92
77
|
}
|
|
93
78
|
/**
|
|
94
|
-
* Whether the operator reads the JSON
|
|
95
|
-
*
|
|
96
|
-
* a way no cast recovers portably: PostgreSQL raises `operator does not exist: text = boolean`,
|
|
97
|
-
* MySQL compares `'true'` to `1` and silently matches nothing, and SQLite's `JSON_EXTRACT` yields
|
|
98
|
-
* `1`. Comparing the JSON value against a JSON-encoded parameter is exact on every dialect.
|
|
99
|
-
*
|
|
100
|
-
* Numbers stay on the text accessor with a numeric cast, which keeps `1` equal to `1.0` - JSON
|
|
101
|
-
* equality would not.
|
|
79
|
+
* Whether the operator reads the JSON value rather than its text: the array operators, and equality
|
|
80
|
+
* against a boolean, which no cast recovers portably from text.
|
|
102
81
|
*/
|
|
103
82
|
export function isJsonbOp(op, value) {
|
|
104
83
|
if (op === '$all' || op === '$size' || op === '$elemMatch') {
|
|
@@ -1,33 +1,15 @@
|
|
|
1
1
|
import type { QueryConflictPaths, QueryContext, QueryPager, Type } from '../type/index.js';
|
|
2
2
|
import { AbstractSqlDialect } from './abstractSqlDialect.js';
|
|
3
|
-
/**
|
|
4
|
-
* Shared SQL between SQL Server and Oracle: the two engines that spell paging and upsert the way the
|
|
5
|
-
* standard does, where the Postgres and MySQL families each predate it.
|
|
6
|
-
*
|
|
7
|
-
* A family base rather than a pair of knobs, the way {@link PgLikeSqlDialect} and
|
|
8
|
-
* {@link MysqlLikeSqlDialect} already are - `pager` and `upsert` are both plain overrides, so nothing
|
|
9
|
-
* in the core has to learn that a second spelling exists.
|
|
10
|
-
*/
|
|
3
|
+
/** What SQL Server and Oracle share: paging and upsert spelled as the standard does. */
|
|
11
4
|
export declare abstract class MergeSqlDialect extends AbstractSqlDialect {
|
|
12
5
|
readonly escapeIdChar = "\"";
|
|
13
|
-
/**
|
|
14
|
-
* `OFFSET ... ROWS FETCH NEXT ... ROWS ONLY`, and an `ORDER BY` where the statement has none.
|
|
15
|
-
*
|
|
16
|
-
* SQL Server refuses to page an unordered statement. A constant `ORDER BY` costs one clause the
|
|
17
|
-
* optimizer discards and keeps `$limit` and `$skip` meaning the same thing here as everywhere
|
|
18
|
-
* else; the alternative, `TOP (n)` in the select list, needs a second hook and still leaves a
|
|
19
|
-
* `$skip` with no `$sort` unanswerable.
|
|
20
|
-
*/
|
|
6
|
+
/** `OFFSET ... FETCH NEXT`, and a constant `ORDER BY` where there is none, since SQL Server refuses to page without one. */
|
|
21
7
|
pager(ctx: QueryContext, opts: QueryPager & {
|
|
22
8
|
$distinct?: boolean;
|
|
23
9
|
}, sorted?: boolean): void;
|
|
24
10
|
/**
|
|
25
|
-
* `MERGE`,
|
|
26
|
-
*
|
|
27
|
-
* {@link AbstractSqlDialect.insertShape} so both shapes apply `onInsert` defaults identically.
|
|
28
|
-
*
|
|
29
|
-
* Every value binds before the assignments are rendered, so a `?`-placeholder engine needs none of
|
|
30
|
-
* the scratch-context reordering `ON CONFLICT` does - the source is read positionally, in order.
|
|
11
|
+
* `MERGE`, its rows a `VALUES` source built by {@link AbstractSqlDialect.insertShape}. Every value binds
|
|
12
|
+
* before the assignments, so `?` placeholders read in order.
|
|
31
13
|
*/
|
|
32
14
|
upsert<E>(ctx: QueryContext, entity: Type<E>, conflictPaths: QueryConflictPaths<E>, payload: E | E[], extraReturning?: string): void;
|
|
33
15
|
/** `<target>.<col> = <source>.<col>` for every conflict key, which is what makes a row "the same". */
|
|
@@ -2,24 +2,10 @@ import { getMeta } from '../entity/index.js';
|
|
|
2
2
|
import { assertNonNegativeInteger, getKeys } from '../util/index.js';
|
|
3
3
|
import { AbstractSqlDialect } from './abstractSqlDialect.js';
|
|
4
4
|
import { UPSERT_SOURCE_ALIAS } from './aliases.js';
|
|
5
|
-
/**
|
|
6
|
-
* Shared SQL between SQL Server and Oracle: the two engines that spell paging and upsert the way the
|
|
7
|
-
* standard does, where the Postgres and MySQL families each predate it.
|
|
8
|
-
*
|
|
9
|
-
* A family base rather than a pair of knobs, the way {@link PgLikeSqlDialect} and
|
|
10
|
-
* {@link MysqlLikeSqlDialect} already are - `pager` and `upsert` are both plain overrides, so nothing
|
|
11
|
-
* in the core has to learn that a second spelling exists.
|
|
12
|
-
*/
|
|
5
|
+
/** What SQL Server and Oracle share: paging and upsert spelled as the standard does. */
|
|
13
6
|
export class MergeSqlDialect extends AbstractSqlDialect {
|
|
14
7
|
escapeIdChar = '"';
|
|
15
|
-
/**
|
|
16
|
-
* `OFFSET ... ROWS FETCH NEXT ... ROWS ONLY`, and an `ORDER BY` where the statement has none.
|
|
17
|
-
*
|
|
18
|
-
* SQL Server refuses to page an unordered statement. A constant `ORDER BY` costs one clause the
|
|
19
|
-
* optimizer discards and keeps `$limit` and `$skip` meaning the same thing here as everywhere
|
|
20
|
-
* else; the alternative, `TOP (n)` in the select list, needs a second hook and still leaves a
|
|
21
|
-
* `$skip` with no `$sort` unanswerable.
|
|
22
|
-
*/
|
|
8
|
+
/** `OFFSET ... FETCH NEXT`, and a constant `ORDER BY` where there is none, since SQL Server refuses to page without one. */
|
|
23
9
|
pager(ctx, opts, sorted = false) {
|
|
24
10
|
if (opts.$limit === undefined && opts.$skip === undefined) {
|
|
25
11
|
return;
|
|
@@ -35,12 +21,8 @@ export class MergeSqlDialect extends AbstractSqlDialect {
|
|
|
35
21
|
}
|
|
36
22
|
}
|
|
37
23
|
/**
|
|
38
|
-
* `MERGE`,
|
|
39
|
-
*
|
|
40
|
-
* {@link AbstractSqlDialect.insertShape} so both shapes apply `onInsert` defaults identically.
|
|
41
|
-
*
|
|
42
|
-
* Every value binds before the assignments are rendered, so a `?`-placeholder engine needs none of
|
|
43
|
-
* the scratch-context reordering `ON CONFLICT` does - the source is read positionally, in order.
|
|
24
|
+
* `MERGE`, its rows a `VALUES` source built by {@link AbstractSqlDialect.insertShape}. Every value binds
|
|
25
|
+
* before the assignments, so `?` placeholders read in order.
|
|
44
26
|
*/
|
|
45
27
|
upsert(ctx, entity, conflictPaths, payload, extraReturning = '') {
|
|
46
28
|
const meta = getMeta(entity);
|
|
@@ -1,18 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { EntityMeta, FieldOptions, InsertIdSource, Query, QueryConflictPaths, QueryContext, QueryOptions, QueryPager, QuerySizeComparisonOps, QueryTextSearchOptions, SqlDialectFeatures, Type } from '../type/index.js';
|
|
2
2
|
import { AbstractSqlDialect, type DerivedRelation, type RelationRows } from './abstractSqlDialect.js';
|
|
3
|
-
/**
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* Both dialects support the MySQL-compatible JSON functions/operators used by:
|
|
7
|
-
* - `$size` (JSON_LENGTH)
|
|
8
|
-
* - `$all` (JSON_CONTAINS)
|
|
9
|
-
* - `$elemMatch` (JSON_TABLE, or fast JSON_CONTAINS for the simple case)
|
|
10
|
-
* - the update operators `$set` (JSON_SET), `$unset` (JSON_REMOVE), `$push` (JSON_MERGE_PRESERVE)
|
|
11
|
-
* and `$pull` (JSON_REPLACE over JSON_TABLE)
|
|
12
|
-
*/
|
|
3
|
+
/** What the MySQL-family engines have. */
|
|
4
|
+
export declare const MYSQL_FEATURES: SqlDialectFeatures;
|
|
5
|
+
/** What MySQL and MariaDB share, their JSON functions above all: `JSON_LENGTH`, `JSON_CONTAINS`, `JSON_TABLE`, `JSON_SET`. */
|
|
13
6
|
export declare abstract class MysqlLikeSqlDialect extends AbstractSqlDialect {
|
|
14
|
-
|
|
15
|
-
protected readonly featureDefaults: DialectFeatures;
|
|
7
|
+
readonly features: SqlDialectFeatures;
|
|
16
8
|
/**
|
|
17
9
|
* `information_schema` keeps InnoDB's own row estimate, which is live enough to answer before
|
|
18
10
|
* anything has been analyzed. `DATABASE()` where the entity names no schema, so the estimate comes
|
|
@@ -21,13 +13,7 @@ export declare abstract class MysqlLikeSqlDialect extends AbstractSqlDialect {
|
|
|
21
13
|
estimatedCount<E>(ctx: QueryContext, entity: Type<E>): void;
|
|
22
14
|
/** `OFFSET` is only legal after a `LIMIT` here, so a bare `$skip` needs one. */
|
|
23
15
|
pager(ctx: QueryContext, opts: QueryPager): void;
|
|
24
|
-
/**
|
|
25
|
-
* Signed, though MySQL's own convention is `UNSIGNED`: a foreign key column takes its type from the
|
|
26
|
-
* key it points at, resolved through the *canonical* type, which has no way to know this string said
|
|
27
|
-
* `UNSIGNED`. The two then disagree and the engine refuses the constraint - the same trap knex hit
|
|
28
|
-
* (knex#6129) and MikroORM still carries (mikro-orm#5485). Signed is also the portable half: no
|
|
29
|
-
* other engine here has unsigned integers, so an `@Id` means one range everywhere.
|
|
30
|
-
*/
|
|
16
|
+
/** A signed key, so a foreign key taking its type from it matches, as MySQL refuses an `UNSIGNED` mismatch. */
|
|
31
17
|
readonly autoIncrementSuffix = "AUTO_INCREMENT";
|
|
32
18
|
readonly escapeIdChar = "`";
|
|
33
19
|
readonly tableOptions = "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4";
|
|
@@ -42,19 +28,11 @@ export declare abstract class MysqlLikeSqlDialect extends AbstractSqlDialect {
|
|
|
42
28
|
readonly booleanLiteral = "integer";
|
|
43
29
|
readonly insertIdSource: InsertIdSource;
|
|
44
30
|
/**
|
|
45
|
-
* `INSERT ... ON DUPLICATE KEY UPDATE`,
|
|
46
|
-
*
|
|
47
|
-
* unique index for you.
|
|
48
|
-
*
|
|
49
|
-
* The update assignments are built into their own context and pushed afterwards, since they read
|
|
50
|
-
* the inserted row rather than binding, and any value they *do* bind (an `onUpdate` field absent from
|
|
51
|
-
* the payload) has to land after the insert's for a `?`-placeholder driver.
|
|
31
|
+
* `INSERT ... ON DUPLICATE KEY UPDATE`, or `INSERT IGNORE` where there is nothing to assign. The
|
|
32
|
+
* assignments bind after the insert, where a `?` reads them.
|
|
52
33
|
*/
|
|
53
34
|
upsert<E>(ctx: QueryContext, entity: Type<E>, conflictPaths: QueryConflictPaths<E>, payload: E | E[]): void;
|
|
54
|
-
/**
|
|
55
|
-
* Appended to both branches above. Empty on MySQL, which has no `INSERT ... RETURNING`; MariaDB
|
|
56
|
-
* 10.5+ has it, and used to restate this whole method just to add it.
|
|
57
|
-
*/
|
|
35
|
+
/** Appended to both branches above: empty on MySQL, which has no `INSERT ... RETURNING`. */
|
|
58
36
|
protected upsertReturning<E>(_meta: EntityMeta<E>): string;
|
|
59
37
|
/**
|
|
60
38
|
* The alias the inserted row is given after the values list, and read back by the assignments.
|
|
@@ -132,12 +110,8 @@ export declare abstract class MysqlLikeSqlDialect extends AbstractSqlDialect {
|
|
|
132
110
|
protected jsonAll(ctx: QueryContext, jsonField: string, value: unknown): string;
|
|
133
111
|
protected jsonSize(ctx: QueryContext, jsonField: string, value: number | QuerySizeComparisonOps): string;
|
|
134
112
|
/**
|
|
135
|
-
* `JSON_TABLE`
|
|
136
|
-
*
|
|
137
|
-
* a compound (array/object) element as `NULL`, since MySQL doesn't coerce those to text; only a
|
|
138
|
-
* true scalar element survives that coercion. A nested `$elemMatch` (each element being an array
|
|
139
|
-
* that itself gets exploded) always requests `asJson`, so this is what makes that case reach the
|
|
140
|
-
* inner elements at all rather than finding nothing.
|
|
113
|
+
* `JSON_TABLE` with its columns declared up front. A scalar element reads as `JSON` where `asJson`,
|
|
114
|
+
* since `TEXT` reads a nested array as `NULL`.
|
|
141
115
|
*/
|
|
142
116
|
protected jsonElemFrom(jsonField: string, fields: readonly string[], alias: string, asJson?: boolean): string;
|
|
143
117
|
protected jsonElemRef(alias: string, field?: string, asJson?: boolean): string;
|
|
@@ -11,34 +11,36 @@ import { aggregatesRelations } from './queryJoins.js';
|
|
|
11
11
|
* and the largest `group_concat_max_len` either engine takes.
|
|
12
12
|
*/
|
|
13
13
|
const MAX_LIMIT = BigInt.asUintN(64, -1n);
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
14
|
+
/** What the MySQL-family engines have. */
|
|
15
|
+
export const MYSQL_FEATURES = {
|
|
16
|
+
ifNotExists: true,
|
|
17
|
+
indexIfNotExists: false,
|
|
18
|
+
schemas: true,
|
|
19
|
+
dropTableCascade: false,
|
|
20
|
+
foreignKeyAlter: true,
|
|
21
|
+
primaryKeyAlter: true,
|
|
22
|
+
generatedColumnAdd: true,
|
|
23
|
+
commentSyntax: 'inline',
|
|
24
|
+
vectorIndexRequiresNotNull: false,
|
|
25
|
+
vectorSupportsLength: false,
|
|
26
|
+
supportsTimestamptz: false,
|
|
27
|
+
stringSizing: 'varchar',
|
|
28
|
+
supportsUnsigned: true,
|
|
29
|
+
serverSideCursors: false,
|
|
30
|
+
rowLocks: true,
|
|
31
|
+
rowLockWithWindow: true,
|
|
32
|
+
rowLockOf: true,
|
|
33
|
+
orderedUpsertReturning: true,
|
|
34
|
+
orderedJsonAggregates: true,
|
|
35
|
+
partialJsonContainment: true,
|
|
36
|
+
typedJsonElements: false,
|
|
37
|
+
narrowVectorTypes: false,
|
|
38
|
+
vectorTuningNeedsTransaction: false,
|
|
39
|
+
serialDeclaresPrimaryKey: false,
|
|
40
|
+
};
|
|
41
|
+
/** What MySQL and MariaDB share, their JSON functions above all: `JSON_LENGTH`, `JSON_CONTAINS`, `JSON_TABLE`, `JSON_SET`. */
|
|
24
42
|
export class MysqlLikeSqlDialect extends AbstractSqlDialect {
|
|
25
|
-
|
|
26
|
-
featureDefaults = {
|
|
27
|
-
ifNotExists: true,
|
|
28
|
-
indexIfNotExists: false,
|
|
29
|
-
schemas: true,
|
|
30
|
-
dropTableCascade: false,
|
|
31
|
-
foreignKeyAlter: true,
|
|
32
|
-
primaryKeyAlter: true,
|
|
33
|
-
generatedColumnAdd: true,
|
|
34
|
-
commentSyntax: 'inline',
|
|
35
|
-
vectorIndexRequiresNotNull: false,
|
|
36
|
-
vectorSupportsLength: false,
|
|
37
|
-
supportsTimestamptz: false,
|
|
38
|
-
stringSizing: 'varchar',
|
|
39
|
-
supportsUnsigned: true,
|
|
40
|
-
serverSideCursors: false,
|
|
41
|
-
};
|
|
43
|
+
features = MYSQL_FEATURES;
|
|
42
44
|
/**
|
|
43
45
|
* `information_schema` keeps InnoDB's own row estimate, which is live enough to answer before
|
|
44
46
|
* anything has been analyzed. `DATABASE()` where the entity names no schema, so the estimate comes
|
|
@@ -64,13 +66,7 @@ export class MysqlLikeSqlDialect extends AbstractSqlDialect {
|
|
|
64
66
|
}
|
|
65
67
|
super.pager(ctx, opts);
|
|
66
68
|
}
|
|
67
|
-
/**
|
|
68
|
-
* Signed, though MySQL's own convention is `UNSIGNED`: a foreign key column takes its type from the
|
|
69
|
-
* key it points at, resolved through the *canonical* type, which has no way to know this string said
|
|
70
|
-
* `UNSIGNED`. The two then disagree and the engine refuses the constraint - the same trap knex hit
|
|
71
|
-
* (knex#6129) and MikroORM still carries (mikro-orm#5485). Signed is also the portable half: no
|
|
72
|
-
* other engine here has unsigned integers, so an `@Id` means one range everywhere.
|
|
73
|
-
*/
|
|
69
|
+
/** A signed key, so a foreign key taking its type from it matches, as MySQL refuses an `UNSIGNED` mismatch. */
|
|
74
70
|
autoIncrementSuffix = 'AUTO_INCREMENT';
|
|
75
71
|
escapeIdChar = '`';
|
|
76
72
|
tableOptions = 'ENGINE=InnoDB DEFAULT CHARSET=utf8mb4';
|
|
@@ -87,13 +83,8 @@ export class MysqlLikeSqlDialect extends AbstractSqlDialect {
|
|
|
87
83
|
// `innodb_autoinc_lock_mode` caveat on `buildUpdateResult` in `util/sql.util.ts`.
|
|
88
84
|
insertIdSource = 'firstId';
|
|
89
85
|
/**
|
|
90
|
-
* `INSERT ... ON DUPLICATE KEY UPDATE`,
|
|
91
|
-
*
|
|
92
|
-
* unique index for you.
|
|
93
|
-
*
|
|
94
|
-
* The update assignments are built into their own context and pushed afterwards, since they read
|
|
95
|
-
* the inserted row rather than binding, and any value they *do* bind (an `onUpdate` field absent from
|
|
96
|
-
* the payload) has to land after the insert's for a `?`-placeholder driver.
|
|
86
|
+
* `INSERT ... ON DUPLICATE KEY UPDATE`, or `INSERT IGNORE` where there is nothing to assign. The
|
|
87
|
+
* assignments bind after the insert, where a `?` reads them.
|
|
97
88
|
*/
|
|
98
89
|
upsert(ctx, entity, conflictPaths, payload) {
|
|
99
90
|
const meta = getMeta(entity);
|
|
@@ -113,10 +104,7 @@ export class MysqlLikeSqlDialect extends AbstractSqlDialect {
|
|
|
113
104
|
ctx.append(returning);
|
|
114
105
|
ctx.pushValue(...insertCtx.values);
|
|
115
106
|
}
|
|
116
|
-
/**
|
|
117
|
-
* Appended to both branches above. Empty on MySQL, which has no `INSERT ... RETURNING`; MariaDB
|
|
118
|
-
* 10.5+ has it, and used to restate this whole method just to add it.
|
|
119
|
-
*/
|
|
107
|
+
/** Appended to both branches above: empty on MySQL, which has no `INSERT ... RETURNING`. */
|
|
120
108
|
upsertReturning(_meta) {
|
|
121
109
|
return '';
|
|
122
110
|
}
|
|
@@ -250,12 +238,8 @@ export class MysqlLikeSqlDialect extends AbstractSqlDialect {
|
|
|
250
238
|
return this.buildFragment(ctx, (fragmentCtx) => this.buildSizeComparison(fragmentCtx, () => fragmentCtx.append(`JSON_LENGTH(${jsonField})`), value));
|
|
251
239
|
}
|
|
252
240
|
/**
|
|
253
|
-
* `JSON_TABLE`
|
|
254
|
-
*
|
|
255
|
-
* a compound (array/object) element as `NULL`, since MySQL doesn't coerce those to text; only a
|
|
256
|
-
* true scalar element survives that coercion. A nested `$elemMatch` (each element being an array
|
|
257
|
-
* that itself gets exploded) always requests `asJson`, so this is what makes that case reach the
|
|
258
|
-
* inner elements at all rather than finding nothing.
|
|
241
|
+
* `JSON_TABLE` with its columns declared up front. A scalar element reads as `JSON` where `asJson`,
|
|
242
|
+
* since `TEXT` reads a nested array as `NULL`.
|
|
259
243
|
*/
|
|
260
244
|
jsonElemFrom(jsonField, fields, alias, asJson = false) {
|
|
261
245
|
const columns = fields.length
|
|
@@ -1,27 +1,18 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type DriverCapabilities, type EntityMeta, type FieldOptions, type JsonColumnType, type Query, type QueryContext, type QuerySizeComparisonOps, type QueryTextSearchOptions, type SqlDialectFeatures, type Type } from '../type/index.js';
|
|
2
2
|
import type { DialectOptions } from './abstractDialect.js';
|
|
3
3
|
import { AbstractSqlDialect, type RelationRows } from './abstractSqlDialect.js';
|
|
4
4
|
/** A Postgres-wire dialect's options: the base's, and how its driver binds a parameter. */
|
|
5
5
|
export type PgLikeDialectOptions = DialectOptions & {
|
|
6
6
|
readonly driverCapabilities?: Partial<DriverCapabilities>;
|
|
7
7
|
};
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* and pgvector's `<=>`/`<->`/`<#>` distance operators, which CockroachDB implements natively).
|
|
12
|
-
* `xmax`-based upsert `created` detection is Postgres-only (CockroachDB has no `xmax`/`ctid`) and
|
|
13
|
-
* stays in {@link PostgresDialect}, along with the `vectorExtension`/`vectorIndexStyle` values that
|
|
14
|
-
* differ (Postgres needs `CREATE EXTENSION vector` and pgvector's `USING ivfflat/hnsw` index
|
|
15
|
-
* syntax; CockroachDB's vector type and `CREATE VECTOR INDEX` syntax are both native).
|
|
16
|
-
*/
|
|
8
|
+
/** What the Postgres-wire engines have. */
|
|
9
|
+
export declare const PG_FEATURES: SqlDialectFeatures;
|
|
10
|
+
/** What Postgres and CockroachDB share: JSONB, full-text search, pgvector's operators, and the upsert. */
|
|
17
11
|
export declare abstract class PgLikeSqlDialect extends AbstractSqlDialect {
|
|
18
12
|
/** How the driver binds a parameter: node-`pg`'s, unless the pool states its own. */
|
|
19
13
|
readonly driverCapabilities: DriverCapabilities;
|
|
20
14
|
constructor(options?: PgLikeDialectOptions);
|
|
21
|
-
|
|
22
|
-
readonly supportsWindowWithRowLock = false;
|
|
23
|
-
/** Default {@link DialectFeatures} for Postgres-wire dialects. */
|
|
24
|
-
protected readonly featureDefaults: DialectFeatures;
|
|
15
|
+
readonly features: SqlDialectFeatures;
|
|
25
16
|
readonly escapeIdChar = "\"";
|
|
26
17
|
readonly autoIncrementSuffix: string;
|
|
27
18
|
readonly tableOptions = "";
|
|
@@ -53,8 +44,6 @@ export declare abstract class PgLikeSqlDialect extends AbstractSqlDialect {
|
|
|
53
44
|
readonly op: string;
|
|
54
45
|
readonly opsSuffix: string;
|
|
55
46
|
}>;
|
|
56
|
-
/** `SET LOCAL` applies to the enclosing transaction and to nothing at all without one. */
|
|
57
|
-
readonly vectorTuningNeedsTransaction = true;
|
|
58
47
|
/**
|
|
59
48
|
* The GUC each pgvector index type reads for "how much of the index to explore". They are not the
|
|
60
49
|
* same quantity - `ef_search` is a candidate-list size, `probes` a count of lists - which is why
|
|
@@ -62,11 +51,8 @@ export declare abstract class PgLikeSqlDialect extends AbstractSqlDialect {
|
|
|
62
51
|
*/
|
|
63
52
|
private static readonly ANN_SETTINGS;
|
|
64
53
|
/**
|
|
65
|
-
* `SET LOCAL hnsw.ef_search = N`, plus `hnsw.iterative_scan`
|
|
66
|
-
* distance
|
|
67
|
-
* from it, so a `$near` can hand back fewer rows than qualify - the recall bug `$candidates`
|
|
68
|
-
* exists to answer. `strict_order`, never `relaxed_order`: the latter returns rows out of distance
|
|
69
|
-
* order, which would quietly contradict the `ORDER BY` the caller asked for.
|
|
54
|
+
* `SET LOCAL hnsw.ef_search = N`, plus `hnsw.iterative_scan = strict_order` where the query also filters
|
|
55
|
+
* by distance, which would otherwise drop rows the candidate list missed.
|
|
70
56
|
*/
|
|
71
57
|
vectorTuningStatements<E>(meta: EntityMeta<E>, q: Query<E>): readonly string[];
|
|
72
58
|
normalizeValue(value: unknown): unknown;
|
|
@@ -89,7 +75,7 @@ export declare abstract class PgLikeSqlDialect extends AbstractSqlDialect {
|
|
|
89
75
|
protected readonly caseInsensitiveMatch = "ilike";
|
|
90
76
|
protected get neOp(): string;
|
|
91
77
|
/** One array parameter, which a context that inlines values has none of: it lists them instead. */
|
|
92
|
-
protected formatIn(ctx: QueryContext, values: unknown[], negate: boolean): string;
|
|
78
|
+
protected formatIn(ctx: QueryContext, operand: string, values: unknown[], negate: boolean): string;
|
|
93
79
|
protected numericCast(expr: string): string;
|
|
94
80
|
protected appendJsonValue(ctx: QueryContext, value: unknown, type: JsonColumnType): void;
|
|
95
81
|
/**
|
|
@@ -7,15 +7,34 @@ import { BYTES_PREFIX } from './hydrateColumn.js';
|
|
|
7
7
|
import { jsonSetTarget } from './jsonSql.js';
|
|
8
8
|
import { PG_VECTOR_METRICS } from './pgVectorMetrics.js';
|
|
9
9
|
import { resolveVectorCast, toSparsevecLiteral } from './vectorCast.js';
|
|
10
|
-
/**
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
/** What the Postgres-wire engines have. */
|
|
11
|
+
export const PG_FEATURES = {
|
|
12
|
+
ifNotExists: true,
|
|
13
|
+
indexIfNotExists: true,
|
|
14
|
+
schemas: true,
|
|
15
|
+
dropTableCascade: true,
|
|
16
|
+
foreignKeyAlter: true,
|
|
17
|
+
primaryKeyAlter: true,
|
|
18
|
+
generatedColumnAdd: true,
|
|
19
|
+
commentSyntax: 'statement',
|
|
20
|
+
vectorIndexRequiresNotNull: false,
|
|
21
|
+
vectorSupportsLength: true,
|
|
22
|
+
supportsTimestamptz: true,
|
|
23
|
+
stringSizing: 'bounded-text',
|
|
24
|
+
supportsUnsigned: false,
|
|
25
|
+
serverSideCursors: true,
|
|
26
|
+
rowLocks: true,
|
|
27
|
+
rowLockWithWindow: false,
|
|
28
|
+
rowLockOf: true,
|
|
29
|
+
orderedUpsertReturning: true,
|
|
30
|
+
orderedJsonAggregates: true,
|
|
31
|
+
partialJsonContainment: true,
|
|
32
|
+
typedJsonElements: false,
|
|
33
|
+
narrowVectorTypes: false,
|
|
34
|
+
vectorTuningNeedsTransaction: true,
|
|
35
|
+
serialDeclaresPrimaryKey: false,
|
|
36
|
+
};
|
|
37
|
+
/** What Postgres and CockroachDB share: JSONB, full-text search, pgvector's operators, and the upsert. */
|
|
19
38
|
export class PgLikeSqlDialect extends AbstractSqlDialect {
|
|
20
39
|
/** How the driver binds a parameter: node-`pg`'s, unless the pool states its own. */
|
|
21
40
|
driverCapabilities;
|
|
@@ -23,25 +42,7 @@ export class PgLikeSqlDialect extends AbstractSqlDialect {
|
|
|
23
42
|
super(options);
|
|
24
43
|
this.driverCapabilities = { nativeArrays: true, explicitJsonCast: false, ...options.driverCapabilities };
|
|
25
44
|
}
|
|
26
|
-
|
|
27
|
-
supportsWindowWithRowLock = false;
|
|
28
|
-
/** Default {@link DialectFeatures} for Postgres-wire dialects. */
|
|
29
|
-
featureDefaults = {
|
|
30
|
-
ifNotExists: true,
|
|
31
|
-
indexIfNotExists: true,
|
|
32
|
-
schemas: true,
|
|
33
|
-
dropTableCascade: true,
|
|
34
|
-
foreignKeyAlter: true,
|
|
35
|
-
primaryKeyAlter: true,
|
|
36
|
-
generatedColumnAdd: true,
|
|
37
|
-
commentSyntax: 'statement',
|
|
38
|
-
vectorIndexRequiresNotNull: false,
|
|
39
|
-
vectorSupportsLength: true,
|
|
40
|
-
supportsTimestamptz: true,
|
|
41
|
-
stringSizing: 'bounded-text',
|
|
42
|
-
supportsUnsigned: false,
|
|
43
|
-
serverSideCursors: true,
|
|
44
|
-
};
|
|
45
|
+
features = PG_FEATURES;
|
|
45
46
|
escapeIdChar = '"';
|
|
46
47
|
// Shared default for both dialects. CockroachDB docs flag sequential PKs as a hotspotting risk
|
|
47
48
|
// under heavy concurrent insert load (writes concentrate on one range); this default still beats
|
|
@@ -80,8 +81,6 @@ export class PgLikeSqlDialect extends AbstractSqlDialect {
|
|
|
80
81
|
insertIdSource = 'returning';
|
|
81
82
|
maxBindValues = 65535;
|
|
82
83
|
vectorMetrics = PG_VECTOR_METRICS;
|
|
83
|
-
/** `SET LOCAL` applies to the enclosing transaction and to nothing at all without one. */
|
|
84
|
-
vectorTuningNeedsTransaction = true;
|
|
85
84
|
/**
|
|
86
85
|
* The GUC each pgvector index type reads for "how much of the index to explore". They are not the
|
|
87
86
|
* same quantity - `ef_search` is a candidate-list size, `probes` a count of lists - which is why
|
|
@@ -92,11 +91,8 @@ export class PgLikeSqlDialect extends AbstractSqlDialect {
|
|
|
92
91
|
['ivfflat', 'ivfflat.probes'],
|
|
93
92
|
]);
|
|
94
93
|
/**
|
|
95
|
-
* `SET LOCAL hnsw.ef_search = N`, plus `hnsw.iterative_scan`
|
|
96
|
-
* distance
|
|
97
|
-
* from it, so a `$near` can hand back fewer rows than qualify - the recall bug `$candidates`
|
|
98
|
-
* exists to answer. `strict_order`, never `relaxed_order`: the latter returns rows out of distance
|
|
99
|
-
* order, which would quietly contradict the `ORDER BY` the caller asked for.
|
|
94
|
+
* `SET LOCAL hnsw.ef_search = N`, plus `hnsw.iterative_scan = strict_order` where the query also filters
|
|
95
|
+
* by distance, which would otherwise drop rows the candidate list missed.
|
|
100
96
|
*/
|
|
101
97
|
vectorTuningStatements(meta, q) {
|
|
102
98
|
const indexType = this.tunedVectorIndex(meta, q)?.type;
|
|
@@ -162,11 +158,12 @@ export class PgLikeSqlDialect extends AbstractSqlDialect {
|
|
|
162
158
|
return 'IS DISTINCT FROM';
|
|
163
159
|
}
|
|
164
160
|
/** One array parameter, which a context that inlines values has none of: it lists them instead. */
|
|
165
|
-
formatIn(ctx, values, negate) {
|
|
166
|
-
if (values.length
|
|
167
|
-
return super.formatIn(ctx, values, negate);
|
|
161
|
+
formatIn(ctx, operand, values, negate) {
|
|
162
|
+
if (!values.length || ctx.inlineValues) {
|
|
163
|
+
return super.formatIn(ctx, operand, values, negate);
|
|
164
|
+
}
|
|
168
165
|
const ph = this.addValue(ctx, values);
|
|
169
|
-
return negate ?
|
|
166
|
+
return negate ? `${operand} <> ALL(${ph})` : `${operand} = ANY(${ph})`;
|
|
170
167
|
}
|
|
171
168
|
numericCast(expr) {
|
|
172
169
|
return `(${expr})::numeric`;
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import type { QueryContext, SqlQueryDialect } from '../type/index.js';
|
|
2
|
-
/**
|
|
3
|
-
* SqlQueryContext is an implementation of the QueryContext interface specifically for SQL-based dialects.
|
|
4
|
-
* It follows the "Accumulator" or "Builder" pattern to construct SQL queries and their corresponding parameters.
|
|
5
|
-
*
|
|
6
|
-
* This pattern solves the problem of building complex SQL strings while safely managing parameterized values,
|
|
7
|
-
* preventing SQL injection and handling dialect-specific parameter placeholders (e.g., '?' for MySQL, '$n' for PostgreSQL).
|
|
8
|
-
*/
|
|
2
|
+
/** A SQL statement being built: its text, and the values it binds, placeholders numbered by the dialect. */
|
|
9
3
|
export declare class SqlQueryContext implements QueryContext {
|
|
10
4
|
readonly dialect: SqlQueryDialect;
|
|
11
5
|
private readonly statement?;
|
|
@@ -14,14 +8,8 @@ export declare class SqlQueryContext implements QueryContext {
|
|
|
14
8
|
private readonly params;
|
|
15
9
|
private readonly tableAliases;
|
|
16
10
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* fragment context built via {@link AbstractSqlDialect.buildFragment}, so a bound value's
|
|
20
|
-
* placeholder is numbered correctly against the real query from the moment it's added, rather
|
|
21
|
-
* than needing to be reconciled after the fact.
|
|
22
|
-
* @param statement The context this one renders a fragment of, which owns the claimed aliases: a
|
|
23
|
-
* fragment is part of one statement, so its aliases have to be unique across the whole of it.
|
|
24
|
-
* @param inlineValues See {@link QueryContext.inlineValues}; a fragment takes its statement's.
|
|
11
|
+
* `params` and `statement` are a fragment's parent's, so a value numbers against the whole statement and
|
|
12
|
+
* an alias is unique across it; a fragment inlines values where its statement does.
|
|
25
13
|
*/
|
|
26
14
|
constructor(dialect: SqlQueryDialect, params?: unknown[], statement?: SqlQueryContext | undefined, inlineValues?: boolean);
|
|
27
15
|
createFragment(): QueryContext;
|
|
@@ -37,13 +25,7 @@ export declare class SqlQueryContext implements QueryContext {
|
|
|
37
25
|
* where this context inlines values.
|
|
38
26
|
*/
|
|
39
27
|
addValue(value: unknown): this;
|
|
40
|
-
/**
|
|
41
|
-
* Pushes values to the parameters list without appending placeholders to the SQL.
|
|
42
|
-
* This is useful when the placeholder is already present in the SQL string or handled elsewhere.
|
|
43
|
-
*
|
|
44
|
-
* @param values The values to be added to the parameters.
|
|
45
|
-
* @returns The current context instance for method chaining.
|
|
46
|
-
*/
|
|
28
|
+
/** Binds values whose placeholders the SQL already carries. */
|
|
47
29
|
pushValue(...values: unknown[]): this;
|
|
48
30
|
claimAlias(name: string, parent?: string): string;
|
|
49
31
|
/**
|