@malloydata/db-bigquery 0.0.96-dev231025212541 → 0.0.96-dev231025215824
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.
package/dist/bigquery.spec.js
CHANGED
|
@@ -166,5 +166,94 @@ describe('db:BigQuery', () => {
|
|
|
166
166
|
expect(results[0]).toStrictEqual({ t: 1 });
|
|
167
167
|
});
|
|
168
168
|
});
|
|
169
|
+
describe('Caching', () => {
|
|
170
|
+
let getTableFieldSchema;
|
|
171
|
+
let getSQLBlockSchema;
|
|
172
|
+
beforeEach(async () => {
|
|
173
|
+
getTableFieldSchema = jest
|
|
174
|
+
.spyOn(bigquery_connection_1.BigQueryConnection.prototype, 'getTableFieldSchema')
|
|
175
|
+
.mockResolvedValue({
|
|
176
|
+
schema: {},
|
|
177
|
+
needsTableSuffixPseudoColumn: false,
|
|
178
|
+
needsPartitionTimePseudoColumn: false,
|
|
179
|
+
needsPartitionDatePseudoColumn: false,
|
|
180
|
+
});
|
|
181
|
+
getSQLBlockSchema = jest
|
|
182
|
+
.spyOn(bigquery_connection_1.BigQueryConnection.prototype, 'getSQLBlockSchema')
|
|
183
|
+
.mockResolvedValue({
|
|
184
|
+
schema: {},
|
|
185
|
+
needsTableSuffixPseudoColumn: false,
|
|
186
|
+
needsPartitionTimePseudoColumn: false,
|
|
187
|
+
needsPartitionDatePseudoColumn: false,
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
afterEach(() => {
|
|
191
|
+
jest.resetAllMocks();
|
|
192
|
+
});
|
|
193
|
+
it('caches table schema', async () => {
|
|
194
|
+
await bq.fetchSchemaForTables({ 'test1': 'table1' }, {});
|
|
195
|
+
expect(getTableFieldSchema).toBeCalledTimes(1);
|
|
196
|
+
await new Promise(resolve => setTimeout(resolve));
|
|
197
|
+
await bq.fetchSchemaForTables({ 'test1': 'table1' }, {});
|
|
198
|
+
expect(getTableFieldSchema).toBeCalledTimes(1);
|
|
199
|
+
});
|
|
200
|
+
it('refreshes table schema', async () => {
|
|
201
|
+
await bq.fetchSchemaForTables({ 'test2': 'table2' }, {});
|
|
202
|
+
expect(getTableFieldSchema).toBeCalledTimes(1);
|
|
203
|
+
await new Promise(resolve => setTimeout(resolve));
|
|
204
|
+
await bq.fetchSchemaForTables({ 'test2': 'table2' }, { refreshTimestamp: Date.now() });
|
|
205
|
+
expect(getTableFieldSchema).toBeCalledTimes(2);
|
|
206
|
+
});
|
|
207
|
+
it('caches sql schema', async () => {
|
|
208
|
+
await bq.fetchSchemaForSQLBlock(SQL_BLOCK_1, {});
|
|
209
|
+
expect(getSQLBlockSchema).toBeCalledTimes(1);
|
|
210
|
+
await new Promise(resolve => setTimeout(resolve));
|
|
211
|
+
await bq.fetchSchemaForSQLBlock(SQL_BLOCK_1, {});
|
|
212
|
+
expect(getSQLBlockSchema).toBeCalledTimes(1);
|
|
213
|
+
});
|
|
214
|
+
it('refreshes sql schema', async () => {
|
|
215
|
+
await bq.fetchSchemaForSQLBlock(SQL_BLOCK_2, {});
|
|
216
|
+
expect(getSQLBlockSchema).toBeCalledTimes(1);
|
|
217
|
+
await new Promise(resolve => setTimeout(resolve));
|
|
218
|
+
await bq.fetchSchemaForSQLBlock(SQL_BLOCK_2, {
|
|
219
|
+
refreshTimestamp: Date.now(),
|
|
220
|
+
});
|
|
221
|
+
expect(getSQLBlockSchema).toBeCalledTimes(2);
|
|
222
|
+
});
|
|
223
|
+
});
|
|
169
224
|
});
|
|
225
|
+
const SQL_BLOCK_1 = {
|
|
226
|
+
type: 'sqlBlock',
|
|
227
|
+
name: 'block1',
|
|
228
|
+
selectStr: `
|
|
229
|
+
SELECT
|
|
230
|
+
created_at,
|
|
231
|
+
sale_price,
|
|
232
|
+
inventory_item_id
|
|
233
|
+
FROM 'order_items.parquet'
|
|
234
|
+
SELECT
|
|
235
|
+
id,
|
|
236
|
+
product_department,
|
|
237
|
+
product_category,
|
|
238
|
+
created_at AS inventory_items_created_at
|
|
239
|
+
FROM "inventory_items.parquet"
|
|
240
|
+
`,
|
|
241
|
+
};
|
|
242
|
+
const SQL_BLOCK_2 = {
|
|
243
|
+
type: 'sqlBlock',
|
|
244
|
+
name: 'block2',
|
|
245
|
+
selectStr: `
|
|
246
|
+
SELECT
|
|
247
|
+
created_at,
|
|
248
|
+
sale_price,
|
|
249
|
+
inventory_item_id
|
|
250
|
+
FROM read_parquet('order_items2.parquet', arg='value')
|
|
251
|
+
SELECT
|
|
252
|
+
id,
|
|
253
|
+
product_department,
|
|
254
|
+
product_category,
|
|
255
|
+
created_at AS inventory_items_created_at
|
|
256
|
+
FROM read_parquet("inventory_items2.parquet")
|
|
257
|
+
`,
|
|
258
|
+
};
|
|
170
259
|
//# sourceMappingURL=bigquery.spec.js.map
|
|
@@ -2,6 +2,7 @@ import { RowMetadata } from '@google-cloud/bigquery';
|
|
|
2
2
|
import bigquery from '@google-cloud/bigquery/build/src/types';
|
|
3
3
|
import { ResourceStream } from '@google-cloud/paginator';
|
|
4
4
|
import { Connection, MalloyQueryData, PersistSQLResults, PooledConnection, QueryData, QueryDataRow, QueryRunStats, SQLBlock, StreamingConnection, StructDef } from '@malloydata/malloy';
|
|
5
|
+
import { FetchSchemaOptions } from '@malloydata/malloy-interfaces';
|
|
5
6
|
export interface BigQueryManagerOptions {
|
|
6
7
|
credentials?: {
|
|
7
8
|
clientId: string;
|
|
@@ -77,12 +78,12 @@ export declare class BigQueryConnection implements Connection, PersistSQLResults
|
|
|
77
78
|
private addFieldsToStructDef;
|
|
78
79
|
private structDefFromTableSchema;
|
|
79
80
|
private structDefFromSQLSchema;
|
|
80
|
-
fetchSchemaForTables(missing: Record<string, string
|
|
81
|
+
fetchSchemaForTables(missing: Record<string, string>, { refreshTimestamp }: FetchSchemaOptions): Promise<{
|
|
81
82
|
schemas: Record<string, StructDef>;
|
|
82
83
|
errors: Record<string, string>;
|
|
83
84
|
}>;
|
|
84
85
|
private getSQLBlockSchema;
|
|
85
|
-
fetchSchemaForSQLBlock(sqlRef: SQLBlock): Promise<{
|
|
86
|
+
fetchSchemaForSQLBlock(sqlRef: SQLBlock, { refreshTimestamp }: FetchSchemaOptions): Promise<{
|
|
86
87
|
structDef: StructDef;
|
|
87
88
|
error?: undefined;
|
|
88
89
|
} | {
|
|
@@ -442,22 +442,25 @@ class BigQueryConnection {
|
|
|
442
442
|
this.addFieldsToStructDef(structDef, tableFieldSchema);
|
|
443
443
|
return structDef;
|
|
444
444
|
}
|
|
445
|
-
async fetchSchemaForTables(missing) {
|
|
445
|
+
async fetchSchemaForTables(missing, { refreshTimestamp }) {
|
|
446
446
|
const schemas = {};
|
|
447
447
|
const errors = {};
|
|
448
448
|
for (const tableKey in missing) {
|
|
449
449
|
let inCache = this.schemaCache.get(tableKey);
|
|
450
|
-
if (!inCache
|
|
450
|
+
if (!inCache ||
|
|
451
|
+
(refreshTimestamp && refreshTimestamp > inCache.timestamp)) {
|
|
452
|
+
const timestamp = refreshTimestamp !== null && refreshTimestamp !== void 0 ? refreshTimestamp : Date.now();
|
|
451
453
|
const tablePath = this.normalizeTablePath(missing[tableKey]);
|
|
452
454
|
try {
|
|
453
455
|
const tableFieldSchema = await this.getTableFieldSchema(tablePath);
|
|
454
456
|
inCache = {
|
|
455
457
|
schema: this.structDefFromTableSchema(tableKey, tablePath, tableFieldSchema),
|
|
458
|
+
timestamp,
|
|
456
459
|
};
|
|
457
460
|
this.schemaCache.set(tableKey, inCache);
|
|
458
461
|
}
|
|
459
462
|
catch (error) {
|
|
460
|
-
inCache = { error: error.message };
|
|
463
|
+
inCache = { error: error.message, timestamp };
|
|
461
464
|
}
|
|
462
465
|
}
|
|
463
466
|
if (inCache.schema !== undefined) {
|
|
@@ -491,18 +494,21 @@ class BigQueryConnection {
|
|
|
491
494
|
}
|
|
492
495
|
throw lastFetchError;
|
|
493
496
|
}
|
|
494
|
-
async fetchSchemaForSQLBlock(sqlRef) {
|
|
497
|
+
async fetchSchemaForSQLBlock(sqlRef, { refreshTimestamp }) {
|
|
495
498
|
const key = sqlRef.name;
|
|
496
499
|
let inCache = this.sqlSchemaCache.get(key);
|
|
497
|
-
if (!inCache
|
|
500
|
+
if (!inCache ||
|
|
501
|
+
(refreshTimestamp && refreshTimestamp > inCache.timestamp)) {
|
|
502
|
+
const timestamp = refreshTimestamp !== null && refreshTimestamp !== void 0 ? refreshTimestamp : Date.now();
|
|
498
503
|
try {
|
|
499
504
|
const tableFieldSchema = await this.getSQLBlockSchema(sqlRef);
|
|
500
505
|
inCache = {
|
|
501
506
|
structDef: this.structDefFromSQLSchema(sqlRef, tableFieldSchema),
|
|
507
|
+
timestamp,
|
|
502
508
|
};
|
|
503
509
|
}
|
|
504
510
|
catch (error) {
|
|
505
|
-
inCache = { error: error.message };
|
|
511
|
+
inCache = { error: error.message, timestamp };
|
|
506
512
|
}
|
|
507
513
|
this.sqlSchemaCache.set(key, inCache);
|
|
508
514
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@malloydata/db-bigquery",
|
|
3
|
-
"version": "0.0.96-
|
|
3
|
+
"version": "0.0.96-dev231025215824",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"@google-cloud/bigquery": "^5.5.0",
|
|
26
26
|
"@google-cloud/common": "^3.6.0",
|
|
27
27
|
"@google-cloud/paginator": "^4.0.1",
|
|
28
|
-
"@malloydata/malloy": "^0.0.96-
|
|
28
|
+
"@malloydata/malloy": "^0.0.96-dev231025215824",
|
|
29
|
+
"@malloydata/malloy-interfaces": "^0.0.96-dev231025215824",
|
|
29
30
|
"gaxios": "^4.2.0"
|
|
30
31
|
}
|
|
31
32
|
}
|