From df8a976eabcc92917b9bc75612ba8ea9e6b32698 Mon Sep 17 00:00:00 2001 From: Adam Hilton Date: Sat, 1 Jan 2022 20:11:16 -0700 Subject: [PATCH 1/4] Allow passing of params and injecting into http request params for use in parameterized queries. --- index.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 7d835aa..0a5ccc8 100644 --- a/index.js +++ b/index.js @@ -483,7 +483,21 @@ class QueryCursor { let data = me.data; let query = me.query; - + + // check for any query params passed for interpolation + // https://clickhouse.com/docs/en/interfaces/http/#cli-queries-with-parameters + if (data && data.params) { + + // each variable used in the query is expected to be prefixed with `param_` + // when passed in the request. + Object.keys(data.params).forEach(k => { + url.searchParams.append( + `param_${k}`, JSON.stringify(data.params[k]) + ); + }); + + } + if (typeof query === 'string') { if (/with totals/i.test(query)) { me.useTotals = true; From e241089891f9d46446eee2cabe7184897c443072 Mon Sep 17 00:00:00 2001 From: Adam Hilton Date: Sat, 1 Jan 2022 20:11:36 -0700 Subject: [PATCH 2/4] Add test for query parameterization. --- test/test.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/test.js b/test/test.js index 7ef743c..9fc6fc0 100644 --- a/test/test.js +++ b/test/test.js @@ -275,6 +275,34 @@ describe('Select', () => { }); }); }); + + it('parameterized ', callback => { + + let params_sql = `SELECT + number, + toString(number * 2) AS str, + toDate(number + 1) AS date + FROM numbers(10) + WHERE number = {num:UInt64} + OR number IN {nums:Array(UInt64)}`; + + let params_data = { + params: { + num: 0, + nums: [1,2] + } + } + + clickhouse.query(params_sql, params_data).exec((err, rows) => { + expect(err).to.not.be.ok(); + + expect(rows).to.have.length(3); + expect(rows[0]).to.eql({ number: 0, str: '0', date: '1970-01-02' }); + + callback(); + }); + }); + }); describe('session', () => { From 3b1ca804ae792210101aeddc8b0baa5c638d1cc4 Mon Sep 17 00:00:00 2001 From: Adam Hilton Date: Sat, 1 Jan 2022 20:11:48 -0700 Subject: [PATCH 3/4] Add documentation example. --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 92778cd..2d76161 100644 --- a/README.md +++ b/README.md @@ -195,6 +195,20 @@ const ws = clickhouse.insert('INSERT INTO session_temp2').stream(); const result = await rs.pipe(tf).pipe(ws).exec(); ``` +*** + +Parameterized Values: +```javascript +const rows = await clickhouse.query( + 'SELECT * AS count FROM temp_table WHERE version = {ver:UInt16}', + { + params: { + ver: 1 + }, + } +).toPromise(); +``` +For more information on encoding in the query, see [this section](https://clickhouse.com/docs/en/interfaces/http/#cli-queries-with-parameters) of the ClickHouse documentation. *** From a5d552ce2ce859d1cb637745c78530f4ca754f7b Mon Sep 17 00:00:00 2001 From: Adam Hilton Date: Sat, 1 Jan 2022 21:37:30 -0700 Subject: [PATCH 4/4] Correctly handle expected format of strings. --- index.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 0a5ccc8..fed41ec 100644 --- a/index.js +++ b/index.js @@ -491,8 +491,15 @@ class QueryCursor { // each variable used in the query is expected to be prefixed with `param_` // when passed in the request. Object.keys(data.params).forEach(k => { + + let value = data.params[k].toString(); + + if (Array.isArray(data.params[k])) { + value = '[' + value + ']' + }; + url.searchParams.append( - `param_${k}`, JSON.stringify(data.params[k]) + `param_${k}`, value ); });