diff --git a/src/statement/hydrateResponse.ts b/src/statement/hydrateResponse.ts index c2c3cf3d..900c0f25 100644 --- a/src/statement/hydrateResponse.ts +++ b/src/statement/hydrateResponse.ts @@ -49,6 +49,10 @@ const getHydratedValue = ( type: string, executeQueryOptions: ExecuteQueryOptions ): any => { + // strip null to ensure correct type checking in the following steps + if (type.endsWith("null")) { + type = type.replace("null", "").trim(); + } if (isStructType(type)) { return hydrateStruct( value as Record, diff --git a/test/integration/v2/fetchTypes.test.ts b/test/integration/v2/fetchTypes.test.ts index f366bfec..8e817f95 100644 --- a/test/integration/v2/fetchTypes.test.ts +++ b/test/integration/v2/fetchTypes.test.ts @@ -42,6 +42,26 @@ describe("test type casting on fetch", () => { const row = data[0]; expect((row as unknown[])[0]).toEqual(new BigNumber("9223372036854775807")); }); + it("select nullable bigint", async () => { + const firebolt = Firebolt({ + apiEndpoint: process.env.FIREBOLT_API_ENDPOINT as string + }); + // Max value for a signed 64-bit integer (bigint) + const testQuery = ` + WITH a AS ( + SELECT 9223372036854775807::bigint UNION ALL SELECT null::bigint + ) + SELECT * FROM a + `; + const connection = await firebolt.connect(connectionParams); + + const statement = await connection.execute(testQuery); + + const { data, meta } = await statement.fetchResult(); + expect(meta[0].type).toEqual("long null"); + const row = data[0]; + expect((row as unknown[])[0]).toEqual(new BigNumber("9223372036854775807")); + }); it("select negative bigint", async () => { const firebolt = Firebolt({ apiEndpoint: process.env.FIREBOLT_API_ENDPOINT as string diff --git a/test/unit/v1/statement.test.ts b/test/unit/v1/statement.test.ts index 955f9519..04f00d65 100644 --- a/test/unit/v1/statement.test.ts +++ b/test/unit/v1/statement.test.ts @@ -313,6 +313,18 @@ describe("parse values", () => { new BigNumber(1000000000000000000000000000000000000) ); }); + it("parses bigint null into BigNumber container", () => { + allure.description("Verify nullable bigint is parsed correctly"); + const row = { + big: "1000000000000000000000000000000000000" + }; + const meta = [{ name: "big", type: "long null" }]; + const res: Record = hydrateRow(row, meta, {}); + expect(res["big"] instanceof BigNumber).toBe(true); + expect(res["big"]).toEqual( + new BigNumber(1000000000000000000000000000000000000) + ); + }); }); describe("set statements", () => { diff --git a/test/unit/v2/statement.test.ts b/test/unit/v2/statement.test.ts index a057aaff..968a0809 100644 --- a/test/unit/v2/statement.test.ts +++ b/test/unit/v2/statement.test.ts @@ -321,6 +321,18 @@ describe("parse values", () => { const res: Record = hydrateRow(row, meta, {}); expect(res["bytea"]).toEqual(Buffer.from("hello_world")); }); + it("parses bigint null into BigNumber container", () => { + allure.description("Verify nullable bigint is parsed correctly"); + const row = { + big: "1000000000000000000000000000000000000" + }; + const meta = [{ name: "big", type: "long null" }]; + const res: Record = hydrateRow(row, meta, {}); + expect(res["big"] instanceof BigNumber).toBe(true); + expect(res["big"]).toEqual( + new BigNumber(1000000000000000000000000000000000000) + ); + }); it("parses struct into object", () => { const row = { s: { a: [1, 2], b: "\\x68656c6c6f5f776f726c64" }