Skip to content

Commit 0618e90

Browse files
Query parameters: implement support for binding NULL parameters (#189)
* Query parameters: implement support for binding NULL parameters Signed-off-by: Levko Kravets <levko.ne@gmail.com> * Handle explicit NULL type Signed-off-by: Levko Kravets <levko.ne@gmail.com> --------- Signed-off-by: Levko Kravets <levko.ne@gmail.com>
1 parent 911e5b0 commit 0618e90

2 files changed

Lines changed: 52 additions & 11 deletions

File tree

lib/DBSQLParameter.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import Int64 from 'node-int64';
22
import { TSparkParameter, TSparkParameterValue } from '../thrift/TCLIService_types';
33

4-
export type DBSQLParameterValue = boolean | number | bigint | Int64 | Date | string;
4+
export type DBSQLParameterValue = undefined | null | boolean | number | bigint | Int64 | Date | string;
55

66
export enum DBSQLParameterType {
7+
VOID = 'VOID', // aka NULL
78
STRING = 'STRING',
89
DATE = 'DATE',
910
TIMESTAMP = 'TIMESTAMP',
@@ -35,6 +36,16 @@ export class DBSQLParameter {
3536
}
3637

3738
public toSparkParameter(): TSparkParameter {
39+
// If VOID type was set explicitly - ignore value
40+
if (this.type === DBSQLParameterType.VOID) {
41+
return new TSparkParameter(); // for NULL neither `type` nor `value` should be set
42+
}
43+
44+
// Infer NULL values
45+
if (this.value === undefined || this.value === null) {
46+
return new TSparkParameter(); // for NULL neither `type` nor `value` should be set
47+
}
48+
3849
if (typeof this.value === 'boolean') {
3950
return new TSparkParameter({
4051
type: this.type ?? DBSQLParameterType.BOOLEAN,

tests/e2e/query_parameters.test.js

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ describe('Query parameters', () => {
2626
const operation = await session.executeStatement(
2727
`
2828
SELECT
29+
:p_null_1 AS col_null_1,
30+
:p_null_2 AS col_null_2,
31+
:p_null_3 AS col_null_3,
2932
:p_bool AS col_bool,
3033
:p_int AS col_int,
3134
:p_double AS col_double,
@@ -37,6 +40,9 @@ describe('Query parameters', () => {
3740
`,
3841
{
3942
namedParameters: {
43+
p_null_1: new DBSQLParameter({ value: undefined }),
44+
p_null_2: new DBSQLParameter({ value: null }),
45+
p_null_3: new DBSQLParameter({ type: DBSQLParameterType.VOID, value: 'Test' }),
4046
p_bool: new DBSQLParameter({ value: true }),
4147
p_int: new DBSQLParameter({ value: 1234 }),
4248
p_double: new DBSQLParameter({ value: 3.14 }),
@@ -51,6 +57,9 @@ describe('Query parameters', () => {
5157
const result = await operation.fetchAll();
5258
expect(result).to.deep.equal([
5359
{
60+
col_null_1: null,
61+
col_null_2: null,
62+
col_null_3: null,
5463
col_bool: true,
5564
col_int: 1234,
5665
col_double: 3.14,
@@ -68,6 +77,8 @@ describe('Query parameters', () => {
6877
const operation = await session.executeStatement(
6978
`
7079
SELECT
80+
:p_null_1 AS col_null_1,
81+
:p_null_2 AS col_null_2,
7182
:p_bool AS col_bool,
7283
:p_int AS col_int,
7384
:p_double AS col_double,
@@ -78,6 +89,8 @@ describe('Query parameters', () => {
7889
`,
7990
{
8091
namedParameters: {
92+
p_null_1: undefined,
93+
p_null_2: null,
8194
p_bool: true,
8295
p_int: 1234,
8396
p_double: 3.14,
@@ -91,6 +104,8 @@ describe('Query parameters', () => {
91104
const result = await operation.fetchAll();
92105
expect(result).to.deep.equal([
93106
{
107+
col_null_1: null,
108+
col_null_2: null,
94109
col_bool: true,
95110
col_int: 1234,
96111
col_double: 3.14,
@@ -107,6 +122,9 @@ describe('Query parameters', () => {
107122
const operation = await session.executeStatement(
108123
`
109124
SELECT
125+
? AS col_null_1,
126+
? AS col_null_2,
127+
? AS col_null_3,
110128
? AS col_bool,
111129
? AS col_int,
112130
? AS col_double,
@@ -117,21 +135,27 @@ describe('Query parameters', () => {
117135
? AS col_str
118136
`,
119137
{
120-
namedParameters: {
121-
p_bool: new DBSQLParameter({ value: true }),
122-
p_int: new DBSQLParameter({ value: 1234 }),
123-
p_double: new DBSQLParameter({ value: 3.14 }),
124-
p_bigint_1: new DBSQLParameter({ value: BigInt(1234) }),
125-
p_bigint_2: new DBSQLParameter({ value: new Int64(1234) }),
126-
p_date: new DBSQLParameter({ value: new Date('2023-09-06T03:14:27.843Z'), type: DBSQLParameterType.DATE }),
127-
p_timestamp: new DBSQLParameter({ value: new Date('2023-09-06T03:14:27.843Z') }),
128-
p_str: new DBSQLParameter({ value: 'Hello' }),
129-
},
138+
ordinalParameters: [
139+
new DBSQLParameter({ value: undefined }),
140+
new DBSQLParameter({ value: null }),
141+
new DBSQLParameter({ type: DBSQLParameterType.VOID, value: 'Test' }),
142+
new DBSQLParameter({ value: true }),
143+
new DBSQLParameter({ value: 1234 }),
144+
new DBSQLParameter({ value: 3.14 }),
145+
new DBSQLParameter({ value: BigInt(1234) }),
146+
new DBSQLParameter({ value: new Int64(1234) }),
147+
new DBSQLParameter({ value: new Date('2023-09-06T03:14:27.843Z'), type: DBSQLParameterType.DATE }),
148+
new DBSQLParameter({ value: new Date('2023-09-06T03:14:27.843Z') }),
149+
new DBSQLParameter({ value: 'Hello' }),
150+
],
130151
},
131152
);
132153
const result = await operation.fetchAll();
133154
expect(result).to.deep.equal([
134155
{
156+
col_null_1: null,
157+
col_null_2: null,
158+
col_null_3: null,
135159
col_bool: true,
136160
col_int: 1234,
137161
col_double: 3.14,
@@ -149,6 +173,8 @@ describe('Query parameters', () => {
149173
const operation = await session.executeStatement(
150174
`
151175
SELECT
176+
? AS col_null_1,
177+
? AS col_null_2,
152178
? AS col_bool,
153179
? AS col_int,
154180
? AS col_double,
@@ -159,6 +185,8 @@ describe('Query parameters', () => {
159185
`,
160186
{
161187
ordinalParameters: [
188+
undefined,
189+
null,
162190
true,
163191
1234,
164192
3.14,
@@ -172,6 +200,8 @@ describe('Query parameters', () => {
172200
const result = await operation.fetchAll();
173201
expect(result).to.deep.equal([
174202
{
203+
col_null_1: null,
204+
col_null_2: null,
175205
col_bool: true,
176206
col_int: 1234,
177207
col_double: 3.14,

0 commit comments

Comments
 (0)