@lightdash/warehouses 2.228.1 → 2.229.1
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/.tsbuildinfo.build +1 -0
- package/package.json +4 -4
- package/dist/.tsbuildinfo +0 -1
- package/dist/ssh/sshTunnelFailure.test.d.ts +0 -2
- package/dist/ssh/sshTunnelFailure.test.d.ts.map +0 -1
- package/dist/ssh/sshTunnelFailure.test.js +0 -90
- package/dist/validateWarehouseColumnReferences.test.d.ts +0 -2
- package/dist/validateWarehouseColumnReferences.test.d.ts.map +0 -1
- package/dist/validateWarehouseColumnReferences.test.js +0 -168
- package/dist/warehouseClients/AthenaWarehouseClient.test.d.ts +0 -2
- package/dist/warehouseClients/AthenaWarehouseClient.test.d.ts.map +0 -1
- package/dist/warehouseClients/AthenaWarehouseClient.test.js +0 -261
- package/dist/warehouseClients/BigqueryWarehouseClient.mock.d.ts +0 -83
- package/dist/warehouseClients/BigqueryWarehouseClient.mock.d.ts.map +0 -1
- package/dist/warehouseClients/BigqueryWarehouseClient.mock.js +0 -130
- package/dist/warehouseClients/BigqueryWarehouseClient.test.d.ts +0 -2
- package/dist/warehouseClients/BigqueryWarehouseClient.test.d.ts.map +0 -1
- package/dist/warehouseClients/BigqueryWarehouseClient.test.js +0 -493
- package/dist/warehouseClients/ClickhouseWarehouseClient.test.d.ts +0 -2
- package/dist/warehouseClients/ClickhouseWarehouseClient.test.d.ts.map +0 -1
- package/dist/warehouseClients/ClickhouseWarehouseClient.test.js +0 -115
- package/dist/warehouseClients/DatabricksWarehouseClient.mock.d.ts +0 -17
- package/dist/warehouseClients/DatabricksWarehouseClient.mock.d.ts.map +0 -1
- package/dist/warehouseClients/DatabricksWarehouseClient.mock.js +0 -111
- package/dist/warehouseClients/DatabricksWarehouseClient.test.d.ts +0 -2
- package/dist/warehouseClients/DatabricksWarehouseClient.test.d.ts.map +0 -1
- package/dist/warehouseClients/DatabricksWarehouseClient.test.js +0 -592
- package/dist/warehouseClients/DatabricksWarehouseStartupRetry.test.d.ts +0 -2
- package/dist/warehouseClients/DatabricksWarehouseStartupRetry.test.d.ts.map +0 -1
- package/dist/warehouseClients/DatabricksWarehouseStartupRetry.test.js +0 -129
- package/dist/warehouseClients/DuckdbWarehouseClient.embedded.test.d.ts +0 -2
- package/dist/warehouseClients/DuckdbWarehouseClient.embedded.test.d.ts.map +0 -1
- package/dist/warehouseClients/DuckdbWarehouseClient.embedded.test.js +0 -92
- package/dist/warehouseClients/DuckdbWarehouseClient.test.d.ts +0 -2
- package/dist/warehouseClients/DuckdbWarehouseClient.test.d.ts.map +0 -1
- package/dist/warehouseClients/DuckdbWarehouseClient.test.js +0 -1749
- package/dist/warehouseClients/MotherduckErrorClassifier.test.d.ts +0 -2
- package/dist/warehouseClients/MotherduckErrorClassifier.test.d.ts.map +0 -1
- package/dist/warehouseClients/MotherduckErrorClassifier.test.js +0 -31
- package/dist/warehouseClients/MotherduckInstanceCache.catalog.test.d.ts +0 -2
- package/dist/warehouseClients/MotherduckInstanceCache.catalog.test.d.ts.map +0 -1
- package/dist/warehouseClients/MotherduckInstanceCache.catalog.test.js +0 -52
- package/dist/warehouseClients/MotherduckInstanceCache.integration.test.d.ts +0 -2
- package/dist/warehouseClients/MotherduckInstanceCache.integration.test.d.ts.map +0 -1
- package/dist/warehouseClients/MotherduckInstanceCache.integration.test.js +0 -172
- package/dist/warehouseClients/MotherduckInstanceCache.security.test.d.ts +0 -2
- package/dist/warehouseClients/MotherduckInstanceCache.security.test.d.ts.map +0 -1
- package/dist/warehouseClients/MotherduckInstanceCache.security.test.js +0 -192
- package/dist/warehouseClients/MotherduckInstanceCache.test.d.ts +0 -2
- package/dist/warehouseClients/MotherduckInstanceCache.test.d.ts.map +0 -1
- package/dist/warehouseClients/MotherduckInstanceCache.test.js +0 -302
- package/dist/warehouseClients/PostgresWarehouseClient.mock.d.ts +0 -8
- package/dist/warehouseClients/PostgresWarehouseClient.mock.d.ts.map +0 -1
- package/dist/warehouseClients/PostgresWarehouseClient.mock.js +0 -66
- package/dist/warehouseClients/PostgresWarehouseClient.test.d.ts +0 -2
- package/dist/warehouseClients/PostgresWarehouseClient.test.d.ts.map +0 -1
- package/dist/warehouseClients/PostgresWarehouseClient.test.js +0 -371
- package/dist/warehouseClients/RedshiftWarehouseClient.test.d.ts +0 -2
- package/dist/warehouseClients/RedshiftWarehouseClient.test.d.ts.map +0 -1
- package/dist/warehouseClients/RedshiftWarehouseClient.test.js +0 -126
- package/dist/warehouseClients/SnowflakeWarehouseClient.mock.d.ts +0 -41
- package/dist/warehouseClients/SnowflakeWarehouseClient.mock.d.ts.map +0 -1
- package/dist/warehouseClients/SnowflakeWarehouseClient.mock.js +0 -184
- package/dist/warehouseClients/SnowflakeWarehouseClient.test.d.ts +0 -2
- package/dist/warehouseClients/SnowflakeWarehouseClient.test.d.ts.map +0 -1
- package/dist/warehouseClients/SnowflakeWarehouseClient.test.js +0 -777
- package/dist/warehouseClients/TrinoWarehouseClient.mock.d.ts +0 -23
- package/dist/warehouseClients/TrinoWarehouseClient.mock.d.ts.map +0 -1
- package/dist/warehouseClients/TrinoWarehouseClient.mock.js +0 -102
- package/dist/warehouseClients/TrinoWarehouseClient.test.d.ts +0 -2
- package/dist/warehouseClients/TrinoWarehouseClient.test.d.ts.map +0 -1
- package/dist/warehouseClients/TrinoWarehouseClient.test.js +0 -230
- package/dist/warehouseClients/WarehouseClient.mock.d.ts +0 -13
- package/dist/warehouseClients/WarehouseClient.mock.d.ts.map +0 -1
- package/dist/warehouseClients/WarehouseClient.mock.js +0 -51
- package/dist/warehouseClients/numericKinds.test.d.ts +0 -2
- package/dist/warehouseClients/numericKinds.test.d.ts.map +0 -1
- package/dist/warehouseClients/numericKinds.test.js +0 -168
- package/dist/warehouseClients/pgProtocolGuard.integration.test.d.ts +0 -2
- package/dist/warehouseClients/pgProtocolGuard.integration.test.d.ts.map +0 -1
- package/dist/warehouseClients/pgProtocolGuard.integration.test.js +0 -93
- package/dist/warehouseClients/pgProtocolGuard.test.d.ts +0 -2
- package/dist/warehouseClients/pgProtocolGuard.test.d.ts.map +0 -1
- package/dist/warehouseClients/pgProtocolGuard.test.js +0 -48
- package/dist/warehouseClients/redshiftIamCredentials.test.d.ts +0 -2
- package/dist/warehouseClients/redshiftIamCredentials.test.d.ts.map +0 -1
- package/dist/warehouseClients/redshiftIamCredentials.test.js +0 -210
- package/dist/warehouseClients/timestampDomain.test.d.ts +0 -2
- package/dist/warehouseClients/timestampDomain.test.d.ts.map +0 -1
- package/dist/warehouseClients/timestampDomain.test.js +0 -101
|
@@ -1,371 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
/* eslint-disable prefer-arrow-callback, func-names */
|
|
37
|
-
const pg = __importStar(require("pg"));
|
|
38
|
-
const stream_1 = require("stream");
|
|
39
|
-
const PostgresWarehouseClient_1 = require("./PostgresWarehouseClient");
|
|
40
|
-
const PostgresWarehouseClient_mock_1 = require("./PostgresWarehouseClient.mock");
|
|
41
|
-
const WarehouseClient_mock_1 = require("./WarehouseClient.mock");
|
|
42
|
-
vi.mock('pg', async () => ({
|
|
43
|
-
...(await vi.importActual('pg')).default,
|
|
44
|
-
Pool: vi.fn(function () {
|
|
45
|
-
return {
|
|
46
|
-
connect: vi.fn((callback) => {
|
|
47
|
-
callback(null, {
|
|
48
|
-
query: vi.fn((arg) => {
|
|
49
|
-
// Session statements (SET statement_timeout / timezone)
|
|
50
|
-
// are issued as plain string queries and must return a
|
|
51
|
-
// thenable, not a stream.
|
|
52
|
-
if (typeof arg === 'string') {
|
|
53
|
-
return Promise.resolve({
|
|
54
|
-
rows: [],
|
|
55
|
-
fields: [],
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
const mockedStream = new stream_1.PassThrough();
|
|
59
|
-
setTimeout(() => {
|
|
60
|
-
mockedStream.emit('data', {
|
|
61
|
-
row: WarehouseClient_mock_1.expectedRow,
|
|
62
|
-
fields: PostgresWarehouseClient_mock_1.queryColumnsMock,
|
|
63
|
-
});
|
|
64
|
-
mockedStream.end();
|
|
65
|
-
}, 100);
|
|
66
|
-
return mockedStream;
|
|
67
|
-
}),
|
|
68
|
-
on: vi.fn(async () => undefined),
|
|
69
|
-
}, vi.fn());
|
|
70
|
-
}),
|
|
71
|
-
end: vi.fn(async () => undefined),
|
|
72
|
-
on: vi.fn(async () => undefined),
|
|
73
|
-
};
|
|
74
|
-
}),
|
|
75
|
-
}));
|
|
76
|
-
describe('PostgresWarehouseClient', () => {
|
|
77
|
-
it('expect query rows', async () => {
|
|
78
|
-
const warehouse = new PostgresWarehouseClient_1.PostgresWarehouseClient(PostgresWarehouseClient_mock_1.credentials);
|
|
79
|
-
const results = await warehouse.runQuery('fake sql');
|
|
80
|
-
expect(results.fields).toEqual(WarehouseClient_mock_1.expectedFields);
|
|
81
|
-
expect(results.rows[0]).toEqual(WarehouseClient_mock_1.expectedRow);
|
|
82
|
-
});
|
|
83
|
-
it('expect schema with postgres types mapped to dimension types', async () => {
|
|
84
|
-
const warehouse = new PostgresWarehouseClient_1.PostgresWarehouseClient(PostgresWarehouseClient_mock_1.credentials);
|
|
85
|
-
pg.Pool
|
|
86
|
-
.mockImplementationOnce(function () {
|
|
87
|
-
return {
|
|
88
|
-
connect: vi.fn((callback) => {
|
|
89
|
-
callback(null, {
|
|
90
|
-
query: vi.fn((arg) => {
|
|
91
|
-
if (typeof arg === 'string') {
|
|
92
|
-
return Promise.resolve({
|
|
93
|
-
rows: [],
|
|
94
|
-
fields: [],
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
const mockedStream = new stream_1.PassThrough();
|
|
98
|
-
setTimeout(() => {
|
|
99
|
-
mockedStream.emit('data', {
|
|
100
|
-
row: { version: 'PostgreSQL 15.4' },
|
|
101
|
-
fields: [],
|
|
102
|
-
});
|
|
103
|
-
mockedStream.end();
|
|
104
|
-
}, 100);
|
|
105
|
-
return mockedStream;
|
|
106
|
-
}),
|
|
107
|
-
on: vi.fn(async () => undefined),
|
|
108
|
-
}, vi.fn());
|
|
109
|
-
}),
|
|
110
|
-
end: vi.fn(async () => undefined),
|
|
111
|
-
on: vi.fn(async () => undefined),
|
|
112
|
-
};
|
|
113
|
-
})
|
|
114
|
-
.mockImplementationOnce(function () {
|
|
115
|
-
return {
|
|
116
|
-
connect: vi.fn((callback) => {
|
|
117
|
-
callback(null, {
|
|
118
|
-
query: vi.fn((arg) => {
|
|
119
|
-
if (typeof arg === 'string') {
|
|
120
|
-
return Promise.resolve({
|
|
121
|
-
rows: [],
|
|
122
|
-
fields: [],
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
const mockedStream = new stream_1.PassThrough();
|
|
126
|
-
setTimeout(() => {
|
|
127
|
-
PostgresWarehouseClient_mock_1.columns.forEach((column) => {
|
|
128
|
-
mockedStream.emit('data', {
|
|
129
|
-
row: column,
|
|
130
|
-
fields: [],
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
mockedStream.end();
|
|
134
|
-
}, 100);
|
|
135
|
-
return mockedStream;
|
|
136
|
-
}),
|
|
137
|
-
on: vi.fn(async () => undefined),
|
|
138
|
-
}, vi.fn());
|
|
139
|
-
}),
|
|
140
|
-
end: vi.fn(async () => undefined),
|
|
141
|
-
on: vi.fn(async () => undefined),
|
|
142
|
-
};
|
|
143
|
-
});
|
|
144
|
-
expect(await warehouse.getCatalog(WarehouseClient_mock_1.config)).toEqual(WarehouseClient_mock_1.expectedWarehouseSchemaWithNaiveTimestamp);
|
|
145
|
-
});
|
|
146
|
-
it('expect empty catalog when dbt project has no references', async () => {
|
|
147
|
-
const warehouse = new PostgresWarehouseClient_1.PostgresWarehouseClient(PostgresWarehouseClient_mock_1.credentials);
|
|
148
|
-
expect(await warehouse.getCatalog([])).toEqual({});
|
|
149
|
-
});
|
|
150
|
-
it('binds catalog filter values as query parameters', async () => {
|
|
151
|
-
const warehouse = new PostgresWarehouseClient_1.PostgresWarehouseClient(PostgresWarehouseClient_mock_1.credentials);
|
|
152
|
-
const database = "missing') OR (SELECT CAST(current_database() AS integer)=0) OR ('x'='x";
|
|
153
|
-
const runQuery = vi
|
|
154
|
-
.spyOn(warehouse, 'runQuery')
|
|
155
|
-
.mockResolvedValueOnce({
|
|
156
|
-
rows: [{ version: 'PostgreSQL 15.4' }],
|
|
157
|
-
fields: {},
|
|
158
|
-
})
|
|
159
|
-
.mockResolvedValueOnce({ rows: [], fields: {} });
|
|
160
|
-
await warehouse.getCatalog([
|
|
161
|
-
{ database, schema: 'public', table: 'orders' },
|
|
162
|
-
]);
|
|
163
|
-
const catalogQuery = runQuery.mock.calls[1][0];
|
|
164
|
-
expect(catalogQuery).toContain('table_catalog IN ($1)');
|
|
165
|
-
expect(catalogQuery).toContain('table_schema IN ($2)');
|
|
166
|
-
expect(catalogQuery).toContain('table_name IN ($3)');
|
|
167
|
-
expect(catalogQuery).not.toContain(database);
|
|
168
|
-
expect(runQuery.mock.calls[1][3]).toEqual([
|
|
169
|
-
database,
|
|
170
|
-
'public',
|
|
171
|
-
'orders',
|
|
172
|
-
]);
|
|
173
|
-
});
|
|
174
|
-
describe('getAllTables', () => {
|
|
175
|
-
it('lists tables, views and materialized views', async () => {
|
|
176
|
-
const warehouse = new PostgresWarehouseClient_1.PostgresWarehouseClient(PostgresWarehouseClient_mock_1.credentials);
|
|
177
|
-
const runQuery = vi
|
|
178
|
-
.spyOn(warehouse, 'runQuery')
|
|
179
|
-
.mockResolvedValueOnce({
|
|
180
|
-
rows: [{ version: 'PostgreSQL 15.4' }],
|
|
181
|
-
fields: {},
|
|
182
|
-
})
|
|
183
|
-
.mockResolvedValueOnce({
|
|
184
|
-
rows: [
|
|
185
|
-
{
|
|
186
|
-
table_catalog: 'warehouse',
|
|
187
|
-
table_schema: 'public',
|
|
188
|
-
table_name: 'orders_view',
|
|
189
|
-
table_type: 'VIEW',
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
table_catalog: 'warehouse',
|
|
193
|
-
table_schema: 'public',
|
|
194
|
-
table_name: 'orders_mv',
|
|
195
|
-
table_type: 'MATERIALIZED VIEW',
|
|
196
|
-
},
|
|
197
|
-
],
|
|
198
|
-
fields: {},
|
|
199
|
-
});
|
|
200
|
-
const tables = await warehouse.getAllTables();
|
|
201
|
-
const [query] = runQuery.mock.calls[1];
|
|
202
|
-
expect(query).toContain("table_type IN ('BASE TABLE', 'VIEW', 'FOREIGN')");
|
|
203
|
-
expect(query).toContain('FROM pg_catalog.pg_matviews');
|
|
204
|
-
expect(tables).toEqual([
|
|
205
|
-
{
|
|
206
|
-
database: 'warehouse',
|
|
207
|
-
schema: 'public',
|
|
208
|
-
table: 'orders_view',
|
|
209
|
-
tableType: 'view',
|
|
210
|
-
},
|
|
211
|
-
{
|
|
212
|
-
database: 'warehouse',
|
|
213
|
-
schema: 'public',
|
|
214
|
-
table: 'orders_mv',
|
|
215
|
-
tableType: 'materialized_view',
|
|
216
|
-
},
|
|
217
|
-
]);
|
|
218
|
-
});
|
|
219
|
-
it('skips pg_matviews on servers that predate it', async () => {
|
|
220
|
-
const warehouse = new PostgresWarehouseClient_1.PostgresWarehouseClient(PostgresWarehouseClient_mock_1.credentials);
|
|
221
|
-
const runQuery = vi
|
|
222
|
-
.spyOn(warehouse, 'runQuery')
|
|
223
|
-
.mockResolvedValueOnce({
|
|
224
|
-
rows: [{ version: 'PostgreSQL 8.0.2' }],
|
|
225
|
-
fields: {},
|
|
226
|
-
})
|
|
227
|
-
.mockResolvedValueOnce({ rows: [], fields: {} });
|
|
228
|
-
await warehouse.getAllTables();
|
|
229
|
-
expect(runQuery.mock.calls[1][0]).not.toContain('pg_matviews');
|
|
230
|
-
});
|
|
231
|
-
});
|
|
232
|
-
describe('getFields', () => {
|
|
233
|
-
it('includes materialized view columns and binds filters in order', async () => {
|
|
234
|
-
const warehouse = new PostgresWarehouseClient_1.PostgresWarehouseClient(PostgresWarehouseClient_mock_1.credentials);
|
|
235
|
-
const runQuery = vi
|
|
236
|
-
.spyOn(warehouse, 'runQuery')
|
|
237
|
-
.mockResolvedValueOnce({
|
|
238
|
-
rows: [{ version: 'PostgreSQL 15.4' }],
|
|
239
|
-
fields: {},
|
|
240
|
-
})
|
|
241
|
-
.mockResolvedValueOnce({
|
|
242
|
-
rows: [
|
|
243
|
-
{
|
|
244
|
-
table_catalog: 'warehouse',
|
|
245
|
-
table_schema: 'public',
|
|
246
|
-
table_name: 'orders_mv',
|
|
247
|
-
column_name: 'amount',
|
|
248
|
-
data_type: 'numeric',
|
|
249
|
-
},
|
|
250
|
-
],
|
|
251
|
-
fields: {},
|
|
252
|
-
});
|
|
253
|
-
const fields = await warehouse.getFields('orders_mv', undefined, 'warehouse');
|
|
254
|
-
const [query, , , values] = runQuery.mock.calls[1];
|
|
255
|
-
expect(query).toContain("c.relkind = 'm'");
|
|
256
|
-
expect(query).toContain('table_catalog = $2');
|
|
257
|
-
expect(query).not.toContain('$3');
|
|
258
|
-
expect(values).toEqual(['orders_mv', 'warehouse']);
|
|
259
|
-
expect(fields).toEqual({
|
|
260
|
-
warehouse: { public: { orders_mv: { amount: 'number' } } },
|
|
261
|
-
});
|
|
262
|
-
});
|
|
263
|
-
});
|
|
264
|
-
});
|
|
265
|
-
describe('PostgresWarehouseClient statement timeout', () => {
|
|
266
|
-
const mockPoolWithQuery = (queryMock) => {
|
|
267
|
-
pg.Pool.mockImplementationOnce(function () {
|
|
268
|
-
return {
|
|
269
|
-
connect: vi.fn((callback) => {
|
|
270
|
-
callback(null, { query: queryMock, on: vi.fn() }, vi.fn());
|
|
271
|
-
}),
|
|
272
|
-
end: vi.fn(async () => undefined),
|
|
273
|
-
on: vi.fn(),
|
|
274
|
-
};
|
|
275
|
-
});
|
|
276
|
-
};
|
|
277
|
-
const respondingQueryMock = () => vi.fn((arg) => {
|
|
278
|
-
if (typeof arg === 'string') {
|
|
279
|
-
return Promise.resolve({ rows: [], fields: [] });
|
|
280
|
-
}
|
|
281
|
-
const stream = new stream_1.PassThrough();
|
|
282
|
-
setTimeout(() => {
|
|
283
|
-
stream.emit('data', {
|
|
284
|
-
row: WarehouseClient_mock_1.expectedRow,
|
|
285
|
-
fields: PostgresWarehouseClient_mock_1.queryColumnsMock,
|
|
286
|
-
});
|
|
287
|
-
stream.end();
|
|
288
|
-
}, 10);
|
|
289
|
-
return stream;
|
|
290
|
-
});
|
|
291
|
-
afterEach(() => {
|
|
292
|
-
vi.useRealTimers();
|
|
293
|
-
});
|
|
294
|
-
it('sets a server-side statement_timeout using the 9-minute default ceiling', async () => {
|
|
295
|
-
const queryMock = respondingQueryMock();
|
|
296
|
-
mockPoolWithQuery(queryMock);
|
|
297
|
-
const warehouse = new PostgresWarehouseClient_1.PostgresWarehouseClient(PostgresWarehouseClient_mock_1.credentials);
|
|
298
|
-
await warehouse.runQuery('select 1');
|
|
299
|
-
const sessionStatement = queryMock.mock.calls
|
|
300
|
-
.map((call) => call[0])
|
|
301
|
-
.find((arg) => typeof arg === 'string');
|
|
302
|
-
expect(sessionStatement).toContain('SET statement_timeout = 540000');
|
|
303
|
-
});
|
|
304
|
-
it('omits the competing pg query_timeout from the pool', async () => {
|
|
305
|
-
const queryMock = respondingQueryMock();
|
|
306
|
-
mockPoolWithQuery(queryMock);
|
|
307
|
-
const warehouse = new PostgresWarehouseClient_1.PostgresWarehouseClient(PostgresWarehouseClient_mock_1.credentials);
|
|
308
|
-
await warehouse.runQuery('select 1');
|
|
309
|
-
const poolConfig = pg.Pool.mock.lastCall?.[0];
|
|
310
|
-
expect(poolConfig).not.toHaveProperty('query_timeout');
|
|
311
|
-
});
|
|
312
|
-
it('honors a configured timeoutSeconds for the statement_timeout', async () => {
|
|
313
|
-
const queryMock = respondingQueryMock();
|
|
314
|
-
mockPoolWithQuery(queryMock);
|
|
315
|
-
const warehouse = new PostgresWarehouseClient_1.PostgresWarehouseClient({
|
|
316
|
-
...PostgresWarehouseClient_mock_1.credentials,
|
|
317
|
-
timeoutSeconds: 120,
|
|
318
|
-
});
|
|
319
|
-
await warehouse.runQuery('select 1');
|
|
320
|
-
const sessionStatement = queryMock.mock.calls
|
|
321
|
-
.map((call) => call[0])
|
|
322
|
-
.find((arg) => typeof arg === 'string');
|
|
323
|
-
expect(sessionStatement).toContain('SET statement_timeout = 120000');
|
|
324
|
-
});
|
|
325
|
-
it('rejects with a timeout error when a query stalls past the client backstop', async () => {
|
|
326
|
-
vi.useFakeTimers();
|
|
327
|
-
const queryMock = vi.fn((arg) => {
|
|
328
|
-
if (typeof arg === 'string') {
|
|
329
|
-
return Promise.resolve({ rows: [], fields: [] });
|
|
330
|
-
}
|
|
331
|
-
// A stream that never emits or ends — simulates a stalled cursor.
|
|
332
|
-
return new stream_1.PassThrough();
|
|
333
|
-
});
|
|
334
|
-
mockPoolWithQuery(queryMock);
|
|
335
|
-
const warehouse = new PostgresWarehouseClient_1.PostgresWarehouseClient(PostgresWarehouseClient_mock_1.credentials);
|
|
336
|
-
const resultPromise = warehouse.runQuery('select pg_sleep(9999)');
|
|
337
|
-
// Attach the rejection handler before advancing the clock so the
|
|
338
|
-
// rejection is never momentarily unhandled.
|
|
339
|
-
await Promise.all([
|
|
340
|
-
expect(resultPromise).rejects.toThrow('Query timed out after 570s'),
|
|
341
|
-
// 9-minute statement_timeout + 30s client buffer = 570s
|
|
342
|
-
vi.advanceTimersByTimeAsync(570 * 1000 + 1000),
|
|
343
|
-
]);
|
|
344
|
-
});
|
|
345
|
-
});
|
|
346
|
-
describe('PostgresSqlBuilder escaping', () => {
|
|
347
|
-
const postgresSqlBuilder = new PostgresWarehouseClient_1.PostgresSqlBuilder();
|
|
348
|
-
test('Should not escape regular characters', () => {
|
|
349
|
-
expect(postgresSqlBuilder.escapeString('%')).toBe('%');
|
|
350
|
-
expect(postgresSqlBuilder.escapeString('_')).toBe('_');
|
|
351
|
-
expect(postgresSqlBuilder.escapeString('?')).toBe('?');
|
|
352
|
-
expect(postgresSqlBuilder.escapeString('!')).toBe('!');
|
|
353
|
-
expect(postgresSqlBuilder.escapeString('credit_card')).toBe('credit_card');
|
|
354
|
-
});
|
|
355
|
-
test('Should escape single quotes in postgres', () => {
|
|
356
|
-
expect(postgresSqlBuilder.escapeString("single'quote")).toBe("single''quote");
|
|
357
|
-
});
|
|
358
|
-
test('Should escape backslashes and quotes in postgres', () => {
|
|
359
|
-
expect(postgresSqlBuilder.escapeString("\\') OR (1=1) --")).toBe("\\\\'') OR (1=1) ");
|
|
360
|
-
});
|
|
361
|
-
test('Should handle SQL injection attempts', () => {
|
|
362
|
-
// Test with a typical SQL injection pattern
|
|
363
|
-
const maliciousInput = "'; DROP TABLE users; --";
|
|
364
|
-
const escaped = postgresSqlBuilder.escapeString(maliciousInput);
|
|
365
|
-
expect(escaped).toBe("''; DROP TABLE users; ");
|
|
366
|
-
// Test with another common SQL injection pattern
|
|
367
|
-
const anotherMaliciousInput = "' OR '1'='1";
|
|
368
|
-
const anotherEscaped = postgresSqlBuilder.escapeString(anotherMaliciousInput);
|
|
369
|
-
expect(anotherEscaped).toBe("'' OR ''1''=''1");
|
|
370
|
-
});
|
|
371
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"RedshiftWarehouseClient.test.d.ts","sourceRoot":"","sources":["../../src/warehouseClients/RedshiftWarehouseClient.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const common_1 = require("@lightdash/common");
|
|
4
|
-
const RedshiftWarehouseClient_1 = require("./RedshiftWarehouseClient");
|
|
5
|
-
const credentials = {
|
|
6
|
-
type: common_1.WarehouseTypes.REDSHIFT,
|
|
7
|
-
host: 'localhost',
|
|
8
|
-
user: 'analytics',
|
|
9
|
-
password: 'password',
|
|
10
|
-
port: 5439,
|
|
11
|
-
dbname: 'warehouse',
|
|
12
|
-
schema: 'public',
|
|
13
|
-
authenticationType: common_1.RedshiftAuthenticationType.PASSWORD,
|
|
14
|
-
};
|
|
15
|
-
const redshiftVersion = {
|
|
16
|
-
rows: [
|
|
17
|
-
{ version: 'PostgreSQL 8.0.2 on i686-pc-linux-gnu, Redshift 1.0.77' },
|
|
18
|
-
],
|
|
19
|
-
fields: {},
|
|
20
|
-
};
|
|
21
|
-
describe('RedshiftWarehouseClient', () => {
|
|
22
|
-
it('keeps catalog filters in the Redshift query', async () => {
|
|
23
|
-
const warehouse = new RedshiftWarehouseClient_1.RedshiftWarehouseClient(credentials);
|
|
24
|
-
const runQuery = vi
|
|
25
|
-
.spyOn(warehouse, 'runQuery')
|
|
26
|
-
.mockResolvedValueOnce({
|
|
27
|
-
rows: [{ version: 'PostgreSQL 8.0.2' }],
|
|
28
|
-
fields: {},
|
|
29
|
-
})
|
|
30
|
-
.mockResolvedValueOnce({ rows: [], fields: {} });
|
|
31
|
-
await warehouse.getCatalog([
|
|
32
|
-
{ database: 'warehouse', schema: 'public', table: 'orders' },
|
|
33
|
-
]);
|
|
34
|
-
const catalogQuery = runQuery.mock.calls[1][0];
|
|
35
|
-
expect(catalogQuery).toContain("table_catalog IN ('warehouse')");
|
|
36
|
-
expect(catalogQuery).toContain("table_schema IN ('public')");
|
|
37
|
-
expect(catalogQuery).toContain("table_name IN ('orders')");
|
|
38
|
-
expect(runQuery.mock.calls[1][3]).toBeUndefined();
|
|
39
|
-
});
|
|
40
|
-
it('lists tables and views from svv_tables scoped to the database', async () => {
|
|
41
|
-
const warehouse = new RedshiftWarehouseClient_1.RedshiftWarehouseClient(credentials);
|
|
42
|
-
const runQuery = vi
|
|
43
|
-
.spyOn(warehouse, 'runQuery')
|
|
44
|
-
.mockResolvedValueOnce(redshiftVersion)
|
|
45
|
-
.mockResolvedValueOnce({
|
|
46
|
-
rows: [
|
|
47
|
-
{
|
|
48
|
-
table_catalog: 'warehouse',
|
|
49
|
-
table_schema: 'public',
|
|
50
|
-
table_name: 'orders_lbv',
|
|
51
|
-
table_type: 'VIEW',
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
table_catalog: 'warehouse',
|
|
55
|
-
table_schema: 'spectrum',
|
|
56
|
-
table_name: 'sales',
|
|
57
|
-
table_type: 'EXTERNAL TABLE',
|
|
58
|
-
},
|
|
59
|
-
],
|
|
60
|
-
fields: {},
|
|
61
|
-
});
|
|
62
|
-
const tables = await warehouse.getAllTables();
|
|
63
|
-
const [query, , , values] = runQuery.mock.calls[1];
|
|
64
|
-
expect(query).toContain('FROM svv_tables');
|
|
65
|
-
expect(query).toContain('table_catalog = $1');
|
|
66
|
-
expect(values).toEqual(['warehouse']);
|
|
67
|
-
expect(tables).toEqual([
|
|
68
|
-
{
|
|
69
|
-
database: 'warehouse',
|
|
70
|
-
schema: 'public',
|
|
71
|
-
table: 'orders_lbv',
|
|
72
|
-
tableType: 'view',
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
database: 'warehouse',
|
|
76
|
-
schema: 'spectrum',
|
|
77
|
-
table: 'sales',
|
|
78
|
-
tableType: 'external',
|
|
79
|
-
},
|
|
80
|
-
]);
|
|
81
|
-
});
|
|
82
|
-
it('reads columns from svv_columns so late-binding views resolve', async () => {
|
|
83
|
-
const warehouse = new RedshiftWarehouseClient_1.RedshiftWarehouseClient(credentials);
|
|
84
|
-
const runQuery = vi
|
|
85
|
-
.spyOn(warehouse, 'runQuery')
|
|
86
|
-
.mockResolvedValueOnce(redshiftVersion)
|
|
87
|
-
.mockResolvedValueOnce({
|
|
88
|
-
rows: [
|
|
89
|
-
{
|
|
90
|
-
table_catalog: 'warehouse',
|
|
91
|
-
table_schema: 'public',
|
|
92
|
-
table_name: 'orders_lbv',
|
|
93
|
-
column_name: 'quantity',
|
|
94
|
-
data_type: 'integer',
|
|
95
|
-
},
|
|
96
|
-
],
|
|
97
|
-
fields: {},
|
|
98
|
-
});
|
|
99
|
-
const fields = await warehouse.getFields('orders_lbv', 'public', 'warehouse');
|
|
100
|
-
const [query, , , values] = runQuery.mock.calls[1];
|
|
101
|
-
expect(query).toContain('FROM svv_columns');
|
|
102
|
-
expect(values).toEqual(['orders_lbv', 'public', 'warehouse']);
|
|
103
|
-
expect(fields).toEqual({
|
|
104
|
-
warehouse: {
|
|
105
|
-
public: { orders_lbv: { quantity: 'number' } },
|
|
106
|
-
},
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
it('keeps the Postgres catalog when the server is not Redshift', async () => {
|
|
110
|
-
const warehouse = new RedshiftWarehouseClient_1.RedshiftWarehouseClient(credentials);
|
|
111
|
-
const runQuery = vi
|
|
112
|
-
.spyOn(warehouse, 'runQuery')
|
|
113
|
-
.mockResolvedValueOnce({
|
|
114
|
-
rows: [{ version: 'PostgreSQL 15.4' }],
|
|
115
|
-
fields: {},
|
|
116
|
-
})
|
|
117
|
-
.mockResolvedValueOnce({ rows: [], fields: {} })
|
|
118
|
-
.mockResolvedValueOnce({ rows: [], fields: {} });
|
|
119
|
-
await warehouse.getAllTables();
|
|
120
|
-
await warehouse.getFields('orders', 'public');
|
|
121
|
-
expect(runQuery).toHaveBeenCalledTimes(3);
|
|
122
|
-
expect(runQuery.mock.calls[1][0]).toContain('FROM information_schema.tables');
|
|
123
|
-
expect(runQuery.mock.calls[1][0]).not.toContain('svv_tables');
|
|
124
|
-
expect(runQuery.mock.calls[2][0]).toContain('FROM information_schema.columns');
|
|
125
|
-
});
|
|
126
|
-
});
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { AnyType, CreateSnowflakeCredentials, DimensionType } from '@lightdash/common';
|
|
2
|
-
export declare const credentials: CreateSnowflakeCredentials;
|
|
3
|
-
export declare const columns: Record<string, AnyType>[];
|
|
4
|
-
declare class ColumnMock {
|
|
5
|
-
private readonly name;
|
|
6
|
-
private readonly type;
|
|
7
|
-
private readonly scale;
|
|
8
|
-
constructor(name: string, type: string, scale?: number);
|
|
9
|
-
getName(): string;
|
|
10
|
-
getType(): string;
|
|
11
|
-
getScale(): number;
|
|
12
|
-
}
|
|
13
|
-
export declare const queryColumnsMock: ColumnMock[];
|
|
14
|
-
export declare const expectedWarehouseSchema: {
|
|
15
|
-
myDatabase: {
|
|
16
|
-
mySchema: {
|
|
17
|
-
myTable: {
|
|
18
|
-
MYSTRINGCOLUMN: DimensionType;
|
|
19
|
-
MYNUMBERCOLUMN: DimensionType;
|
|
20
|
-
MYDATECOLUMN: DimensionType;
|
|
21
|
-
MYTIMESTAMPCOLUMN: DimensionType;
|
|
22
|
-
MYBOOLEANCOLUMN: DimensionType;
|
|
23
|
-
MYARRAYCOLUMN: DimensionType;
|
|
24
|
-
MYOBJECTCOLUMN: DimensionType;
|
|
25
|
-
};
|
|
26
|
-
};
|
|
27
|
-
};
|
|
28
|
-
__lightdashTimestampDomains: {
|
|
29
|
-
myDatabase: {
|
|
30
|
-
mySchema: {
|
|
31
|
-
myTable: {
|
|
32
|
-
MYTIMESTAMPCOLUMN: string;
|
|
33
|
-
};
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
};
|
|
37
|
-
};
|
|
38
|
-
export declare const expectedFields: Record<string, AnyType>;
|
|
39
|
-
export declare const expectedRow: Record<string, AnyType>;
|
|
40
|
-
export {};
|
|
41
|
-
//# sourceMappingURL=SnowflakeWarehouseClient.mock.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SnowflakeWarehouseClient.mock.d.ts","sourceRoot":"","sources":["../../src/warehouseClients/SnowflakeWarehouseClient.mock.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,OAAO,EACP,0BAA0B,EAC1B,aAAa,EAEhB,MAAM,mBAAmB,CAAC;AAI3B,eAAO,MAAM,WAAW,EAAE,0BASzB,CAAC;AASF,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAiG5C,CAAC;AAEF,cAAM,UAAU;IACZ,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAE9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAE9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAE/B,YAAY,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,EAIxD;IAED,OAAO,WAEN;IAED,OAAO,WAEN;IAED,QAAQ,WAEP;CACJ;AAED,eAAO,MAAM,gBAAgB,cAQ5B,CAAC;AAEF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;QAgB5B,UAAU;YACN,QAAQ;gBAAI,OAAO;oBAAI,iBAAiB;;;;;CAGnD,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAQlD,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAQ/C,CAAC"}
|