@evidence-dev/bigquery
Version:
BigQuery driver for Evidence projects
171 lines (157 loc) • 5.7 kB
JavaScript
import { test } from 'uvu';
import * as assert from 'uvu/assert';
import runQuery from '../index.cjs';
import { TypeFidelity, batchedAsyncGeneratorToArray } from '@evidence-dev/db-commons';
import 'dotenv/config';
test('query runs', async () => {
const { rows: row_generator, columnTypes } = await runQuery(
`select
INTERVAL 5 DAY AS interval_col,
NUMERIC '123456' as numeric_col,
BIGNUMERIC '1234567890123456789012345678' as bignumeric_col,
'hello!' as string_col,
B"abc" as bytes_col,
123456 as int_col,
123456.789 as float_col,
true as bool_col,
DATE '2021-01-01' as date_col,
TIME '12:34:56' as time_col,
TIMESTAMP '2021-01-01 12:34:56' as timestamp_col,
DATETIME '2021-01-01 12:34:56' as datetime_col
`,
{
project_id: process.env.BIGQUERY_PROJECT_ID,
client_email: process.env.BIGQUERY_CLIENT_EMAIL,
private_key: process.env.BIGQUERY_PRIVATE_KEY
}
);
const rows = await batchedAsyncGeneratorToArray(row_generator);
assert.instance(rows, Array);
assert.instance(columnTypes, Array);
assert.type(rows[0], 'object');
const result = rows[0];
assert.equal(result.int_col, 123456, 'INT types should be converted to JS Numbers');
assert.equal(result.float_col, 123456.789, 'FLOAT types should be converted to JS Numbers');
assert.equal(result.bool_col, true, 'BOOL types should be converted to JS Booleans');
assert.equal(result.string_col, 'hello!', 'STRING types should be converted to JS Strings');
assert.equal(result.bytes_col, 'YWJj', 'BYTES types should be converted to base64 strings');
assert.equal(
result.date_col.getTime(),
new Date('2021-01-01').getTime(),
'DATE types should be converted to JS Date objects'
);
assert.equal(result.time_col, '12:34:56', 'TIME types should be converted to strings');
assert.equal(
result.timestamp_col.getTime(),
new Date('2021-01-01T12:34:56.000Z').getTime(),
'TIMESTAMP types should be converted to JS Date objects'
);
assert.equal(
result.datetime_col.getTime(),
new Date('2021-01-01T12:34:56.000Z').getTime(),
'DATETIME types should be converted to JS Date objects'
);
assert.equal(result.interval_col, '0-0 5 0:0:0', 'INTERVAL types should be converted to strings');
assert.equal(result.numeric_col, 123456, 'NUMERIC types should be converted to JS Numbers');
assert.equal(
result.bignumeric_col,
1.2345678901234569e27,
'BIGNUMERIC types should be converted to JS Numbers'
);
const actualColumnTypes = columnTypes.map((columnType) => columnType.evidenceType);
const actualColumnNames = columnTypes.map((columnType) => columnType.name);
const expectedColumnTypes = [
'string',
'number',
'number',
'string',
'string',
'number',
'number',
'boolean',
'date',
'string',
'date',
'date'
];
const expectedColumnNames = [
'interval_col',
'numeric_col',
'bignumeric_col',
'string_col',
'bytes_col',
'int_col',
'float_col',
'bool_col',
'date_col',
'time_col',
'timestamp_col',
'datetime_col'
];
assert.equal(
true,
expectedColumnTypes.length === actualColumnTypes.length &&
expectedColumnTypes.every((value, index) => value === actualColumnTypes[index])
);
assert.equal(
true,
expectedColumnNames.length === actualColumnNames.length &&
expectedColumnNames.every((value, index) => value === actualColumnNames[index])
);
});
test('numeric types are retrieved correctly', async () => {
const { rows: row_generator, columnTypes } = await runQuery(
'select CAST(1.23456789 AS NUMERIC) as numeric_number, CAST(1.23456789 AS FLOAT64) as float64_number, CAST(1.23456789 AS DECIMAL) as decimal_number, CAST(1.23456789 AS STRING) as string_number',
{
project_id: process.env.BIGQUERY_PROJECT_ID,
client_email: process.env.BIGQUERY_CLIENT_EMAIL,
private_key: process.env.BIGQUERY_PRIVATE_KEY
}
);
const rows = await batchedAsyncGeneratorToArray(row_generator);
let actualColumnTypes = columnTypes.map((columnType) => columnType.evidenceType);
let actualColumnNames = columnTypes.map((columnType) => columnType.name);
let actualTypePrecisions = columnTypes.map((columnType) => columnType.typeFidelity);
let actualValues = Object.keys(rows[0]).map((key) => rows[0][key]);
let expectedColumnTypes = ['number', 'number', 'number', 'string'];
let expectedColumnNames = ['numeric_number', 'float64_number', 'decimal_number', 'string_number'];
let expectedTypePrecision = Array(4).fill(TypeFidelity.PRECISE);
let expectedValues = [1.23456789, 1.23456789, 1.23456789, '1.23456789'];
assert.equal(
true,
expectedColumnTypes.length === actualColumnTypes.length &&
expectedColumnTypes.every((value, index) => value === actualColumnTypes[index])
);
assert.equal(
true,
expectedColumnNames.length === actualColumnNames.length &&
expectedColumnNames.every((value, index) => value === actualColumnNames[index])
);
assert.equal(
true,
expectedTypePrecision.length === actualTypePrecisions.length &&
expectedTypePrecision.every((value, index) => value === actualTypePrecisions[index])
);
assert.equal(expectedValues, actualValues);
});
test('query batches results properly', async () => {
const { rows, expectedRowCount } = await runQuery(
'select 1 union all select 2 union all select 3 union all select 4 union all select 5',
{
project_id: process.env.BIGQUERY_PROJECT_ID,
client_email: process.env.BIGQUERY_CLIENT_EMAIL,
private_key: process.env.BIGQUERY_PRIVATE_KEY
},
2
);
const arr = [];
for await (const batch of rows()) {
arr.push(batch);
}
for (const batch of arr.slice(0, -1)) {
assert.equal(batch.length, 2);
}
assert.equal(arr[arr.length - 1].length, 1);
assert.equal(expectedRowCount, 5);
});
test.run();