@atscript/db-postgres 0.1.146 → 0.1.148

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import { AggregateFn, BaseDbAdapter, BucketUnit, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDefaultFn, TDbDeleteResult, TDbFieldMeta, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TPrimaryKeyChange, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair } from "@atscript/db";
1
+ import { AggregateFn, BaseDbAdapter, BucketUnit, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDefaultFn, TDbDeleteResult, TDbFieldMeta, TDbInsertIgnoreSlot, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TPrimaryKeyChange, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair, TViewCapability } from "@atscript/db";
2
2
  import { TMetadataMap } from "@atscript/typescript/utils";
3
- import { TSqlFragment } from "@atscript/db-sql-tools";
3
+ import { TFilterVisitorOptions, TSqlFragment } from "@atscript/db-sql-tools";
4
4
 
5
5
  //#region src/types.d.ts
6
6
  /**
@@ -89,7 +89,7 @@ declare class PostgresAdapter extends BaseDbAdapter {
89
89
  private _vectorThresholds;
90
90
  /**
91
91
  * Schema name for catalog queries and qualification — `@db.schema` of the
92
- * bound table, or `null` (→ `'public'`, the same default the bound path
92
+ * bound table, or `null` (→ the connection's `current_schema()`, the same default the bound path
93
93
  * uses) when the table declares none or the adapter is an administrative
94
94
  * one with no readable (the name-taking schema-sync primitives run on such
95
95
  * an adapter).
@@ -108,6 +108,13 @@ declare class PostgresAdapter extends BaseDbAdapter {
108
108
  * otherwise the pool-based driver.
109
109
  */
110
110
  private _exec;
111
+ /**
112
+ * Relational predicates (`$some` / `$none`) render as correlated
113
+ * `[NOT] EXISTS` subqueries — in reads and in mutation filters alike.
114
+ *
115
+ * @since 0.1.147
116
+ */
117
+ supportsRelationFilters(_mode: "read" | "write"): boolean;
111
118
  /** PostgreSQL enforces FK constraints natively. */
112
119
  supportsNativeForeignKeys(): boolean;
113
120
  prepareId(id: unknown, _fieldType: unknown): unknown;
@@ -118,8 +125,12 @@ declare class PostgresAdapter extends BaseDbAdapter {
118
125
  * server's tz database (an unknown one maps to `BUCKET_TZ_UNAVAILABLE`).
119
126
  */
120
127
  calendarBucketUnits(): ReadonlySet<BucketUnit>;
121
- /** Every aggregate function, `countDistinct` included. */
128
+ /** Every aggregate function: `countDistinct`, `first` and `last` included. */
122
129
  aggregateFns(): ReadonlySet<AggregateFn>;
130
+ /** Arithmetic in an aggregate `$select` (`{ $expr }`, `{ $fn, $expr }`). */
131
+ supportsAggregateExpressions(): boolean;
132
+ /** Computed view columns and first-row joins. */
133
+ viewCapabilities(): ReadonlySet<TViewCapability>;
123
134
  onBeforeFlatten(_type: unknown): void;
124
135
  onAfterFlatten(): void;
125
136
  onFieldScanned(field: string, _type: unknown, metadata: TMetadataMap<AtscriptMetadata>): void;
@@ -140,22 +151,35 @@ declare class PostgresAdapter extends BaseDbAdapter {
140
151
  * - 23503 = foreign_key_violation
141
152
  */
142
153
  private _wrapConstraintError;
154
+ /** Rethrows `error` as a structured `DbError` when it is a unique / FK violation, else as is. */
155
+ private _mapConstraintError;
143
156
  private _extractFieldFromConstraint;
144
157
  private _mapFkError;
145
158
  insertOne(data: Record<string, unknown>): Promise<TDbInsertResult>;
146
159
  insertMany(data: Array<Record<string, unknown>>): Promise<TDbInsertManyResult>;
160
+ supportsInsertIgnore(): boolean;
161
+ /**
162
+ * Batched `INSERT … VALUES (…), (…) ON CONFLICT DO NOTHING RETURNING <pk +
163
+ * unique key columns>`: one statement per chunk (a conflict never raises, so
164
+ * the surrounding transaction survives). Skipped rows are the ones missing
165
+ * from RETURNING — mapped back by key values, see {@link mapIgnoredBatch}.
166
+ * Each chunk runs inside a SAVEPOINT: when the mapping is ambiguous (a key
167
+ * the server returns in another form than it was sent) the chunk is rolled
168
+ * back to the savepoint and redone row by row with the same
169
+ * `ON CONFLICT DO NOTHING`, so the result is always exact.
170
+ */
171
+ insertManyIgnore(data: Array<Record<string, unknown>>): Promise<TDbInsertIgnoreSlot[]>;
147
172
  findOne(query: DbQuery): Promise<Record<string, unknown> | null>;
148
173
  findMany(query: DbQuery): Promise<Array<Record<string, unknown>>>;
149
- count(query: DbQuery): Promise<number>;
150
- aggregate(query: DbQuery): Promise<Array<Record<string, unknown>>>;
151
174
  /**
152
- * Maps PostgreSQL's unknown-zone error — SQLSTATE 22023
153
- * (`invalid_parameter_value`), `time zone "…" not recognized` — raised by a
154
- * calendar bucket's `AT TIME ZONE '<tz>'` to `BUCKET_TZ_UNAVAILABLE`. The
155
- * zone passed the core's IANA validation, so the server's tz database is
156
- * older than the runtime's. Other errors propagate unchanged.
175
+ * `$skip` / `$limit` per partition in one statement: a `ROW_NUMBER()`
176
+ * window over `partitionBy` (the generic `$with` loader's per-parent page).
157
177
  */
158
- private _wrapBucketZoneError;
178
+ findManyPerPartition(query: DbQuery, partitionBy: readonly string[]): Promise<Array<Record<string, unknown>>>;
179
+ count(query: DbQuery): Promise<number>;
180
+ aggregate(query: DbQuery): Promise<Array<Record<string, unknown>>>;
181
+ /** Physical primary-key columns (`@db.column` renames applied). */
182
+ private _pkColumns;
159
183
  /**
160
184
  * The predicate that narrows a single-row UPDATE/DELETE to the first row
161
185
  * matching `whereSql`: `<key> <op> (SELECT <cols> … LIMIT 1)`. Single-col
@@ -329,6 +353,8 @@ declare class PgDriver implements TPgDriver {
329
353
  get<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T | null>;
330
354
  exec(sql: string): Promise<void>;
331
355
  getConnection(): Promise<TPgConnection>;
356
+ private _closing?;
357
+ /** Idempotent: every call returns the first call's promise. */
332
358
  close(): Promise<void>;
333
359
  }
334
360
  //#endregion
@@ -342,8 +368,14 @@ declare class PgDriver implements TPgDriver {
342
368
  *
343
369
  * Case-insensitive columns (`@db.collate 'nocase'`) are handled by CITEXT
344
370
  * column type at the storage level — no query-side wrapping needed.
371
+ *
372
+ * Relational predicates (`$some` / `$none`) render as correlated `EXISTS`
373
+ * subqueries referencing the outer table by `opts.qualifier` (default: the
374
+ * source table) — a statement with an aliased FROM must pass its alias.
375
+ *
376
+ * @param opts - since 0.1.147
345
377
  */
346
- declare function buildWhere(filter: FilterExpr): TSqlFragment;
378
+ declare function buildWhere(filter: FilterExpr, opts?: TFilterVisitorOptions): TSqlFragment;
347
379
  //#endregion
348
380
  //#region src/index.d.ts
349
381
  /**
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { AggregateFn, BaseDbAdapter, BucketUnit, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDefaultFn, TDbDeleteResult, TDbFieldMeta, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TPrimaryKeyChange, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair } from "@atscript/db";
2
- import { TSqlFragment } from "@atscript/db-sql-tools";
1
+ import { AggregateFn, BaseDbAdapter, BucketUnit, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDefaultFn, TDbDeleteResult, TDbFieldMeta, TDbInsertIgnoreSlot, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TPrimaryKeyChange, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair, TViewCapability } from "@atscript/db";
2
+ import { TFilterVisitorOptions, TSqlFragment } from "@atscript/db-sql-tools";
3
3
  import { TMetadataMap } from "@atscript/typescript/utils";
4
4
 
5
5
  //#region src/types.d.ts
@@ -89,7 +89,7 @@ declare class PostgresAdapter extends BaseDbAdapter {
89
89
  private _vectorThresholds;
90
90
  /**
91
91
  * Schema name for catalog queries and qualification — `@db.schema` of the
92
- * bound table, or `null` (→ `'public'`, the same default the bound path
92
+ * bound table, or `null` (→ the connection's `current_schema()`, the same default the bound path
93
93
  * uses) when the table declares none or the adapter is an administrative
94
94
  * one with no readable (the name-taking schema-sync primitives run on such
95
95
  * an adapter).
@@ -108,6 +108,13 @@ declare class PostgresAdapter extends BaseDbAdapter {
108
108
  * otherwise the pool-based driver.
109
109
  */
110
110
  private _exec;
111
+ /**
112
+ * Relational predicates (`$some` / `$none`) render as correlated
113
+ * `[NOT] EXISTS` subqueries — in reads and in mutation filters alike.
114
+ *
115
+ * @since 0.1.147
116
+ */
117
+ supportsRelationFilters(_mode: "read" | "write"): boolean;
111
118
  /** PostgreSQL enforces FK constraints natively. */
112
119
  supportsNativeForeignKeys(): boolean;
113
120
  prepareId(id: unknown, _fieldType: unknown): unknown;
@@ -118,8 +125,12 @@ declare class PostgresAdapter extends BaseDbAdapter {
118
125
  * server's tz database (an unknown one maps to `BUCKET_TZ_UNAVAILABLE`).
119
126
  */
120
127
  calendarBucketUnits(): ReadonlySet<BucketUnit>;
121
- /** Every aggregate function, `countDistinct` included. */
128
+ /** Every aggregate function: `countDistinct`, `first` and `last` included. */
122
129
  aggregateFns(): ReadonlySet<AggregateFn>;
130
+ /** Arithmetic in an aggregate `$select` (`{ $expr }`, `{ $fn, $expr }`). */
131
+ supportsAggregateExpressions(): boolean;
132
+ /** Computed view columns and first-row joins. */
133
+ viewCapabilities(): ReadonlySet<TViewCapability>;
123
134
  onBeforeFlatten(_type: unknown): void;
124
135
  onAfterFlatten(): void;
125
136
  onFieldScanned(field: string, _type: unknown, metadata: TMetadataMap<AtscriptMetadata>): void;
@@ -140,22 +151,35 @@ declare class PostgresAdapter extends BaseDbAdapter {
140
151
  * - 23503 = foreign_key_violation
141
152
  */
142
153
  private _wrapConstraintError;
154
+ /** Rethrows `error` as a structured `DbError` when it is a unique / FK violation, else as is. */
155
+ private _mapConstraintError;
143
156
  private _extractFieldFromConstraint;
144
157
  private _mapFkError;
145
158
  insertOne(data: Record<string, unknown>): Promise<TDbInsertResult>;
146
159
  insertMany(data: Array<Record<string, unknown>>): Promise<TDbInsertManyResult>;
160
+ supportsInsertIgnore(): boolean;
161
+ /**
162
+ * Batched `INSERT … VALUES (…), (…) ON CONFLICT DO NOTHING RETURNING <pk +
163
+ * unique key columns>`: one statement per chunk (a conflict never raises, so
164
+ * the surrounding transaction survives). Skipped rows are the ones missing
165
+ * from RETURNING — mapped back by key values, see {@link mapIgnoredBatch}.
166
+ * Each chunk runs inside a SAVEPOINT: when the mapping is ambiguous (a key
167
+ * the server returns in another form than it was sent) the chunk is rolled
168
+ * back to the savepoint and redone row by row with the same
169
+ * `ON CONFLICT DO NOTHING`, so the result is always exact.
170
+ */
171
+ insertManyIgnore(data: Array<Record<string, unknown>>): Promise<TDbInsertIgnoreSlot[]>;
147
172
  findOne(query: DbQuery): Promise<Record<string, unknown> | null>;
148
173
  findMany(query: DbQuery): Promise<Array<Record<string, unknown>>>;
149
- count(query: DbQuery): Promise<number>;
150
- aggregate(query: DbQuery): Promise<Array<Record<string, unknown>>>;
151
174
  /**
152
- * Maps PostgreSQL's unknown-zone error — SQLSTATE 22023
153
- * (`invalid_parameter_value`), `time zone "…" not recognized` — raised by a
154
- * calendar bucket's `AT TIME ZONE '<tz>'` to `BUCKET_TZ_UNAVAILABLE`. The
155
- * zone passed the core's IANA validation, so the server's tz database is
156
- * older than the runtime's. Other errors propagate unchanged.
175
+ * `$skip` / `$limit` per partition in one statement: a `ROW_NUMBER()`
176
+ * window over `partitionBy` (the generic `$with` loader's per-parent page).
157
177
  */
158
- private _wrapBucketZoneError;
178
+ findManyPerPartition(query: DbQuery, partitionBy: readonly string[]): Promise<Array<Record<string, unknown>>>;
179
+ count(query: DbQuery): Promise<number>;
180
+ aggregate(query: DbQuery): Promise<Array<Record<string, unknown>>>;
181
+ /** Physical primary-key columns (`@db.column` renames applied). */
182
+ private _pkColumns;
159
183
  /**
160
184
  * The predicate that narrows a single-row UPDATE/DELETE to the first row
161
185
  * matching `whereSql`: `<key> <op> (SELECT <cols> … LIMIT 1)`. Single-col
@@ -329,6 +353,8 @@ declare class PgDriver implements TPgDriver {
329
353
  get<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T | null>;
330
354
  exec(sql: string): Promise<void>;
331
355
  getConnection(): Promise<TPgConnection>;
356
+ private _closing?;
357
+ /** Idempotent: every call returns the first call's promise. */
332
358
  close(): Promise<void>;
333
359
  }
334
360
  //#endregion
@@ -342,8 +368,14 @@ declare class PgDriver implements TPgDriver {
342
368
  *
343
369
  * Case-insensitive columns (`@db.collate 'nocase'`) are handled by CITEXT
344
370
  * column type at the storage level — no query-side wrapping needed.
371
+ *
372
+ * Relational predicates (`$some` / `$none`) render as correlated `EXISTS`
373
+ * subqueries referencing the outer table by `opts.qualifier` (default: the
374
+ * source table) — a statement with an aliased FROM must pass its alias.
375
+ *
376
+ * @param opts - since 0.1.147
345
377
  */
346
- declare function buildWhere(filter: FilterExpr): TSqlFragment;
378
+ declare function buildWhere(filter: FilterExpr, opts?: TFilterVisitorOptions): TSqlFragment;
347
379
  //#endregion
348
380
  //#region src/index.d.ts
349
381
  /**