@malloydata/db-bigquery 0.0.24-dev230224184907 → 0.0.24-dev230228224434

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -51,119 +51,119 @@ const bigquery_1 = require("@google-cloud/bigquery");
51
51
  const util = __importStar(require("util"));
52
52
  const fs = __importStar(require("fs"));
53
53
  const url_1 = require("url");
54
- describe("db:BigQuery", () => {
54
+ describe('db:BigQuery', () => {
55
55
  let bq;
56
56
  let runtime;
57
57
  beforeAll(() => {
58
- bq = new bigquery_connection_1.BigQueryConnection("test");
58
+ bq = new bigquery_connection_1.BigQueryConnection('test');
59
59
  const files = {
60
- "readURL": async (url) => {
60
+ readURL: async (url) => {
61
61
  const filePath = (0, url_1.fileURLToPath)(url);
62
- return await util.promisify(fs.readFile)(filePath, "utf8");
63
- }
62
+ return await util.promisify(fs.readFile)(filePath, 'utf8');
63
+ },
64
64
  };
65
65
  runtime = new malloy.Runtime(files, bq);
66
66
  });
67
- it("runs a SQL query", async () => {
68
- const res = await bq.runSQL(`SELECT 1 as t`);
69
- expect(res.rows[0]["t"]).toBe(1);
67
+ it('runs a SQL query', async () => {
68
+ const res = await bq.runSQL('SELECT 1 as t');
69
+ expect(res.rows[0]['t']).toBe(1);
70
70
  });
71
- it("costs a SQL query", async () => {
72
- const res = await bq.costQuery(`SELECT * FROM malloy-data.faa.airports`);
71
+ it('costs a SQL query', async () => {
72
+ const res = await bq.costQuery('SELECT * FROM malloy-data.faa.airports');
73
73
  expect(res).toBe(3029200);
74
74
  });
75
- it("gets table schema", async () => {
76
- const res = await bq.getTableFieldSchema(`malloy-data.faa.carriers`);
75
+ it('gets table schema', async () => {
76
+ const res = await bq.getTableFieldSchema('malloy-data.faa.carriers');
77
77
  expect(res.schema).toStrictEqual({
78
- "fields": [
79
- { "name": "code", "type": "STRING" },
80
- { "name": "name", "type": "STRING" },
81
- { "name": "nickname", "type": "STRING" }
82
- ]
78
+ fields: [
79
+ { name: 'code', type: 'STRING' },
80
+ { name: 'name', type: 'STRING' },
81
+ { name: 'nickname', type: 'STRING' },
82
+ ],
83
83
  });
84
84
  });
85
- it.todo("gets table structdefs");
86
- it("runs a Malloy query", async () => {
85
+ it.todo('gets table structdefs');
86
+ it('runs a Malloy query', async () => {
87
87
  const sql = await runtime
88
88
  .loadModel("explore: carriers is table('malloy-data.faa.carriers') { measure: carrier_count is count() }")
89
- .loadQuery("query: carriers -> { aggregate: carrier_count }")
89
+ .loadQuery('query: carriers -> { aggregate: carrier_count }')
90
90
  .getSQL();
91
91
  const res = await bq.runSQL(sql);
92
- expect(res.rows[0]["carrier_count"]).toBe(21);
92
+ expect(res.rows[0]['carrier_count']).toBe(21);
93
93
  });
94
- it("streams a Malloy query for download", async () => {
94
+ it('streams a Malloy query for download', async () => {
95
95
  const sql = await runtime
96
96
  .loadModel("explore: carriers is table('malloy-data.faa.carriers') { measure: carrier_count is count() }")
97
- .loadQuery("query: carriers -> { group_by: name }")
97
+ .loadQuery('query: carriers -> { group_by: name }')
98
98
  .getSQL();
99
99
  const res = await bq.downloadMalloyQuery(sql);
100
- return new Promise((resolve) => {
100
+ return new Promise(resolve => {
101
101
  let count = 0;
102
- res.on("data", () => (count += 1));
103
- res.on("end", () => {
102
+ res.on('data', () => (count += 1));
103
+ res.on('end', () => {
104
104
  expect(count).toBe(21);
105
105
  resolve(true);
106
106
  });
107
107
  });
108
108
  });
109
- it("manifests a temporary table", async () => {
110
- const fullTempTableName = await bq.manifestTemporaryTable("SELECT 1 as t");
111
- const splitTableName = fullTempTableName.split(".");
109
+ it('manifests a temporary table', async () => {
110
+ const fullTempTableName = await bq.manifestTemporaryTable('SELECT 1 as t');
111
+ const splitTableName = fullTempTableName.split('.');
112
112
  const sdk = new bigquery_1.BigQuery();
113
113
  const dataset = sdk.dataset(splitTableName[1]);
114
114
  const table = dataset.table(splitTableName[2]);
115
115
  const exists = await table.exists();
116
116
  expect(exists).toBeTruthy();
117
117
  });
118
- describe.skip("manifests permanent table", () => {
119
- const datasetName = "test_malloy_test_dataset";
120
- const tableName = "test_malloy_test_table";
118
+ describe.skip('manifests permanent table', () => {
119
+ const datasetName = 'test_malloy_test_dataset';
120
+ const tableName = 'test_malloy_test_table';
121
121
  const sdk = new bigquery_1.BigQuery();
122
122
  // delete entire dataset before each test and once tests are complete
123
123
  const deleteTestDataset = async () => {
124
124
  const dataset = sdk.dataset(datasetName);
125
125
  if ((await dataset.exists())[0]) {
126
126
  await dataset.delete({
127
- "force": true
127
+ force: true,
128
128
  });
129
129
  }
130
130
  };
131
131
  beforeEach(deleteTestDataset);
132
132
  afterAll(deleteTestDataset);
133
- it("throws if dataset does not exist and createDataset=false", async () => {
133
+ it('throws if dataset does not exist and createDataset=false', async () => {
134
134
  await expect(async () => {
135
- await bq.manifestPermanentTable("SELECT 1 as t", datasetName, tableName, false, false);
135
+ await bq.manifestPermanentTable('SELECT 1 as t', datasetName, tableName, false, false);
136
136
  }).rejects.toThrowError(`Dataset ${datasetName} does not exist`);
137
137
  });
138
- it("creates dataset if createDataset=true", async () => {
138
+ it('creates dataset if createDataset=true', async () => {
139
139
  // note - dataset does not exist b/c of beforeEach()
140
- await bq.manifestPermanentTable("SELECT 1 as t", datasetName, tableName, false, true);
140
+ await bq.manifestPermanentTable('SELECT 1 as t', datasetName, tableName, false, true);
141
141
  const dataset = sdk.dataset(datasetName);
142
142
  const [exists] = await dataset.exists();
143
143
  expect(exists).toBeTruthy();
144
144
  });
145
- it("throws if table exist and overwriteExistingTable=false", async () => {
145
+ it('throws if table exist and overwriteExistingTable=false', async () => {
146
146
  const newDatasetResponse = await sdk.createDataset(datasetName);
147
147
  const dataset = newDatasetResponse[0];
148
- const tableMeta = { "name": tableName };
148
+ const tableMeta = { name: tableName };
149
149
  await dataset.createTable(tableName, tableMeta);
150
150
  await expect(async () => {
151
- await bq.manifestPermanentTable("SELECT 1 as t", datasetName, tableName, false, true);
151
+ await bq.manifestPermanentTable('SELECT 1 as t', datasetName, tableName, false, true);
152
152
  }).rejects.toThrowError(`Table ${tableName} already exists`);
153
153
  });
154
- it("manifests a table", async () => {
155
- const jobId = await bq.manifestPermanentTable("SELECT 1 as t", datasetName, tableName, false, true);
154
+ it('manifests a table', async () => {
155
+ const jobId = await bq.manifestPermanentTable('SELECT 1 as t', datasetName, tableName, false, true);
156
156
  // wait for job to complete
157
157
  const [job] = await sdk.job(jobId).get();
158
158
  let [metaData] = await job.getMetadata();
159
- while (metaData.status.state !== "DONE") {
160
- await new Promise((resolve) => setTimeout(resolve, 1000));
159
+ while (metaData.status.state !== 'DONE') {
160
+ await new Promise(resolve => setTimeout(resolve, 1000));
161
161
  [metaData] = await job.getMetadata();
162
162
  }
163
163
  // query the new table
164
164
  const [queryJob] = await sdk.createQueryJob(`SELECT * FROM ${datasetName}.${tableName}`);
165
165
  const [results] = await queryJob.getQueryResults();
166
- expect(results[0]).toStrictEqual({ "t": 1 });
166
+ expect(results[0]).toStrictEqual({ t: 1 });
167
167
  });
168
168
  });
169
169
  });
@@ -1,7 +1,7 @@
1
- import { RowMetadata } from "@google-cloud/bigquery";
2
- import bigquery from "@google-cloud/bigquery/build/src/types";
3
- import { ResourceStream } from "@google-cloud/paginator";
4
- import { Connection, FieldTypeDef, MalloyQueryData, PersistSQLResults, PooledConnection, QueryData, QueryDataRow, SQLBlock, StreamingConnection, StructDef } from "@malloydata/malloy";
1
+ import { RowMetadata } from '@google-cloud/bigquery';
2
+ import bigquery from '@google-cloud/bigquery/build/src/types';
3
+ import { ResourceStream } from '@google-cloud/paginator';
4
+ import { Connection, FieldTypeDef, MalloyQueryData, PersistSQLResults, PooledConnection, QueryData, QueryDataRow, SQLBlock, StreamingConnection, StructDef } from '@malloydata/malloy';
5
5
  export interface BigQueryManagerOptions {
6
6
  credentials?: {
7
7
  clientId: string;
@@ -57,7 +57,7 @@ const malloy_1 = require("@malloydata/malloy");
57
57
  class BigQueryAuthenticationError extends Error {
58
58
  constructor(message) {
59
59
  super(message);
60
- this.name = "BigQueryAuthenticationError";
60
+ this.name = 'BigQueryAuthenticationError';
61
61
  }
62
62
  }
63
63
  exports.BigQueryAuthenticationError = BigQueryAuthenticationError;
@@ -66,7 +66,7 @@ const maybeRewriteError = (e) => {
66
66
  // the refresh token is invalid
67
67
  // ApiErrors happen if token is revoked (for example, client.revokeToken(creds.access_token!))
68
68
  if (e instanceof Error) {
69
- if ((e instanceof gaxios_1.GaxiosError && e.code === "400") ||
69
+ if ((e instanceof gaxios_1.GaxiosError && e.code === '400') ||
70
70
  (e instanceof googleCommon.ApiError && e.code === 401)) {
71
71
  return new BigQueryAuthenticationError(e.message);
72
72
  }
@@ -93,18 +93,18 @@ class BigQueryConnection {
93
93
  this.schemaCache = new Map();
94
94
  this.sqlSchemaCache = new Map();
95
95
  this.bqToMalloyTypes = {
96
- "DATE": { "type": "date" },
97
- "STRING": { "type": "string" },
98
- "INTEGER": { "type": "number", "numberType": "integer" },
99
- "INT64": { "type": "number", "numberType": "integer" },
100
- "FLOAT": { "type": "number", "numberType": "float" },
101
- "FLOAT64": { "type": "number", "numberType": "float" },
102
- "NUMERIC": { "type": "number", "numberType": "float" },
103
- "BIGNUMERIC": { "type": "number", "numberType": "float" },
104
- "TIMESTAMP": { "type": "timestamp" },
105
- "BOOLEAN": { "type": "boolean" },
106
- "BOOL": { "type": "boolean" },
107
- "JSON": { "type": "json" }
96
+ DATE: { type: 'date' },
97
+ STRING: { type: 'string' },
98
+ INTEGER: { type: 'number', numberType: 'integer' },
99
+ INT64: { type: 'number', numberType: 'integer' },
100
+ FLOAT: { type: 'number', numberType: 'float' },
101
+ FLOAT64: { type: 'number', numberType: 'float' },
102
+ NUMERIC: { type: 'number', numberType: 'float' },
103
+ BIGNUMERIC: { type: 'number', numberType: 'float' },
104
+ TIMESTAMP: { type: 'timestamp' },
105
+ BOOLEAN: { type: 'boolean' },
106
+ BOOL: { type: 'boolean' },
107
+ JSON: { type: 'json' },
108
108
  // TODO (https://cloud.google.com/bigquery/docs/reference/rest/v2/tables#tablefieldschema):
109
109
  // BYTES
110
110
  // DATETIME
@@ -113,8 +113,8 @@ class BigQueryConnection {
113
113
  };
114
114
  this.name = name;
115
115
  this.bigQuery = new bigquery_1.BigQuery({
116
- "userAgent": `Malloy/${malloy_1.Malloy.version}`,
117
- "keyFilename": config.serviceAccountKeyPath
116
+ userAgent: `Malloy/${malloy_1.Malloy.version}`,
117
+ keyFilename: config.serviceAccountKeyPath,
118
118
  });
119
119
  // record project ID because for unclear reasons we have to modify the project ID on the SDK when
120
120
  // we want to use the tables API
@@ -122,10 +122,10 @@ class BigQueryConnection {
122
122
  this.defaultProject = config.defaultProject || this.bigQuery.projectId;
123
123
  this.queryOptions = queryOptions;
124
124
  this.config = config;
125
- this.location = config.location || "US";
125
+ this.location = config.location || 'US';
126
126
  }
127
127
  get dialectName() {
128
- return "standardsql";
128
+ return 'standardsql';
129
129
  }
130
130
  readQueryOptions() {
131
131
  const options = BigQueryConnection.DEFAULT_QUERY_OPTIONS;
@@ -156,19 +156,19 @@ class BigQueryConnection {
156
156
  const pageSize = (_a = options.rowLimit) !== null && _a !== void 0 ? _a : defaultOptions.rowLimit;
157
157
  try {
158
158
  const queryResultsOptions = {
159
- "maxResults": pageSize,
160
- "startIndex": rowIndex.toString()
159
+ maxResults: pageSize,
160
+ startIndex: rowIndex.toString(),
161
161
  };
162
162
  const jobResult = await this.createBigQueryJobAndGetResults(sqlCommand, undefined, queryResultsOptions);
163
163
  const totalRows = +(((_b = jobResult[2]) === null || _b === void 0 ? void 0 : _b.totalRows)
164
164
  ? jobResult[2].totalRows
165
- : "0");
165
+ : '0');
166
166
  // TODO need to probably surface the cause of the schema not present error
167
167
  if (((_c = jobResult[2]) === null || _c === void 0 ? void 0 : _c.schema) === undefined) {
168
- throw new Error("Schema not present");
168
+ throw new Error('Schema not present');
169
169
  }
170
170
  // TODO even though we have 10 minute timeout limit, we still should confirm that resulting metadata has "jobComplete: true"
171
- const data = { "rows": jobResult[0], totalRows };
171
+ const data = { rows: jobResult[0], totalRows };
172
172
  const schema = (_d = jobResult[2]) === null || _d === void 0 ? void 0 : _d.schema;
173
173
  return { data, schema };
174
174
  }
@@ -181,22 +181,22 @@ class BigQueryConnection {
181
181
  return data;
182
182
  }
183
183
  async runSQLBlockAndFetchResultSchema(sqlBlock, options) {
184
- const { data, "schema": schemaRaw } = await this._runSQL(sqlBlock.selectStr, options);
184
+ const { data, schema: schemaRaw } = await this._runSQL(sqlBlock.selectStr, options);
185
185
  const schema = this.structDefFromSQLSchema(sqlBlock, schemaRaw);
186
186
  return { data, schema };
187
187
  }
188
188
  async downloadMalloyQuery(sqlCommand) {
189
189
  const job = await this.createBigQueryJob({
190
- "query": sqlCommand
190
+ query: sqlCommand,
191
191
  });
192
192
  return job.getQueryResultsStream();
193
193
  }
194
194
  async dryRunSQLQuery(sqlCommand) {
195
195
  try {
196
196
  const [result] = await this.bigQuery.createQueryJob({
197
- "location": this.location,
198
- "query": sqlCommand,
199
- "dryRun": true
197
+ location: this.location,
198
+ query: sqlCommand,
199
+ dryRun: true,
200
200
  });
201
201
  return result;
202
202
  }
@@ -215,8 +215,8 @@ class BigQueryConnection {
215
215
  }
216
216
  async getTableFieldSchema(tableURL) {
217
217
  var _a, _b;
218
- const { "tablePath": tableName } = (0, malloy_1.parseTableURI)(tableURL);
219
- const segments = tableName.split(".");
218
+ const { tablePath: tableName } = (0, malloy_1.parseTableURI)(tableURL);
219
+ const segments = tableName.split('.');
220
220
  // paths can have two or three segments
221
221
  // if there are only two segments, assume the dataset is "local" to the current billing project
222
222
  let projectId, datasetNamePart, tableNamePart;
@@ -241,9 +241,9 @@ class BigQueryConnection {
241
241
  this.bigQuery.projectId = this.projectId;
242
242
  const [metadata] = await metadataPromise;
243
243
  return {
244
- "schema": metadata.schema,
245
- "needsPartitionPsuedoColumn": ((_a = metadata.timePartitioning) === null || _a === void 0 ? void 0 : _a.type) !== undefined &&
246
- ((_b = metadata.timePartitioning) === null || _b === void 0 ? void 0 : _b.field) === undefined
244
+ schema: metadata.schema,
245
+ needsPartitionPsuedoColumn: ((_a = metadata.timePartitioning) === null || _a === void 0 ? void 0 : _a.type) !== undefined &&
246
+ ((_b = metadata.timePartitioning) === null || _b === void 0 ? void 0 : _b.field) === undefined,
247
247
  };
248
248
  }
249
249
  catch (e) {
@@ -255,7 +255,7 @@ class BigQueryConnection {
255
255
  return result[0];
256
256
  }
257
257
  async test() {
258
- await this.dryRunSQLQuery("SELECT 1");
258
+ await this.dryRunSQLQuery('SELECT 1');
259
259
  }
260
260
  /*
261
261
  * Do we need to care about multiple overlapping calls to this function? No.
@@ -276,7 +276,7 @@ class BigQueryConnection {
276
276
  *
277
277
  */
278
278
  async manifestTemporaryTable(sqlCommand) {
279
- const hash = crypto.createHash("md5").update(sqlCommand).digest("hex");
279
+ const hash = crypto.createHash('md5').update(sqlCommand).digest('hex');
280
280
  const tempTableName = this.temporaryTables.get(hash);
281
281
  if (tempTableName !== undefined) {
282
282
  return tempTableName;
@@ -284,16 +284,16 @@ class BigQueryConnection {
284
284
  else {
285
285
  try {
286
286
  const [job] = await this.bigQuery.createQueryJob({
287
- "location": this.location,
288
- "query": sqlCommand
287
+ location: this.location,
288
+ query: sqlCommand,
289
289
  });
290
290
  let [metaData] = await job.getMetadata();
291
291
  // wait for job to complete, because we need the table name
292
292
  // TODO just because a job is "DONE" doesn't mean it ended correctly, should probably also confirm
293
293
  // status is successful & that table was created
294
294
  // TODO this needs better error handling and a timeout so that issues dont result in infinite looping
295
- while (metaData.status.state !== "DONE") {
296
- await new Promise((resolve) => setTimeout(resolve, 1000));
295
+ while (metaData.status.state !== 'DONE') {
296
+ await new Promise(resolve => setTimeout(resolve, 1000));
297
297
  [metaData] = await job.getMetadata();
298
298
  }
299
299
  // save table name
@@ -306,7 +306,7 @@ class BigQueryConnection {
306
306
  return fullTableName;
307
307
  }
308
308
  else {
309
- throw new Error("bigquery.job.getMetadata() - metadata should have configuration but does not");
309
+ throw new Error('bigquery.job.getMetadata() - metadata should have configuration but does not');
310
310
  }
311
311
  }
312
312
  catch (e) {
@@ -332,9 +332,9 @@ class BigQueryConnection {
332
332
  throw new Error(`Table ${tableName} already exists`);
333
333
  }
334
334
  const [job] = await this.bigQuery.createQueryJob({
335
- "query": sqlCommand,
336
- "location": this.location,
337
- "destination": table
335
+ query: sqlCommand,
336
+ location: this.location,
337
+ destination: table,
338
338
  });
339
339
  // if creating this job didn't throw, there's an ID.
340
340
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -348,44 +348,42 @@ class BigQueryConnection {
348
348
  const type = field.type;
349
349
  const name = field.name;
350
350
  // check for an array
351
- if (field.mode === "REPEATED" && !["STRUCT", "RECORD"].includes(type)) {
351
+ if (field.mode === 'REPEATED' && !['STRUCT', 'RECORD'].includes(type)) {
352
352
  const malloyType = this.bqToMalloyTypes[type];
353
353
  if (malloyType) {
354
354
  const innerStructDef = {
355
- "type": "struct",
355
+ type: 'struct',
356
356
  name,
357
- "dialect": this.dialectName,
358
- "structSource": { "type": "nested" },
359
- "structRelationship": {
360
- "type": "nested",
361
- "field": name,
362
- "isArray": true
357
+ dialect: this.dialectName,
358
+ structSource: { type: 'nested' },
359
+ structRelationship: {
360
+ type: 'nested',
361
+ field: name,
362
+ isArray: true,
363
363
  },
364
- "fields": [{ ...malloyType, "name": "value" }]
364
+ fields: [{ ...malloyType, name: 'value' }],
365
365
  };
366
366
  structDef.fields.push(innerStructDef);
367
367
  }
368
368
  }
369
- else if (["STRUCT", "RECORD"].includes(type)) {
369
+ else if (['STRUCT', 'RECORD'].includes(type)) {
370
370
  const innerStructDef = {
371
- "type": "struct",
371
+ type: 'struct',
372
372
  name,
373
- "dialect": this.dialectName,
374
- "structSource": field.mode === "REPEATED"
375
- ? { "type": "nested" }
376
- : { "type": "inline" },
377
- "structRelationship": field.mode === "REPEATED"
378
- ? { "type": "nested", "field": name, "isArray": false }
379
- : { "type": "inline" },
380
- "fields": []
373
+ dialect: this.dialectName,
374
+ structSource: field.mode === 'REPEATED' ? { type: 'nested' } : { type: 'inline' },
375
+ structRelationship: field.mode === 'REPEATED'
376
+ ? { type: 'nested', field: name, isArray: false }
377
+ : { type: 'inline' },
378
+ fields: [],
381
379
  };
382
380
  this.addFieldsToStructDef(innerStructDef, field);
383
381
  structDef.fields.push(innerStructDef);
384
382
  }
385
383
  else {
386
384
  const malloyType = this.bqToMalloyTypes[type] || {
387
- "type": "unsupported",
388
- "rawType": type.toLowerCase()
385
+ type: 'unsupported',
386
+ rawType: type.toLowerCase(),
389
387
  };
390
388
  structDef.fields.push({ name, ...malloyType });
391
389
  }
@@ -393,7 +391,7 @@ class BigQueryConnection {
393
391
  }
394
392
  tableURLtoTablePath(tableURL) {
395
393
  const { tablePath } = (0, malloy_1.parseTableURI)(tableURL);
396
- if (tablePath.split(".").length === 2) {
394
+ if (tablePath.split('.').length === 2) {
397
395
  return `${this.defaultProject}.${tablePath}`;
398
396
  }
399
397
  else {
@@ -402,43 +400,43 @@ class BigQueryConnection {
402
400
  }
403
401
  structDefFromTableSchema(tableURL, schemaInfo) {
404
402
  const structDef = {
405
- "type": "struct",
406
- "name": tableURL,
407
- "dialect": this.dialectName,
408
- "structSource": {
409
- "type": "table",
410
- "tablePath": this.tableURLtoTablePath(tableURL)
403
+ type: 'struct',
404
+ name: tableURL,
405
+ dialect: this.dialectName,
406
+ structSource: {
407
+ type: 'table',
408
+ tablePath: this.tableURLtoTablePath(tableURL),
411
409
  },
412
- "structRelationship": {
413
- "type": "basetable",
414
- "connectionName": this.name
410
+ structRelationship: {
411
+ type: 'basetable',
412
+ connectionName: this.name,
415
413
  },
416
- "fields": []
414
+ fields: [],
417
415
  };
418
416
  this.addFieldsToStructDef(structDef, schemaInfo.schema);
419
417
  if (schemaInfo.needsPartitionPsuedoColumn) {
420
418
  structDef.fields.push({
421
- "type": "timestamp",
422
- "name": "_PARTITIONTIME"
419
+ type: 'timestamp',
420
+ name: '_PARTITIONTIME',
423
421
  });
424
422
  }
425
423
  return structDef;
426
424
  }
427
425
  structDefFromSQLSchema(sqlBlock, tableFieldSchema) {
428
426
  const structDef = {
429
- "type": "struct",
430
- "name": sqlBlock.name,
431
- "dialect": this.dialectName,
432
- "structSource": {
433
- "type": "sql",
434
- "method": "subquery",
435
- sqlBlock
427
+ type: 'struct',
428
+ name: sqlBlock.name,
429
+ dialect: this.dialectName,
430
+ structSource: {
431
+ type: 'sql',
432
+ method: 'subquery',
433
+ sqlBlock,
436
434
  },
437
- "structRelationship": {
438
- "type": "basetable",
439
- "connectionName": this.name
435
+ structRelationship: {
436
+ type: 'basetable',
437
+ connectionName: this.name,
440
438
  },
441
- "fields": []
439
+ fields: [],
442
440
  };
443
441
  this.addFieldsToStructDef(structDef, tableFieldSchema);
444
442
  return structDef;
@@ -452,12 +450,12 @@ class BigQueryConnection {
452
450
  try {
453
451
  const tableFieldSchema = await this.getTableFieldSchema(tableURL);
454
452
  inCache = {
455
- "schema": this.structDefFromTableSchema(tableURL, tableFieldSchema)
453
+ schema: this.structDefFromTableSchema(tableURL, tableFieldSchema),
456
454
  };
457
455
  this.schemaCache.set(tableURL, inCache);
458
456
  }
459
457
  catch (error) {
460
- inCache = { "error": error.message };
458
+ inCache = { error: error.message };
461
459
  }
462
460
  }
463
461
  if (inCache.schema !== undefined) {
@@ -479,9 +477,9 @@ class BigQueryConnection {
479
477
  for (let retries = 0; retries < 3; retries++) {
480
478
  try {
481
479
  const [job] = await this.bigQuery.createQueryJob({
482
- "location": this.location,
483
- "query": sqlRef.selectStr,
484
- "dryRun": true
480
+ location: this.location,
481
+ query: sqlRef.selectStr,
482
+ dryRun: true,
485
483
  });
486
484
  return job.metadata.statistics.query.schema;
487
485
  }
@@ -498,11 +496,11 @@ class BigQueryConnection {
498
496
  try {
499
497
  const tableFieldSchema = await this.getSQLBlockSchema(sqlRef);
500
498
  inCache = {
501
- "structDef": this.structDefFromSQLSchema(sqlRef, tableFieldSchema)
499
+ structDef: this.structDefFromSQLSchema(sqlRef, tableFieldSchema),
502
500
  };
503
501
  }
504
502
  catch (error) {
505
- inCache = { "error": error.message };
503
+ inCache = { error: error.message };
506
504
  }
507
505
  this.sqlSchemaCache.set(key, inCache);
508
506
  }
@@ -514,8 +512,8 @@ class BigQueryConnection {
514
512
  async createBigQueryJobAndGetResults(sqlCommand, createQueryJobOptions, getQueryResultsOptions) {
515
513
  try {
516
514
  const job = await this.createBigQueryJob({
517
- "query": sqlCommand,
518
- ...createQueryJobOptions
515
+ query: sqlCommand,
516
+ ...createQueryJobOptions,
519
517
  });
520
518
  // TODO we should check if this is still required?
521
519
  // We do a simple retry-loop here, as a temporary fix for a transient
@@ -527,8 +525,8 @@ class BigQueryConnection {
527
525
  for (let retries = 0; retries < 3; retries++) {
528
526
  try {
529
527
  return await job.getQueryResults({
530
- "timeoutMs": 1000 * 60 * 2,
531
- ...getQueryResultsOptions
528
+ timeoutMs: 1000 * 60 * 2,
529
+ ...getQueryResultsOptions,
532
530
  });
533
531
  }
534
532
  catch (fetchError) {
@@ -543,10 +541,10 @@ class BigQueryConnection {
543
541
  }
544
542
  async createBigQueryJob(createQueryJobOptions) {
545
543
  const [job] = await this.bigQuery.createQueryJob({
546
- "location": this.location,
547
- "maximumBytesBilled": this.config.maximumBytesBilled || MAXIMUM_BYTES_BILLED,
548
- "jobTimeoutMs": Number(this.config.timeoutMs) || TIMEOUT_MS,
549
- ...createQueryJobOptions
544
+ location: this.location,
545
+ maximumBytesBilled: this.config.maximumBytesBilled || MAXIMUM_BYTES_BILLED,
546
+ jobTimeoutMs: Number(this.config.timeoutMs) || TIMEOUT_MS,
547
+ ...createQueryJobOptions,
550
548
  });
551
549
  return job;
552
550
  }
@@ -563,9 +561,9 @@ class BigQueryConnection {
563
561
  }
564
562
  bigQuery
565
563
  .createQueryStream(sqlCommand)
566
- .on("error", onError)
567
- .on("data", handleData)
568
- .on("end", onEnd);
564
+ .on('error', onError)
565
+ .on('data', handleData)
566
+ .on('end', onEnd);
569
567
  }
570
568
  return (0, malloy_1.toAsyncGenerator)(streamBigQuery);
571
569
  }
@@ -575,6 +573,6 @@ class BigQueryConnection {
575
573
  }
576
574
  exports.BigQueryConnection = BigQueryConnection;
577
575
  BigQueryConnection.DEFAULT_QUERY_OPTIONS = {
578
- "rowLimit": 10
576
+ rowLimit: 10,
579
577
  };
580
578
  //# sourceMappingURL=bigquery_connection.js.map
package/dist/index.d.ts CHANGED
@@ -1 +1 @@
1
- export { BigQueryConnection } from "./bigquery_connection";
1
+ export { BigQueryConnection } from './bigquery_connection';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/db-bigquery",
3
- "version": "0.0.24-dev230224184907",
3
+ "version": "0.0.24-dev230228224434",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -9,6 +9,9 @@
9
9
  "type": "git",
10
10
  "url": "https://github.com/malloydata/malloy"
11
11
  },
12
+ "engines": {
13
+ "node": ">=10"
14
+ },
12
15
  "scripts": {
13
16
  "lint": "eslint '**/*.ts{,x}'",
14
17
  "lint-fix": "eslint '**/*.ts{,x}' --fix",
@@ -21,7 +24,8 @@
21
24
  "dependencies": {
22
25
  "@google-cloud/bigquery": "^5.5.0",
23
26
  "@google-cloud/common": "^3.6.0",
24
- "@malloydata/malloy": "^0.0.24-dev230224184907",
27
+ "@google-cloud/paginator": "^4.0.1",
28
+ "@malloydata/malloy": "^0.0.24-dev230228224434",
25
29
  "gaxios": "^4.2.0"
26
30
  }
27
31
  }