uql-orm 0.66.0 → 0.67.1

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 (193) hide show
  1. package/dist/browser/querier/httpQuerier.js +1 -8
  2. package/dist/browser/uql-browser.min.js.map +5 -5
  3. package/dist/bunSql/bunSql.util.d.ts +2 -6
  4. package/dist/bunSql/bunSql.util.js +2 -6
  5. package/dist/bunSql/bunSqlQuerier.d.ts +2 -5
  6. package/dist/bunSql/bunSqlQuerier.js +2 -5
  7. package/dist/cockroachdb/cockroachDialect.d.ts +4 -13
  8. package/dist/cockroachdb/cockroachDialect.js +4 -13
  9. package/dist/context/context.browser.js +2 -10
  10. package/dist/context/context.d.ts +4 -17
  11. package/dist/context/context.js +4 -17
  12. package/dist/dialect/abstractDialect.d.ts +4 -19
  13. package/dist/dialect/abstractDialect.js +2 -20
  14. package/dist/dialect/abstractSqlDialect.d.ts +47 -212
  15. package/dist/dialect/abstractSqlDialect.js +68 -222
  16. package/dist/dialect/aliases.d.ts +2 -12
  17. package/dist/dialect/aliases.js +4 -12
  18. package/dist/dialect/hydrateColumn.d.ts +2 -6
  19. package/dist/dialect/hydrateColumn.js +3 -13
  20. package/dist/dialect/jsonArrayElemMatchUtils.d.ts +1 -7
  21. package/dist/dialect/jsonArrayElemMatchUtils.js +1 -7
  22. package/dist/dialect/jsonSql.d.ts +6 -27
  23. package/dist/dialect/jsonSql.js +6 -27
  24. package/dist/dialect/mergeSqlDialect.d.ts +4 -22
  25. package/dist/dialect/mergeSqlDialect.js +4 -22
  26. package/dist/dialect/mysqlLikeSqlDialect.d.ts +11 -37
  27. package/dist/dialect/mysqlLikeSqlDialect.js +35 -51
  28. package/dist/dialect/pgLikeSqlDialect.d.ts +8 -22
  29. package/dist/dialect/pgLikeSqlDialect.js +36 -39
  30. package/dist/dialect/queryContext.d.ts +4 -22
  31. package/dist/dialect/queryContext.js +4 -22
  32. package/dist/dialect/queryJoins.d.ts +3 -12
  33. package/dist/dialect/queryJoins.js +3 -12
  34. package/dist/dialect/vectorCast.d.ts +2 -12
  35. package/dist/dialect/vectorCast.js +3 -19
  36. package/dist/dialect/vectorSqlDialect.d.ts +8 -38
  37. package/dist/dialect/vectorSqlDialect.js +7 -38
  38. package/dist/entity/decorator/bag.d.ts +6 -19
  39. package/dist/entity/decorator/bag.js +6 -22
  40. package/dist/entity/decorator/entity.d.ts +2 -7
  41. package/dist/entity/decorator/entity.js +2 -7
  42. package/dist/entity/decorator/members.d.ts +7 -30
  43. package/dist/entity/decorator/members.js +3 -12
  44. package/dist/entity/metadata/definition.d.ts +2 -18
  45. package/dist/entity/metadata/definition.js +6 -28
  46. package/dist/http/handler.d.ts +2 -14
  47. package/dist/index.d.ts +4 -1
  48. package/dist/index.js +3 -1
  49. package/dist/libsql/libsqlDialect.d.ts +1 -8
  50. package/dist/libsql/libsqlDialect.js +1 -8
  51. package/dist/maria/mariaDialect.d.ts +3 -5
  52. package/dist/maria/mariaDialect.js +5 -5
  53. package/dist/maria/mariadbQuerier.js +2 -2
  54. package/dist/maria/mariadbQuerierPool.js +1 -6
  55. package/dist/migrate/builder/migrationBuilder.js +3 -19
  56. package/dist/migrate/builder/splitSqlStatements.d.ts +1 -14
  57. package/dist/migrate/builder/splitSqlStatements.js +2 -22
  58. package/dist/migrate/builder/types.d.ts +2 -15
  59. package/dist/migrate/cli-config.js +2 -11
  60. package/dist/migrate/cli.js +2 -7
  61. package/dist/migrate/codegen/entityCodeGenerator.d.ts +0 -15
  62. package/dist/migrate/codegen/entityCodeGenerator.js +15 -44
  63. package/dist/migrate/codegen/fieldOptionsSource.d.ts +1 -8
  64. package/dist/migrate/codegen/fieldOptionsSource.js +3 -22
  65. package/dist/migrate/ddl/indexDdl.d.ts +2 -5
  66. package/dist/migrate/ddl/indexDdl.js +2 -5
  67. package/dist/migrate/ddl/pgIndexDdl.d.ts +3 -13
  68. package/dist/migrate/ddl/pgIndexDdl.js +3 -13
  69. package/dist/migrate/generator/definitionToNode.d.ts +2 -9
  70. package/dist/migrate/generator/definitionToNode.js +3 -17
  71. package/dist/migrate/generator/indexNodeToSchema.d.ts +2 -3
  72. package/dist/migrate/generator/indexNodeToSchema.js +2 -3
  73. package/dist/migrate/generator/mongoCommand.d.ts +1 -8
  74. package/dist/migrate/generator/mongoSchemaGenerator.d.ts +1 -8
  75. package/dist/migrate/generator/mongoSchemaGenerator.js +1 -8
  76. package/dist/migrate/introspection/abstractSqlSchemaIntrospector.d.ts +6 -26
  77. package/dist/migrate/introspection/abstractSqlSchemaIntrospector.js +9 -41
  78. package/dist/migrate/introspection/baseSqlIntrospector.js +0 -1
  79. package/dist/migrate/introspection/mongoIntrospector.d.ts +3 -1
  80. package/dist/migrate/introspection/mongoIntrospector.js +48 -46
  81. package/dist/migrate/introspection/mssqlIntrospector.d.ts +4 -4
  82. package/dist/migrate/introspection/mssqlIntrospector.js +18 -27
  83. package/dist/migrate/introspection/mysqlIntrospector.d.ts +7 -2
  84. package/dist/migrate/introspection/mysqlIntrospector.js +16 -14
  85. package/dist/migrate/introspection/postgresIntrospector.d.ts +24 -9
  86. package/dist/migrate/introspection/postgresIntrospector.js +68 -59
  87. package/dist/migrate/introspection/sqliteIntrospector.d.ts +1 -1
  88. package/dist/migrate/introspection/sqliteIntrospector.js +8 -10
  89. package/dist/migrate/migrator.d.ts +9 -53
  90. package/dist/migrate/migrator.js +32 -65
  91. package/dist/migrate/schemaGenerator.d.ts +16 -66
  92. package/dist/migrate/schemaGenerator.js +21 -74
  93. package/dist/mongo/mongoDialect.d.ts +21 -53
  94. package/dist/mongo/mongoDialect.js +25 -70
  95. package/dist/mongo/mongodbQuerier.d.ts +5 -8
  96. package/dist/mongo/mongodbQuerier.js +31 -65
  97. package/dist/mssql/mssqlDialect.d.ts +8 -34
  98. package/dist/mssql/mssqlDialect.js +37 -51
  99. package/dist/mssql/mssqlQuerier.d.ts +37 -4
  100. package/dist/mssql/mssqlQuerier.js +2 -2
  101. package/dist/mssql/mssqlWireTypes.d.ts +2 -14
  102. package/dist/mssql/mssqlWireTypes.js +2 -14
  103. package/dist/nestjs/uqlModule.js +2 -7
  104. package/dist/pglite/pgliteQuerier.d.ts +1 -9
  105. package/dist/pglite/pgliteQuerierPool.d.ts +4 -26
  106. package/dist/pglite/pgliteQuerierPool.js +3 -18
  107. package/dist/postgres/abstractPgQuerierPool.d.ts +1 -8
  108. package/dist/postgres/abstractPgQuerierPool.js +1 -8
  109. package/dist/postgres/pgNumericTypes.d.ts +3 -26
  110. package/dist/postgres/pgNumericTypes.js +3 -26
  111. package/dist/postgres/postgresDialect.d.ts +4 -10
  112. package/dist/postgres/postgresDialect.js +4 -10
  113. package/dist/querier/abstractQuerier.d.ts +35 -103
  114. package/dist/querier/abstractQuerier.js +105 -201
  115. package/dist/querier/abstractSharedHandleQuerierPool.d.ts +3 -17
  116. package/dist/querier/abstractSharedHandleQuerierPool.js +3 -17
  117. package/dist/querier/abstractSqlQuerier.d.ts +15 -36
  118. package/dist/querier/abstractSqlQuerier.js +49 -131
  119. package/dist/schema/canonicalType.d.ts +3 -21
  120. package/dist/schema/canonicalType.js +22 -67
  121. package/dist/schema/dependencyGraph.d.ts +2 -8
  122. package/dist/schema/dependencyGraph.js +2 -32
  123. package/dist/schema/index.d.ts +1 -25
  124. package/dist/schema/index.js +0 -26
  125. package/dist/schema/indexColumns.d.ts +1 -8
  126. package/dist/schema/indexColumns.js +1 -8
  127. package/dist/schema/indexDifferences.d.ts +7 -40
  128. package/dist/schema/indexDifferences.js +6 -31
  129. package/dist/schema/schemaAST.d.ts +8 -175
  130. package/dist/schema/schemaAST.js +13 -365
  131. package/dist/schema/schemaASTBuilder.d.ts +2 -24
  132. package/dist/schema/schemaASTBuilder.js +2 -30
  133. package/dist/schema/schemaASTDiffer.d.ts +6 -46
  134. package/dist/schema/schemaASTDiffer.js +8 -56
  135. package/dist/schema/types.d.ts +5 -61
  136. package/dist/schema/types.js +3 -6
  137. package/dist/sqlite/abstractSqliteQuerier.d.ts +1 -8
  138. package/dist/sqlite/localSqliteQuerierPool.d.ts +1 -7
  139. package/dist/sqlite/localSqliteQuerierPool.js +1 -7
  140. package/dist/sqlite/nodeSqliteQuerierPool.d.ts +2 -7
  141. package/dist/sqlite/nodeSqliteQuerierPool.js +2 -7
  142. package/dist/sqlite/sqliteDialect.d.ts +5 -20
  143. package/dist/sqlite/sqliteDialect.js +29 -35
  144. package/dist/turso/tursoDialect.d.ts +4 -6
  145. package/dist/turso/tursoDialect.js +4 -6
  146. package/dist/turso/tursoLocalQuerierPool.d.ts +1 -7
  147. package/dist/turso/tursoLocalQuerierPool.js +1 -7
  148. package/dist/turso/tursoQuerierPool.d.ts +2 -6
  149. package/dist/turso/tursoQuerierPool.js +2 -6
  150. package/dist/turso/tursoSessionQuerier.d.ts +1 -7
  151. package/dist/turso/tursoSessionQuerier.js +1 -7
  152. package/dist/type/dialect.d.ts +42 -94
  153. package/dist/type/dialect.js +3 -13
  154. package/dist/type/entity.d.ts +163 -534
  155. package/dist/type/entity.js +26 -9
  156. package/dist/type/logger.d.ts +2 -14
  157. package/dist/type/migration.d.ts +9 -38
  158. package/dist/type/querier.d.ts +9 -28
  159. package/dist/type/querierPool.d.ts +4 -26
  160. package/dist/type/query.d.ts +19 -73
  161. package/dist/type/query.js +2 -7
  162. package/dist/type/queryAggregate.d.ts +18 -98
  163. package/dist/type/queryRaw.d.ts +1 -8
  164. package/dist/type/queryRaw.js +1 -8
  165. package/dist/type/queryWhere.d.ts +13 -61
  166. package/dist/type/universalQuerier.d.ts +18 -105
  167. package/dist/type/utility.d.ts +12 -24
  168. package/dist/type/vector.d.ts +8 -38
  169. package/dist/type/vector.js +1 -1
  170. package/dist/type/wire.d.ts +2 -5
  171. package/dist/util/dialect.util.d.ts +9 -27
  172. package/dist/util/dialect.util.js +10 -27
  173. package/dist/util/field.util.d.ts +2 -31
  174. package/dist/util/field.util.js +3 -43
  175. package/dist/util/fieldOption.util.d.ts +7 -15
  176. package/dist/util/fieldOption.util.js +1 -1
  177. package/dist/util/filters.util.d.ts +2 -5
  178. package/dist/util/filters.util.js +2 -5
  179. package/dist/util/logger.d.ts +2 -6
  180. package/dist/util/logger.js +2 -6
  181. package/dist/util/object.util.d.ts +2 -6
  182. package/dist/util/object.util.js +1 -5
  183. package/dist/util/raw.d.ts +3 -23
  184. package/dist/util/relationQuery.util.d.ts +3 -14
  185. package/dist/util/relationQuery.util.js +3 -14
  186. package/dist/util/rowKey.util.d.ts +2 -10
  187. package/dist/util/rowKey.util.js +2 -10
  188. package/dist/util/sql.util.d.ts +6 -37
  189. package/dist/util/sql.util.js +13 -73
  190. package/dist/util/sqlLiteral.d.ts +2 -13
  191. package/dist/util/sqlLiteral.js +8 -13
  192. package/dist/util/string.util.js +0 -2
  193. package/package.json +4 -4
@@ -1,25 +1,4 @@
1
- import type { EntityMeta, FieldOptions } from '../type/index.js';
2
- /**
3
- * The kind of column a field lands on, which is what decides whether an option means anything on it:
4
- * `length` is a string's, `precision` a number's, `dimensions` a vector's. Named in the words an
5
- * error reports it in, so there is no second table of labels to keep in step.
6
- */
7
- export type ColumnFamily = 'string' | 'numeric' | 'boolean' | 'date' | 'json' | 'blob' | 'vector';
8
- /**
9
- * The runtime half of the column-type unions in `type/entity.ts`, which TypeScript erases. Each list
10
- * is checked against its own union, so a type cannot be filed under the wrong family, and
11
- * {@link UnplacedColumnType} refuses to compile if a new one is filed under none. Nothing here
12
- * restates the unions: the compile-time side of the same question reads them directly.
13
- */
14
- export declare const COLUMN_TYPES_BY_FAMILY: {
15
- readonly numeric: readonly ["int", "integer", "tinyint", "smallint", "bigint", "float", "float4", "float8", "double", "double precision", "decimal", "numeric", "real"];
16
- readonly string: readonly ["char", "varchar", "text", "uuid"];
17
- readonly date: readonly ["date", "time", "datetime", "timestamp", "timestamptz"];
18
- readonly json: readonly ["json", "jsonb"];
19
- readonly blob: readonly ["blob", "bytea"];
20
- readonly boolean: readonly ["bool", "boolean"];
21
- readonly vector: readonly ["vector", "halfvec", "sparsevec"];
22
- };
1
+ import { type ColumnFamily, type EntityMeta, type FieldOptions } from '../type/index.js';
23
2
  /** The family of a logical field type, or `undefined` where it names none. */
24
3
  export declare function columnFamily(type: unknown): ColumnFamily | undefined;
25
4
  /**
@@ -38,15 +17,7 @@ export declare function isInlinedExpression<F extends FieldOptions>(field: F): f
38
17
  * computed column *is* a real column, read like one, but writing to it is an error on every engine.
39
18
  */
40
19
  export declare function isDatabaseWritten(field: FieldOptions): boolean;
41
- /**
42
- * Whether the field is the entity's *whole* primary key - the only kind a serial can stand in for,
43
- * and the only one that may state `PRIMARY KEY` in its own column definition.
44
- *
45
- * One column of a composite is a value the caller supplies, and the table states the key over every
46
- * column at once. Asked in one place because the two schema paths - the AST that builds a
47
- * `CREATE TABLE` and the diff that builds an `ALTER` - have to answer it the same way, and each
48
- * answering for itself is what put a serial `PRIMARY KEY` on both columns of a composite.
49
- */
20
+ /** Whether the field is the whole primary key, the only kind a serial stands for and a column may declare. */
50
21
  export declare function isSoleIdField<E>(meta: EntityMeta<E>, field: FieldOptions): boolean;
51
22
  /**
52
23
  * Whether the database generates this column's value: a numeric key nothing else fills. `onInsert` fills
@@ -1,33 +1,5 @@
1
+ import { COLUMN_TYPES, } from '../type/index.js';
1
2
  import { getKeys } from './object.util.js';
2
- /**
3
- * The runtime half of the column-type unions in `type/entity.ts`, which TypeScript erases. Each list
4
- * is checked against its own union, so a type cannot be filed under the wrong family, and
5
- * {@link UnplacedColumnType} refuses to compile if a new one is filed under none. Nothing here
6
- * restates the unions: the compile-time side of the same question reads them directly.
7
- */
8
- export const COLUMN_TYPES_BY_FAMILY = {
9
- numeric: [
10
- 'int',
11
- 'integer',
12
- 'tinyint',
13
- 'smallint',
14
- 'bigint',
15
- 'float',
16
- 'float4',
17
- 'float8',
18
- 'double',
19
- 'double precision',
20
- 'decimal',
21
- 'numeric',
22
- 'real',
23
- ],
24
- string: ['char', 'varchar', 'text', 'uuid'],
25
- date: ['date', 'time', 'datetime', 'timestamp', 'timestamptz'],
26
- json: ['json', 'jsonb'],
27
- blob: ['blob', 'bytea'],
28
- boolean: ['bool', 'boolean'],
29
- vector: ['vector', 'halfvec', 'sparsevec'],
30
- };
31
3
  // Constructors and type strings in one map: a logical type is either, and every caller asks the same
32
4
  // question of both.
33
5
  const FAMILY_OF = new Map([
@@ -36,12 +8,8 @@ const FAMILY_OF = new Map([
36
8
  [BigInt, 'numeric'],
37
9
  [Boolean, 'boolean'],
38
10
  [Date, 'date'],
11
+ ...getKeys(COLUMN_TYPES).flatMap((family) => COLUMN_TYPES[family].map((type) => [type, family])),
39
12
  ]);
40
- for (const family of getKeys(COLUMN_TYPES_BY_FAMILY)) {
41
- for (const columnType of COLUMN_TYPES_BY_FAMILY[family]) {
42
- FAMILY_OF.set(columnType, family);
43
- }
44
- }
45
13
  /** The family of a logical field type, or `undefined` where it names none. */
46
14
  export function columnFamily(type) {
47
15
  return FAMILY_OF.get(typeof type === 'string' ? type.toLowerCase() : type);
@@ -80,15 +48,7 @@ export function isInlinedExpression(field) {
80
48
  export function isDatabaseWritten(field) {
81
49
  return field.computed !== undefined;
82
50
  }
83
- /**
84
- * Whether the field is the entity's *whole* primary key - the only kind a serial can stand in for,
85
- * and the only one that may state `PRIMARY KEY` in its own column definition.
86
- *
87
- * One column of a composite is a value the caller supplies, and the table states the key over every
88
- * column at once. Asked in one place because the two schema paths - the AST that builds a
89
- * `CREATE TABLE` and the diff that builds an `ALTER` - have to answer it the same way, and each
90
- * answering for itself is what put a serial `PRIMARY KEY` on both columns of a composite.
91
- */
51
+ /** Whether the field is the whole primary key, the only kind a serial stands for and a column may declare. */
92
52
  export function isSoleIdField(meta, field) {
93
53
  return field.isId === true && meta.ids.length === 1;
94
54
  }
@@ -1,5 +1,4 @@
1
- import type { BlobColumnType, BooleanColumnType, DateColumnType, FieldOptions, JsonColumnType, NumericColumnType, QueryRaw, StringColumnType, VectorColumnType } from '../type/index.js';
2
- import { type ColumnFamily } from './field.util.js';
1
+ import type { ColumnFamily, FamilyOf, FieldOptions, QueryRaw } from '../type/index.js';
3
2
  /**
4
3
  * The column family each field option means anything on, or `'*'` where it applies to every column.
5
4
  * Exhaustive over {@link FieldOptions}, so a new option cannot be added without placing it - the
@@ -54,13 +53,11 @@ type GeneratedWrite = (typeof GENERATED_WRITES)[number];
54
53
  */
55
54
  export declare function fieldOptionConflict(opts: FieldOptions): string | undefined;
56
55
  /** The family the options put the column in; every family where they name no type to put it in. */
57
- type FamilyOf<O> = O extends {
56
+ type OptionsFamily<O> = O extends {
58
57
  readonly columnType: infer C;
59
- } ? FamilyOfType<C> : O extends {
58
+ } ? FamilyOf<C> : O extends {
60
59
  readonly type: infer T;
61
- } ? FamilyOfType<T> : ColumnFamily;
62
- /** Read off the column-type unions themselves, which is what `COLUMN_TYPES_BY_FAMILY` is checked against. */
63
- type FamilyOfType<T> = T extends NumericColumnType | NumberConstructor | BigIntConstructor ? 'numeric' : T extends StringColumnType | StringConstructor ? 'string' : T extends VectorColumnType ? 'vector' : T extends JsonColumnType ? 'json' : T extends DateColumnType | DateConstructor ? 'date' : T extends BooleanColumnType | BooleanConstructor ? 'boolean' : T extends BlobColumnType ? 'blob' : ColumnFamily;
60
+ } ? FamilyOf<T> : ColumnFamily;
64
61
  /** What the field's own values leave unread, matching {@link deadOn} line for line. */
65
62
  type DeadOptions<O> = (O extends {
66
63
  readonly stored: true;
@@ -74,16 +71,11 @@ type DeadOptions<O> = (O extends {
74
71
  } ? 'onUpdate' : never);
75
72
  type Given<O> = Extract<keyof O, keyof FieldOptions>;
76
73
  type Offending<O> = {
77
- [K in Given<O>]: (typeof FIELD_OPTION_FAMILY)[K] extends FamilyOf<O> | '*' ? K extends DeadOptions<O> ? K : never : K;
74
+ [K in Given<O>]: (typeof FIELD_OPTION_FAMILY)[K] extends OptionsFamily<O> | '*' ? K extends DeadOptions<O> ? K : never : K;
78
75
  }[Given<O>];
79
76
  /**
80
- * Maps every option `O` states but cannot use to `never`, the way `RejectUnknown` maps a typo'd one,
81
- * so an option that would be silently ignored reads as the same compile error. Resolves to `unknown`
82
- * - an inert intersection member - when there are none.
83
- *
84
- * `@Id` adds `{ nullable?: false }` of its own rather than passing the `isId` it stamps on, which
85
- * would have to reach `O` as an intersection - and a non-naked `O` in its own constraint stops it
86
- * inferring from the options at all.
77
+ * Every option `O` states but cannot use, mapped to `never`, so one that would be ignored does not compile.
78
+ * `@Id` states `{ nullable?: false }` itself, since `O` has to stay naked to be inferred.
87
79
  */
88
80
  export type RejectIncompatible<O> = [Offending<O>] extends [never] ? unknown : Record<Offending<O> & string, never>;
89
81
  export {};
@@ -83,7 +83,7 @@ function deadOn(opts, key) {
83
83
  export function fieldOptionConflict(opts) {
84
84
  const family = columnFamily(opts.columnType ?? opts.type);
85
85
  // Walked in table order, not in the order the field happened to be written, so a field with two
86
- // conflicts always reports the same one. An option no rule knows is a typo, which `RejectUnknown`
86
+ // conflicts always reports the same one. An option no rule knows is a typo, which `@Field`'s own check
87
87
  // reports where it can still be spelled right.
88
88
  for (const key of getKeys(FIELD_OPTION_FAMILY)) {
89
89
  const applies = FIELD_OPTION_FAMILY[key];
@@ -1,10 +1,7 @@
1
1
  import type { QueryOptions } from '../type/index.js';
2
2
  /**
3
- * Query options that include soft-deleted rows in the result - disables the built-in `softDelete`
4
- * filter for this call. This is a server-side option: filter bypass is intentionally not serialized
5
- * over the wire. To list *only* trashed rows with a serializable query, constrain the field instead,
6
- * e.g. `querier.findMany(User, { $where: { deletedAt: { $ne: null } } })` - the filter steps aside
7
- * for any key you set in `$where`.
3
+ * Options including soft-deleted rows, server-side only. To list only deleted ones over the wire, filter
4
+ * the field: `{ $where: { deletedAt: { $ne: null } } }`.
8
5
  * @example `querier.findMany(User, {}, withDeleted())`
9
6
  */
10
7
  export declare function withDeleted(): QueryOptions;
@@ -1,9 +1,6 @@
1
1
  /**
2
- * Query options that include soft-deleted rows in the result - disables the built-in `softDelete`
3
- * filter for this call. This is a server-side option: filter bypass is intentionally not serialized
4
- * over the wire. To list *only* trashed rows with a serializable query, constrain the field instead,
5
- * e.g. `querier.findMany(User, { $where: { deletedAt: { $ne: null } } })` - the filter steps aside
6
- * for any key you set in `$where`.
2
+ * Options including soft-deleted rows, server-side only. To list only deleted ones over the wire, filter
3
+ * the field: `{ $where: { deletedAt: { $ne: null } } }`.
7
4
  * @example `querier.findMany(User, {}, withDeleted())`
8
5
  */
9
6
  export function withDeleted() {
@@ -63,11 +63,7 @@ export interface ErrorEmittingPool {
63
63
  on(event: 'error', listener: (err: Error) => void): unknown;
64
64
  }
65
65
  /**
66
- * Attaches an error listener to a connection pool so a dropped connection is logged instead of left
67
- * unhandled - which crashes the process for drivers that don't guard against it themselves
68
- * (node-postgres, `mssql`), or is silently swallowed by those that install a no-op of their own
69
- * (`mariadb`). Reported through the pool's own logger when it has one, and through the default one
70
- * otherwise: never dropped, whatever levels were configured, since a swallowed pool error is exactly
71
- * the failure this guards against.
66
+ * Logs a pool's dropped connection, which some drivers would otherwise crash the process on, through
67
+ * the pool's logger or the default one, whatever levels were configured.
72
68
  */
73
69
  export declare function attachPoolErrorHandler(pool: ErrorEmittingPool, message: string, logging?: LoggingOptions): void;
@@ -155,12 +155,8 @@ export function queryLoggerFor(extra) {
155
155
  return wrapper;
156
156
  }
157
157
  /**
158
- * Attaches an error listener to a connection pool so a dropped connection is logged instead of left
159
- * unhandled - which crashes the process for drivers that don't guard against it themselves
160
- * (node-postgres, `mssql`), or is silently swallowed by those that install a no-op of their own
161
- * (`mariadb`). Reported through the pool's own logger when it has one, and through the default one
162
- * otherwise: never dropped, whatever levels were configured, since a swallowed pool error is exactly
163
- * the failure this guards against.
158
+ * Logs a pool's dropped connection, which some drivers would otherwise crash the process on, through
159
+ * the pool's logger or the default one, whatever levels were configured.
164
160
  */
165
161
  export function attachPoolErrorHandler(pool, message, logging) {
166
162
  const logger = new LoggerWrapper(isOwnLogger(logging) ? logging : true);
@@ -11,17 +11,13 @@ export declare function hasKeys<T>(obj: T): obj is NonNullable<T>;
11
11
  export declare function someKey<T extends object>(obj: T, pred: (key: keyof T & string) => boolean): boolean;
12
12
  /** Whether any enumerable value of `obj` satisfies `pred`, short-circuiting like {@link someKey}. */
13
13
  export declare function someValue(obj: object, pred: (value: unknown) => boolean): boolean;
14
- /**
15
- * Whether `value` is a non-empty object whose keys are query/update operators (`$eq`, `$push`, ...).
16
- * The single source of this test: the SQL dialects, the MongoDB dialect and the `$elemMatch` walker
17
- * all classify operator objects with it, and they used to disagree about `{}`.
18
- */
14
+ /** Whether `value` is a non-empty object with an operator key (`$eq`, `$push`...): the one test every dialect classifies with. */
19
15
  export declare function isOperatorObject(value: unknown): value is Record<string, unknown>;
20
16
  /** Whether every key of the non-empty object `value` is an operator (no plain field names mixed in). */
21
17
  export declare function isOperatorOnlyObject(value: unknown): value is Record<string, unknown>;
22
18
  /** Whether `value` is an object that is not an array, whose keys can be read. */
23
19
  export declare function isRecord(value: unknown): value is Record<string, unknown>;
24
- export declare function getKeys<T extends object>(obj: T): (keyof T & string)[];
20
+ export declare function getKeys<T extends object>(obj: T | null | undefined): (keyof T & string)[];
25
21
  /** The entries of `record` holding a value: a key declared but left `undefined` is no entry at all. */
26
22
  export declare function definedEntries<K extends string, V>(record: Partial<Record<K, V>>): [K, V][];
27
23
  /**
@@ -37,11 +37,7 @@ export function someValue(obj, pred) {
37
37
  return someKey(obj, (key) => pred(obj[key]));
38
38
  }
39
39
  const isOperatorKey = (key) => key.startsWith('$');
40
- /**
41
- * Whether `value` is a non-empty object whose keys are query/update operators (`$eq`, `$push`, ...).
42
- * The single source of this test: the SQL dialects, the MongoDB dialect and the `$elemMatch` walker
43
- * all classify operator objects with it, and they used to disagree about `{}`.
44
- */
40
+ /** Whether `value` is a non-empty object with an operator key (`$eq`, `$push`...): the one test every dialect classifies with. */
45
41
  export function isOperatorObject(value) {
46
42
  return hasKeys(value) && !Array.isArray(value) && someKey(value, isOperatorKey);
47
43
  }
@@ -1,28 +1,8 @@
1
1
  import { type EntitySql, type EntityWhere, type EntityWhereMeta, QueryRaw, type QueryRawFn, type RefMap, type Type } from '../type/index.js';
2
2
  /**
3
- * Create a raw SQL expression.
4
- *
5
- * As a tagged template the literal text is emitted as written and every interpolation is resolved by
6
- * what it is, so a value cannot become SQL whatever it holds:
7
- *
8
- * | Interpolated | Becomes |
9
- * | :------------------ | :------------------------------------- |
10
- * | any value | a bound parameter; in DDL, its literal |
11
- * | a {@link ColumnRef} | its column, escaped and qualified |
12
- * | a {@link QueryRaw} | that fragment, in place |
13
- *
14
- * ```ts
15
- * const user = refs(User);
16
- * raw`GREATEST(0, ${user.creditsAllowance} - ${amount})`
17
- * raw`CONCAT(${user.firstName}, ' ', ${user.lastName})`
18
- * raw`LOG10(${points})`.as('score')
19
- * ```
20
- *
21
- * The callback form remains for SQL a template cannot express, such as a sub-query generated through
22
- * `dialect.find(...)`.
23
- *
24
- * **⚠️ Security:** the tag is safe because it binds; a callback is not, since it emits whatever it
25
- * writes, so never build one from user input. Inside a callback, bind with `ctx.addValue()`.
3
+ * Raw SQL, where an interpolated value binds, a `refs` field renders its column, and a `raw` renders
4
+ * in place: `raw`GREATEST(0, ${user.credits} - ${amount})``. A callback writes whatever it writes, so
5
+ * never build one from user input. See the Raw SQL guide.
26
6
  */
27
7
  export declare function raw(strings: TemplateStringsArray, ...values: readonly unknown[]): QueryRaw;
28
8
  export declare function raw(value: QueryRawFn): QueryRaw;
@@ -15,22 +15,11 @@ export type ParentJoin = {
15
15
  readonly joined: string;
16
16
  };
17
17
  /**
18
- * How a relation joins to its parent: `parent` is a column of the parent's own table, `joined` the
19
- * column matching it on the table the relation reads - a junction's own column for a relation that
20
- * goes through one, the child's foreign key otherwise.
21
- *
22
- * The two are spelled from opposite ends of `references` (`local` names a column of the table the
23
- * relation is declared on, `foreign` a column of the other one), and getting that backwards reads a
24
- * real column of the wrong table, so it is answered once here. One pair per key of the parent.
18
+ * How a relation joins its parent, one pair per key: `parent` a column of the parent's table, `joined` the
19
+ * matching one on the table the relation reads, a junction's or the child's.
25
20
  */
26
21
  export declare function parentJoins(relOpts: Pick<RelationMeta, 'references' | 'through'>, parentKeyCount: number): ParentJoin[];
27
- /**
28
- * The junction columns holding the target's key, the other half of {@link parentJoins}.
29
- *
30
- * `parentKeyCount` is required: the target's columns start after the parent's, so guessing the
31
- * boundary returned the parent's *second* column as the target's - a real column of the wrong side,
32
- * which is the mistake this module exists to prevent.
33
- */
22
+ /** The junction columns holding the target's key, after the parent's `parentKeyCount` ones. */
34
23
  export declare function targetKeyColumns(relOpts: Pick<RelationMeta, 'references'>, parentKeyCount: number): string[];
35
24
  /**
36
25
  * The `$where` naming exactly the children of the rows `parentIds` identifies: an `IN` over the one
@@ -14,13 +14,8 @@ export function isToManyRelation(relation) {
14
14
  return relation.cardinality === '1m' || relation.cardinality === 'mm';
15
15
  }
16
16
  /**
17
- * How a relation joins to its parent: `parent` is a column of the parent's own table, `joined` the
18
- * column matching it on the table the relation reads - a junction's own column for a relation that
19
- * goes through one, the child's foreign key otherwise.
20
- *
21
- * The two are spelled from opposite ends of `references` (`local` names a column of the table the
22
- * relation is declared on, `foreign` a column of the other one), and getting that backwards reads a
23
- * real column of the wrong table, so it is answered once here. One pair per key of the parent.
17
+ * How a relation joins its parent, one pair per key: `parent` a column of the parent's table, `joined` the
18
+ * matching one on the table the relation reads, a junction's or the child's.
24
19
  */
25
20
  export function parentJoins(relOpts, parentKeyCount) {
26
21
  if (!relOpts.through) {
@@ -30,13 +25,7 @@ export function parentJoins(relOpts, parentKeyCount) {
30
25
  // something its caller already knows - so the boundary is passed rather than stored on a relation.
31
26
  return relOpts.references.slice(0, parentKeyCount).map(({ local, foreign }) => ({ parent: foreign, joined: local }));
32
27
  }
33
- /**
34
- * The junction columns holding the target's key, the other half of {@link parentJoins}.
35
- *
36
- * `parentKeyCount` is required: the target's columns start after the parent's, so guessing the
37
- * boundary returned the parent's *second* column as the target's - a real column of the wrong side,
38
- * which is the mistake this module exists to prevent.
39
- */
28
+ /** The junction columns holding the target's key, after the parent's `parentKeyCount` ones. */
40
29
  export function targetKeyColumns(relOpts, parentKeyCount) {
41
30
  return relOpts.references.slice(parentKeyCount).map(({ local }) => local);
42
31
  }
@@ -1,13 +1,5 @@
1
1
  /**
2
- * A row's key as a string, for matching rows to each other.
3
- *
4
- * Reads the columns off the row rather than taking their values, because every caller matches a
5
- * whole page of rows against one fixed column list: taking an array would make each of them build
6
- * one per row, which is what a page of 250 rows paid 56 KB for.
7
- *
8
- * Values are normalized before joining, not stringified: `String(date)` is locale- and
9
- * timezone-dependent, so two equal dates could key apart, and a `Uint8Array` stringifies to its
10
- * bytes with commas. Every column is included, so two rows agreeing on one column of a composite
11
- * key are not treated as one row.
2
+ * A row's key over `columns`, for matching rows: read off the row, so a page builds no array per row, and
3
+ * normalized rather than stringified, since `String(date)` depends on the locale.
12
4
  */
13
5
  export declare function rowKey(row: unknown, columns: readonly string[]): string;
@@ -1,16 +1,8 @@
1
1
  /** Separates the parts of a composite key: a unit separator, which no column value carries. */
2
2
  const KEY_SEPARATOR = '\u001f';
3
3
  /**
4
- * A row's key as a string, for matching rows to each other.
5
- *
6
- * Reads the columns off the row rather than taking their values, because every caller matches a
7
- * whole page of rows against one fixed column list: taking an array would make each of them build
8
- * one per row, which is what a page of 250 rows paid 56 KB for.
9
- *
10
- * Values are normalized before joining, not stringified: `String(date)` is locale- and
11
- * timezone-dependent, so two equal dates could key apart, and a `Uint8Array` stringifies to its
12
- * bytes with commas. Every column is included, so two rows agreeing on one column of a composite
13
- * key are not treated as one row.
4
+ * A row's key over `columns`, for matching rows: read off the row, so a page builds no array per row, and
5
+ * normalized rather than stringified, since `String(date)` depends on the locale.
14
6
  */
15
7
  export function rowKey(row, columns) {
16
8
  const values = row;
@@ -17,18 +17,8 @@ export declare function obtainAttrsPaths<T extends object>(row: T): {
17
17
  */
18
18
  export declare function qualifyName(name: string, schema?: string): string;
19
19
  /**
20
- * The name a derived index or constraint gets when nothing named it: `Order__total_idx`.
21
- *
22
- * One owner for all four kinds, because it is a rule two layers apply and a third has to match: the
23
- * entity AST derives it, the DDL generator falls back to it, and a `DROP` names what it drops.
24
- * `table` is the table's own name, never qualified - the result is a single identifier.
25
- *
26
- * The kind goes last, as Postgres spells its own (`users_pkey`, `users_email_idx`), so a table's
27
- * constraints sort together under the table they belong to.
28
- *
29
- * Not overridable, deliberately: a `NamingStrategy` hook would have to reach the eight call sites
30
- * these have, an introspector and two builders among them, to replace a name any declaration can
31
- * already set outright with `name:`. Worth revisiting only for a case that option cannot express.
20
+ * The name a derived index or constraint gets, `Order__total_idx`, kind last as Postgres names its own.
21
+ * One rule for the AST, the DDL and a `DROP`; not a naming strategy hook, since `name:` already overrides it.
32
22
  */
33
23
  export declare function derivedConstraintName(table: string, parts: readonly (string | number)[], kind: ConstraintKind): string;
34
24
  /** The kinds of derived name, which is also what `indexNameStem` strips to compare them. */
@@ -49,13 +39,7 @@ export declare function derivedPrimaryKeyName(table: string, columns: readonly s
49
39
  export declare function derivedCheckName(table: string, position: number): string;
50
40
  /** The constraint name a foreign key gets when nothing named it: `Order__customerId_fk`. */
51
41
  export declare function derivedForeignKeyName(table: string, columns: readonly string[]): string;
52
- /**
53
- * Escape a SQL identifier (table name, column name, etc.)
54
- * @param val the identifier to escape
55
- * @param escapeIdChar the escape character to use (e.g. ` or ")
56
- * @param forbidQualified whether to forbid qualified identifiers (containing dots)
57
- * @param addDot whether to add a dot suffix
58
- */
42
+ /** Escapes an identifier with `escapeIdChar`, refusing a dotted one where `forbidQualified`, with a trailing dot where `addDot`. */
59
43
  export declare function escapeSqlId(val: string | undefined, escapeIdChar?: '`' | '"', forbidQualified?: boolean, addDot?: boolean): string;
60
44
  /**
61
45
  * Payload for building a QueryUpdateResult.
@@ -81,24 +65,9 @@ export interface BuildUpdateResultPayload {
81
65
  upsertStatus?: number;
82
66
  }
83
67
  /**
84
- * Unified utility to build a QueryUpdateResult from driver-specific results.
85
- *
86
- * UQL's SQL dialects always alias the entity's ID column to `id` in RETURNING clauses,
87
- * so the result rows always contain an `id` property regardless of the entity's @Id() key name.
88
- *
89
- * The header-derived ID path assumes the database allocated consecutive values for the
90
- * statement, which holds for a single multi-row `INSERT ... VALUES` on auto-increment keys
91
- * (with the standard `auto_increment_increment = 1`); the querier only maps these IDs onto
92
- * payloads when that assumption is safe.
93
- *
94
- * Caveat (MySQL/MariaDB-compatible engines with no `RETURNING`, i.e. `insertIdSource: 'firstId'`):
95
- * contiguous allocation across a statement's rows is only guaranteed under
96
- * `innodb_autoinc_lock_mode` 0 (`traditional`) or 1 (`consecutive`). Under mode 2 (`interleaved`,
97
- * MySQL 8.0's default), other connections inserting into the same table concurrently with this
98
- * statement can interleave with its auto-increment allocation, so the inferred IDs may not be
99
- * contiguous. There is no code-level fix for this (MySQL has no `RETURNING`); avoid relying on
100
- * inferred multi-row IDs for a table under heavy concurrent insert load, or set
101
- * `innodb_autoinc_lock_mode` to 0 or 1.
68
+ * A driver's result as a {@link QueryUpdateResult}: `RETURNING` rows name their id `id`; a MySQL header's
69
+ * first id is extended by the increment, which holds only where auto-increment allocation is contiguous
70
+ * (`innodb_autoinc_lock_mode` 0 or 1).
102
71
  */
103
72
  export declare function buildUpdateResult(payload: BuildUpdateResultPayload): QueryUpdateResult;
104
73
  /**
@@ -2,7 +2,7 @@ import { hasKeys } from './object.util.js';
2
2
  /** Pre-computed regex for each SQL identifier escape character to avoid per-call allocation. */
3
3
  const escapeIdRegexCache = { '`': /`/g, '"': /"/g };
4
4
  export function unflatObjects(objects) {
5
- if (!Array.isArray(objects) || !objects.length) {
5
+ if (!objects.length) {
6
6
  return objects;
7
7
  }
8
8
  const attrsPaths = obtainAttrsPaths(objects[0]);
@@ -66,40 +66,16 @@ const MAX_IDENTIFIER_LENGTH = 63;
66
66
  /** Hex chars of hash kept when a name has to be shortened. 24 bits over one table's constraints. */
67
67
  const NAME_HASH_LENGTH = 6;
68
68
  /**
69
- * The name a derived index or constraint gets when nothing named it: `Order__total_idx`.
70
- *
71
- * One owner for all four kinds, because it is a rule two layers apply and a third has to match: the
72
- * entity AST derives it, the DDL generator falls back to it, and a `DROP` names what it drops.
73
- * `table` is the table's own name, never qualified - the result is a single identifier.
74
- *
75
- * The kind goes last, as Postgres spells its own (`users_pkey`, `users_email_idx`), so a table's
76
- * constraints sort together under the table they belong to.
77
- *
78
- * Not overridable, deliberately: a `NamingStrategy` hook would have to reach the eight call sites
79
- * these have, an introspector and two builders among them, to replace a name any declaration can
80
- * already set outright with `name:`. Worth revisiting only for a case that option cannot express.
69
+ * The name a derived index or constraint gets, `Order__total_idx`, kind last as Postgres names its own.
70
+ * One rule for the AST, the DDL and a `DROP`; not a naming strategy hook, since `name:` already overrides it.
81
71
  */
82
72
  export function derivedConstraintName(table, parts, kind) {
83
73
  const body = parts.length ? `${table}${TABLE_SEPARATOR}${parts.join('_')}` : table;
84
74
  return clampIdentifier(`${body}_${kind}`);
85
75
  }
86
- /**
87
- * What separates the table from the columns, doubled where every other join is single.
88
- *
89
- * Postgres and SQLite keep index and constraint names in one flat namespace across the whole
90
- * database rather than scoping them to a table, so a single underscore lets two tables collide:
91
- * `user` + `profile_id` and `user_profile` + `id` both reduce to `user_profile_id_idx`. Doubling the
92
- * one ambiguous boundary settles it, on the same assumption Drupal made for the same engines - that
93
- * nothing sane carries `__` in a table or column name.
94
- */
76
+ /** Between table and columns, doubled: index names share one namespace per database, where `a` + `b_c` and `a_b` + `c` would collide. */
95
77
  const TABLE_SEPARATOR = '__';
96
- /**
97
- * A name the engine will store whole, shortened around a hash of the full one when it is too long.
98
- *
99
- * Truncating alone collides - two long names over the same table differ only in their tail - and a
100
- * collision means one constraint silently replacing another. The hash is of the *whole* name, so it
101
- * stays the same on every run, which is what lets a later migration still recognise what it made.
102
- */
78
+ /** A name the engine stores whole, shortened around a hash of the full one, which stays stable across runs. */
103
79
  function clampIdentifier(name) {
104
80
  if (name.length <= MAX_IDENTIFIER_LENGTH) {
105
81
  return name;
@@ -144,13 +120,7 @@ export function derivedCheckName(table, position) {
144
120
  export function derivedForeignKeyName(table, columns) {
145
121
  return derivedConstraintName(table, columns, 'fk');
146
122
  }
147
- /**
148
- * Escape a SQL identifier (table name, column name, etc.)
149
- * @param val the identifier to escape
150
- * @param escapeIdChar the escape character to use (e.g. ` or ")
151
- * @param forbidQualified whether to forbid qualified identifiers (containing dots)
152
- * @param addDot whether to add a dot suffix
153
- */
123
+ /** Escapes an identifier with `escapeIdChar`, refusing a dotted one where `forbidQualified`, with a trailing dot where `addDot`. */
154
124
  export function escapeSqlId(val, escapeIdChar = '`', forbidQualified, addDot) {
155
125
  if (!val) {
156
126
  return '';
@@ -167,41 +137,16 @@ export function escapeSqlId(val, escapeIdChar = '`', forbidQualified, addDot) {
167
137
  return escaped + suffix;
168
138
  }
169
139
  /**
170
- * Unified utility to build a QueryUpdateResult from driver-specific results.
171
- *
172
- * UQL's SQL dialects always alias the entity's ID column to `id` in RETURNING clauses,
173
- * so the result rows always contain an `id` property regardless of the entity's @Id() key name.
174
- *
175
- * The header-derived ID path assumes the database allocated consecutive values for the
176
- * statement, which holds for a single multi-row `INSERT ... VALUES` on auto-increment keys
177
- * (with the standard `auto_increment_increment = 1`); the querier only maps these IDs onto
178
- * payloads when that assumption is safe.
179
- *
180
- * Caveat (MySQL/MariaDB-compatible engines with no `RETURNING`, i.e. `insertIdSource: 'firstId'`):
181
- * contiguous allocation across a statement's rows is only guaranteed under
182
- * `innodb_autoinc_lock_mode` 0 (`traditional`) or 1 (`consecutive`). Under mode 2 (`interleaved`,
183
- * MySQL 8.0's default), other connections inserting into the same table concurrently with this
184
- * statement can interleave with its auto-increment allocation, so the inferred IDs may not be
185
- * contiguous. There is no code-level fix for this (MySQL has no `RETURNING`); avoid relying on
186
- * inferred multi-row IDs for a table under heavy concurrent insert load, or set
187
- * `innodb_autoinc_lock_mode` to 0 or 1.
140
+ * A driver's result as a {@link QueryUpdateResult}: `RETURNING` rows name their id `id`; a MySQL header's
141
+ * first id is extended by the increment, which holds only where auto-increment allocation is contiguous
142
+ * (`innodb_autoinc_lock_mode` 0 or 1).
188
143
  */
189
144
  export function buildUpdateResult(payload) {
190
145
  const { rows, id, insertIdSource, upsertStatus } = payload;
191
146
  const changes = payload.changes ?? rows?.length ?? 0;
192
147
  const stride = payload.insertIdIncrement && payload.insertIdIncrement > 0 ? payload.insertIdIncrement : 1;
193
- // ID mapping. RETURNING rows are exact. Otherwise the sequence is derived from the single id in
194
- // the driver header: `firstId` dialects (MySQL) report the FIRST generated id, and the rest are
195
- // inferred by incrementing it. A header id of `0`/`0n` means no id was generated (e.g. a
196
- // non-auto-increment key), so we infer none.
197
- //
198
- // This arithmetic assumes `changes` equals the batch's row count, which always holds for a plain
199
- // `insertMany` - but not for `upsertMany` on a `firstId` dialect (MySQL): its `ON DUPLICATE KEY
200
- // UPDATE` convention makes `changes` a per-row weighted sum (1=insert, 2=update, 0=no-op), so a
201
- // batch mixing an insert and an update would fabricate ids for rows that were never touched. This
202
- // function has no way to tell the two call sites apart (`internalRun` reports the same header
203
- // shape either way), so `AbstractSqlQuerier`'s `runUpsert` discards them for a multi-row `firstId`
204
- // upsert and reads the ids back by the conflict columns instead.
148
+ // Ids from `RETURNING` are exact; otherwise from the header's first id onward, which assumes `changes`
149
+ // counts the rows (false for a MySQL upsert batch, whose querier reads ids back instead). `0` means none.
205
150
  let ids = [];
206
151
  if (rows?.length) {
207
152
  ids = rows.map((r) => r['id']);
@@ -215,13 +160,8 @@ export function buildUpdateResult(payload) {
215
160
  ids = sequentialIds(id, changes, stride);
216
161
  }
217
162
  }
218
- // 2. Creation Status
219
- // PostgreSQL: `(xmax = 0) AS "_created"` in the RETURNING clause provides a boolean per row.
220
- // MySQL: `affectedRows` convention - 1 = insert, 2 = update, 0 = no-op. Gated on `!== 'returning'`
221
- // since that convention is unreliable once RETURNING is in play (verified: MariaDB's affectedRows
222
- // for an `ON DUPLICATE KEY UPDATE ... RETURNING` statement differs by driver and doesn't follow
223
- // the 1/2/0 convention at all) - `insertIdSource === 'returning'` dialects without a `_created`
224
- // column (MariaDB, SQLite, CockroachDB) correctly get `undefined` instead of a misleading guess.
163
+ // Whether the row was created: Postgres's `_created` column, or MySQL's 1/2/0 `affectedRows`,
164
+ // which is unreliable under `RETURNING`, so those dialects report nothing.
225
165
  const created = (rows?.length === 1 ? rows[0]?.['_created'] : undefined) ??
226
166
  (insertIdSource !== 'returning' && typeof upsertStatus === 'number' && upsertStatus >= 0 && upsertStatus <= 2
227
167
  ? upsertStatus === 1
@@ -1,18 +1,7 @@
1
- /**
2
- * SQL string literal escaping for `Dialect.escape`, in two flavors: ANSI single-quote doubling
3
- * (Postgres, SQLite) and MySQL backslash escaping (MySQL, MariaDB). Only the quoting step differs.
4
- *
5
- * **Security.** UQL never calls `Dialect.escape` itself, so this is the hand-written-SQL hatch; prefer
6
- * bound parameters. Two limits are inherent to inline MySQL literals (`sqlstring` and `sql-escaper`
7
- * share them): escaping breaks under the server's `NO_BACKSLASH_ESCAPES` mode, and under a charset
8
- * whose trailing byte can be `0x5C` (GBK, Big5, SJIS). `toSqlString()` values are emitted raw.
9
- *
10
- * PostgreSQL **array** literals (`{...}` with double-quoted elements and their own escape rules)
11
- * are separate from this helper; see {@link PostgresDialect} (array text format when
12
- * `nativeArrays` is false) - do not "unify" that path with this function.
13
- */
14
1
  /** Doubles every single quote in `val`, the ANSI escaping shared by string literals and JSON path keys. */
15
2
  export declare function escapeSingleQuotes(val: string): string;
3
+ /** The text a MySQL string literal's body stands for: its backslash escapes and doubled quotes undone. */
4
+ export declare function unescapeMysqlString(body: string): string;
16
5
  /** Escape `value` for Postgres, SQLite and related dialects (single-quote doubling). */
17
6
  export declare const escapeAnsiSqlLiteral: (value: unknown) => string;
18
7
  /** Escape `value` for MySQL and MariaDB (backslash escaping). */