@malloydata/db-bigquery 0.0.240-dev250311202829 → 0.0.240-dev250311214430

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/db-bigquery",
3
- "version": "0.0.240-dev250311202829",
3
+ "version": "0.0.240-dev250311214430",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -25,7 +25,7 @@
25
25
  "@google-cloud/bigquery": "^7.3.0",
26
26
  "@google-cloud/common": "^5.0.1",
27
27
  "@google-cloud/paginator": "^5.0.0",
28
- "@malloydata/malloy": "^0.0.240-dev250311202829",
28
+ "@malloydata/malloy": "^0.0.240-dev250311214430",
29
29
  "gaxios": "^4.2.0"
30
30
  }
31
31
  }
@@ -1 +0,0 @@
1
- export {};
@@ -1,267 +0,0 @@
1
- "use strict";
2
- /*
3
- * Copyright 2023 Google LLC
4
- *
5
- * Permission is hereby granted, free of charge, to any person obtaining
6
- * a copy of this software and associated documentation files
7
- * (the "Software"), to deal in the Software without restriction,
8
- * including without limitation the rights to use, copy, modify, merge,
9
- * publish, distribute, sublicense, and/or sell copies of the Software,
10
- * and to permit persons to whom the Software is furnished to do so,
11
- * subject to the following conditions:
12
- *
13
- * The above copyright notice and this permission notice shall be
14
- * included in all copies or substantial portions of the Software.
15
- *
16
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
- */
24
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
25
- if (k2 === undefined) k2 = k;
26
- var desc = Object.getOwnPropertyDescriptor(m, k);
27
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
28
- desc = { enumerable: true, get: function() { return m[k]; } };
29
- }
30
- Object.defineProperty(o, k2, desc);
31
- }) : (function(o, m, k, k2) {
32
- if (k2 === undefined) k2 = k;
33
- o[k2] = m[k];
34
- }));
35
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
36
- Object.defineProperty(o, "default", { enumerable: true, value: v });
37
- }) : function(o, v) {
38
- o["default"] = v;
39
- });
40
- var __importStar = (this && this.__importStar) || function (mod) {
41
- if (mod && mod.__esModule) return mod;
42
- var result = {};
43
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
44
- __setModuleDefault(result, mod);
45
- return result;
46
- };
47
- Object.defineProperty(exports, "__esModule", { value: true });
48
- const malloy = __importStar(require("@malloydata/malloy"));
49
- const test_1 = require("@malloydata/malloy/test");
50
- const bigquery_connection_1 = require("./bigquery_connection");
51
- const bigquery_1 = require("@google-cloud/bigquery");
52
- const util = __importStar(require("util"));
53
- const fs = __importStar(require("fs"));
54
- const url_1 = require("url");
55
- const [describe] = (0, test_1.describeIfDatabaseAvailable)(['bigquery']);
56
- describe('db:BigQuery', () => {
57
- let bq;
58
- let runtime;
59
- beforeAll(() => {
60
- bq = new bigquery_connection_1.BigQueryConnection('test');
61
- const files = {
62
- readURL: async (url) => {
63
- const filePath = (0, url_1.fileURLToPath)(url);
64
- return await util.promisify(fs.readFile)(filePath, 'utf8');
65
- },
66
- };
67
- runtime = new malloy.Runtime({
68
- urlReader: files,
69
- connection: bq,
70
- });
71
- });
72
- it('runs a SQL query', async () => {
73
- const res = await bq.runSQL('SELECT 1 as t');
74
- expect(res.rows[0]['t']).toBe(1);
75
- });
76
- it('costs a SQL query', async () => {
77
- const res = await bq.estimateQueryCost('SELECT * FROM malloydata-org.malloytest.airports');
78
- expect(res.queryCostBytes).toBe(3029200);
79
- });
80
- it('gets table schema', async () => {
81
- const res = await bq.getTableFieldSchema('malloydata-org.malloytest.carriers');
82
- expect(res.schema).toStrictEqual({
83
- fields: [
84
- { name: 'code', type: 'STRING' },
85
- { name: 'name', type: 'STRING' },
86
- { name: 'nickname', type: 'STRING' },
87
- ],
88
- });
89
- });
90
- it.todo('gets table structdefs');
91
- it('runs a Malloy query', async () => {
92
- const sql = await runtime
93
- .loadModel("source: carriers is bigquery.table('malloydata-org.malloytest.carriers') extend { measure: carrier_count is count() }")
94
- .loadQuery('run: carriers -> { aggregate: carrier_count }')
95
- .getSQL();
96
- const res = await bq.runSQL(sql);
97
- expect(res.rows[0]['carrier_count']).toBe(21);
98
- });
99
- it('streams a Malloy query for download', async () => {
100
- const sql = await runtime
101
- .loadModel("source: carriers is bigquery.table('malloydata-org.malloytest.carriers') extend { measure: carrier_count is count() }")
102
- .loadQuery('run: carriers -> { group_by: name }')
103
- .getSQL();
104
- const res = await bq.downloadMalloyQuery(sql);
105
- return new Promise(resolve => {
106
- let count = 0;
107
- res.on('data', () => (count += 1));
108
- res.on('end', () => {
109
- expect(count).toBe(21);
110
- resolve(true);
111
- });
112
- });
113
- });
114
- it('manifests a temporary table', async () => {
115
- const fullTempTableName = await bq.manifestTemporaryTable('SELECT 1 as t');
116
- const splitTableName = fullTempTableName.split('.');
117
- const sdk = new bigquery_1.BigQuery();
118
- const dataset = sdk.dataset(splitTableName[1]);
119
- const table = dataset.table(splitTableName[2]);
120
- const exists = await table.exists();
121
- expect(exists).toBeTruthy();
122
- });
123
- const skipThisTestSetion = false; // describe.skip is not ok, given how we patch describe
124
- if (skipThisTestSetion) {
125
- describe.skip('manifests permanent table', () => {
126
- const datasetName = 'test_malloy_test_dataset';
127
- const tableName = 'test_malloy_test_table';
128
- const sdk = new bigquery_1.BigQuery();
129
- // delete entire dataset before each test and once tests are complete
130
- const deleteTestDataset = async () => {
131
- const dataset = sdk.dataset(datasetName);
132
- if ((await dataset.exists())[0]) {
133
- await dataset.delete({
134
- force: true,
135
- });
136
- }
137
- };
138
- beforeEach(deleteTestDataset);
139
- afterAll(deleteTestDataset);
140
- it('throws if dataset does not exist and createDataset=false', async () => {
141
- await expect(async () => {
142
- await bq.manifestPermanentTable('SELECT 1 as t', datasetName, tableName, false, false);
143
- }).rejects.toThrowError(`Dataset ${datasetName} does not exist`);
144
- });
145
- it('creates dataset if createDataset=true', async () => {
146
- // note - dataset does not exist b/c of beforeEach()
147
- await bq.manifestPermanentTable('SELECT 1 as t', datasetName, tableName, false, true);
148
- const dataset = sdk.dataset(datasetName);
149
- const [exists] = await dataset.exists();
150
- expect(exists).toBeTruthy();
151
- });
152
- it('throws if table exist and overwriteExistingTable=false', async () => {
153
- const newDatasetResponse = await sdk.createDataset(datasetName);
154
- const dataset = newDatasetResponse[0];
155
- const tableMeta = { name: tableName };
156
- await dataset.createTable(tableName, tableMeta);
157
- await expect(async () => {
158
- await bq.manifestPermanentTable('SELECT 1 as t', datasetName, tableName, false, true);
159
- }).rejects.toThrowError(`Table ${tableName} already exists`);
160
- });
161
- it('manifests a table', async () => {
162
- const jobId = await bq.manifestPermanentTable('SELECT 1 as t', datasetName, tableName, false, true);
163
- // wait for job to complete
164
- const [job] = await sdk.job(jobId).get();
165
- let [metaData] = await job.getMetadata();
166
- while (metaData.status.state !== 'DONE') {
167
- await new Promise(resolve => setTimeout(resolve, 1000));
168
- [metaData] = await job.getMetadata();
169
- }
170
- // query the new table
171
- const [queryJob] = await sdk.createQueryJob(`SELECT * FROM ${datasetName}.${tableName}`);
172
- const [results] = await queryJob.getQueryResults();
173
- expect(results[0]).toStrictEqual({ t: 1 });
174
- });
175
- });
176
- }
177
- describe('Caching', () => {
178
- let getTableFieldSchema;
179
- let getSQLBlockSchema;
180
- beforeEach(async () => {
181
- getTableFieldSchema = jest
182
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
183
- .spyOn(bigquery_connection_1.BigQueryConnection.prototype, 'getTableFieldSchema')
184
- .mockResolvedValue({
185
- schema: {},
186
- needsTableSuffixPseudoColumn: false,
187
- needsPartitionTimePseudoColumn: false,
188
- needsPartitionDatePseudoColumn: false,
189
- });
190
- getSQLBlockSchema = jest
191
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
192
- .spyOn(bigquery_connection_1.BigQueryConnection.prototype, 'getSQLBlockSchema')
193
- .mockResolvedValue({
194
- schema: {},
195
- needsTableSuffixPseudoColumn: false,
196
- needsPartitionTimePseudoColumn: false,
197
- needsPartitionDatePseudoColumn: false,
198
- });
199
- });
200
- afterEach(() => {
201
- jest.resetAllMocks();
202
- });
203
- it('caches table schema', async () => {
204
- await bq.fetchSchemaForTables({ 'test1': 'table1' }, {});
205
- expect(getTableFieldSchema).toBeCalledTimes(1);
206
- await new Promise(resolve => setTimeout(resolve));
207
- await bq.fetchSchemaForTables({ 'test1': 'table1' }, {});
208
- expect(getTableFieldSchema).toBeCalledTimes(1);
209
- });
210
- it('refreshes table schema', async () => {
211
- await bq.fetchSchemaForTables({ 'test2': 'table2' }, {});
212
- expect(getTableFieldSchema).toBeCalledTimes(1);
213
- await new Promise(resolve => setTimeout(resolve));
214
- await bq.fetchSchemaForTables({ 'test2': 'table2' }, { refreshTimestamp: Date.now() + 10 });
215
- expect(getTableFieldSchema).toBeCalledTimes(2);
216
- });
217
- it('caches sql schema', async () => {
218
- await bq.fetchSchemaForSQLStruct(SQL_BLOCK_1, {});
219
- expect(getSQLBlockSchema).toBeCalledTimes(1);
220
- await new Promise(resolve => setTimeout(resolve));
221
- await bq.fetchSchemaForSQLStruct(SQL_BLOCK_1, {});
222
- expect(getSQLBlockSchema).toBeCalledTimes(1);
223
- });
224
- it('refreshes sql schema', async () => {
225
- await bq.fetchSchemaForSQLStruct(SQL_BLOCK_2, {});
226
- expect(getSQLBlockSchema).toBeCalledTimes(1);
227
- await new Promise(resolve => setTimeout(resolve));
228
- await bq.fetchSchemaForSQLStruct(SQL_BLOCK_2, {
229
- refreshTimestamp: Date.now() + 10,
230
- });
231
- expect(getSQLBlockSchema).toBeCalledTimes(2);
232
- });
233
- });
234
- });
235
- const SQL_BLOCK_1 = {
236
- connection: 'bigquery',
237
- selectStr: `
238
- SELECT
239
- created_at,
240
- sale_price,
241
- inventory_item_id
242
- FROM 'order_items.parquet'
243
- SELECT
244
- id,
245
- product_department,
246
- product_category,
247
- created_at AS inventory_items_created_at
248
- FROM "inventory_items.parquet"
249
- `,
250
- };
251
- const SQL_BLOCK_2 = {
252
- connection: 'bigquery',
253
- selectStr: `
254
- SELECT
255
- created_at,
256
- sale_price,
257
- inventory_item_id
258
- FROM read_parquet('order_items2.parquet', arg='value')
259
- SELECT
260
- id,
261
- product_department,
262
- product_category,
263
- created_at AS inventory_items_created_at
264
- FROM read_parquet("inventory_items2.parquet")
265
- `,
266
- };
267
- //# sourceMappingURL=bigquery.spec.js.map