@atscript/db 0.1.152 → 0.1.154

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 (45) hide show
  1. package/dist/agg.cjs +1 -1
  2. package/dist/agg.d.cts +1 -1
  3. package/dist/agg.d.mts +1 -1
  4. package/dist/agg.mjs +1 -1
  5. package/dist/{aggregate-fns-CyaZyb9I.mjs → aggregate-fns-B_sgl4mB.mjs} +1 -1
  6. package/dist/{aggregate-fns-C-UJRobm.cjs → aggregate-fns-DFtKAv7Q.cjs} +1 -1
  7. package/dist/{buckets-Cb0zmhDc.d.mts → buckets-CBKL_ZWE.d.mts} +205 -7
  8. package/dist/{buckets-tzd8iIM2.d.cts → buckets-jy8BfswO.d.cts} +205 -7
  9. package/dist/{column-diff-CnyLjbQ8.mjs → column-diff-DAIAq6XR.mjs} +728 -29
  10. package/dist/{column-diff-CU7KHj9-.cjs → column-diff-qnzx1o3c.cjs} +727 -28
  11. package/dist/{db-error-DRQH4sLY.cjs → db-error-JcfJqqpk.cjs} +29 -0
  12. package/dist/{db-error-Az85UhTX.mjs → db-error-eSsQX7rt.mjs} +24 -1
  13. package/dist/{fk-diff-Bw26lwSc.d.cts → fk-diff-BIJ8l_hF.d.mts} +1 -1
  14. package/dist/{fk-diff-lcAnwvm9.d.mts → fk-diff-D1mrLMjU.d.cts} +1 -1
  15. package/dist/index.cjs +93 -5
  16. package/dist/index.d.cts +29 -5
  17. package/dist/index.d.mts +29 -5
  18. package/dist/index.mjs +92 -6
  19. package/dist/{nested-writer-cvbVAkNo.mjs → nested-writer-BOj_c_lI.mjs} +1 -1
  20. package/dist/{nested-writer-BzbOPSUp.cjs → nested-writer-Bl1SZS7x.cjs} +1 -1
  21. package/dist/ops.cjs +1 -1
  22. package/dist/ops.mjs +1 -1
  23. package/dist/plugin.cjs +48 -1
  24. package/dist/plugin.mjs +48 -1
  25. package/dist/rel.cjs +2 -2
  26. package/dist/rel.d.cts +2 -2
  27. package/dist/rel.d.mts +2 -2
  28. package/dist/rel.mjs +2 -2
  29. package/dist/{relation-helpers-Bdo4NHPC.d.mts → relation-helpers-BUsxNNGU.d.mts} +1 -1
  30. package/dist/{relation-helpers-DxIZKvnJ.d.cts → relation-helpers-D_8bydc2.d.cts} +1 -1
  31. package/dist/{relation-loader-DYab07lw.mjs → relation-loader-CNBMPfRr.mjs} +2 -1
  32. package/dist/{relation-loader-fNjHgBMs.cjs → relation-loader-DeulLrAw.cjs} +2 -1
  33. package/dist/sync.cjs +2 -2
  34. package/dist/sync.d.cts +2 -2
  35. package/dist/sync.d.mts +2 -2
  36. package/dist/sync.mjs +2 -2
  37. package/dist/{validator-tBNvM1qc.d.cts → validator-B3xlbrWf.d.cts} +36 -2
  38. package/dist/{validator-tBNvM1qc.d.mts → validator-B3xlbrWf.d.mts} +36 -2
  39. package/dist/{validator-BTiIOTKP.mjs → validator-BACewoRj.mjs} +51 -7
  40. package/dist/{validator-UcuJxHNT.cjs → validator-BxWwh3wf.cjs} +50 -6
  41. package/dist/validator.cjs +2 -2
  42. package/dist/validator.d.cts +1 -1
  43. package/dist/validator.d.mts +1 -1
  44. package/dist/validator.mjs +2 -2
  45. package/package.json +8 -8
package/dist/agg.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_aggregate_fns = require("./aggregate-fns-C-UJRobm.cjs");
2
+ const require_aggregate_fns = require("./aggregate-fns-DFtKAv7Q.cjs");
3
3
  let _uniqu_core = require("@uniqu/core");
4
4
  //#region src/agg.ts
5
5
  /**
package/dist/agg.d.cts CHANGED
@@ -1,3 +1,3 @@
1
- import { r as TResolvedBucket } from "./buckets-tzd8iIM2.cjs";
1
+ import { r as TResolvedBucket } from "./buckets-jy8BfswO.cjs";
2
2
  import { _ as TDbAggregateFn, a as AggregateResult, c as CalendarBucketLabel, d as WeekStart, f as isAggregateExpr, h as resolveAlias, i as AggregateQuery, l as ComputedExpr, m as resolveAggregateSearch, n as AggregateExpr, o as BucketExpr, p as isBucketExpr, r as AggregateFn, s as BucketUnit, t as AggregateControls, u as ResolvedBucket, v as assertAggregateFn } from "./agg-42CSpGDR.cjs";
3
3
  export { type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, type BucketExpr, type BucketUnit, type CalendarBucketLabel, type ComputedExpr, type ResolvedBucket, type TDbAggregateFn, type TResolvedBucket, type WeekStart, assertAggregateFn, isAggregateExpr, isBucketExpr, resolveAggregateSearch, resolveAlias };
package/dist/agg.d.mts CHANGED
@@ -1,3 +1,3 @@
1
- import { r as TResolvedBucket } from "./buckets-Cb0zmhDc.mjs";
1
+ import { r as TResolvedBucket } from "./buckets-CBKL_ZWE.mjs";
2
2
  import { _ as TDbAggregateFn, a as AggregateResult, c as CalendarBucketLabel, d as WeekStart, f as isAggregateExpr, h as resolveAlias, i as AggregateQuery, l as ComputedExpr, m as resolveAggregateSearch, n as AggregateExpr, o as BucketExpr, p as isBucketExpr, r as AggregateFn, s as BucketUnit, t as AggregateControls, u as ResolvedBucket, v as assertAggregateFn } from "./agg-Wo-smrYV.mjs";
3
3
  export { type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, type BucketExpr, type BucketUnit, type CalendarBucketLabel, type ComputedExpr, type ResolvedBucket, type TDbAggregateFn, type TResolvedBucket, type WeekStart, assertAggregateFn, isAggregateExpr, isBucketExpr, resolveAggregateSearch, resolveAlias };
package/dist/agg.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { s as assertAggregateFn } from "./aggregate-fns-CyaZyb9I.mjs";
1
+ import { s as assertAggregateFn } from "./aggregate-fns-B_sgl4mB.mjs";
2
2
  import { isAggregateExpr, isBucketExpr, resolveAlias } from "@uniqu/core";
3
3
  //#region src/agg.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { r as DbError } from "./db-error-Az85UhTX.mjs";
1
+ import { r as DbError } from "./db-error-eSsQX7rt.mjs";
2
2
  import { ROW_ORDER_FNS, isAggregateExpr } from "@uniqu/core";
3
3
  //#region src/query/aggregate-fns.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- const require_db_error = require("./db-error-DRQH4sLY.cjs");
1
+ const require_db_error = require("./db-error-JcfJqqpk.cjs");
2
2
  let _uniqu_core = require("@uniqu/core");
3
3
  //#region src/query/aggregate-fns.ts
4
4
  /**
@@ -1,6 +1,6 @@
1
1
  import { f as TFieldOps } from "./ops-AqhV7s9o.mjs";
2
2
  import { AtscriptExprNode, AtscriptExprNode as AtscriptExprNode$1, AtscriptOrderItem, AtscriptQueryComparison, AtscriptQueryFieldRef, AtscriptQueryFieldRef as AtscriptQueryFieldRef$1, AtscriptQueryNode, AtscriptQueryNode as AtscriptQueryNode$1, AtscriptRef, FlatOf, FlatOf as FlatOf$1, NavPropsOf, NavPropsOf as NavPropsOf$1, OwnPropsOf, OwnPropsOf as OwnPropsOf$1, PrimaryKeyOf, PrimaryKeyOf as PrimaryKeyOf$1, TAtscriptAnnotatedType, TAtscriptDataType, TAtscriptTypeObject, TMetadataMap, TSerializedAnnotatedType, TValidatorOptions, TValidatorPlugin, Validator } from "@atscript/typescript/utils";
3
- import { AggregateControls, AggregateExpr, AggregateExpr as AggregateExpr$1, AggregateFn, AggregateFn as AggregateFn$1, AggregateQuery, AggregateQuery as AggregateQuery$1, AggregateResult, BucketUnit, FieldOpsFor, FilterExpr, FilterExpr as FilterExpr$1, RelationOp, ResolvedBucket, ResolvedRowOrderKey, ResolvedSelectExpr, TypedWithRelation, Uniquery, Uniquery as Uniquery$1, UniqueryControls, UniqueryControls as UniqueryControls$1, UniqueryInsights, WithRelation, WithRelation as WithRelation$1 } from "@uniqu/core";
3
+ import { AggregateControls, AggregateExpr, AggregateExpr as AggregateExpr$1, AggregateFn, AggregateFn as AggregateFn$1, AggregateQuery, AggregateQuery as AggregateQuery$1, AggregateResult, BucketUnit, FieldOpsFor, FilterExpr, FilterExpr as FilterExpr$1, NullsPlacement, NullsPlacement as NullsPlacement$1, RelationOp, ResolvedBucket, ResolvedRowOrderKey, ResolvedSelectExpr, TypedWithRelation, Uniquery, Uniquery as Uniquery$1, UniqueryControls, UniqueryControls as UniqueryControls$1, UniqueryInsights, WithRelation, WithRelation as WithRelation$1 } from "@uniqu/core";
4
4
 
5
5
  //#region src/query/uniqu-select.d.ts
6
6
  /** A row-level expression aggregate: `fn(<expr>)` over each row (physical field leaves). */
@@ -28,6 +28,13 @@ interface TFirstLast {
28
28
  interface TRowOrderKey {
29
29
  column: string;
30
30
  desc: boolean;
31
+ /**
32
+ * Requested NULL placement (`$nulls`, or the field's `@db.sort.nulls`);
33
+ * absent: the uniform "NULL is the smallest value" order. Only set on
34
+ * adapters whose `supportsNullsPlacement()` is `true`.
35
+ * @since 0.1.153
36
+ */
37
+ nulls?: NullsPlacement;
31
38
  }
32
39
  /** The arithmetic and representative-row parts of an aggregate `$select`, as the field mapper resolves them. */
33
40
  interface TUniquComputed {
@@ -212,8 +219,6 @@ declare abstract class FieldMappingStrategy {
212
219
  * `first(raisedAt):raisedAt`, is the alias, exactly as in `$sort`).
213
220
  */
214
221
  private translateHaving;
215
- /** Output aliases of the computed `$select` entries (aggregates, expressions and calendar buckets). */
216
- private computedAliasSet;
217
222
  /**
218
223
  * The arithmetic and `$rowOrder` parts of a grouped query with PHYSICAL
219
224
  * names: a row-level operand is a column; a group-level operand stays an
@@ -232,6 +237,13 @@ declare abstract class FieldMappingStrategy {
232
237
  protected physicalSelect(select: NonNullable<UniqueryControls["$select"]>, meta: TableMetadata): NonNullable<UniqueryControls["$select"]>;
233
238
  /** `$sort` with physical keys; computed `aliases` (grouped queries) pass through. */
234
239
  protected physicalSort(sort: NonNullable<DbControls["$sort"]>, meta: TableMetadata, aliases?: ReadonlySet<string>): DbControls["$sort"];
240
+ /**
241
+ * `$nulls` with physical keys, like {@link physicalSort}. The core hands
242
+ * over only the resolved entries (since 0.1.153).
243
+ */
244
+ protected physicalNulls(nulls: NonNullable<DbControls["$nulls"]>, meta: TableMetadata, aliases?: ReadonlySet<string>): DbControls["$nulls"];
245
+ /** `map` with its field-path keys made physical; computed `aliases` pass through. */
246
+ private physicalKeys;
235
247
  /**
236
248
  * Translates a logical filter for the adapter: relational predicates are
237
249
  * resolved first (`resolveRelationFilterTree`), then every key and value
@@ -703,7 +715,8 @@ declare class AtscriptDbReadable<T extends TAtscriptAnnotatedType = TAtscriptAnn
703
715
  get primaryKeys(): readonly string[];
704
716
  /**
705
717
  * Physical column lists that must be unique: the primary key (when declared)
706
- * followed by every unique index and every adapter-contributed unique field. Used by conflict-ignoring inserts.
718
+ * followed by every unique index and every adapter-contributed unique field / key. Used by
719
+ * conflict-ignoring inserts and view read pruning.
707
720
  * @since 0.1.148
708
721
  */
709
722
  get uniqueKeySets(): string[][];
@@ -841,6 +854,41 @@ declare class AtscriptDbReadable<T extends TAtscriptAnnotatedType = TAtscriptAnn
841
854
  * by default), loads their `$with` relations and strips widened keys.
842
855
  */
843
856
  private _finishRead;
857
+ /**
858
+ * `query` with {@link _withPkTieBreak} applied and its `$nulls` resolved
859
+ * ({@link NullsSource.resolveSort}) — a copy when either changes.
860
+ */
861
+ private _withStableSort;
862
+ private _nullsCache?;
863
+ /** NULL-placement resolution for this table (`$nulls`, `@db.sort.nulls`; since 0.1.153). */
864
+ private get _nulls();
865
+ /**
866
+ * `$sort` with the primary-key tie-breaker appended (since 0.1.153), or
867
+ * `undefined` when the read keeps its `$sort` as written. Rows that tie on
868
+ * every `$sort` key otherwise come back in an engine-chosen order that can
869
+ * differ between two reads, so offset pages overlap or skip rows. The
870
+ * primary-key fields the `$sort` leaves out are appended in declaration
871
+ * order, in the direction of the LAST `$sort` key (a backward index scan
872
+ * serves `amount DESC, id DESC`).
873
+ *
874
+ * Unchanged when there is no `$sort` (no order is imposed), when the
875
+ * `$sort` already names every field of the primary key or of a unique key
876
+ * over non-nullable fields ({@link _totalOrderKeys}), when the table has no
877
+ * primary key (a view without `@meta.id`), and on grouped / aggregate /
878
+ * `$count` reads. Search, vector and geo relevance is never touched: the
879
+ * key is appended only to an explicit `$sort`. Every read path applies it
880
+ * ({@link _translateRead}, and {@link _translateForAdapter} for a native
881
+ * `$with` loader), so nested relation rows get it too.
882
+ */
883
+ private _withPkTieBreak;
884
+ private _totalOrderKeysCache?;
885
+ /**
886
+ * Physical column sets that order rows totally: the primary key, then
887
+ * every unique index (and adapter-contributed unique field) whose fields
888
+ * are all non-nullable — a unique key over a nullable column admits
889
+ * several NULLs, so it does not.
890
+ */
891
+ private _totalOrderKeys;
844
892
  /** `$select` plus the join keys of `withRelations` it leaves out — `undefined` when none is missing. */
845
893
  private _widenSelectForWith;
846
894
  private _joinKeysCache?;
@@ -955,6 +1003,12 @@ declare class AtscriptDbReadable<T extends TAtscriptAnnotatedType = TAtscriptAnn
955
1003
  * then reverse-maps and applies fromStorage formatters on results.
956
1004
  */
957
1005
  aggregate(query: AggregateQuery): Promise<Array<Record<string, unknown>>>;
1006
+ /**
1007
+ * A grouped read's `$nulls` resolved for its `$sort` keys (computed aliases
1008
+ * take a request entry only) and its `$rowOrder` keys — see
1009
+ * {@link NullsSource}.
1010
+ */
1011
+ private _aggregateNulls;
958
1012
  /**
959
1013
  * The computed aliases of one source field that is a boolean or a decimal —
960
1014
  * `min` / `max` / `first` / `last` — with that field's descriptor: the
@@ -971,6 +1025,12 @@ declare class AtscriptDbReadable<T extends TAtscriptAnnotatedType = TAtscriptAnn
971
1025
  supportsAggregateExpressions(): boolean;
972
1026
  /** Aggregate functions the adapter renders (proxies adapter capability). @since 0.1.136 */
973
1027
  aggregateFns(): ReadonlySet<AggregateFn>;
1028
+ /**
1029
+ * Whether the adapter honours a requested NULL placement (`$nulls`,
1030
+ * `@db.sort.nulls`) — proxies adapter capability.
1031
+ * @since 0.1.153
1032
+ */
1033
+ supportsNullsPlacement(): boolean;
974
1034
  /** Whether the adapter can sort by a given field (proxies adapter capability). */
975
1035
  canSortField(fd: TDbFieldMeta): boolean;
976
1036
  /** Returns available search indexes from the adapter. */
@@ -1661,6 +1721,25 @@ interface TViewSource {
1661
1721
  */
1662
1722
  declare function aliasTargetOf(type: TAtscriptAnnotatedType | undefined): TAtscriptAnnotatedType | undefined;
1663
1723
  //#endregion
1724
+ //#region src/table/view-read-plan.d.ts
1725
+ /**
1726
+ * One read variant of a managed view with the left joins its query does not
1727
+ * need removed — see `AtscriptDbView.readPlan`.
1728
+ * @since 0.1.153
1729
+ */
1730
+ interface TViewReadPlan {
1731
+ /** The view plan without the dropped joins (entry table and view filter unchanged). */
1732
+ readonly plan: TViewPlan;
1733
+ /** The column mappings that remain readable — every mapping none of whose sources was dropped. */
1734
+ readonly columns: TViewColumnMapping[];
1735
+ /** Scopes of the dropped joins, in declaration order. */
1736
+ readonly dropped: readonly string[];
1737
+ /** Physical view columns the variant no longer exposes. */
1738
+ readonly droppedColumns: readonly string[];
1739
+ /** Identifies the variant within its view (the dropped scopes) — a cache key. */
1740
+ readonly key: string;
1741
+ }
1742
+ //#endregion
1664
1743
  //#region src/table/db-view.d.ts
1665
1744
  interface TViewColumnMapping {
1666
1745
  /**
@@ -1739,6 +1818,7 @@ declare function isViewType(type: TAtscriptAnnotatedType): boolean;
1739
1818
  declare class AtscriptDbView<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedType, DataType = TAtscriptDataType<T>, FlatType = NullableOptional<FlatOf<T>>, A extends BaseDbAdapter = BaseDbAdapter, IdType = PrimaryKeyOf<T>, OwnProps = NullableOptional<OwnPropsOf<T>>, NavType extends Record<string, unknown> = NavPropsOf<T>> extends AtscriptDbReadable<T, DataType, FlatType, A, IdType, OwnProps, NavType> {
1740
1819
  private _viewPlan?;
1741
1820
  private _columnMappings?;
1821
+ private _readPlanner?;
1742
1822
  get isView(): boolean;
1743
1823
  /**
1744
1824
  * Builds the view's metadata — first stamping its fields with their
@@ -1811,6 +1891,28 @@ declare class AtscriptDbView<T extends TAtscriptAnnotatedType = TAtscriptAnnotat
1811
1891
  * aggregate other than `count` over `'*'`.
1812
1892
  */
1813
1893
  getViewColumnMappings(): TViewColumnMapping[];
1894
+ /**
1895
+ * The read variant of this managed view for a query that reads only the
1896
+ * `needed` PHYSICAL view columns (`undefined`: every column) — the view
1897
+ * plan with every LEFT join removed that (a) matches at most one row per
1898
+ * input row and (b) feeds no needed column, no other kept join's ON clause
1899
+ * and no `@db.view.filter`. Dropping such a join leaves every row of the
1900
+ * view in place, so a query over the variant returns exactly what it
1901
+ * returns over the view. `undefined` when nothing can be dropped.
1902
+ *
1903
+ * At most one match is proven from the model: a first-row join, or an ON
1904
+ * clause whose `=` conjuncts pin every column of one of the target's unique
1905
+ * keys (primary key included) — see the views guide. Inner joins, joins to
1906
+ * a view, grouped (`@db.agg.*`), materialized and external views are never
1907
+ * pruned. A variant's {@link TViewReadPlan.columns} omit the columns of the
1908
+ * dropped joins, so a column reference the caller failed to declare fails
1909
+ * loudly instead of reading wrong data.
1910
+ *
1911
+ * Memoised per dropped-join set. Adapters use it to read through an
1912
+ * inline, pruned definition instead of the stored view.
1913
+ * @since 0.1.153
1914
+ */
1915
+ readPlan(needed: Iterable<string> | undefined): TViewReadPlan | undefined;
1814
1916
  /**
1815
1917
  * Why the bound adapter cannot render this managed view: one message per
1816
1918
  * computed column / first-row join whose feature its `viewCapabilities()`
@@ -2245,6 +2347,22 @@ declare abstract class BaseDbAdapter {
2245
2347
  * @since 0.1.148
2246
2348
  */
2247
2349
  supportsAggregateExpressions(): boolean;
2350
+ /**
2351
+ * Whether this adapter honours a requested NULL placement: `controls.$nulls`
2352
+ * (PHYSICAL `$sort` keys → `'first'` / `'last'`, or computed aliases on a
2353
+ * grouped read) and `TRowOrderKey.nulls` on the `first` / `last` row
2354
+ * order. NULL (and, on document stores, a missing value) goes before or
2355
+ * after every non-null value whatever the sort direction. The core only
2356
+ * forwards entries for keys that can be NULL; a key without an entry keeps
2357
+ * the adapter's native order (`$sort`) or "NULL is the smallest value"
2358
+ * (grouped / row order). Default `false` (fail-closed): the core refuses a
2359
+ * request naming a placement with `INVALID_QUERY` and drops
2360
+ * `@db.sort.nulls` defaults. moost-db advertises it as
2361
+ * `/meta.nullsPlacement`.
2362
+ *
2363
+ * @since 0.1.153
2364
+ */
2365
+ supportsNullsPlacement(): boolean;
2248
2366
  /**
2249
2367
  * Revision of how this adapter renders a managed view (its SQL / pipeline)
2250
2368
  * from an unchanged view definition. Stored in each managed view's sync
@@ -2266,6 +2384,18 @@ declare abstract class BaseDbAdapter {
2266
2384
  * @since 0.1.147
2267
2385
  */
2268
2386
  viewCapabilities(): ReadonlySet<TViewCapability>;
2387
+ /**
2388
+ * Whether reads of a managed view drop the LEFT joins the query does not
2389
+ * need (`AtscriptDbView.readPlan`) — reading through an inline, pruned
2390
+ * definition instead of the stored view. Only adapters that implement it
2391
+ * honour it; each sets its own default from its constructor options (the
2392
+ * bundled MySQL, SQLite and MongoDB adapters: on; PostgreSQL removes such
2393
+ * joins itself). Set it to `false` on one view's adapter
2394
+ * (`space.getAdapter(View)`) to read that view by name again.
2395
+ *
2396
+ * @since 0.1.153
2397
+ */
2398
+ viewJoinPruning: boolean;
2269
2399
  /**
2270
2400
  * Whether this adapter enforces foreign key constraints natively.
2271
2401
  * When `true`, the generic layer skips application-level cascade/setNull
@@ -2618,10 +2748,13 @@ declare abstract class BaseDbAdapter {
2618
2748
  * and every other error must throw — and a skipped row must never abort the
2619
2749
  * surrounding transaction. Fail-closed by default: throws
2620
2750
  * `DbError("ON_CONFLICT_NOT_SUPPORTED")`; also override
2621
- * {@link supportsInsertIgnore}.
2751
+ * {@link supportsInsertIgnore}. `opts` (since 0.1.153) tells whether the
2752
+ * call joins a caller's transaction and whether to lock the stored rows the
2753
+ * batch collides with — see {@link TDbInsertIgnoreOptions}; an adapter
2754
+ * without row locks ignores it.
2622
2755
  * @since 0.1.148
2623
2756
  */
2624
- insertManyIgnore(_data: Array<Record<string, unknown>>): Promise<TDbInsertIgnoreSlot[]>;
2757
+ insertManyIgnore(_data: Array<Record<string, unknown>>, _opts?: TDbInsertIgnoreOptions): Promise<TDbInsertIgnoreSlot[]>;
2625
2758
  /** Whether {@link insertManyIgnore} is implemented (drives `crud.insert: ["onConflict"]` in `/meta`). @since 0.1.148 */
2626
2759
  supportsInsertIgnore(): boolean;
2627
2760
  abstract replaceOne(filter: FilterExpr, data: Record<string, unknown>, expectedVersion?: number): Promise<TDbUpdateResult>;
@@ -2922,6 +3055,8 @@ declare class TableMetadata {
2922
3055
  navFields: Set<string>;
2923
3056
  ignoredFields: Set<string>;
2924
3057
  uniqueProps: Set<string>;
3058
+ /** Adapter-contributed multi-field unique keys (logical paths) — see `TMetadataOverrides.addUniqueKeys`. */
3059
+ uniqueKeys: string[][];
2925
3060
  defaults: Map<string, TDbDefaultValue>;
2926
3061
  /** Logical path → `@db.column` override (top-level keys only on document storage). */
2927
3062
  columnMap: Map<string, string>;
@@ -3044,6 +3179,17 @@ declare class TableMetadata {
3044
3179
  * 10. Build allPhysicalFields list
3045
3180
  */
3046
3181
  build(type: TAtscriptAnnotatedType<TAtscriptTypeObject>, adapter: BaseDbAdapter, logger: TGenericLogger): void;
3182
+ /**
3183
+ * `flattenAnnotatedType` merges the metadata of every union / tuple member
3184
+ * into the synthetic flat entry of the prop's path, so a member's
3185
+ * annotations would reach the column (DDL type, size, default). Since
3186
+ * atscript 0.1.103 a built-in primitive member carries its built-in
3187
+ * annotations (`number.timestamp.created | null` → `@db.default.now`,
3188
+ * `string.char` → `@expect.maxLength 1`). Rebuild such an entry from the
3189
+ * prop's own annotations plus the non-`db.*` annotations of named members
3190
+ * (aliases, interfaces), so the column is described as before 0.1.103.
3191
+ */
3192
+ private _dropMemberMetadata;
3047
3193
  /**
3048
3194
  * Applies adapter-provided metadata overrides atomically.
3049
3195
  * Processing order: injectFields → removePrimaryKeys → addPrimaryKeys → addUniqueFields.
@@ -3138,6 +3284,8 @@ declare class TableMetadata {
3138
3284
  * overrides (`addUniqueFields`); these aren't reflected in
3139
3285
  * `this.indexes` but still legitimate addressing identifications.
3140
3286
  * Deduped against any single-field unique index already captured.
3287
+ * - `this.uniqueKeys` — multi-field uniques contributed by adapter
3288
+ * overrides (`addUniqueKeys`).
3141
3289
  */
3142
3290
  private _buildIdentifications;
3143
3291
  /** Legitimate row-identifier shapes — primary key first, then each unique index. */
@@ -3329,6 +3477,15 @@ interface TMetaResponse {
3329
3477
  * @since 0.1.148
3330
3478
  */
3331
3479
  aggregateExpressions?: boolean;
3480
+ /**
3481
+ * Present (true) when the adapter honours a requested NULL placement in
3482
+ * sorts: the `$nulls` control (URL suffix `$sort=-amount:last`) and the
3483
+ * fields' `@db.sort.nulls` defaults (serialized in {@link type} as the
3484
+ * `db.sort.nulls` annotation) — see `BaseDbAdapter.supportsNullsPlacement()`.
3485
+ *
3486
+ * @since 0.1.153
3487
+ */
3488
+ nullsPlacement?: true;
3332
3489
  }
3333
3490
  /** Where the action applies on the UI. */
3334
3491
  type TDbActionLevel = "table" | "row" | "rows";
@@ -3535,6 +3692,26 @@ interface TDbInsertManyIgnoreResult extends TDbInsertManyResult {
3535
3692
  type TDbInsertIgnoreSlot = {
3536
3693
  insertedId: unknown;
3537
3694
  } | null;
3695
+ /**
3696
+ * Options the table hands to `BaseDbAdapter.insertManyIgnore`.
3697
+ * @since 0.1.153
3698
+ */
3699
+ interface TDbInsertIgnoreOptions {
3700
+ /**
3701
+ * `true` when the call joins a transaction its CALLER opened (more
3702
+ * statements may follow in it), `false` when the transaction (if any) is the
3703
+ * call's own. Adapters whose failed duplicate INSERT leaves a lock behind
3704
+ * (MySQL / InnoDB: a shared lock held to commit) look up the stored keys
3705
+ * first in that case, so no lock outlives the call. Omitted (a direct
3706
+ * adapter call): the adapter decides from `isInTransaction()`.
3707
+ */
3708
+ inCallerTransaction?: boolean;
3709
+ /**
3710
+ * Lock the stored rows the batch collides with until the transaction ends
3711
+ * (`TInsertOptions.lockConflicts`). Only sent inside a caller transaction.
3712
+ */
3713
+ lockConflicts?: boolean;
3714
+ }
3538
3715
  interface TDbUpdateResult {
3539
3716
  matchedCount: number;
3540
3717
  modifiedCount: number;
@@ -3929,6 +4106,13 @@ interface TMetadataOverrides {
3929
4106
  removePrimaryKeys?: string[];
3930
4107
  /** Fields to register as having a unique constraint. */
3931
4108
  addUniqueFields?: string[];
4109
+ /**
4110
+ * Multi-field unique keys (logical paths) the adapter enforces with an index
4111
+ * of its own — no field of one is unique alone (MongoDB: a composite
4112
+ * `@meta.id` beside an explicit `_id`, indexed as one `__pk` key).
4113
+ * @since 0.1.153
4114
+ */
4115
+ addUniqueKeys?: string[][];
3932
4116
  /** Synthetic fields to inject into flatMap (e.g. MongoDB's `_id`). */
3933
4117
  injectFields?: Array<{
3934
4118
  path: string;
@@ -4198,6 +4382,20 @@ interface TInsertOptions<Row = Record<string, unknown>> extends TWriteOptions<Ro
4198
4382
  * parent (`@db.rel.to` nested object) is rejected in this mode.
4199
4383
  */
4200
4384
  onConflict?: "error" | "ignore";
4385
+ /**
4386
+ * With `onConflict: 'ignore'` inside a caller's transaction: lock the STORED
4387
+ * rows the batch collides with until that transaction ends, so the caller
4388
+ * can update them next without racing — or deadlocking — a concurrent
4389
+ * transaction doing the same. MySQL and PostgreSQL take exclusive row locks
4390
+ * (`SELECT … FOR UPDATE`) on those rows only, in key order, before
4391
+ * inserting the rest (on MySQL a row that a concurrent writer commits while
4392
+ * the call runs keeps the shared lock of its failed INSERT instead); SQLite (database-level write lock), MongoDB and the
4393
+ * in-memory adapter need no row locks and ignore it. Outside a caller
4394
+ * transaction it is a no-op (the call's own transaction ends on return).
4395
+ * Throws `INVALID_QUERY` without `onConflict: 'ignore'`.
4396
+ * @since 0.1.153
4397
+ */
4398
+ lockConflicts?: boolean;
4201
4399
  }
4202
4400
  /**
4203
4401
  * Context handed to a write {@link TWriteOptions.check} (since 0.1.143) — and
@@ -4375,4 +4573,4 @@ declare function isJsonValueField(fd: TDbFieldMeta): boolean;
4375
4573
  */
4376
4574
  declare function jsonValueAncestor(path: string, jsonValueParents: ReadonlySet<string>): string | undefined;
4377
4575
  //#endregion
4378
- export { TDbReferentialAction as $, TDbSpaceOptions as $t, TCrudOp as A, andFilters as An, TRowResolveOptions as At, TDbDefaultValue as B, TReadControls as Bn, TypedWithRelation as Bt, NavPropsOf$1 as C, REL_FILTER_MAX_DEPTH as Cn, TIdentification as Ct, TCascadeResolver as D, TRelationFilterJunction as Dn, TPrimaryKeyChange as Dt, PrimaryKeyOf$1 as E, TRelGuardState as En, TMetadataOverrides as Et, TDbActionProcessor as F, relationStaticFilter as Fn, TTouchManyOptions as Ft, TDbIndexField as G, TRowOrderKey as Gn, isGeoIndexableType as Gt, TDbFieldMeta as H, TGenericLogger as Hn, UniqueryControls$1 as Ht, TDbActionTargetSummary as I, DbEncryption as In, TValueFormatterPair as It, TDbInsertIgnoreSlot as J, ALL_VIEW_CAPABILITIES as Jt, TDbIndexType as K, UniquSelect as Kn, isGeoPointType as Kt, TDbAvailableActions as L, TDbEncryptionOptions as Ln, TViewJsonType as Lt, TDbActionInfo as M, forEachResolvedRelation as Mn, TSyncColumnResult as Mt, TDbActionIntent as N, hasRelationOp as Nn, TTableOptionDiff as Nt, TCascadeTarget as O, TRelationFilterTable as On, TReferencingForeignKey as Ot, TDbActionLevel as P, isResolvedRelationFilter as Pn, TTableResolver as Pt, TDbObjectKind as Q, TAdapterFactory as Qt, TDbCollation as R, DocumentFieldMapper as Rn, TWriteOptions as Rt, FlatOf$1 as S, resolveDesignType as Sn, TIdResolveOptions as St, OwnPropsOf$1 as T, ResolvedRelationFilter as Tn, TMetaResponse as Tt, TDbForeignKey as U, TExprAggregate as Un, WithRelation$1 as Ut, TDbDeleteResult as V, NoopLogger as Vn, Uniquery$1 as Vt, TDbIndex as W, TFirstLast as Wn, TableMetadata as Wt, TDbInsertManyResult as X, TViewCapability as Xt, TDbInsertManyIgnoreResult as Y, BaseDbAdapter as Yt, TDbInsertResult as Z, DbSpace as Zt, DbPatch as _, IntegrityStrategy as _n, TExistingTableOption as _t, isJsonValueField as a, AtscriptExprNode$1 as an, TDbUpdateResult as at, FieldOpsFor as b, AtscriptDbReadable as bn, TFkLookupTarget as bt, resolveCalendarBuckets as c, AtscriptQueryFieldRef$1 as cn, TDbWriteCheckContext as ct, AggregateFn$1 as d, TViewJoin as dn, TDeleteOptions as dt, AtscriptDbView as en, TDbRelation as et, AggregateQuery$1 as f, TViewPlan as fn, TDerivedChangeReason as ft, DbControls as g, AtscriptDbTable as gn, TExistingForeignKey as gt, AtscriptDbWritable as h, translateQueryTree as hn, TExistingColumn as ht, isBucketableField as i, aliasTargetOf as in, TDbUpdateOptions as it, TCrudPermissions as j, containsRelationFilter as jn, TSearchIndexInfo as jt, TColumnDiff as k, TRelationStaticFilter as kn, TRelationInfo as kt, AggregateControls as l, AtscriptQueryNode$1 as ln, TDbWriteGuard as lt, AtscriptDbTableLike as m, isFieldRef as mn, TEnsureTableOptions as mt, TComputedSelect as n, isAtscriptDbView as nn, TDbRemoveGuardContext as nt, jsonValueAncestor as o, AtscriptOrderItem as on, TDbWriteAction as ot, AggregateResult as p, evaluateExpr as pn, TDerivedColumn as pt, TDbInsertIgnoreResult as q, ALL_BUCKET_UNITS as qt, TResolvedBucket as r, isViewType as rn, TDbStorageType as rt, normalizeComputedSelect as s, AtscriptQueryComparison as sn, TDbWriteCheck as st, TBucketFieldSource as t, TViewColumnMapping as tn, TDbRemoveGuard as tt, AggregateExpr$1 as u, AtscriptRef as un, TDbWriteGuardContext as ut, DbQuery as v, NativeIntegrity as vn, TFieldMeta as vt, NullableOptional as w, REL_FILTER_MAX_NODES as wn, TInsertOptions as wt, FilterExpr$1 as x, DbResponse as xn, TIdDescriptor as xt, DbRow as y, TCascadePin as yn, TFkLookupResolver as yt, TDbDefaultFn as z, FieldMappingStrategy as zn, TWriteTableResolver as zt };
4576
+ export { TDbInsertResult as $, DbSpace as $t, TColumnDiff as A, TRelationFilterJunction as An, TReferencingForeignKey as At, TDbDefaultFn as B, TDbEncryptionOptions as Bn, TWriteOptions as Bt, NavPropsOf$1 as C, AtscriptDbReadable as Cn, TIdDescriptor as Ct, PrimaryKeyOf$1 as D, REL_FILTER_MAX_NODES as Dn, TMetaResponse as Dt, OwnPropsOf$1 as E, REL_FILTER_MAX_DEPTH as En, TInsertOptions as Et, TDbActionLevel as F, forEachResolvedRelation as Fn, TTableOptionDiff as Ft, TDbIndex as G, TGenericLogger as Gn, WithRelation$1 as Gt, TDbDeleteResult as H, FieldMappingStrategy as Hn, TypedWithRelation as Ht, TDbActionProcessor as I, hasRelationOp as In, TTableResolver as It, TDbInsertIgnoreOptions as J, TRowOrderKey as Jn, isGeoPointType as Jt, TDbIndexField as K, TExprAggregate as Kn, TableMetadata as Kt, TDbActionTargetSummary as L, isResolvedRelationFilter as Ln, TTouchManyOptions as Lt, TCrudPermissions as M, TRelationStaticFilter as Mn, TRowResolveOptions as Mt, TDbActionInfo as N, andFilters as Nn, TSearchIndexInfo as Nt, TCascadeResolver as O, ResolvedRelationFilter as On, TMetadataOverrides as Ot, TDbActionIntent as P, containsRelationFilter as Pn, TSyncColumnResult as Pt, TDbInsertManyResult as Q, TViewCapability as Qt, TDbAvailableActions as R, relationStaticFilter as Rn, TValueFormatterPair as Rt, FlatOf$1 as S, TCascadePin as Sn, TFkLookupTarget as St, NullsPlacement$1 as T, resolveDesignType as Tn, TIdentification as Tt, TDbFieldMeta as U, TReadControls as Un, Uniquery$1 as Ut, TDbDefaultValue as V, DocumentFieldMapper as Vn, TWriteTableResolver as Vt, TDbForeignKey as W, NoopLogger as Wn, UniqueryControls$1 as Wt, TDbInsertIgnoreSlot as X, ALL_VIEW_CAPABILITIES as Xt, TDbInsertIgnoreResult as Y, UniquSelect as Yn, ALL_BUCKET_UNITS as Yt, TDbInsertManyIgnoreResult as Z, BaseDbAdapter as Zt, DbPatch as _, isFieldRef as _n, TExistingColumn as _t, isJsonValueField as a, isViewType as an, TDbStorageType as at, FieldOpsFor as b, IntegrityStrategy as bn, TFieldMeta as bt, resolveCalendarBuckets as c, AtscriptExprNode$1 as cn, TDbWriteAction as ct, AggregateFn$1 as d, AtscriptQueryFieldRef$1 as dn, TDbWriteGuard as dt, TAdapterFactory as en, TDbObjectKind as et, AggregateQuery$1 as f, AtscriptQueryNode$1 as fn, TDbWriteGuardContext as ft, DbControls as g, evaluateExpr as gn, TEnsureTableOptions as gt, AtscriptDbWritable as h, TViewPlan as hn, TDerivedColumn as ht, isBucketableField as i, isAtscriptDbView as in, TDbRemoveGuardContext as it, TCrudOp as j, TRelationFilterTable as jn, TRelationInfo as jt, TCascadeTarget as k, TRelGuardState as kn, TPrimaryKeyChange as kt, AggregateControls as l, AtscriptOrderItem as ln, TDbWriteCheck as lt, AtscriptDbTableLike as m, TViewJoin as mn, TDerivedChangeReason as mt, TComputedSelect as n, AtscriptDbView as nn, TDbRelation as nt, jsonValueAncestor as o, TViewReadPlan as on, TDbUpdateOptions as ot, AggregateResult as p, AtscriptRef as pn, TDeleteOptions as pt, TDbIndexType as q, TFirstLast as qn, isGeoIndexableType as qt, TResolvedBucket as r, TViewColumnMapping as rn, TDbRemoveGuard as rt, normalizeComputedSelect as s, aliasTargetOf as sn, TDbUpdateResult as st, TBucketFieldSource as t, TDbSpaceOptions as tn, TDbReferentialAction as tt, AggregateExpr$1 as u, AtscriptQueryComparison as un, TDbWriteCheckContext as ut, DbQuery as v, translateQueryTree as vn, TExistingForeignKey as vt, NullableOptional as w, DbResponse as wn, TIdResolveOptions as wt, FilterExpr$1 as x, NativeIntegrity as xn, TFkLookupResolver as xt, DbRow as y, AtscriptDbTable as yn, TExistingTableOption as yt, TDbCollation as z, DbEncryption as zn, TViewJsonType as zt };