serverless: Add support for named parameters

This commit is contained in:
Pekka Enberg
2025-07-30 14:30:54 +03:00
parent 1b8d95a79f
commit fff7bf52f3
3 changed files with 38 additions and 15 deletions

View File

@@ -18,12 +18,17 @@ export interface ExecuteResult {
last_insert_rowid?: string;
}
export interface NamedArg {
name: string;
value: Value;
}
export interface ExecuteRequest {
type: 'execute';
stmt: {
sql: string;
args: Value[];
named_args: Value[];
named_args: NamedArg[];
want_rows: boolean;
};
}
@@ -32,6 +37,7 @@ export interface BatchStep {
stmt: {
sql: string;
args: Value[];
named_args?: NamedArg[];
want_rows: boolean;
};
condition?: {

View File

@@ -8,7 +8,9 @@ import {
type CursorEntry,
type PipelineRequest,
type SequenceRequest,
type CloseRequest
type CloseRequest,
type NamedArg,
type Value
} from './protocol.js';
import { DatabaseError } from './error.js';
@@ -50,10 +52,10 @@ export class Session {
* Execute a SQL statement and return all results.
*
* @param sql - The SQL statement to execute
* @param args - Optional array of parameter values
* @param args - Optional array of parameter values or object with named parameters
* @returns Promise resolving to the complete result set
*/
async execute(sql: string, args: any[] = []): Promise<any> {
async execute(sql: string, args: any[] | Record<string, any> = []): Promise<any> {
const { response, entries } = await this.executeRaw(sql, args);
const result = await this.processCursorEntries(entries);
return result;
@@ -63,17 +65,31 @@ export class Session {
* Execute a SQL statement and return the raw response and entries.
*
* @param sql - The SQL statement to execute
* @param args - Optional array of parameter values
* @param args - Optional array of parameter values or object with named parameters
* @returns Promise resolving to the raw response and cursor entries
*/
async executeRaw(sql: string, args: any[] = []): Promise<{ response: CursorResponse; entries: AsyncGenerator<CursorEntry> }> {
async executeRaw(sql: string, args: any[] | Record<string, any> = []): Promise<{ response: CursorResponse; entries: AsyncGenerator<CursorEntry> }> {
let positionalArgs: Value[] = [];
let namedArgs: NamedArg[] = [];
if (Array.isArray(args)) {
positionalArgs = args.map(encodeValue);
} else {
// Convert object with named parameters to NamedArg array
namedArgs = Object.entries(args).map(([name, value]) => ({
name,
value: encodeValue(value)
}));
}
const request: CursorRequest = {
baton: this.baton,
batch: {
steps: [{
stmt: {
sql,
args: args.map(encodeValue),
args: positionalArgs,
named_args: namedArgs,
want_rows: true
}
}]
@@ -181,6 +197,7 @@ export class Session {
stmt: {
sql,
args: [],
named_args: [],
want_rows: false
}
}))

View File

@@ -26,7 +26,7 @@ export class Statement {
/**
* Executes the prepared statement.
*
* @param args - Optional array of parameter values for the SQL statement
* @param args - Optional array of parameter values or object with named parameters
* @returns Promise resolving to the result of the statement
*
* @example
@@ -36,7 +36,7 @@ export class Statement {
* console.log(`Inserted user with ID ${result.lastInsertRowid}`);
* ```
*/
async run(args: any[] = []): Promise<any> {
async run(args: any[] | Record<string, any> = []): Promise<any> {
const result = await this.session.execute(this.sql, args);
return { changes: result.rowsAffected, lastInsertRowid: result.lastInsertRowid };
}
@@ -44,7 +44,7 @@ export class Statement {
/**
* Execute the statement and return the first row.
*
* @param args - Optional array of parameter values for the SQL statement
* @param args - Optional array of parameter values or object with named parameters
* @returns Promise resolving to the first row or null if no results
*
* @example
@@ -56,7 +56,7 @@ export class Statement {
* }
* ```
*/
async get(args: any[] = []): Promise<any> {
async get(args: any[] | Record<string, any> = []): Promise<any> {
const result = await this.session.execute(this.sql, args);
return result.rows[0] || null;
}
@@ -64,7 +64,7 @@ export class Statement {
/**
* Execute the statement and return all rows.
*
* @param args - Optional array of parameter values for the SQL statement
* @param args - Optional array of parameter values or object with named parameters
* @returns Promise resolving to an array of all result rows
*
* @example
@@ -74,7 +74,7 @@ export class Statement {
* console.log(`Found ${activeUsers.length} active users`);
* ```
*/
async all(args: any[] = []): Promise<any[]> {
async all(args: any[] | Record<string, any> = []): Promise<any[]> {
const result = await this.session.execute(this.sql, args);
return result.rows;
}
@@ -85,7 +85,7 @@ export class Statement {
* This method provides memory-efficient processing of large result sets
* by streaming rows one at a time instead of loading everything into memory.
*
* @param args - Optional array of parameter values for the SQL statement
* @param args - Optional array of parameter values or object with named parameters
* @returns AsyncGenerator that yields individual rows
*
* @example
@@ -97,7 +97,7 @@ export class Statement {
* }
* ```
*/
async *iterate(args: any[] = []): AsyncGenerator<any> {
async *iterate(args: any[] | Record<string, any> = []): AsyncGenerator<any> {
const { response, entries } = await this.session.executeRaw(this.sql, args);
let columns: string[] = [];