Skip to main content

Executing Queries

Both SqbClient and SqbConnection expose an execute() method with the same signature:

execute(query: string | Query, options?: QueryExecuteOptions): Promise<QueryResult>;

query is either a raw SQL string or a Query object built with @sqb/builder (Select(), Insert(), Update(), Delete(), ...).

client.execute() vs connection.execute()​

// SqbClient.execute(): acquires a connection, runs the query, releases the connection.
const result = await client.execute('select * from customers where id = $1', {
params: [1],
});
// SqbConnection.execute(): runs on a connection you already hold.
await client.acquire(async connection => {
const result = await connection.execute('select * from customers where id = $1', {
params: [1],
});
});

client.execute() is a convenience wrapper: it calls client.acquire() internally, runs your query on the freshly acquired connection, and releases that connection in a finally block — unless the result carries an open Cursor, in which case the connection is instead retain()-ed and only released once the cursor is closed. Use connection.execute() directly when you need multiple statements to share one connection (e.g. inside a transaction).

Queries on a given connection are also serialized through an internal task queue, so calling execute() multiple times concurrently on the same SqbConnection runs them one after another rather than interleaved.

QueryExecuteOptions​

interface QueryExecuteOptions {
params?: Record<string, any> | any[];
autoCommit?: boolean;
cursor?: boolean;
transform?: ValueTransformFunction;
fetchRows?: number;
ignoreNulls?: boolean;
namingStrategy?: FieldNaming;
objectRows?: boolean;
showSql?: boolean;
prettyPrint?: boolean;
action?: string;
fetchAsString?: DataType[];
}

Any option you don't pass falls back to the matching field on ClientDefaults (config.defaults from SqbClient's constructor), and if that's also unset, to a hard-coded runtime default. The table below documents the actual runtime defaults, verified directly against the _prepareQueryRequest() method in sqb-connection.ts — several of these differ from what the inline // Default = ... comments in the source say, so trust this table over the JSDoc:

OptionResolved viaRuntime defaultNotes
autoCommitoptions.autoCommit → connection's ConnectionOptions.autoCommit → defaults.autoCommit → truetrueOnly applies when the connection isn't already inside a transaction — if connection.inTransaction is true, autoCommit is forced to false regardless of what you pass. The JSDoc on ConnectionOptions.autoCommit / QueryExecuteOptions.autoCommit says "Default = false" — that is incorrect; outside a transaction, a query auto-commits unless you explicitly pass autoCommit: false.
cursoroptions.cursor → defaults.cursor → falsefalseSee Cursors & Streaming.
objectRowsoptions.objectRows → defaults.objectRows → truetrueRows are returned as plain objects (keyed by field name) unless you opt into array rows. The JSDoc says "Default = driver default" — in the actual code it's hard-coded to true, independent of the adapter.
ignoreNullsoptions.ignoreNulls → defaults.ignoreNulls → falsefalseAlso forced back to false whenever the effective objectRows is false — ignoreNulls only ever applies to object rows.
fetchRowsoptions.fetchRows → defaults.fetchRows → 100100In regular (non-cursor) mode, the maximum number of rows fetched. In cursor mode, the prefetch batch size (see Cursors & Streaming). Both ClientDefaults.fetchRows and QueryExecuteOptions.fetchRows carry a stale // Default = 10 comment in the source — the actual fallback coded in _prepareQueryRequest() is 100.
namingStrategyoptions.namingStrategy → defaults.fieldNaming → undefinednone (original names)See FieldNaming.
transformoptions.transform → defaults.transform → undefinednoneSee below.
showSqloptions.showSql → defaults.showSql → falsefalseWhen true, QueryResult.query is populated with the executed QueryRequest (SQL + params).
prettyPrintoptions.prettyPrint → defaults.prettyPrint → falsefalsePassed through to the SQL generator when the query is a Query builder object.
params—nonePositional array or named-parameter object, forwarded to the query generator (for Query objects) or the driver (for raw SQL).
action—''Free-form label attached to the request, mainly useful for logging/hooks.
fetchAsString—noneList of DataTypes the adapter should coerce to string instead of native type.

objectRows and row shape​

With the default objectRows: true, rows come back as Record<string, any> keyed by field name (after namingStrategy is applied). With objectRows: false, rows come back as arrays, positioned by QueryResult.fields' index.

Field naming​

namingStrategy accepts a FieldNaming value — 'original' | 'lowercase' | 'uppercase' | 'camelcase' | 'pascalcase', or a (fieldName: string) => string | undefined function. It renames both the keys on object rows and the name field on each FieldInfo in QueryResult.fields. Returning undefined from a custom function drops that field from object rows entirely.

transform​

type ValueTransformFunction = (value: any, fieldInfo?: FieldInfo) => any;

Runs over every field value as rows are normalized, letting you convert/mask driver values before they reach your code (e.g. converting a driver-specific date type to a plain Date).

Reading the result: QueryResult​

interface QueryResult {
executeTime: number;
fields?: FieldInfoMap;
rows?: any;
rowType?: 'array' | 'object';
query?: QueryRequest; // only populated when showSql: true
returns?: any;
rowsAffected?: number;
cursor?: Cursor; // only populated when cursor: true
}
  • executeTime — milliseconds the query took, measured around the adapter call.
  • fields / rowType / rows — populated for statements that return rows (accessing result.fields.get('columnName') gives you a FieldInfo).
  • rowsAffected — populated for statements that report an affected-row count (e.g. UPDATE, DELETE).
  • cursor — populated instead of rows when cursor: true was requested — see Cursors & Streaming.

Example: raw SQL with parameters​

const result = await client.execute(
'select id, name from customers where active = $1',
{ params: [true], fetchRows: 500 },
);
console.log(result.rows);

Next steps​