diff --git a/.changeset/quiet-garlics-compare.md b/.changeset/quiet-garlics-compare.md new file mode 100644 index 0000000000..1c5f10689a --- /dev/null +++ b/.changeset/quiet-garlics-compare.md @@ -0,0 +1,5 @@ +--- +"electric-sql": patch +--- + +Use parametrized SQL queries. diff --git a/clients/typescript/src/client/execution/db.ts b/clients/typescript/src/client/execution/db.ts index 9d0a76953a..8e4f1c42ae 100644 --- a/clients/typescript/src/client/execution/db.ts +++ b/clients/typescript/src/client/execution/db.ts @@ -12,22 +12,11 @@ import { Row, Statement } from '../../util' * some underlying drivers do not support promises. */ export interface DB { - run( - statement: string, - successCallback?: (tx: DB, res: RunResult) => void, - errorCallback?: (error: any) => void - ): void run( statement: QueryBuilder, successCallback?: (tx: DB, res: RunResult) => void, errorCallback?: (error: any) => void ): void - query( - statement: string, - schema: z.ZodType, - successCallback: (tx: DB, res: Z[]) => void, - errorCallback?: (error: any) => void - ): void query( statement: QueryBuilder, schema: z.ZodType, diff --git a/clients/typescript/src/client/execution/nonTransactionalDB.ts b/clients/typescript/src/client/execution/nonTransactionalDB.ts index a5dda9d23c..dc3e849b8b 100644 --- a/clients/typescript/src/client/execution/nonTransactionalDB.ts +++ b/clients/typescript/src/client/execution/nonTransactionalDB.ts @@ -8,12 +8,13 @@ export class NonTransactionalDB implements DB { constructor(private _adapter: DatabaseAdapter) {} run( - statement: string | QueryBuilder, + statement: QueryBuilder, successCallback?: (db: DB, res: RunResult) => void, errorCallback?: (error: any) => void ) { + const { text, values } = statement.toParam({ numberedParameters: false }) this._adapter - .run({ sql: statement.toString() }) + .run({ sql: text, args: values }) .then((res) => { if (typeof successCallback !== 'undefined') { try { @@ -33,13 +34,14 @@ export class NonTransactionalDB implements DB { } query( - statement: string | QueryBuilder, + statement: QueryBuilder, schema: z.ZodType, successCallback: (db: DB, res: Z[]) => void, errorCallback?: (error: any) => void ) { + const { text, values } = statement.toParam({ numberedParameters: false }) this._adapter - .query({ sql: statement.toString() }) + .query({ sql: text, args: values }) .then((rows) => { try { const objects = rows.map((row) => schema.parse(row)) diff --git a/clients/typescript/src/client/execution/transactionalDB.ts b/clients/typescript/src/client/execution/transactionalDB.ts index 7e2f006399..a4ebe62ff1 100644 --- a/clients/typescript/src/client/execution/transactionalDB.ts +++ b/clients/typescript/src/client/execution/transactionalDB.ts @@ -7,12 +7,13 @@ import { Row, Statement } from '../../util' export class TransactionalDB implements DB { constructor(private _tx: Transaction) {} run( - statement: QueryBuilder | string, + statement: QueryBuilder, successCallback?: (db: DB, res: RunResult) => void, errorCallback?: (error: any) => void ): void { + const { text, values } = statement.toParam({ numberedParameters: false }) this._tx.run( - { sql: statement.toString() }, + { sql: text, args: values }, (tx, res) => { if (typeof successCallback !== 'undefined') successCallback(new TransactionalDB(tx), res) @@ -22,13 +23,14 @@ export class TransactionalDB implements DB { } query( - statement: QueryBuilder | string, + statement: QueryBuilder, schema: z.ZodType, successCallback: (db: DB, res: Z[]) => void, errorCallback?: (error: any) => void ): void { + const { text, values } = statement.toParam({ numberedParameters: false }) this._tx.query( - { sql: statement.toString() }, + { sql: text, args: values }, (tx, rows) => { if (typeof successCallback !== 'undefined') { const objects = rows.map((row) => schema.parse(row)) //.partial().parse(row)) diff --git a/clients/typescript/src/squel.d.ts b/clients/typescript/src/squel.d.ts new file mode 100644 index 0000000000..7393a3cdee --- /dev/null +++ b/clients/typescript/src/squel.d.ts @@ -0,0 +1,8 @@ +import {} from 'squel' + +declare module 'squel' { + export interface ToParamOptions { + numberedParametersStartAt?: number + numberedParameters?: boolean + } +}