/** * @license * Copyright 2025 Steven Roussey * SPDX-License-Identifier: Apache-2.0 */ import { DataPortSchemaObject, FromSchema, JsonSchema, TypedArraySchemaOptions } from "@workglow/util/schema"; import { BaseTabularStorage, ClientProvidedKeysOption } from "./BaseTabularStorage"; import { AutoGeneratedKeys, InsertEntity, OrderBy, Page, PageRequest, SearchCriteria, SimplifyPrimaryKey, ValueOptionType } from "./ITabularStorage"; /** * Base class for SQL-based tabular repositories, shared by SQLite and PostgreSQL * implementations. */ export declare abstract class BaseSqlTabularStorage, Entity = FromSchema, PrimaryKey = SimplifyPrimaryKey, Value = Omit, InsertType extends InsertEntity> = InsertEntity>> extends BaseTabularStorage { protected readonly table: string; /** Caches for computed column definition strings, keyed by quote delimiter. */ private readonly _pkColsCache; private readonly _valColsCache; private readonly _pkColListCache; private readonly _valColListCache; constructor(table: string | undefined, schema: Schema, primaryKeyNames: PrimaryKeyNames, indexes?: readonly (keyof NoInfer | readonly (keyof NoInfer)[])[], clientProvidedKeys?: ClientProvidedKeysOption, tabularMigrations?: ReadonlyArray, migrationName?: string, uniqueIndexes?: readonly (readonly (keyof NoInfer)[])[]); /** Maps a JSON Schema type to its dialect-specific SQL type. */ protected abstract mapTypeToSQL(typeDef: JsonSchema): string; protected constructPrimaryKeyColumns($delimiter?: string): string; protected constructValueColumns($delimiter?: string): string; protected isNullable(typeDef: JsonSchema): boolean; protected primaryKeyColumnList($delimiter?: string): string; protected valueColumnList($delimiter?: string): string; /** Extracts the non-null branch from a `T | null` union schema. */ protected getNonNullType(typeDef: JsonSchema): JsonSchema; /** * Determines if a numeric field should be treated as unsigned, i.e. it is a * `number`/`integer` schema with a `minimum` of zero or greater. Shared by * the Postgres-shaped backends when selecting integer range types. */ protected shouldBeUnsigned(typeDef: JsonSchema): boolean; /** Returns value fields ordered to match the schema declaration. */ protected getValueAsOrderedArray(value: Value): ValueOptionType[]; protected getPrimaryKeyAsOrderedArray(key: PrimaryKey): ValueOptionType[]; protected jsToSqlValue(column: string, value: Entity[keyof Entity]): ValueOptionType; protected sqlToJsValue(column: string, value: ValueOptionType): Entity[keyof Entity]; /** * Rejects table names and schema keys that cannot be safely interpolated into * DDL, and rejects schemas where PK and value keys collide. */ protected validateTableAndSchema(): void; /** * Builds a keyset (seek) WHERE clause that selects rows strictly after * the cursor position according to the provided ordering. Handles mixed * ASC/DESC by expanding into the OR-of-AND form: * * (col1 OP1 v1) * OR (col1 = v1 AND col2 OP2 v2) * OR (col1 = v1 AND col2 = v2 AND col3 OP3 v3) * ... * * NULL handling. We adopt the same NULL ordering as the in-memory * comparator: NULLs sort *before* non-null values for ASC, *after* them * for DESC. The pair `runSqlPage` / `buildKeysetWhere` enforce this with * explicit `NULLS FIRST` / `NULLS LAST` in the ORDER BY plus NULL-aware * predicates here. Because the cursor's values are known at SQL-build * time, we branch at build time on NULL vs non-NULL rather than relying * on dialect-specific operators like `IS NOT DISTINCT FROM`: * * - Equality on a preceding column: * NULL -> `col IS NULL` * value -> `col = ?` * - Strict comparison on the i-th column: * ASC, NULL -> `col IS NOT NULL` (NULL is the smallest) * ASC, value -> `col > ?` (NULLs sort before, excluded) * DESC, NULL -> `1 = 0` (nothing comes after a NULL trailer) * DESC, value-> `(col < ? OR col IS NULL)` (smaller, then NULLs) * * @param effectiveOrderBy - Ordering to satisfy; must include the primary * key columns at the tail so the comparison is total. * @param cursorValues - Values pulled from the cursor in the same order * as `effectiveOrderBy`. * @param quote - Identifier quote character (e.g. `` ` `` or `"`). * @param placeholder - Function returning the placeholder string for the * given 1-based parameter index. * @param startIndex - Param index to start numbering from. Returns the * index to use after this clause's params. */ protected buildKeysetWhere(effectiveOrderBy: ReadonlyArray>, cursorValues: ReadonlyArray, quote: string, placeholder: (index: number) => string, startIndex: number): { whereClause: string; params: ValueOptionType[]; nextIndex: number; }; /** * Shared SQL `getPage`/`queryPage` driver. Builds a single SELECT that * pushes the keyset predicate, ordering, and limit down to the database * so memory and wire traffic are O(pageSize) regardless of table size. * * Concrete SQL backends call this from their `getPage`/`queryPage` * overrides, supplying the dialect-specific quoting, placeholder * formatting, search-criteria WHERE builder, and select executor. */ protected runSqlPage(criteria: SearchCriteria | undefined, request: PageRequest, dialect: { readonly quote: string; readonly placeholder: (index: number) => string; readonly buildSearchWhere: (criteria: SearchCriteria, startIndex: number) => { whereClause: string; params: ValueOptionType[]; nextIndex: number; }; readonly executeSelect: (sql: string, params: ValueOptionType[]) => Promise; }): Promise>; } //# sourceMappingURL=BaseSqlTabularStorage.d.ts.map