From b977e9ce182c0474c92485ad4d712f8da4429efa Mon Sep 17 00:00:00 2001 From: "Visal .In" Date: Thu, 21 Nov 2024 13:32:44 +0700 Subject: [PATCH 01/11] support raw based holder --- src/connections/postgre/postgresql.ts | 13 +-- src/connections/sql-base.ts | 33 ++++++- src/utils/placeholder.ts | 133 ++++++++++++++++++++++++++ 3 files changed, 166 insertions(+), 13 deletions(-) create mode 100644 src/utils/placeholder.ts diff --git a/src/connections/postgre/postgresql.ts b/src/connections/postgre/postgresql.ts index 6787e5b..7acd3d2 100644 --- a/src/connections/postgre/postgresql.ts +++ b/src/connections/postgre/postgresql.ts @@ -3,22 +3,16 @@ import { QueryResult } from '..'; import { Query } from '../../query'; import { AbstractDialect } from './../../query-builder'; import { PostgresDialect } from './../../query-builder/dialects/postgres'; -import { QueryType } from './../../query-params'; import { createErrorResult, transformArrayBasedResult, } from './../../utils/transformer'; import { PostgreBaseConnection } from './base'; -function replacePlaceholders(query: string): string { - let index = 1; - return query.replace(/\?/g, () => `$${index++}`); -} - export class PostgreSQLConnection extends PostgreBaseConnection { client: Client; dialect: AbstractDialect = new PostgresDialect(); - queryType: QueryType = QueryType.positional; + protected numberedPlaceholder = true; constructor(pgClient: any) { super(); @@ -38,10 +32,7 @@ export class PostgreSQLConnection extends PostgreBaseConnection { ): Promise> { try { const { rows, fields } = await this.client.query({ - text: - query.parameters?.length === 0 - ? query.query - : replacePlaceholders(query.query), + text: query.query, rowMode: 'array', values: query.parameters as unknown[], }); diff --git a/src/connections/sql-base.ts b/src/connections/sql-base.ts index 9cba01d..5df9114 100644 --- a/src/connections/sql-base.ts +++ b/src/connections/sql-base.ts @@ -7,9 +7,14 @@ import { } from '..'; import { AbstractDialect, ColumnDataType } from './../query-builder'; import { TableColumn, TableColumnDefinition } from './../models/database'; +import { + namedPlaceholder, + toNumberedPlaceholders, +} from './../utils/placeholder'; export abstract class SqlConnection extends Connection { abstract dialect: AbstractDialect; + protected numberedPlaceholder = false; abstract query>( query: Query @@ -21,8 +26,32 @@ export abstract class SqlConnection extends Connection { return dataType; } - async raw(query: string): Promise { - return await this.query({ query }); + async raw( + query: string, + params?: Record | unknown[] + ): Promise { + if (!params) return await this.query({ query }); + + // Positional placeholder + if (Array.isArray(params)) { + if (this.numberedPlaceholder) { + const { query: newQuery, bindings } = toNumberedPlaceholders( + query, + params + ); + + return await this.query({ + query: newQuery, + parameters: bindings, + }); + } + + return await this.query({ query, parameters: params }); + } + + // Named placeholder + const { query: newQuery, bindings } = namedPlaceholder(query, params!); + return await this.query({ query: newQuery, parameters: bindings }); } async select( diff --git a/src/utils/placeholder.ts b/src/utils/placeholder.ts new file mode 100644 index 0000000..3be331a --- /dev/null +++ b/src/utils/placeholder.ts @@ -0,0 +1,133 @@ +const RE_PARAM = /(?:\?)|(?::(\d+|(?:[a-zA-Z][a-zA-Z0-9_]*)))/g, + DQUOTE = 34, + SQUOTE = 39, + BSLASH = 92; + +/** + * This code is based on https://github.com/mscdex/node-mariasql/blob/master/lib/Client.js#L296-L420 + * License: https://github.com/mscdex/node-mariasql/blob/master/LICENSE + * + * @param query + * @returns + */ +function parse(query: string): [string] | [string[], (string | number)[]] { + let ppos = RE_PARAM.exec(query); + let curpos = 0; + let start = 0; + let end; + const parts = []; + let inQuote = false; + let escape = false; + let qchr; + const tokens = []; + let qcnt = 0; + let lastTokenEndPos = 0; + let i; + + if (ppos) { + do { + for (i = curpos, end = ppos.index; i < end; ++i) { + let chr = query.charCodeAt(i); + console.log(i, query[i], inQuote, qchr); + if (chr === BSLASH) escape = !escape; + else { + if (escape) { + escape = false; + continue; + } + if (inQuote && chr === qchr) { + if (query.charCodeAt(i + 1) === qchr) { + // quote escaped via "" or '' + ++i; + continue; + } + inQuote = false; + } else if (!inQuote && (chr === DQUOTE || chr === SQUOTE)) { + inQuote = true; + qchr = chr; + } + } + } + if (!inQuote) { + parts.push(query.substring(start, end)); + tokens.push(ppos[0].length === 1 ? qcnt++ : ppos[1]); + start = end + ppos[0].length; + lastTokenEndPos = start; + } + curpos = end + ppos[0].length; + } while ((ppos = RE_PARAM.exec(query))); + + if (tokens.length) { + if (curpos < query.length) { + parts.push(query.substring(lastTokenEndPos)); + } + return [parts, tokens]; + } + } + return [query]; +} + +export function namedPlaceholder( + query: string, + params: Record, + numbered = false +): { query: string; bindings: unknown[] } { + const parts = parse(query); + + if (parts.length === 1) { + return { query, bindings: [] }; + } + + const bindings = []; + let newQuery = ''; + + const [sqlFragments, placeholders] = parts; + + for (let i = 0; i < sqlFragments.length; i++) { + newQuery += sqlFragments[i]; + + if (i < placeholders.length) { + const key = placeholders[i]; + + if (numbered) { + newQuery += `$${key}`; + } else { + newQuery += `?`; + } + + bindings.push(params[key]); + } + } + + return { query: newQuery, bindings }; +} + +export function toNumberedPlaceholders( + query: string, + params: unknown[] +): { + query: string; + bindings: unknown[]; +} { + const parts = parse(query); + + if (parts.length === 1) { + return { query, bindings: [] }; + } + + const bindings = []; + let newQuery = ''; + + const [sqlFragments, placeholders] = parts; + + for (let i = 0; i < sqlFragments.length; i++) { + newQuery += sqlFragments[i]; + + if (i < placeholders.length) { + newQuery += `$${i + 1}`; + bindings.push(params[i]); + } + } + + return { query: newQuery, bindings }; +} From acff5c5f08fe7e90e9f7dec70c4d35e3fa43f82e Mon Sep 17 00:00:00 2001 From: "Visal .In" Date: Thu, 21 Nov 2024 13:52:22 +0700 Subject: [PATCH 02/11] deprecated the query --- src/connections/bigquery.ts | 2 +- src/connections/index.ts | 5 ++++- src/connections/motherduck.ts | 2 +- src/connections/mysql.ts | 2 +- src/connections/postgre/postgresql.ts | 2 +- src/connections/snowflake/snowflake.ts | 2 +- src/connections/sql-base.ts | 24 ++++++++++++++++++++++-- src/connections/sqlite/cloudflare.ts | 2 +- src/connections/sqlite/starbase.ts | 2 +- src/connections/sqlite/turso.ts | 2 +- 10 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/connections/bigquery.ts b/src/connections/bigquery.ts index 8edcab4..04d8138 100644 --- a/src/connections/bigquery.ts +++ b/src/connections/bigquery.ts @@ -204,7 +204,7 @@ export class BigQueryConnection extends SqlConnection { * @param parameters - An object containing the parameters to be used in the query. * @returns Promise<{ data: any, error: Error | null }> */ - async query>( + async internalQuery>( query: Query ): Promise> { try { diff --git a/src/connections/index.ts b/src/connections/index.ts index 250da7b..4199a72 100644 --- a/src/connections/index.ts +++ b/src/connections/index.ts @@ -32,7 +32,10 @@ export abstract class Connection { // Retrieve metadata about the database, useful for introspection. abstract fetchDatabaseSchema(): Promise; - abstract raw(query: string): Promise; + abstract raw( + query: string, + params?: Record | unknown[] + ): Promise; abstract testConnection(): Promise<{ error?: string }>; // Connection common operations that will be used by Outerbase diff --git a/src/connections/motherduck.ts b/src/connections/motherduck.ts index d4dcc7b..06f181b 100644 --- a/src/connections/motherduck.ts +++ b/src/connections/motherduck.ts @@ -51,7 +51,7 @@ export class DuckDBConnection extends PostgreBaseConnection { * @param parameters - An object containing the parameters to be used in the query. * @returns Promise<{ data: any, error: Error | null }> */ - async query>( + async internalQuery>( query: Query ): Promise> { const connection = this.connection; diff --git a/src/connections/mysql.ts b/src/connections/mysql.ts index 6a002ac..33321b4 100644 --- a/src/connections/mysql.ts +++ b/src/connections/mysql.ts @@ -225,7 +225,7 @@ export class MySQLConnection extends SqlConnection { return super.mapDataType(dataType); } - async query>( + async internalQuery>( query: Query ): Promise> { try { diff --git a/src/connections/postgre/postgresql.ts b/src/connections/postgre/postgresql.ts index 7acd3d2..4c36088 100644 --- a/src/connections/postgre/postgresql.ts +++ b/src/connections/postgre/postgresql.ts @@ -27,7 +27,7 @@ export class PostgreSQLConnection extends PostgreBaseConnection { await this.client.end(); } - async query>( + async internalQuery>( query: Query ): Promise> { try { diff --git a/src/connections/snowflake/snowflake.ts b/src/connections/snowflake/snowflake.ts index b4a9798..fbfd365 100644 --- a/src/connections/snowflake/snowflake.ts +++ b/src/connections/snowflake/snowflake.ts @@ -175,7 +175,7 @@ export class SnowflakeConnection extends PostgreBaseConnection { ); } - async query>( + async internalQuery>( query: Query ): Promise> { try { diff --git a/src/connections/sql-base.ts b/src/connections/sql-base.ts index 5df9114..652753c 100644 --- a/src/connections/sql-base.ts +++ b/src/connections/sql-base.ts @@ -16,7 +16,7 @@ export abstract class SqlConnection extends Connection { abstract dialect: AbstractDialect; protected numberedPlaceholder = false; - abstract query>( + abstract internalQuery>( query: Query ): Promise>; @@ -26,6 +26,23 @@ export abstract class SqlConnection extends Connection { return dataType; } + /** + * This is a deprecated function, use raw instead. We keep this for + * backward compatibility. + * + * @deprecated + * @param query + * @returns + */ + async query>( + query: Query + ): Promise> { + return (await this.raw( + query.query, + query.parameters + )) as QueryResult; + } + async raw( query: string, params?: Record | unknown[] @@ -51,7 +68,10 @@ export abstract class SqlConnection extends Connection { // Named placeholder const { query: newQuery, bindings } = namedPlaceholder(query, params!); - return await this.query({ query: newQuery, parameters: bindings }); + return await this.internalQuery({ + query: newQuery, + parameters: bindings, + }); } async select( diff --git a/src/connections/sqlite/cloudflare.ts b/src/connections/sqlite/cloudflare.ts index 0ac5190..adf529a 100644 --- a/src/connections/sqlite/cloudflare.ts +++ b/src/connections/sqlite/cloudflare.ts @@ -107,7 +107,7 @@ export class CloudflareD1Connection extends SqliteBaseConnection { * @param parameters - An object containing the parameters to be used in the query. * @returns Promise<{ data: any, error: Error | null }> */ - async query>( + async internalQuery>( query: Query ): Promise> { if (!this.apiKey) throw new Error('Cloudflare API key is not set'); diff --git a/src/connections/sqlite/starbase.ts b/src/connections/sqlite/starbase.ts index 0d8ee5f..98bba73 100644 --- a/src/connections/sqlite/starbase.ts +++ b/src/connections/sqlite/starbase.ts @@ -90,7 +90,7 @@ export class StarbaseConnection extends SqliteBaseConnection { * @param parameters - An object containing the parameters to be used in the query. * @returns Promise<{ data: any, error: Error | null }> */ - async query>( + async internalQuery>( query: Query ): Promise> { if (!this.url) throw new Error('Starbase URL is not set'); diff --git a/src/connections/sqlite/turso.ts b/src/connections/sqlite/turso.ts index f323608..4e03cd2 100644 --- a/src/connections/sqlite/turso.ts +++ b/src/connections/sqlite/turso.ts @@ -16,7 +16,7 @@ export class TursoConnection extends SqliteBaseConnection { this.client = client; } - async query>( + async internalQuery>( query: Query ): Promise> { try { From 9cbefa7830bc70aa35637dcab3b09fef58651f61 Mon Sep 17 00:00:00 2001 From: "Visal .In" Date: Thu, 21 Nov 2024 13:53:43 +0700 Subject: [PATCH 03/11] raw now will call internalQuery --- src/connections/sql-base.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/connections/sql-base.ts b/src/connections/sql-base.ts index 652753c..8573799 100644 --- a/src/connections/sql-base.ts +++ b/src/connections/sql-base.ts @@ -47,7 +47,7 @@ export abstract class SqlConnection extends Connection { query: string, params?: Record | unknown[] ): Promise { - if (!params) return await this.query({ query }); + if (!params) return await this.internalQuery({ query }); // Positional placeholder if (Array.isArray(params)) { @@ -57,13 +57,13 @@ export abstract class SqlConnection extends Connection { params ); - return await this.query({ + return await this.internalQuery({ query: newQuery, parameters: bindings, }); } - return await this.query({ query, parameters: params }); + return await this.internalQuery({ query, parameters: params }); } // Named placeholder From 386f75867e0d5bde8d3bba298233f95fd2494f08 Mon Sep 17 00:00:00 2001 From: "Visal .In" Date: Thu, 21 Nov 2024 14:16:32 +0700 Subject: [PATCH 04/11] add test for raw with placeholders --- src/connections/sql-base.ts | 6 +++++- src/utils/placeholder.ts | 3 +-- tests/connections/connection.test.ts | 28 ++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/connections/sql-base.ts b/src/connections/sql-base.ts index 8573799..89d62eb 100644 --- a/src/connections/sql-base.ts +++ b/src/connections/sql-base.ts @@ -67,7 +67,11 @@ export abstract class SqlConnection extends Connection { } // Named placeholder - const { query: newQuery, bindings } = namedPlaceholder(query, params!); + const { query: newQuery, bindings } = namedPlaceholder( + query, + params!, + this.numberedPlaceholder + ); return await this.internalQuery({ query: newQuery, parameters: bindings, diff --git a/src/utils/placeholder.ts b/src/utils/placeholder.ts index 3be331a..ce2c484 100644 --- a/src/utils/placeholder.ts +++ b/src/utils/placeholder.ts @@ -28,7 +28,6 @@ function parse(query: string): [string] | [string[], (string | number)[]] { do { for (i = curpos, end = ppos.index; i < end; ++i) { let chr = query.charCodeAt(i); - console.log(i, query[i], inQuote, qchr); if (chr === BSLASH) escape = !escape; else { if (escape) { @@ -90,7 +89,7 @@ export function namedPlaceholder( const key = placeholders[i]; if (numbered) { - newQuery += `$${key}`; + newQuery += `$${i + 1}`; } else { newQuery += `?`; } diff --git a/tests/connections/connection.test.ts b/tests/connections/connection.test.ts index 8c45dc6..387e067 100644 --- a/tests/connections/connection.test.ts +++ b/tests/connections/connection.test.ts @@ -36,6 +36,34 @@ function cleanup(data: Record[]) { } describe('Database Connection', () => { + test('Support named parameters', async () => { + if (process.env.CONNECTION_TYPE === 'mongo') return; + + const sql = + process.env.CONNECTION_TYPE === 'mysql' + ? 'SELECT CONCAT(:hello, :world) AS testing_word' + : 'SELECT (:hello || :world) AS testing_word'; + + const { data } = await db.raw(sql, { + hello: 'hello ', + world: 'world', + }); + + expect(data).toEqual([{ testing_word: 'hello world' }]); + }); + + test('Support positional placeholder', async () => { + if (process.env.CONNECTION_TYPE === 'mongo') return; + + const sql = + process.env.CONNECTION_TYPE === 'mysql' + ? 'SELECT CONCAT(?, ?) AS testing_word' + : 'SELECT (? || ?) AS testing_word'; + + const { data } = await db.raw(sql, ['hello ', 'world']); + expect(data).toEqual([{ testing_word: 'hello world' }]); + }); + test('Create table', async () => { const { error: createTableTeamError } = await db.createTable( DEFAULT_SCHEMA, From 5cd76820ba3186d4efcb802443ab0bd9d5dd7b53 Mon Sep 17 00:00:00 2001 From: "Visal .In" Date: Thu, 21 Nov 2024 14:20:38 +0700 Subject: [PATCH 05/11] exclude the mongodb form testing the placeholder --- tests/connections/connection.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/connections/connection.test.ts b/tests/connections/connection.test.ts index 387e067..421d50a 100644 --- a/tests/connections/connection.test.ts +++ b/tests/connections/connection.test.ts @@ -37,7 +37,7 @@ function cleanup(data: Record[]) { describe('Database Connection', () => { test('Support named parameters', async () => { - if (process.env.CONNECTION_TYPE === 'mongo') return; + if (process.env.CONNECTION_TYPE === 'mongodb') return; const sql = process.env.CONNECTION_TYPE === 'mysql' From 9ed6e2be19160a43961eaa15f67259c9119b96a5 Mon Sep 17 00:00:00 2001 From: "Visal .In" Date: Thu, 21 Nov 2024 18:09:41 +0700 Subject: [PATCH 06/11] add more test case --- tests/connections/connection.test.ts | 2 +- tests/units/placeholder.test.ts | 73 ++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 tests/units/placeholder.test.ts diff --git a/tests/connections/connection.test.ts b/tests/connections/connection.test.ts index 421d50a..bc43424 100644 --- a/tests/connections/connection.test.ts +++ b/tests/connections/connection.test.ts @@ -53,7 +53,7 @@ describe('Database Connection', () => { }); test('Support positional placeholder', async () => { - if (process.env.CONNECTION_TYPE === 'mongo') return; + if (process.env.CONNECTION_TYPE === 'mongodb') return; const sql = process.env.CONNECTION_TYPE === 'mysql' diff --git a/tests/units/placeholder.test.ts b/tests/units/placeholder.test.ts new file mode 100644 index 0000000..b8aa61f --- /dev/null +++ b/tests/units/placeholder.test.ts @@ -0,0 +1,73 @@ +import { + namedPlaceholder, + toNumberedPlaceholders, +} from './../../src/utils/placeholder'; + +test('Positional placeholder', () => { + expect( + namedPlaceholder('SELECT * FROM users WHERE id = :id AND age > :age', { + id: 1, + age: 50, + }) + ).toEqual({ + query: 'SELECT * FROM users WHERE id = ? AND age > ?', + bindings: [1, 50], + }); +}); + +test('Positional placeholder inside the string should be ignored', () => { + expect( + namedPlaceholder( + 'SELECT * FROM users WHERE name = :name AND email = ":email"', + { + name: 'John', + } + ) + ).toEqual({ + query: 'SELECT * FROM users WHERE name = ? AND email = ":email"', + bindings: ['John'], + }); +}); + +test('Named placeholder to number placeholder', () => { + expect( + namedPlaceholder( + 'SELECT * FROM users WHERE id = :id AND age > :age', + { + id: 1, + age: 30, + }, + true + ) + ).toEqual({ + query: 'SELECT * FROM users WHERE id = $1 AND age > $2', + bindings: [1, 30], + }); +}); + +test('Named placeholder to number placeholder with string', () => { + expect( + namedPlaceholder( + 'SELECT * FROM users WHERE id = :id AND email = ":email"', + { + id: 1, + }, + true + ) + ).toEqual({ + query: 'SELECT * FROM users WHERE id = $1 AND email = ":email"', + bindings: [1], + }); +}); + +test('Convert positional placeholder to numbered placeholder', () => { + expect( + toNumberedPlaceholders( + `SELECT * FROM users WHERE id = ? AND email = '?' AND name = 'Outer""base' AND age > ?`, + [1, 30] + ) + ).toEqual({ + query: `SELECT * FROM users WHERE id = $1 AND email = '?' AND name = 'Outer""base' AND age > $2`, + bindings: [1, 30], + }); +}); From 599e04744558493d4b4d2edffa1b992128467486 Mon Sep 17 00:00:00 2001 From: "Visal .In" Date: Thu, 21 Nov 2024 18:09:58 +0700 Subject: [PATCH 07/11] bump version to 2.0.0-rc.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index af2525b..61d60dd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@outerbase/sdk", - "version": "2.0.0-rc.2", + "version": "2.0.0-rc.3", "description": "", "main": "dist/index.js", "module": "dist/index.js", From cfaff2f0e76b7b491294dff7de7913b057e7c8b8 Mon Sep 17 00:00:00 2001 From: "Visal .In" Date: Thu, 21 Nov 2024 18:24:23 +0700 Subject: [PATCH 08/11] add more test cases --- src/utils/placeholder.ts | 25 +++++++++++++++++++++++++ tests/units/placeholder.test.ts | 31 +++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/src/utils/placeholder.ts b/src/utils/placeholder.ts index ce2c484..ad240eb 100644 --- a/src/utils/placeholder.ts +++ b/src/utils/placeholder.ts @@ -82,6 +82,13 @@ export function namedPlaceholder( const [sqlFragments, placeholders] = parts; + // If placeholders contains any number, then it's a mix of named and numbered placeholders + if (placeholders.some((p) => typeof p === 'number')) { + throw new Error( + 'Mixing named and positional placeholder should throw error' + ); + } + for (let i = 0; i < sqlFragments.length; i++) { newQuery += sqlFragments[i]; @@ -94,6 +101,11 @@ export function namedPlaceholder( newQuery += `?`; } + const placeholderValue = params[key]; + if (placeholderValue === undefined) { + throw new Error(`Missing value for placeholder ${key}`); + } + bindings.push(params[key]); } } @@ -119,6 +131,19 @@ export function toNumberedPlaceholders( const [sqlFragments, placeholders] = parts; + if (placeholders.length !== params.length) { + throw new Error( + 'Number of positional placeholder should match with the number of values' + ); + } + + // Mixing named and numbered placeholders should throw error + if (placeholders.some((p) => typeof p === 'string')) { + throw new Error( + 'Mixing named and positional placeholder should throw error' + ); + } + for (let i = 0; i < sqlFragments.length; i++) { newQuery += sqlFragments[i]; diff --git a/tests/units/placeholder.test.ts b/tests/units/placeholder.test.ts index b8aa61f..695dfb5 100644 --- a/tests/units/placeholder.test.ts +++ b/tests/units/placeholder.test.ts @@ -60,6 +60,37 @@ test('Named placeholder to number placeholder with string', () => { }); }); +test('Named placeholder with missing value should throw an error', () => { + expect(() => + namedPlaceholder('SELECT * FROM users WHERE id = :id AND age > :age', { + id: 1, + }) + ).toThrow(); +}); + +test('Number of positional placeholder should match with the number of values', () => { + expect(() => + toNumberedPlaceholders('SELECT * FROM users WHERE id = ? AND age > ?', [ + 1, + ]) + ).toThrow(); +}); + +test('Mixing named and positional placeholder should throw error', () => { + expect(() => + namedPlaceholder('SELECT * FROM users WHERE id = :id AND age > ?', { + id: 1, + }) + ).toThrow(); + + expect(() => { + toNumberedPlaceholders( + `SELECT * FROM users WHERE id = ? AND age > :age`, + [1, 30] + ); + }).toThrow(); +}); + test('Convert positional placeholder to numbered placeholder', () => { expect( toNumberedPlaceholders( From 49991afdce263828a9dede018d00691bf7c688ed Mon Sep 17 00:00:00 2001 From: "Visal .In" Date: Thu, 21 Nov 2024 21:44:20 +0700 Subject: [PATCH 09/11] snowflake always use upper case column name --- tests/connections/connection.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/connections/connection.test.ts b/tests/connections/connection.test.ts index bc43424..21c1fe2 100644 --- a/tests/connections/connection.test.ts +++ b/tests/connections/connection.test.ts @@ -41,15 +41,15 @@ describe('Database Connection', () => { const sql = process.env.CONNECTION_TYPE === 'mysql' - ? 'SELECT CONCAT(:hello, :world) AS testing_word' - : 'SELECT (:hello || :world) AS testing_word'; + ? 'SELECT CONCAT(:hello, :world) AS TESTING_WORD' + : 'SELECT (:hello || :world) AS TESTING_WORD'; const { data } = await db.raw(sql, { hello: 'hello ', world: 'world', }); - expect(data).toEqual([{ testing_word: 'hello world' }]); + expect(data).toEqual([{ TESTING_WORD: 'hello world' }]); }); test('Support positional placeholder', async () => { From 4ebb763cf3e7786a582dfe3888ed34dc10d499ca Mon Sep 17 00:00:00 2001 From: "Visal .In" Date: Thu, 21 Nov 2024 21:56:00 +0700 Subject: [PATCH 10/11] fixng snowflake test case --- tests/connections/connection.test.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/connections/connection.test.ts b/tests/connections/connection.test.ts index 21c1fe2..ffd547a 100644 --- a/tests/connections/connection.test.ts +++ b/tests/connections/connection.test.ts @@ -41,15 +41,19 @@ describe('Database Connection', () => { const sql = process.env.CONNECTION_TYPE === 'mysql' - ? 'SELECT CONCAT(:hello, :world) AS TESTING_WORD' - : 'SELECT (:hello || :world) AS TESTING_WORD'; + ? 'SELECT CONCAT(:hello, :world) AS testing_word' + : 'SELECT (:hello || :world) AS testing_word'; const { data } = await db.raw(sql, { hello: 'hello ', world: 'world', }); - expect(data).toEqual([{ TESTING_WORD: 'hello world' }]); + if (process.env.CONNECTION_TYPE === 'snowflake') { + expect(data).toEqual([{ TESTING_WORD: 'hello world' }]); + } else { + expect(data).toEqual([{ testing_word: 'hello world' }]); + } }); test('Support positional placeholder', async () => { From 86ddce5e290edd7a34b64d468d94e39fea4b2163 Mon Sep 17 00:00:00 2001 From: "Visal .In" Date: Thu, 21 Nov 2024 21:58:13 +0700 Subject: [PATCH 11/11] add another snowflake test fix --- tests/connections/connection.test.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/connections/connection.test.ts b/tests/connections/connection.test.ts index ffd547a..8580605 100644 --- a/tests/connections/connection.test.ts +++ b/tests/connections/connection.test.ts @@ -65,7 +65,12 @@ describe('Database Connection', () => { : 'SELECT (? || ?) AS testing_word'; const { data } = await db.raw(sql, ['hello ', 'world']); - expect(data).toEqual([{ testing_word: 'hello world' }]); + + if (process.env.CONNECTION_TYPE === 'snowflake') { + expect(data).toEqual([{ TESTING_WORD: 'hello world' }]); + } else { + expect(data).toEqual([{ testing_word: 'hello world' }]); + } }); test('Create table', async () => {