@malloydata/db-snowflake 0.0.126-dev240305182920

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.
@@ -0,0 +1 @@
1
+ export { SnowflakeConnection } from './snowflake_connection';
package/dist/index.js ADDED
@@ -0,0 +1,28 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.SnowflakeConnection = void 0;
26
+ var snowflake_connection_1 = require("./snowflake_connection");
27
+ Object.defineProperty(exports, "SnowflakeConnection", { enumerable: true, get: function () { return snowflake_connection_1.SnowflakeConnection; } });
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;;;AAEH,+DAA2D;AAAnD,2HAAA,mBAAmB,OAAA"}
@@ -0,0 +1,51 @@
1
+ import { RunSQLOptions, MalloyQueryData, QueryRunStats, Connection, PersistSQLResults, StreamingConnection, PooledConnection, SQLBlock, StructDef, QueryDataRow } from '@malloydata/malloy';
2
+ import { FetchSchemaOptions, TestableConnection } from '@malloydata/malloy/dist/runtime_types';
3
+ import { ConnectionOptions } from 'snowflake-sdk';
4
+ import { Options as PoolOptions } from 'generic-pool';
5
+ type namespace = {
6
+ database: string;
7
+ schema: string;
8
+ };
9
+ export interface SnowflakeConnectionOptions {
10
+ connOptions?: ConnectionOptions;
11
+ poolOptions?: PoolOptions;
12
+ scratchSpace?: namespace;
13
+ queryOptions?: RunSQLOptions;
14
+ }
15
+ export declare class SnowflakeConnection implements Connection, PersistSQLResults, StreamingConnection, TestableConnection {
16
+ readonly name: string;
17
+ private readonly dialect;
18
+ private executor;
19
+ private schemaCache;
20
+ private sqlSchemaCache;
21
+ private scratchSpace?;
22
+ private queryOptions;
23
+ constructor(name: string, options?: SnowflakeConnectionOptions);
24
+ get dialectName(): string;
25
+ get supportsNesting(): boolean;
26
+ isPool(): this is PooledConnection;
27
+ canPersist(): this is PersistSQLResults;
28
+ canStream(): this is StreamingConnection;
29
+ estimateQueryCost(_sqlCommand: string): Promise<QueryRunStats>;
30
+ close(): Promise<void>;
31
+ private getTempTableName;
32
+ runSQL(sql: string, options?: RunSQLOptions): Promise<MalloyQueryData>;
33
+ runSQLStream(sqlCommand: string, options?: RunSQLOptions): AsyncIterableIterator<QueryDataRow>;
34
+ test(): Promise<void>;
35
+ private schemaFromQuery;
36
+ private getTableSchema;
37
+ fetchSchemaForTables(missing: Record<string, string>, { refreshTimestamp }: FetchSchemaOptions): Promise<{
38
+ schemas: Record<string, StructDef>;
39
+ errors: Record<string, string>;
40
+ }>;
41
+ private getSQLBlockSchema;
42
+ fetchSchemaForSQLBlock(sqlRef: SQLBlock, { refreshTimestamp }: FetchSchemaOptions): Promise<{
43
+ structDef: StructDef;
44
+ error?: undefined;
45
+ } | {
46
+ error: string;
47
+ structDef?: undefined;
48
+ }>;
49
+ manifestTemporaryTable(sqlCommand: string): Promise<string>;
50
+ }
51
+ export {};
@@ -0,0 +1,271 @@
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
+ exports.SnowflakeConnection = void 0;
49
+ const crypto = __importStar(require("crypto"));
50
+ const malloy_1 = require("@malloydata/malloy");
51
+ const snowflake_executor_1 = require("./snowflake_executor");
52
+ class SnowflakeConnection {
53
+ constructor(name, options) {
54
+ var _a;
55
+ this.name = name;
56
+ this.dialect = new malloy_1.SnowflakeDialect();
57
+ this.schemaCache = new Map();
58
+ this.sqlSchemaCache = new Map();
59
+ let connOptions = options === null || options === void 0 ? void 0 : options.connOptions;
60
+ if (connOptions === undefined) {
61
+ // try to get connection options from ~/.snowflake/connections.toml
62
+ connOptions = snowflake_executor_1.SnowflakeExecutor.getConnectionOptionsFromToml();
63
+ }
64
+ this.executor = new snowflake_executor_1.SnowflakeExecutor(connOptions, options === null || options === void 0 ? void 0 : options.poolOptions);
65
+ this.scratchSpace = options === null || options === void 0 ? void 0 : options.scratchSpace;
66
+ this.queryOptions = (_a = options === null || options === void 0 ? void 0 : options.queryOptions) !== null && _a !== void 0 ? _a : {};
67
+ }
68
+ get dialectName() {
69
+ return 'snowflake';
70
+ }
71
+ // TODO: make it support nesting soon
72
+ get supportsNesting() {
73
+ return false;
74
+ }
75
+ isPool() {
76
+ return true;
77
+ }
78
+ canPersist() {
79
+ return true;
80
+ }
81
+ canStream() {
82
+ return true;
83
+ }
84
+ async estimateQueryCost(_sqlCommand) {
85
+ return {};
86
+ }
87
+ async close() {
88
+ await this.executor.done();
89
+ }
90
+ getTempTableName(sqlCommand) {
91
+ const hash = crypto.createHash('md5').update(sqlCommand).digest('hex');
92
+ let tableName = `tt${hash}`;
93
+ if (this.scratchSpace) {
94
+ tableName = `${this.scratchSpace.database}.${this.scratchSpace.schema}.${tableName}`;
95
+ }
96
+ return tableName;
97
+ }
98
+ async runSQL(sql, options) {
99
+ var _a, _b;
100
+ const rowLimit = (_a = options === null || options === void 0 ? void 0 : options.rowLimit) !== null && _a !== void 0 ? _a : (_b = this.queryOptions) === null || _b === void 0 ? void 0 : _b.rowLimit;
101
+ let rows = await this.executor.batch(sql);
102
+ if (rowLimit !== undefined && rows.length > rowLimit) {
103
+ rows = rows.slice(0, rowLimit);
104
+ }
105
+ return { rows, totalRows: rows.length };
106
+ }
107
+ async *runSQLStream(sqlCommand, options = {}) {
108
+ const streamQueryOptions = {
109
+ ...this.queryOptions,
110
+ ...options,
111
+ };
112
+ for await (const row of await this.executor.stream(sqlCommand, streamQueryOptions)) {
113
+ yield row;
114
+ }
115
+ }
116
+ async test() {
117
+ await this.executor.batch('SELECT 1');
118
+ }
119
+ async schemaFromQuery(infoQuery, structDef) {
120
+ const rows = await this.executor.batch(infoQuery);
121
+ for (const row of rows) {
122
+ const snowflakeDataType = row['DATA_TYPE'];
123
+ const s = structDef;
124
+ const malloyType = this.dialect.sqlTypeToMalloyType(snowflakeDataType);
125
+ const name = row['COLUMN_NAME'];
126
+ if (malloyType) {
127
+ s.fields.push({ ...malloyType, name });
128
+ }
129
+ else {
130
+ s.fields.push({
131
+ type: 'unsupported',
132
+ rawType: snowflakeDataType,
133
+ name,
134
+ });
135
+ }
136
+ }
137
+ }
138
+ async getTableSchema(tableKey, tablePath) {
139
+ // looks like snowflake:schemaName.tableName
140
+ tableKey = tableKey.toLowerCase();
141
+ let [schema, tableName] = ['', tablePath];
142
+ const schema_and_table = tablePath.split('.');
143
+ if (schema_and_table.length === 2) {
144
+ [schema, tableName] = schema_and_table;
145
+ }
146
+ const structDef = {
147
+ type: 'struct',
148
+ dialect: 'snowflake',
149
+ name: tableKey,
150
+ structSource: { type: 'table', tablePath },
151
+ structRelationship: {
152
+ type: 'basetable',
153
+ connectionName: this.name,
154
+ },
155
+ fields: [],
156
+ };
157
+ // This is how we get variant information
158
+ // WITH tbl as (
159
+ // SELECT * FROM malloytest.ga_sample
160
+ // )
161
+ // SELECT regexp_replace(PATH, '\\[.*\\]', '[]') as PATH, lower(TYPEOF(value)) as type
162
+ // FROM (select object_construct(*) o from tbl limit 100)
163
+ // ,table(flatten(input => o, recursive => true)) as meta
164
+ // WHERE lower(TYPEOF(value)) <> 'array'
165
+ // GROUP BY 1,2
166
+ // ORDER BY PATH
167
+ const infoQuery = `
168
+ SELECT
169
+ column_name, -- LOWER(COLUMN_NAME) AS column_name,
170
+ LOWER(DATA_TYPE) as data_type
171
+ FROM
172
+ INFORMATION_SCHEMA.COLUMNS
173
+ WHERE
174
+ table_schema = UPPER('${schema}')
175
+ AND table_name = UPPER('${tableName}');
176
+ `;
177
+ await this.schemaFromQuery(infoQuery, structDef);
178
+ return structDef;
179
+ }
180
+ async fetchSchemaForTables(missing, { refreshTimestamp }) {
181
+ const schemas = {};
182
+ const errors = {};
183
+ for (const tableKey in missing) {
184
+ let inCache = this.schemaCache.get(tableKey);
185
+ if (!inCache ||
186
+ (refreshTimestamp && refreshTimestamp > inCache.timestamp)) {
187
+ const tablePath = missing[tableKey];
188
+ const timestamp = refreshTimestamp || Date.now();
189
+ try {
190
+ inCache = {
191
+ schema: await this.getTableSchema(tableKey, tablePath),
192
+ timestamp,
193
+ };
194
+ this.schemaCache.set(tableKey, inCache);
195
+ }
196
+ catch (error) {
197
+ inCache = { error: error.message, timestamp };
198
+ }
199
+ }
200
+ if (inCache.schema !== undefined) {
201
+ schemas[tableKey] = inCache.schema;
202
+ }
203
+ else {
204
+ errors[tableKey] = inCache.error || 'Unknown schema fetch error';
205
+ }
206
+ }
207
+ return { schemas, errors };
208
+ }
209
+ async getSQLBlockSchema(sqlRef) {
210
+ const structDef = {
211
+ type: 'struct',
212
+ dialect: 'snowflake',
213
+ name: sqlRef.name,
214
+ structSource: {
215
+ type: 'sql',
216
+ method: 'subquery',
217
+ sqlBlock: sqlRef,
218
+ },
219
+ structRelationship: {
220
+ type: 'basetable',
221
+ connectionName: this.name,
222
+ },
223
+ fields: [],
224
+ };
225
+ // create temp table with same schema as the query
226
+ const tempTableName = this.getTempTableName(sqlRef.selectStr);
227
+ this.runSQL(`
228
+ CREATE OR REPLACE TEMP TABLE ${tempTableName} as SELECT * FROM (
229
+ ${sqlRef.selectStr}
230
+ ) as x WHERE false;
231
+ `);
232
+ const infoQuery = `
233
+ SELECT
234
+ column_name, -- LOWER(column_name) as column_name,
235
+ LOWER(data_type) as data_type
236
+ FROM
237
+ INFORMATION_SCHEMA.COLUMNS
238
+ WHERE
239
+ table_name = UPPER('${tempTableName}');
240
+ `;
241
+ await this.schemaFromQuery(infoQuery, structDef);
242
+ return structDef;
243
+ }
244
+ async fetchSchemaForSQLBlock(sqlRef, { refreshTimestamp }) {
245
+ const key = sqlRef.name;
246
+ let inCache = this.sqlSchemaCache.get(key);
247
+ if (!inCache ||
248
+ (refreshTimestamp && refreshTimestamp > inCache.timestamp)) {
249
+ const timestamp = refreshTimestamp !== null && refreshTimestamp !== void 0 ? refreshTimestamp : Date.now();
250
+ try {
251
+ inCache = {
252
+ structDef: await this.getSQLBlockSchema(sqlRef),
253
+ timestamp,
254
+ };
255
+ }
256
+ catch (error) {
257
+ inCache = { error: error.message, timestamp };
258
+ }
259
+ this.sqlSchemaCache.set(key, inCache);
260
+ }
261
+ return inCache;
262
+ }
263
+ async manifestTemporaryTable(sqlCommand) {
264
+ const tableName = this.getTempTableName(sqlCommand);
265
+ const cmd = `CREATE OR REPLACE TEMP TABLE ${tableName} AS (${sqlCommand});`;
266
+ await this.runSQL(cmd);
267
+ return tableName;
268
+ }
269
+ }
270
+ exports.SnowflakeConnection = SnowflakeConnection;
271
+ //# sourceMappingURL=snowflake_connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snowflake_connection.js","sourceRoot":"","sources":["../src/snowflake_connection.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,+CAAiC;AACjC,+CAa4B;AAC5B,6DAAuD;AAwBvD,MAAa,mBAAmB;IA4B9B,YACkB,IAAY,EAC5B,OAAoC;;QADpB,SAAI,GAAJ,IAAI,CAAQ;QAtBb,YAAO,GAAG,IAAI,yBAAgB,EAAE,CAAC;QAE1C,gBAAW,GAAG,IAAI,GAAG,EAI1B,CAAC;QACI,mBAAc,GAAG,IAAI,GAAG,EAQ7B,CAAC;QAUF,IAAI,WAAW,GAAG,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,WAAW,CAAC;QACvC,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,mEAAmE;YACnE,WAAW,GAAG,sCAAiB,CAAC,4BAA4B,EAAE,CAAC;QACjE,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,sCAAiB,CAAC,WAAW,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,WAAW,CAAC,CAAC;QACzE,IAAI,CAAC,YAAY,GAAG,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,YAAY,CAAC;QAC1C,IAAI,CAAC,YAAY,GAAG,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,YAAY,mCAAI,EAAE,CAAC;IAClD,CAAC;IAED,IAAI,WAAW;QACb,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,qCAAqC;IACrC,IAAW,eAAe;QACxB,OAAO,KAAK,CAAC;IACf,CAAC;IAEM,MAAM;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,UAAU;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,SAAS;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAAC,WAAmB;QAChD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC7B,CAAC;IAEO,gBAAgB,CAAC,UAAkB;QACzC,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,IAAI,SAAS,GAAG,KAAK,IAAI,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,SAAS,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;QACvF,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAEM,KAAK,CAAC,MAAM,CACjB,GAAW,EACX,OAAuB;;QAEvB,MAAM,QAAQ,GAAG,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,QAAQ,mCAAI,MAAA,IAAI,CAAC,YAAY,0CAAE,QAAQ,CAAC;QAClE,IAAI,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;YACrD,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QACjC,CAAC;QACD,OAAO,EAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAC,CAAC;IACxC,CAAC;IAEM,KAAK,CAAC,CAAC,YAAY,CACxB,UAAkB,EAClB,UAAyB,EAAE;QAE3B,MAAM,kBAAkB,GAAG;YACzB,GAAG,IAAI,CAAC,YAAY;YACpB,GAAG,OAAO;SACX,CAAC;QAEF,IAAI,KAAK,EAAE,MAAM,GAAG,IAAI,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAChD,UAAU,EACV,kBAAkB,CACnB,EAAE,CAAC;YACF,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,IAAI;QACf,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAEO,KAAK,CAAC,eAAe,CAC3B,SAAiB,EACjB,SAAoB;QAEpB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAClD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,iBAAiB,GAAG,GAAG,CAAC,WAAW,CAAW,CAAC;YACrD,MAAM,CAAC,GAAG,SAAS,CAAC;YACpB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;YACvE,MAAM,IAAI,GAAG,GAAG,CAAC,aAAa,CAAW,CAAC;YAC1C,IAAI,UAAU,EAAE,CAAC;gBACf,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAC,GAAG,UAAU,EAAE,IAAI,EAAC,CAAC,CAAC;YACvC,CAAC;iBAAM,CAAC;gBACN,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,aAAa;oBACnB,OAAO,EAAE,iBAAiB;oBAC1B,IAAI;iBACL,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,cAAc,CAC1B,QAAgB,EAChB,SAAiB;QAEjB,4CAA4C;QAC5C,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;QAElC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QAC1C,MAAM,gBAAgB,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9C,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClC,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,gBAAgB,CAAC;QACzC,CAAC;QAED,MAAM,SAAS,GAAc;YAC3B,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,WAAW;YACpB,IAAI,EAAE,QAAQ;YACd,YAAY,EAAE,EAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAC;YACxC,kBAAkB,EAAE;gBAClB,IAAI,EAAE,WAAW;gBACjB,cAAc,EAAE,IAAI,CAAC,IAAI;aAC1B;YACD,MAAM,EAAE,EAAE;SACX,CAAC;QACF,yCAAyC;QAEzC,gBAAgB;QAChB,uCAAuC;QACvC,KAAK;QACL,uFAAuF;QACvF,2DAA2D;QAC3D,8DAA8D;QAC9D,yCAAyC;QACzC,gBAAgB;QAChB,iBAAiB;QAEjB,MAAM,SAAS,GAAG;;;;;;;4BAOM,MAAM;8BACJ,SAAS;KAClC,CAAC;QAEF,MAAM,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACjD,OAAO,SAAS,CAAC;IACnB,CAAC;IAEM,KAAK,CAAC,oBAAoB,CAC/B,OAA+B,EAC/B,EAAC,gBAAgB,EAAqB;QAKtC,MAAM,OAAO,GAAoB,EAAE,CAAC;QACpC,MAAM,MAAM,GAA6B,EAAE,CAAC;QAE5C,KAAK,MAAM,QAAQ,IAAI,OAAO,EAAE,CAAC;YAC/B,IAAI,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC7C,IACE,CAAC,OAAO;gBACR,CAAC,gBAAgB,IAAI,gBAAgB,GAAG,OAAO,CAAC,SAAS,CAAC,EAC1D,CAAC;gBACD,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;gBACpC,MAAM,SAAS,GAAG,gBAAgB,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;gBACjD,IAAI,CAAC;oBACH,OAAO,GAAG;wBACR,MAAM,EAAE,MAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC;wBACtD,SAAS;qBACV,CAAC;oBACF,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAC1C,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,OAAO,GAAG,EAAC,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,EAAC,CAAC;gBAC9C,CAAC;YACH,CAAC;YACD,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBACjC,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;YACrC,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,KAAK,IAAI,4BAA4B,CAAC;YACnE,CAAC;QACH,CAAC;QACD,OAAO,EAAC,OAAO,EAAE,MAAM,EAAC,CAAC;IAC3B,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAAC,MAAgB;QAC9C,MAAM,SAAS,GAAc;YAC3B,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,WAAW;YACpB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,YAAY,EAAE;gBACZ,IAAI,EAAE,KAAK;gBACX,MAAM,EAAE,UAAU;gBAClB,QAAQ,EAAE,MAAM;aACjB;YACD,kBAAkB,EAAE;gBAClB,IAAI,EAAE,WAAW;gBACjB,cAAc,EAAE,IAAI,CAAC,IAAI;aAC1B;YACD,MAAM,EAAE,EAAE;SACX,CAAC;QAEF,kDAAkD;QAClD,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC9D,IAAI,CAAC,MAAM,CACT;qCAC+B,aAAa;UACxC,MAAM,CAAC,SAAS;;OAEnB,CACF,CAAC;QAEF,MAAM,SAAS,GAAG;;;;;;;0BAOI,aAAa;GACpC,CAAC;QACA,MAAM,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACjD,OAAO,SAAS,CAAC;IACnB,CAAC;IAEM,KAAK,CAAC,sBAAsB,CACjC,MAAgB,EAChB,EAAC,gBAAgB,EAAqB;QAKtC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC;QACxB,IAAI,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC3C,IACE,CAAC,OAAO;YACR,CAAC,gBAAgB,IAAI,gBAAgB,GAAG,OAAO,CAAC,SAAS,CAAC,EAC1D,CAAC;YACD,MAAM,SAAS,GAAG,gBAAgB,aAAhB,gBAAgB,cAAhB,gBAAgB,GAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACjD,IAAI,CAAC;gBACH,OAAO,GAAG;oBACR,SAAS,EAAE,MAAM,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC;oBAC/C,SAAS;iBACV,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,GAAG,EAAC,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,EAAC,CAAC;YAC9C,CAAC;YACD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAEM,KAAK,CAAC,sBAAsB,CAAC,UAAkB;QACpD,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;QACpD,MAAM,GAAG,GAAG,gCAAgC,SAAS,QAAQ,UAAU,IAAI,CAAC;QAC5E,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACvB,OAAO,SAAS,CAAC;IACnB,CAAC;CACF;AAxSD,kDAwSC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,123 @@
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 snowflake_connection_1 = require("./snowflake_connection");
50
+ const url_1 = require("url");
51
+ const util = __importStar(require("util"));
52
+ const fs = __importStar(require("fs"));
53
+ const snowflake_executor_1 = require("./snowflake_executor");
54
+ const envDatabases = process.env['MALLOY_DATABASES'] || process.env['MALLOY_DATABASE'];
55
+ let describe = globalThis.describe;
56
+ if (envDatabases && !envDatabases.includes('snowflake')) {
57
+ describe = describe.skip;
58
+ }
59
+ describe('db:Snowflake', () => {
60
+ let conn;
61
+ let runtime;
62
+ beforeAll(() => {
63
+ const connOptions = snowflake_executor_1.SnowflakeExecutor.getConnectionOptionsFromEnv() ||
64
+ snowflake_executor_1.SnowflakeExecutor.getConnectionOptionsFromToml();
65
+ conn = new snowflake_connection_1.SnowflakeConnection('snowflake', {
66
+ connOptions: connOptions,
67
+ queryOptions: { rowLimit: 1000 },
68
+ });
69
+ const files = {
70
+ readURL: async (url) => {
71
+ const filePath = (0, url_1.fileURLToPath)(url);
72
+ return await util.promisify(fs.readFile)(filePath, 'utf8');
73
+ },
74
+ };
75
+ runtime = new malloy.Runtime(files, conn);
76
+ });
77
+ afterAll(async () => {
78
+ await conn.close();
79
+ });
80
+ it('runs a SQL query', async () => {
81
+ const res = await conn.runSQL('SELECT 1 as t');
82
+ expect(res.rows[0]['t']).toBe(1);
83
+ });
84
+ it('runs a Malloy query', async () => {
85
+ var _a;
86
+ const sql = await runtime
87
+ .loadModel("source: aircraft is snowflake.table('malloytest.aircraft')")
88
+ .loadQuery(`run: aircraft -> {
89
+ where: state != null
90
+ aggregate: cnt is count()
91
+ group_by: state}`)
92
+ .getSQL();
93
+ const res = await conn.runSQL(sql);
94
+ expect(res.totalRows).toBe(55);
95
+ let total = 0;
96
+ for (const row of res.rows) {
97
+ total += +((_a = row['cnt']) !== null && _a !== void 0 ? _a : 0);
98
+ }
99
+ expect(total).toBe(3540);
100
+ // if we request for a smaller rowLimit we should get fewer rows
101
+ const res_limited = await conn.runSQL(sql, { rowLimit: 10 });
102
+ expect(res_limited.totalRows).toBe(10);
103
+ });
104
+ it('runs a Malloy query on an sql source', async () => {
105
+ const sql = await runtime
106
+ .loadModel("source: aircraft is snowflake.sql('SELECT * FROM malloytest.AIRCRAFT')")
107
+ .loadQuery('run: aircraft -> { aggregate: cnt is count() }')
108
+ .getSQL();
109
+ const res = await conn.runSQL(sql);
110
+ expect(res.rows.length).toBe(1);
111
+ expect(res.rows[0]['cnt']).toBe(3599);
112
+ });
113
+ it('runs a Malloy function with overrides', async () => {
114
+ const sql = await runtime
115
+ .loadModel("source: aircraft is snowflake.table('malloytest.aircraft')")
116
+ .loadQuery('run: aircraft -> { select: rand is rand(), limit: 1}')
117
+ .getSQL();
118
+ const res = await conn.runSQL(sql);
119
+ expect(res.rows[0]['rand']).toBeGreaterThanOrEqual(0);
120
+ expect(res.rows[0]['rand']).toBeLessThanOrEqual(1);
121
+ });
122
+ });
123
+ //# sourceMappingURL=snowflake_connection.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snowflake_connection.spec.js","sourceRoot":"","sources":["../src/snowflake_connection.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { Connection, ConnectionOptions } from 'snowflake-sdk';
2
+ import { Options as PoolOptions } from 'generic-pool';
3
+ import { QueryData, QueryDataRow, RunSQLOptions } from '@malloydata/malloy';
4
+ export interface ConnectionConfigFile {
5
+ config_file_path?: string;
6
+ connection_name?: string;
7
+ }
8
+ export declare class SnowflakeExecutor {
9
+ private static defaultPoolOptions_;
10
+ private static defaultConnectionOptions;
11
+ private pool_;
12
+ constructor(connOptions: ConnectionOptions, poolOptions?: PoolOptions);
13
+ static getConnectionOptionsFromEnv(): ConnectionOptions | undefined;
14
+ static getConnectionOptionsFromToml(options?: ConnectionConfigFile): ConnectionOptions;
15
+ done(): Promise<void>;
16
+ _execute(sqlText: string, conn: Connection): Promise<QueryData>;
17
+ private _setSessionParams;
18
+ batch(sqlText: string): Promise<QueryData>;
19
+ stream(sqlText: string, options?: RunSQLOptions): Promise<AsyncIterableIterator<QueryDataRow>>;
20
+ }