Skip to content

Commit 6e9c68d

Browse files
committed
added mapping of integers, array of strings for SQLCommonParam
1 parent ead27b3 commit 6e9c68d

6 files changed

Lines changed: 136 additions & 10 deletions

File tree

integration-tests/tests/clickhouse/clickhouse-core.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,13 +184,13 @@ export const commonClickHouseTests = () => {
184184
test('base test with number param', (ctx) => {
185185
const res = ctx.sql`select ${1};`.toSQL();
186186

187-
expect(res).toStrictEqual({ query: `select {param1:String};`, params: { param1: 1 } });
187+
expect(res).toStrictEqual({ query: `select {param1:Int32};`, params: { param1: 1 } });
188188
});
189189

190190
test('base test with bigint param', (ctx) => {
191191
const res = ctx.sql`select ${BigInt(10)};`.toSQL();
192192

193-
expect(res).toStrictEqual({ query: `select {param1:String};`, params: { param1: 10n } });
193+
expect(res).toStrictEqual({ query: `select {param1:Int64};`, params: { param1: 10n } });
194194
});
195195

196196
test('base test with string param', (ctx) => {
@@ -226,7 +226,7 @@ export const commonClickHouseTests = () => {
226226

227227
const res = query.toSQL();
228228
expect(res).toStrictEqual({
229-
query: 'select * from users where id = {param1:String} or id = {param2:String} or id = {param3:String};',
229+
query: 'select * from users where id = {param1:Int32} or id = {param2:Int32} or id = {param3:Int32};',
230230
params: { param1: 1, param2: 3, param3: 4 },
231231
});
232232
});

integration-tests/tests/clickhouse/waddler.test.ts

Lines changed: 80 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,11 +1144,11 @@ test('sql query api test', async () => {
11441144
const query = sql`select * from ${sqlQuery.identifier('users')} where ${filter};`;
11451145

11461146
expect(query.toSQL()).toStrictEqual({
1147-
query: 'select * from `users` where id = {param1:Int32} or id = {param2:String} and email = {param3:String}',
1147+
query: 'select * from `users` where id = {param1:Int32} or id = {param2:Int32} and email = {param3:String}',
11481148
params: { param1: 1, param2: 2, param3: 'hello@test.com' },
11491149
});
11501150
expect(filter.toSQL()).toStrictEqual({
1151-
sql: 'id = {param1:Int32} or id = {param2:String} and email = {param3:String}',
1151+
sql: 'id = {param1:Int32} or id = {param2:Int32} and email = {param3:String}',
11521152
params: { param1: 1, param2: 2, param3: 'hello@test.com' },
11531153
});
11541154
});
@@ -1201,14 +1201,90 @@ engine = MergeTree
12011201
order by id;
12021202
`).command();
12031203

1204-
const valuesIds = Array.from({ length: 10 ** 3 }).fill([1]) as number[][];
1204+
const valuesIds = Array.from({ length: 10 ** 1 }).fill([1]) as number[][];
12051205

12061206
console.time('insert');
1207-
await sql`insert into ${sql.identifier('tests')} values ${sql.values(valuesIds)};`.command();
1207+
const query = sql`insert into ${sql.identifier('tests')} values ${sql.values(valuesIds)};`.command();
1208+
const { query: rawSql, params } = query.toSQL();
1209+
// await query;
1210+
// const rawSqlNew = rawSql.slice(0, -1) + ' FORMAT JSONEachRow;';
1211+
await clickHouseClient.command({ query: rawSql, query_params: params as Record<string, any> });
1212+
await clickHouseClient.insert({
1213+
table: 'tests',
1214+
query_params: params as Record<string, any>,
1215+
values: valuesIds,
1216+
});
1217+
12081218
console.timeEnd('insert');
12091219
// console.log('New user created!');
12101220
// const ids = await sql`select * from ${sql.identifier('tests')};`.query();
12111221
// console.log('Getting all users from the database:', ids);
12121222

12131223
await sql.unsafe(`drop table tests;`).command();
12141224
});
1225+
1226+
test('1d array of strings, integer as SQLCommonParam test', async () => {
1227+
await sql.unsafe(`create table tests(
1228+
id Int32,
1229+
path String
1230+
)
1231+
engine = MergeTree
1232+
order by id;
1233+
`).command();
1234+
1235+
const valuesToInsert = [[1, '/'], [2, '/watch'], [3, '/over_watch']];
1236+
1237+
await sql`insert into tests values ${sql.values(valuesToInsert)};`.command();
1238+
1239+
// case0
1240+
const query0 = sql`select * from tests where path in ${['/', '/watch']};`;
1241+
expect(query0.toSQL()).toStrictEqual({
1242+
query: 'select * from tests where path in {param1:Array(String)};',
1243+
params: { param1: ['/', '/watch'] },
1244+
});
1245+
1246+
const res0 = await query0;
1247+
expect(res0).toStrictEqual([{ id: 1, path: '/' }, { id: 2, path: '/watch' }]);
1248+
1249+
// case1 (datetime)
1250+
const query1 = sql`select toDateTime(${1754055760745}, 3) as some_datetime;`;
1251+
expect(query1.toSQL()).toStrictEqual({
1252+
query: 'select toDateTime({param1:Int64}, 3) as some_datetime;',
1253+
params: { param1: 1754055760745 },
1254+
});
1255+
1256+
const res1 = await query1;
1257+
expect(res1.length).equal(1);
1258+
1259+
// case2 (int32 max)
1260+
const query2 = sql`select ${2_147_483_647} as max_int32;`;
1261+
expect(query2.toSQL()).toStrictEqual({
1262+
query: 'select {param1:Int32} as max_int32;',
1263+
params: { param1: 2147483647 },
1264+
});
1265+
1266+
const res2 = await query2;
1267+
expect(res2).toStrictEqual([{ max_int32: 2147483647 }]);
1268+
1269+
// case3 (int32 min)
1270+
const query3 = sql`select ${-2_147_483_648} as min_int32;`;
1271+
expect(query3.toSQL()).toStrictEqual({
1272+
query: 'select {param1:Int32} as min_int32;',
1273+
params: { param1: -2147483648 },
1274+
});
1275+
1276+
const res3 = await query3;
1277+
expect(res3).toStrictEqual([{ min_int32: -2147483648 }]);
1278+
1279+
// case4 (float)
1280+
const query4 = sql`select ${-2_147_483_648.123} as some_float;`;
1281+
expect(query4.toSQL()).toStrictEqual({
1282+
query: 'select {param1:String} as some_float;',
1283+
params: { param1: -2147483648.123 },
1284+
});
1285+
1286+
const res4 = await query4;
1287+
expect(res4).toStrictEqual([{ some_float: '-2147483648.123' }]);
1288+
1289+
await sql.unsafe(`drop table tests;`).command();
1290+
});

waddler/src/clickhouse-core/utils.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,33 @@ export const getArrayDepth = (value: any[]) => {
6666
return Math.max(d, maxDepth);
6767
}, 0);
6868
};
69+
70+
export const inspectArray = (value: any[]): { depth: number; type: string } => {
71+
if (Array.isArray(value)) {
72+
const { depth, type } = inspectArray(value[0]);
73+
return { depth: depth + 1, type };
74+
}
75+
76+
return { depth: 0, type: typeof value };
77+
};
78+
79+
export const inspectArray1 = (value: any[]): { depth: number; type: string } => {
80+
let currNode: any | any[] = value;
81+
let depth: number = 0;
82+
83+
for (let i = 0; i < 100; i++) {
84+
if (!Array.isArray(currNode)) return { depth, type: typeof currNode };
85+
currNode = currNode[0];
86+
depth++;
87+
}
88+
89+
return { depth, type: typeof value };
90+
};
91+
92+
// console.log(inspectArray(['a', 'b']));
93+
// console.log(inspectArray([['a', 'b'], ['a', 'b']]));
94+
// console.log(inspectArray([[['a', 'b'], ['a', 'b']], [['a', 'b'], ['a', 'b']]]));
95+
96+
// console.log(inspectArray1(['a', 'b']));
97+
// console.log(inspectArray1([['a', 'b'], ['a', 'b']]));
98+
// console.log(inspectArray1([[['a', 'b'], ['a', 'b']], [['a', 'b'], ['a', 'b']]]));

waddler/src/clickhouse/session.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export class ClickHouseSQLTemplate<T> extends SQLTemplate<T> {
4646
}) as any;
4747
}
4848
} catch (error) {
49-
throw new WaddlerQueryError(query, params, error as Error);
49+
throw new WaddlerQueryError(query, JSON.stringify(params), error as Error);
5050
}
5151
}
5252

waddler/src/errors/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
export class WaddlerQueryError extends Error {
22
constructor(
33
public query: string,
4-
public params: any[] | Record<string, any>,
4+
public params: any[] | Record<string, any> | any,
55
public override cause?: Error,
66
) {
77
super(`Failed query: ${query}\nparams: ${params}`);

waddler/src/sql-template-params.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,36 @@ export class SQLQuery extends SQLChunk {
6161
}
6262

6363
export class SQLCommonParam extends SQLChunk {
64+
INT32_MAX = 2_147_483_647;
65+
INT32_MIN = -2_147_483_648;
66+
6467
constructor(
6568
readonly value: UnsafeParamType,
66-
readonly type: string = 'String',
69+
public type: string = 'String',
6770
) {
6871
super();
6972
}
7073

7174
generateSQL(
7275
{ dialect, lastParamIdx }: { dialect: Dialect; lastParamIdx: number },
7376
) {
77+
// bigint case
78+
if (typeof this.value === 'bigint') this.type = 'Int64';
79+
80+
// integer case
81+
if (typeof this.value === 'number' && this.value % 1 === 0) {
82+
this.type = 'Int32';
83+
if (this.value > this.INT32_MAX || this.value < this.INT32_MIN) {
84+
this.type = 'Int64';
85+
}
86+
}
87+
88+
// array case
89+
if (Array.isArray(this.value)) {
90+
const nodeType = typeof this.value[0];
91+
if (nodeType === 'string') this.type = 'Array(String)';
92+
}
93+
7494
const params = dialect.createEmptyParams();
7595
dialect.pushParams(params, this.value, lastParamIdx + 1, 'single');
7696
return {

0 commit comments

Comments
 (0)