uql-orm 0.56.0 → 0.57.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.
Files changed (89) hide show
  1. package/README.md +1 -1
  2. package/dist/browser/uql-browser.min.js +2 -2
  3. package/dist/browser/uql-browser.min.js.map +4 -4
  4. package/dist/cockroachdb/cockroachDialect.d.ts +5 -2
  5. package/dist/cockroachdb/cockroachDialect.js +2 -10
  6. package/dist/d1/d1SqliteDialect.d.ts +1 -0
  7. package/dist/d1/d1SqliteDialect.js +2 -0
  8. package/dist/dialect/abstractSqlDialect.d.ts +195 -32
  9. package/dist/dialect/abstractSqlDialect.js +406 -199
  10. package/dist/dialect/aliases.d.ts +10 -7
  11. package/dist/dialect/aliases.js +12 -7
  12. package/dist/dialect/hydrateColumn.d.ts +8 -2
  13. package/dist/dialect/hydrateColumn.js +33 -1
  14. package/dist/dialect/jsonSql.d.ts +13 -5
  15. package/dist/dialect/jsonSql.js +24 -7
  16. package/dist/dialect/mysqlLikeSqlDialect.d.ts +30 -2
  17. package/dist/dialect/mysqlLikeSqlDialect.js +56 -4
  18. package/dist/dialect/pgLikeSqlDialect.d.ts +20 -20
  19. package/dist/dialect/pgLikeSqlDialect.js +23 -48
  20. package/dist/dialect/pgVectorMetrics.d.ts +13 -0
  21. package/dist/dialect/pgVectorMetrics.js +17 -0
  22. package/dist/dialect/queryContext.d.ts +3 -7
  23. package/dist/dialect/queryContext.js +13 -8
  24. package/dist/dialect/queryJoins.d.ts +8 -4
  25. package/dist/dialect/queryJoins.js +25 -11
  26. package/dist/dialect/vectorSqlDialect.d.ts +2 -2
  27. package/dist/dialect/vectorSqlDialect.js +2 -3
  28. package/dist/entity/metadata/definition.js +3 -3
  29. package/dist/maria/mariaDialect.d.ts +13 -6
  30. package/dist/maria/mariaDialect.js +29 -9
  31. package/dist/migrate/cli.d.ts +2 -3
  32. package/dist/migrate/cli.js +2 -2
  33. package/dist/migrate/ddl/index.d.ts +1 -5
  34. package/dist/migrate/ddl/index.js +14 -25
  35. package/dist/migrate/ddl/indexDdl.d.ts +11 -2
  36. package/dist/migrate/ddl/indexDdl.js +17 -1
  37. package/dist/migrate/ddl/mssqlIndexDdl.d.ts +10 -0
  38. package/dist/migrate/ddl/mssqlIndexDdl.js +10 -0
  39. package/dist/migrate/ddl/mysqlIndexDdl.d.ts +10 -17
  40. package/dist/migrate/ddl/mysqlIndexDdl.js +16 -27
  41. package/dist/migrate/ddl/pgIndexDdl.d.ts +18 -8
  42. package/dist/migrate/ddl/pgIndexDdl.js +29 -12
  43. package/dist/migrate/migrator.d.ts +2 -2
  44. package/dist/migrate/schemaGenerator.d.ts +3 -3
  45. package/dist/migrate/schemaGenerator.js +5 -7
  46. package/dist/migrate/schemaGeneratorAsync.d.ts +2 -3
  47. package/dist/mongo/mongoDialect.d.ts +30 -17
  48. package/dist/mongo/mongoDialect.js +143 -101
  49. package/dist/mongo/mongodbQuerier.d.ts +10 -17
  50. package/dist/mongo/mongodbQuerier.js +31 -105
  51. package/dist/mssql/mssqlDialect.d.ts +16 -0
  52. package/dist/mssql/mssqlDialect.js +26 -4
  53. package/dist/mysql/mysqlDialect.d.ts +2 -0
  54. package/dist/mysql/mysqlDialect.js +4 -0
  55. package/dist/querier/abstractQuerier.d.ts +20 -36
  56. package/dist/querier/abstractQuerier.js +35 -129
  57. package/dist/querier/abstractQuerierPool.d.ts +2 -2
  58. package/dist/querier/abstractSqlQuerier.d.ts +4 -17
  59. package/dist/querier/abstractSqlQuerier.js +34 -44
  60. package/dist/schema/canonicalType.js +4 -4
  61. package/dist/schema/indexDifferences.js +4 -4
  62. package/dist/schema/schemaASTBuilder.js +31 -2
  63. package/dist/schema/schemaASTDiffer.js +5 -5
  64. package/dist/sqlite/sqliteDialect.d.ts +20 -1
  65. package/dist/sqlite/sqliteDialect.js +38 -7
  66. package/dist/turso/tursoDialect.d.ts +2 -0
  67. package/dist/turso/tursoDialect.js +2 -0
  68. package/dist/type/config.d.ts +2 -2
  69. package/dist/type/dialect.d.ts +4 -5
  70. package/dist/type/entity.d.ts +2 -1
  71. package/dist/type/migratorDialect.d.ts +4 -0
  72. package/dist/type/querier.d.ts +6 -6
  73. package/dist/type/query.d.ts +25 -48
  74. package/dist/type/query.js +10 -5
  75. package/dist/type/queryAggregate.d.ts +10 -10
  76. package/dist/type/queryAggregate.js +1 -1
  77. package/dist/type/universalQuerier.d.ts +4 -4
  78. package/dist/util/dialect.util.d.ts +1 -1
  79. package/dist/util/field.util.d.ts +5 -0
  80. package/dist/util/field.util.js +19 -0
  81. package/dist/util/object.util.d.ts +2 -0
  82. package/dist/util/object.util.js +4 -0
  83. package/dist/util/relationQuery.util.d.ts +12 -65
  84. package/dist/util/relationQuery.util.js +27 -81
  85. package/dist/util/rowKey.util.d.ts +1 -11
  86. package/dist/util/rowKey.util.js +1 -13
  87. package/package.json +1 -1
  88. package/dist/querier/relationCount.d.ts +0 -16
  89. package/dist/querier/relationCount.js +0 -121
@@ -1,5 +1,5 @@
1
- import { type EntityData, type EntityMeta, type FieldKey, type FieldOptions, type IsolationLevel, type JsonColumnType, type JsonUpdateOp, type Query, type QueryAggMap, type QueryAggregate, type QueryBuildFn, type QueryComparisonOptions, type QueryConflictPaths, type QueryContext, type QueryDialect, type QueryExclude, type QueryFilter, type QueryGroupMap, type QueryGroupOp, type QueryHavingMap, type QueryOptions, type QueryPager, QueryRaw, type QueryRawFnOptions, type QuerySearch, type QuerySelectOptions, type QuerySelectValue, type QuerySizeComparisonOps, type QuerySortMap, type QueryTextSearchOptions, type QueryVectorNear, type QueryWhere, type QueryWhereArray, type QueryWhereFieldOperatorMap, type QueryWhereOptions, type RelationMeta, type SqlDialectName, type SqlQueryDialect, type Type, type UpdatePayload } from '../type/index.js';
2
- import { type ParentPartition } from '../util/index.js';
1
+ import { type EntityData, type EntityMeta, type FieldKey, type FieldOptions, type IsolationLevel, type JsonColumnType, type JsonUpdateOp, type Query, type QueryAggMap, type QueryAggregate, type QueryBuildFn, type QueryComparisonOptions, type QueryConflictPaths, type QueryContext, type QueryDialect, type QueryExclude, type QueryFilter, type QueryGroupMap, type QueryGroupOp, type QueryHavingMap, type QueryOptions, type QueryPager, QueryRaw, type QueryRawFnOptions, type QuerySearch, type QuerySelectValue, type QuerySizeComparisonOps, type QuerySortMap, type QueryTextSearchOptions, type QueryVectorNear, type QueryWhere, type QueryWhereArray, type QueryWhereFieldOperatorMap, type QueryWhereOptions, type RelationMeta, type SqlDialectName, type SqlQueryDialect, type Type, type UpdatePayload } from '../type/index.js';
2
+ import { type ColumnFamily } from '../util/field.util.js';
3
3
  import type { HydrateKind } from './hydrateColumn.js';
4
4
  import { type JsonAccessMode } from './jsonSql.js';
5
5
  import { type QueryJoins, type QuerySortOptions } from './queryJoins.js';
@@ -17,6 +17,68 @@ type InsertShape<E> = {
17
17
  };
18
18
  /** One entry of {@link AbstractSqlDialect.hydratableFields}: a field key and how it decodes. */
19
19
  type HydratableField = readonly [string, HydrateKind];
20
+ /** A sort term of a relation's rows as their aggregate orders by it: the column carrying it out. */
21
+ export type SortRef = {
22
+ readonly ref: string;
23
+ readonly direction: string;
24
+ };
25
+ /**
26
+ * One column of a read's projection: the key its row answers under, none for a raw expression written
27
+ * without an alias, and whether `sql` already answers under it, being a column of that very name.
28
+ */
29
+ export type SelectTerm = {
30
+ readonly sql: string;
31
+ readonly key?: string;
32
+ readonly bare?: boolean;
33
+ };
34
+ /** What a read selected, and for a relation's rows, the columns carrying their sort terms out. */
35
+ export type ReadProjection = {
36
+ readonly terms: readonly SelectTerm[];
37
+ readonly order?: readonly SortRef[];
38
+ };
39
+ /**
40
+ * A read's options as its statement takes them: the caller's and the alias its table reads as. A
41
+ * relation's rows read inside the parent's statement cross JSON, and where their aggregate orders them,
42
+ * carry their sort terms out as columns.
43
+ */
44
+ type ReadOptions = QueryOptions & {
45
+ readonly alias?: string;
46
+ readonly json?: boolean;
47
+ readonly carried?: boolean;
48
+ };
49
+ /**
50
+ * A projection's options: the alias its columns are qualified by, whether its values cross JSON, and
51
+ * whether it is a joined row's, which keeps its id.
52
+ */
53
+ type SelectOptions = {
54
+ readonly prefix?: string;
55
+ readonly json?: boolean;
56
+ readonly joined?: boolean;
57
+ };
58
+ /** A to-many's rows as the parent's statement reads them: an ordinary read of the related entity. */
59
+ export type RelationRows = {
60
+ readonly entity: Type<object>;
61
+ readonly query: Query<object>;
62
+ readonly alias: string;
63
+ readonly joins: QueryJoins;
64
+ /** Whether the parent deduplicates its rows, which compares this value with the rest. */
65
+ readonly distinct: boolean;
66
+ };
67
+ /**
68
+ * A relation's rows as a derived table: `from` is the table clause, `pairs` each key of a row with the
69
+ * column holding it, and `order` what their aggregate orders them by.
70
+ */
71
+ export type DerivedRelation = {
72
+ readonly from: string;
73
+ readonly pairs: readonly (readonly [key: string, sql: string])[];
74
+ readonly order: string;
75
+ };
76
+ /** How each column family's value is spelled to cross JSON: see {@link AbstractSqlDialect.carriedFields}. */
77
+ export type CarriedFields = {
78
+ readonly [F in ColumnFamily]?: (expr: string, field: FieldOptions) => string;
79
+ };
80
+ /** The key a term answers under in a populated relation's row, which a raw expression has only once aliased. */
81
+ export declare function relationTermKey({ sql, key }: SelectTerm): string;
20
82
  export type { HydrateKind };
21
83
  export declare abstract class AbstractSqlDialect extends VectorSqlDialect implements QueryDialect, SqlQueryDialect {
22
84
  abstract readonly dialectName: SqlDialectName;
@@ -60,19 +122,12 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
60
122
  * `insertMany` splits larger batches into multiple statements based on this limit.
61
123
  */
62
124
  readonly maxBindValues: number;
63
- getBeginTransactionStatements(isolationLevel?: IsolationLevel): string[];
64
125
  /**
65
- * Every parent's own bounded page in one statement: a subquery per parent, each filtered to that
66
- * parent alone and carrying its own `ORDER BY`, `LIMIT` and `OFFSET`. Universal, and reads
67
- * `parents x (skip + limit)` rows where a `ROW_NUMBER` window reads every matching child.
68
- * [The design](../../../../architecture/populate-limits.md).
69
- *
70
- * Each branch is a wrapped derived table rather than a bare parenthesised select: SQLite rejects
71
- * `ORDER BY`/`LIMIT` on the latter, and the wrapper costs nothing elsewhere.
126
+ * The most arguments one SQL function call takes. A variadic call past it, a wide relation row or JSON
127
+ * update, is spread over nested calls. No cap binds unless a dialect declares one.
72
128
  */
73
- findPerParent<E extends object>(ctx: QueryContext, entity: Type<E>, q: Query<E>, partition: ParentPartition): void;
74
- /** The shape {@link findPerParent} emits, which the Postgres family replaces with a `LATERAL` join. */
75
- protected appendPerParent<E extends object>(ctx: QueryContext, entity: Type<E>, q: Query<E>, { joins, parents }: ParentPartition): void;
129
+ readonly maxFunctionArgs: number;
130
+ getBeginTransactionStatements(isolationLevel?: IsolationLevel): string[];
76
131
  createContext(): QueryContext;
77
132
  /**
78
133
  * Builds SQL text in isolation via `build`, so the caller can embed it inline (e.g.
@@ -118,16 +173,32 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
118
173
  returningId<E>(meta: EntityMeta<E>): string;
119
174
  /** `<id column> AS id` on its own, for a statement composing a `RETURNING` list of several items. */
120
175
  protected returningIdExpression<E>(meta: EntityMeta<E>): string;
121
- search<E>(ctx: QueryContext, entity: Type<E>, q?: Query<E>, opts?: QueryOptions, joins?: QueryJoins): void;
122
- selectFields<E>(ctx: QueryContext, entity: Type<E>, select: QuerySelectValue<E> | undefined, opts?: QuerySelectOptions, exclude?: QueryExclude<E>): void;
176
+ search<E>(ctx: QueryContext, entity: Type<E>, q?: Query<E>, opts?: ReadOptions, joins?: QueryJoins, order?: readonly SortRef[]): void;
177
+ /**
178
+ * A relation's rows ordered by the columns their sort terms were carried out in, where they are
179
+ * paged: otherwise the aggregate reading them orders them, and sorting them first is wasted work.
180
+ */
181
+ private orderCarried;
182
+ /**
183
+ * The columns a projection reads: each field under its key, a raw expression under its alias, and
184
+ * `*` where nothing is left, or every field in a row crossing JSON, which answers only under keys. A
185
+ * joined row keeps its key, every column of a composite past any subtraction: it is what tells a
186
+ * matched row from no match.
187
+ */
188
+ selectTerms<E>(ctx: QueryContext, entity: Type<E>, select: QuerySelectValue<E> | undefined, opts?: SelectOptions, exclude?: QueryExclude<E>): SelectTerm[];
189
+ /** One field's column, or the expression an inlined one stands for, as the projection reads it. */
190
+ private fieldTerm;
191
+ /** A `raw()` rendered where it stands, without the alias a projection writes for it. */
192
+ private rawSql;
123
193
  /**
124
194
  * What follows `SELECT` before the projection. Empty everywhere but SQL Server, whose `FETCH` will
125
195
  * not take a zero and which spells "no rows" as `TOP (0)` instead.
126
196
  */
127
197
  protected selectModifier<E>(_q: Query<E>): string;
128
198
  /**
129
- * The expression a scalar field is read through, the plain column by default. MariaDB reads a
130
- * vector column back with `VEC_ToText`, since selecting it raw yields its binary form.
199
+ * The expression a scalar field is read through in the statement's own rows, the plain column by
200
+ * default. MariaDB reads a vector column back with `VEC_ToText`, since selecting it raw yields its
201
+ * binary form. A related row's column crosses JSON through {@link carriedFields} instead.
131
202
  */
132
203
  protected selectFieldExpr(escapedColumn: string, _field: FieldOptions): string;
133
204
  /**
@@ -137,24 +208,43 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
137
208
  * than inheriting another engine's syntax.
138
209
  */
139
210
  protected appendTextSearch<E>(_ctx: QueryContext, _entity: Type<E>, _meta: EntityMeta<E>, _search: QueryTextSearchOptions<E>): void;
140
- select<E>(ctx: QueryContext, entity: Type<E>, q: Query<E>, opts?: QueryOptions, joins?: QueryJoins, totalAlias?: string): void;
211
+ select<E>(ctx: QueryContext, entity: Type<E>, q: Query<E>, opts?: ReadOptions, joins?: QueryJoins, totalAlias?: string): ReadProjection;
212
+ /**
213
+ * Everything a read's rows answer under, in order: its own fields, each joined row's fields and to-many
214
+ * relations under its path, its own to-many relations and `$count`, and each vector distance a `$sort`
215
+ * projects.
216
+ */
217
+ protected projection<E>(ctx: QueryContext, entity: Type<E>, q: Query<E>, opts: SelectOptions, joins: QueryJoins): SelectTerm[];
218
+ /** A term as a projection writes it, aliased unless its SQL already answers under its key. */
219
+ private termSql;
220
+ /** The distance each vector `$sort` projects, under the name it asked for. */
221
+ private selectVectorProjections;
222
+ /**
223
+ * A relation's sort terms carried out beside its rows as columns, for the aggregate reading them to
224
+ * order by: a term that names a column of theirs already is ordered by that one.
225
+ */
226
+ private carrySort;
141
227
  /**
142
228
  * The table as a statement writes it, each part escaped on its own rather than as one dotted
143
229
  * string taken apart again by {@link escapeId}.
144
230
  */
145
231
  protected escapedTableName<E>(meta: EntityMeta<E>): string;
146
232
  /**
147
- * A FROM or JOIN operand plus the alias to prefix its columns by, aliased only once a schema puts
148
- * something in front of the name. See {@link resolveTableAlias} for why the prefix cannot be the
149
- * qualified path.
233
+ * A FROM or JOIN operand plus the alias to prefix its columns by, aliased once a schema puts something
234
+ * in front of the name, or the read takes an alias of its own. See {@link resolveTableAlias} for why
235
+ * the prefix cannot be the qualified path.
150
236
  */
151
- protected tableRef<E>(meta: EntityMeta<E>): {
237
+ protected tableRef<E>(meta: EntityMeta<E>, alias?: string): {
152
238
  alias: string;
153
239
  ref: string;
154
240
  };
155
- /** Columns are alias-qualified once anything else is in play: a join, or a to-many being filled. */
241
+ /**
242
+ * Columns are qualified once anything else is in play: an alias of the read's own, a join, or a
243
+ * relation being read.
244
+ */
156
245
  private resolveRelationAwarePrefix;
157
- protected selectRelationFields(ctx: QueryContext, joins: QueryJoins): void;
246
+ /** Each joined row's columns and to-many relations under its path, which is what unflattens it. */
247
+ protected selectJoinedRows(ctx: QueryContext, joins: QueryJoins, json: boolean | undefined, distinct: boolean): SelectTerm[];
158
248
  protected selectRelationJoins<E>(ctx: QueryContext, meta: EntityMeta<E>, rootAlias: string, joins: QueryJoins): void;
159
249
  where<E>(ctx: QueryContext, entity: Type<E>, where?: QueryWhere<E>, opts?: QueryWhereOptions): void;
160
250
  /** Renders a `$where` tree without applying entity filters (used for same-scope group-operator recursion). */
@@ -245,7 +335,7 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
245
335
  protected abstract jsonSize(ctx: QueryContext, jsonField: string, value: number | QuerySizeComparisonOps): string;
246
336
  /**
247
337
  * Explodes the JSON array at `jsonField` into rows, as the `FROM` of an `EXISTS` subquery, under
248
- * `alias` (from {@link QueryContext.nextAlias} - a fresh name per call, since `$elemMatch`/`$all`
338
+ * `alias` (from {@link QueryContext.claimAlias} - a fresh name per call, since `$elemMatch`/`$all`
249
339
  * can recurse into this on a nested array and a fixed, reused alias would let the inner occurrence
250
340
  * shadow the outer one it needs to correlate against). An empty `fields` means the elements are
251
341
  * scalars, in which case `asJson` says whether they are read as JSON or as text; otherwise they
@@ -297,6 +387,11 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
297
387
  /** Appends the `ORDER BY`, reporting whether there was one - which {@link pager} needs on the
298
388
  * engines that refuse to page an unordered statement. */
299
389
  sort<E>(ctx: QueryContext, entity: Type<E>, sort: QuerySortMap<E> | undefined, opts?: QuerySortOptions): boolean;
390
+ /**
391
+ * The terms of an `ORDER BY`, collected before anything is appended so an unorderable key is reported
392
+ * instead of half a clause, and because a vector distance is the primary ordering wherever it appears.
393
+ */
394
+ private sortTerms;
300
395
  /**
301
396
  * Walks `$sort` against the metadata of the entity each level addresses, rather than flattening it
302
397
  * to dotted strings and reading every key off the root: only that way does a related column resolve
@@ -337,7 +432,7 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
337
432
  * joined: Postgres refuses a bare `FOR UPDATE` over the nullable side of an outer join outright,
338
433
  * and the other engines quietly widen the lock to the joined rows.
339
434
  */
340
- protected appendLock<E>(ctx: QueryContext, entity: Type<E>, q: Query<E>, joins?: QueryJoins): void;
435
+ protected appendLock<E>(ctx: QueryContext, entity: Type<E>, q: Query<E>, joins?: QueryJoins, alias?: string): void;
341
436
  count<E>(ctx: QueryContext, entity: Type<E>, q: QueryFilter<E>, opts?: QueryOptions): void;
342
437
  /**
343
438
  * How many rows a `$distinct` read returns, which `COUNT(*)` cannot answer: the deduplication
@@ -377,6 +472,16 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
377
472
  */
378
473
  protected readonly totalOverExpr = "COUNT(*) OVER ()";
379
474
  find<E>(ctx: QueryContext, entity: Type<E>, q?: Query<E>, opts?: QueryOptions, totalAlias?: string): void;
475
+ /**
476
+ * A read's whole statement. The lock is appended here rather than in `search`, which `count`,
477
+ * `update` and `delete` share: it belongs to a SELECT alone, and every engine spells it last.
478
+ */
479
+ protected read<E>(ctx: QueryContext, entity: Type<E>, q: Query<E>, opts: ReadOptions, joins: QueryJoins, totalAlias?: string): ReadProjection;
480
+ /**
481
+ * `opts` with the alias the read's table claims: its own name, which needs no alias written, unless
482
+ * another table of the statement took it first.
483
+ */
484
+ private readOptions;
380
485
  insert<E>(ctx: QueryContext, entity: Type<E>, payload: E | E[], opts?: QueryOptions): void;
381
486
  /**
382
487
  * Where the clause reporting an insert's generated ids goes. `suffix` is `RETURNING ...` at the end
@@ -499,7 +604,8 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
499
604
  */
500
605
  hydratableAggregates<E, G extends QueryGroupMap<E>, A extends QueryAggMap<E>>(entity: Type<E>, q: QueryAggregate<E, G, A>): readonly HydratableField[];
501
606
  /**
502
- * The mirror of {@link persistKind}: what one column decodes as, or nothing if it needs no decode.
607
+ * The mirror of {@link persistKind}: what one column decodes as, or nothing if it needs no decode. A
608
+ * date and bytes decode because a related row crosses JSON, which spells both as text.
503
609
  *
504
610
  * `BigInt` is asked first because it shares the numeric family with `Number`: let the switch answer
505
611
  * it and every `type: BigInt` property silently decodes to a JS number again.
@@ -545,7 +651,6 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
545
651
  protected abstract jsonUnset(ctx: QueryContext, expr: string, unset: readonly string[]): string;
546
652
  getRawValue(ctx: QueryContext, opts: QueryRawFnOptions & {
547
653
  value: QueryRaw;
548
- autoPrefixAlias?: boolean;
549
654
  }): void;
550
655
  /**
551
656
  * Resolves a dot-notation key to its JSON field metadata.
@@ -591,8 +696,6 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
591
696
  private escapedColumnOf;
592
697
  private escapedColumnName;
593
698
  private escapedColumn;
594
- /** As {@link escapedColumn}, but qualified by the query alias when the parent is nested. */
595
- private escapedParentColumn;
596
699
  /**
597
700
  * The single path from a relation operator to its target, so none can emit an unscoped subquery:
598
701
  * the target's `$where` is merged with its active filters, making a trashed or out-of-scope row
@@ -600,10 +703,70 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
600
703
  * not propagated (`withDeleted()` does not reach into relations), matching `selectRelationJoins`.
601
704
  */
602
705
  private appendRelationSubquery;
706
+ /**
707
+ * One equality per key of the parent, anded: a composite correlates on every column, and matching on
708
+ * part of one would find the rows of a different parent. `parentJoins` keeps the two ends the right
709
+ * way round, whether the join lands on the junction or on the target.
710
+ */
711
+ private correlation;
712
+ /**
713
+ * Each to-many a row populates, as a subquery of the statement's select list correlated to `parent`,
714
+ * the row's alias. [The design](../../../../architecture/relations-in-one-statement.md).
715
+ */
716
+ private selectToManyRelations;
717
+ /** Each relation a read's `$count` tallies, as a correlated count of its select list. */
718
+ private selectRelationCounts;
719
+ /**
720
+ * A to-many's rows as one JSON array: an ordinary read of the related entity under the relation's
721
+ * name, narrowed to the parent's rows, in the engine's own spelling.
722
+ */
723
+ private appendToManyRelation;
724
+ /**
725
+ * A relation that deduplicates its rows is sorted only by what it selects: `SELECT DISTINCT` orders by
726
+ * nothing else, and a column carrying a sort term out would join the set it deduplicates on.
727
+ */
728
+ private assertDistinctSort;
729
+ /**
730
+ * What makes a relation's row one of the parent's: its foreign key on the parent's key, or, through a
731
+ * junction, a pairing of the two that the junction's own filters let through.
732
+ */
733
+ private appendCorrelation;
734
+ /**
735
+ * A junction's rows pairing the parent with the relation's targets, as far as its own filters let them
736
+ * through, since a soft-deleted link is not a link; and the column naming each row's target.
737
+ */
738
+ private junctionRows;
739
+ /**
740
+ * A relation's rows as one JSON array, in the engine's own spelling: an aggregate over them read as
741
+ * a derived table ({@link derivedRelation}), or over the related table itself where the engine cannot
742
+ * correlate a derived table. [The design](../../../../architecture/relations-in-one-statement.md).
743
+ */
744
+ protected abstract appendRelationArray(ctx: QueryContext, rows: RelationRows): void;
745
+ /**
746
+ * Whether the engine's JSON aggregate takes an `ORDER BY` of its own. Where it does not, a relation's
747
+ * rows carry no sort term out and keep their own order, which a derived table hands its aggregate.
748
+ */
749
+ protected readonly orderedAggregates: boolean;
750
+ /**
751
+ * The rows read as a derived table, their values crossing JSON and, where the aggregate orders, each
752
+ * sort term carried out beside them for it to order by, since a derived table's order is not promised
753
+ * past it. The table takes the relation's name, which nothing inside it can see.
754
+ */
755
+ protected derivedRelation(ctx: QueryContext, rows: RelationRows): DerivedRelation;
756
+ /**
757
+ * How each column family crosses JSON inside its parent's statement, where JSON would round it or
758
+ * cannot spell it: as text, which the field's hydrate kind decodes back, and bytes as `\x` and hex,
759
+ * the `BYTES_PREFIX`. A family missing here crosses as it is.
760
+ */
761
+ protected readonly carriedFields: CarriedFields;
762
+ /** `expr` as it crosses JSON, by its field's family: see {@link carriedFields}. */
763
+ private carried;
764
+ /** `'key', column, ...`: the arguments of a JSON object call over `pairs`. */
765
+ protected jsonObjectArgs(pairs: DerivedRelation['pairs']): string;
603
766
  /** Filter by relation: a parent matches when {@link appendRelationSubquery} finds one target row. */
604
- protected compareRelation<E>(ctx: QueryContext, entity: Type<E>, val: QueryWhere<unknown>, rel: RelationMeta, opts: QueryComparisonOptions): void;
767
+ protected compareRelation<E>(ctx: QueryContext, entity: Type<E>, relKey: string, val: QueryWhere<unknown>, rel: RelationMeta, opts: QueryComparisonOptions): void;
605
768
  /** Filter by relation size: the same subquery, counting instead of testing for existence. */
606
- protected compareRelationSize<E>(ctx: QueryContext, entity: Type<E>, sizeVal: number | QuerySizeComparisonOps, rel: RelationMeta, opts: QueryComparisonOptions): void;
769
+ protected compareRelationSize<E>(ctx: QueryContext, entity: Type<E>, relKey: string, sizeVal: number | QuerySizeComparisonOps, rel: RelationMeta, opts: QueryComparisonOptions): void;
607
770
  /**
608
771
  * `<expr> <op> <value>` for each operator, AND-joined and parenthesized when there is more than
609
772
  * one. `exprFn` is re-run per operator because what it appends is an expression, not a column: