Skip to content

QueryModel

Read-only query interface for PostgreSQL tables. Use directly for read-only access, or extend via TableModel for full CRUD.

Import:

js
import { QueryModel } from 'pg-schemata';

Constructor

js
new QueryModel(db, pgp, schema, logger?)
ParameterTypeDescription
dbIDatabasepg-promise database or transaction instance
pgpIMainpg-promise library instance
schemaTableSchemaSchema definition object
loggerobjectOptional logger with .error() and .info() methods

Query Methods

findAll(options?)

Fetches all rows with optional pagination.

OptionTypeDefaultDescription
limitnumber50Maximum rows to return
offsetnumber0Rows to skip

Returns: Promise<Object[]>

findById(id)

Finds a single row by primary key.

ParameterTypeDescription
idstring | numberPrimary key value

Returns: Promise<Object | null>Throws: Error if ID is invalid

findByIdIncludingDeactivated(id)

Same as findById but includes soft-deleted records.

findOneBy(conditions, options?)

Finds the first row matching the given conditions. Always queries with LIMIT 1.

ParameterTypeDescription
conditionsObject[]Array of condition objects
optionsobjectSame as findWhere options; limit is ignored

Returns: Promise<Object | null>

findWhere(conditions?, joinType?, options?)

Finds rows matching conditions with full query options.

ParameterTypeDefaultDescription
conditionsObject[] | Object[]Condition objects; a single plain object is treated as a one-element array
joinTypestring'AND''AND' or 'OR'
options.columnWhiteliststring[]nullColumns to return
options.filtersobject{}Additional filter object
options.orderBystring | string[]nullSort columns
options.limitnumbernullRow limit
options.offsetnumbernullRow offset
options.includeDeactivatedbooleanfalseInclude soft-deleted rows

Returns: Promise<Object[]>

findAfterCursor(cursor?, limit?, orderBy?, options?)

Keyset-based cursor pagination.

ParameterTypeDefaultDescription
cursorobject{}Cursor values keyed by orderBy columns
limitnumber50Maximum rows
orderBystring[]['id']Columns for ordering
options.descendingbooleanfalseDescending order. Applies to every column in orderBy
options.columnWhiteliststring[]nullColumns to return. Must include every orderBy column
options.filtersobject{}Additional filters
options.includeDeactivatedbooleanfalseInclude soft-deleted rows

Returns: Promise<{ rows: Object[], nextCursor: Object | null }>

nextCursor is null on the last page, including one holding exactly limit rows: the query fetches limit + 1 rows and uses the extra one only to decide whether another page exists, returning at most limit. A caller can loop on the cursor without an extra empty round trip.

Throws: SchemaDefinitionError if columnWhitelist omits an orderBy column. The cursor is read off the last returned row, so an ordering column that is not projected would produce a cursor that cannot be passed back in.

findSoftDeleted(conditions?, joinType?, options?)

Returns only soft-deleted records.

Returns: Promise<Object[]>Throws: Error if soft delete is not enabled

isSoftDeleted(id)

Checks if a record is soft-deleted.

Returns: Promise<boolean>

Aggregation Methods

countWhere(conditions?, joinType?, options?)

Counts rows matching conditions.

ParameterTypeDefault
conditionsObject[] | Object[]
joinTypestring'AND'
options.filtersobject{}
options.includeDeactivatedbooleanfalse

A single plain object is treated as a one-element array. Anything else throws SchemaDefinitionError.

Returns: Promise<number>

countAll(options?)

Counts all rows in the table.

Returns: Promise<number>

exists(conditions, options?)

Checks if any row matches the given conditions.

ParameterTypeDescription
conditionsobjectNon-empty condition object

Returns: Promise<boolean>

Utility Methods

sanitizeDto(dto, options?)

Returns a filtered copy of the DTO containing only valid column names.

OptionTypeDefaultDescription
includeImmutablebooleantrueInclude immutable columns

validateDto(data, validator, type?)

Validates a DTO or array of DTOs against a Zod schema.

Throws: SchemaDefinitionError with .cause set to the Zod issues array (ZodError.issues)

buildWhereClause(where, requireNonEmpty?, values?, joinType?, includeDeactivated?)

Builds a SQL WHERE clause from conditions.

When soft delete is enabled and includeDeactivated is false, the returned clause is parenthesized before the deactivated_at IS NULL guard is appended — ("a" = $1 OR "b" = $2) AND deactivated_at IS NULL. Without the parentheses AND would bind tighter than OR and the guard would cover only the last disjunct.

Returns: { clause: string, values: any[] }

buildCondition(group, joiner?, values?)

Builds a SQL fragment from a group of condition objects.

An object carrying $and or $or also emits any ordinary column keys beside it, joined by joiner — see boolean groups alongside plain columns.

Returns: stringThrows: SchemaDefinitionError if joiner is not exactly 'AND' or 'OR'. JoinType erases at compile time and the value is interpolated between predicates as raw SQL, so it is checked at runtime as well.

buildValuesClause(data)

Generates a SQL-safe VALUES clause using the model's ColumnSet.

escapeName(name)

Escapes a column or table name using pg-promise.

forSchema(name)

Returns a model bound to the given schema without mutating this instance. Clones are cached per (instance, schema) pair, and the returned model's ColumnSet is built for the target schema.

Returns: This instance if already bound to name, otherwise a cached clone

reload(id, options?)

Reloads a record by ID. Pass { includeDeactivated: true } to include soft-deleted records; findById does not take options.

exportToSpreadsheet(filePath, where?, joinType?, options?)

Exports query results to an .xlsx file.

Returns: Promise<{ exported: number, filePath: string }>

Properties

PropertyTypeDescription
schemaTableSchemaThe full schema definition
schemaNamestringEscaped PostgreSQL schema name
tableNamestringEscaped table name

A lightweight Postgres-first ORM layer.