@lightdash/warehouses 0.2019.0 → 0.2021.0
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/ssh/sshTunnel.js +1 -0
- package/dist/warehouseClientFromCredentials.js +3 -0
- package/dist/warehouseClients/ClickhouseWarehouseClient.d.ts +71 -0
- package/dist/warehouseClients/ClickhouseWarehouseClient.js +313 -0
- package/dist/warehouseClients/WarehouseBaseClient.d.ts +3 -2
- package/dist/warehouseClients/WarehouseBaseClient.js +4 -2
- package/dist/warehouseSqlBuilderFromType.d.ts +2 -1
- package/dist/warehouseSqlBuilderFromType.js +3 -0
- package/package.json +3 -2
package/dist/ssh/sshTunnel.js
CHANGED
|
@@ -205,6 +205,7 @@ class SshTunnel {
|
|
|
205
205
|
case common_1.WarehouseTypes.TRINO:
|
|
206
206
|
case common_1.WarehouseTypes.SNOWFLAKE:
|
|
207
207
|
case common_1.WarehouseTypes.BIGQUERY:
|
|
208
|
+
case common_1.WarehouseTypes.CLICKHOUSE:
|
|
208
209
|
break;
|
|
209
210
|
default:
|
|
210
211
|
(0, common_1.assertUnreachable)(type, new Error('Unknown warehouse type'));
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.warehouseClientFromCredentials = void 0;
|
|
4
4
|
const common_1 = require("@lightdash/common");
|
|
5
5
|
const BigqueryWarehouseClient_1 = require("./warehouseClients/BigqueryWarehouseClient");
|
|
6
|
+
const ClickhouseWarehouseClient_1 = require("./warehouseClients/ClickhouseWarehouseClient");
|
|
6
7
|
const DatabricksWarehouseClient_1 = require("./warehouseClients/DatabricksWarehouseClient");
|
|
7
8
|
const PostgresWarehouseClient_1 = require("./warehouseClients/PostgresWarehouseClient");
|
|
8
9
|
const RedshiftWarehouseClient_1 = require("./warehouseClients/RedshiftWarehouseClient");
|
|
@@ -22,6 +23,8 @@ const warehouseClientFromCredentials = (credentials) => {
|
|
|
22
23
|
return new DatabricksWarehouseClient_1.DatabricksWarehouseClient(credentials);
|
|
23
24
|
case common_1.WarehouseTypes.TRINO:
|
|
24
25
|
return new TrinoWarehouseClient_1.TrinoWarehouseClient(credentials);
|
|
26
|
+
case common_1.WarehouseTypes.CLICKHOUSE:
|
|
27
|
+
return new ClickhouseWarehouseClient_1.ClickhouseWarehouseClient(credentials);
|
|
25
28
|
default:
|
|
26
29
|
const never = credentials;
|
|
27
30
|
throw new common_1.UnexpectedServerError('Warehouse credentials type were not recognised');
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { type ClickHouseClient } from '@clickhouse/client';
|
|
2
|
+
import { AnyType, CreateClickhouseCredentials, Metric, SupportedDbtAdapter, WarehouseResults, WarehouseTypes } from '@lightdash/common';
|
|
3
|
+
import { WarehouseCatalog } from '../types';
|
|
4
|
+
import WarehouseBaseClient from './WarehouseBaseClient';
|
|
5
|
+
import WarehouseBaseSqlBuilder from './WarehouseBaseSqlBuilder';
|
|
6
|
+
export declare enum ClickhouseTypes {
|
|
7
|
+
UINT8 = "UInt8",
|
|
8
|
+
UINT16 = "UInt16",
|
|
9
|
+
UINT32 = "UInt32",
|
|
10
|
+
UINT64 = "UInt64",
|
|
11
|
+
INT8 = "Int8",
|
|
12
|
+
INT16 = "Int16",
|
|
13
|
+
INT32 = "Int32",
|
|
14
|
+
INT64 = "Int64",
|
|
15
|
+
FLOAT32 = "Float32",
|
|
16
|
+
FLOAT64 = "Float64",
|
|
17
|
+
DECIMAL = "Decimal",
|
|
18
|
+
DECIMAL32 = "Decimal32",
|
|
19
|
+
DECIMAL64 = "Decimal64",
|
|
20
|
+
DECIMAL128 = "Decimal128",
|
|
21
|
+
DECIMAL256 = "Decimal256",
|
|
22
|
+
BOOL = "Bool",
|
|
23
|
+
STRING = "String",
|
|
24
|
+
FIXEDSTRING = "FixedString",
|
|
25
|
+
UUID = "UUID",
|
|
26
|
+
DATE = "Date",
|
|
27
|
+
DATE32 = "Date32",
|
|
28
|
+
DATETIME = "DateTime",
|
|
29
|
+
DATETIME64 = "DateTime64",
|
|
30
|
+
ENUM8 = "Enum8",
|
|
31
|
+
ENUM16 = "Enum16",
|
|
32
|
+
ARRAY = "Array",
|
|
33
|
+
TUPLE = "Tuple",
|
|
34
|
+
MAP = "Map",
|
|
35
|
+
NULLABLE = "Nullable",
|
|
36
|
+
LOWCARDINALITY = "LowCardinality",
|
|
37
|
+
IPV4 = "IPv4",
|
|
38
|
+
IPV6 = "IPv6"
|
|
39
|
+
}
|
|
40
|
+
interface TableInfo {
|
|
41
|
+
database: string;
|
|
42
|
+
schema?: string;
|
|
43
|
+
table: string;
|
|
44
|
+
}
|
|
45
|
+
export declare class ClickhouseSqlBuilder extends WarehouseBaseSqlBuilder {
|
|
46
|
+
readonly type = WarehouseTypes.CLICKHOUSE;
|
|
47
|
+
getAdapterType(): SupportedDbtAdapter;
|
|
48
|
+
getEscapeStringQuoteChar(): string;
|
|
49
|
+
getMetricSql(sql: string, metric: Metric): string;
|
|
50
|
+
escapeString(value: string): string;
|
|
51
|
+
}
|
|
52
|
+
export declare class ClickhouseWarehouseClient extends WarehouseBaseClient<CreateClickhouseCredentials> {
|
|
53
|
+
client: ClickHouseClient;
|
|
54
|
+
constructor(credentials: CreateClickhouseCredentials);
|
|
55
|
+
streamQuery(sql: string, streamCallback: (data: WarehouseResults) => void, options: {
|
|
56
|
+
queryParams?: Record<string, AnyType>;
|
|
57
|
+
tags?: Record<string, string>;
|
|
58
|
+
timezone?: string;
|
|
59
|
+
}): Promise<void>;
|
|
60
|
+
getCatalog(requests: TableInfo[]): Promise<WarehouseCatalog>;
|
|
61
|
+
getTables(schema?: string, tags?: Record<string, string>): Promise<WarehouseCatalog>;
|
|
62
|
+
getFields(tableName: string, schema?: string, database?: string, // always empty string in clickhouse
|
|
63
|
+
tags?: Record<string, string>): Promise<WarehouseCatalog>;
|
|
64
|
+
getAllTables(): Promise<{
|
|
65
|
+
database: any;
|
|
66
|
+
schema: any;
|
|
67
|
+
table: any;
|
|
68
|
+
}[]>;
|
|
69
|
+
test(): Promise<void>;
|
|
70
|
+
}
|
|
71
|
+
export {};
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ClickhouseWarehouseClient = exports.ClickhouseSqlBuilder = exports.ClickhouseTypes = void 0;
|
|
7
|
+
const client_1 = require("@clickhouse/client");
|
|
8
|
+
const common_1 = require("@lightdash/common");
|
|
9
|
+
const processPromisesInBatches_1 = require("../utils/processPromisesInBatches");
|
|
10
|
+
const sql_1 = require("../utils/sql");
|
|
11
|
+
const WarehouseBaseClient_1 = __importDefault(require("./WarehouseBaseClient"));
|
|
12
|
+
const WarehouseBaseSqlBuilder_1 = __importDefault(require("./WarehouseBaseSqlBuilder"));
|
|
13
|
+
var ClickhouseTypes;
|
|
14
|
+
(function (ClickhouseTypes) {
|
|
15
|
+
ClickhouseTypes["UINT8"] = "UInt8";
|
|
16
|
+
ClickhouseTypes["UINT16"] = "UInt16";
|
|
17
|
+
ClickhouseTypes["UINT32"] = "UInt32";
|
|
18
|
+
ClickhouseTypes["UINT64"] = "UInt64";
|
|
19
|
+
ClickhouseTypes["INT8"] = "Int8";
|
|
20
|
+
ClickhouseTypes["INT16"] = "Int16";
|
|
21
|
+
ClickhouseTypes["INT32"] = "Int32";
|
|
22
|
+
ClickhouseTypes["INT64"] = "Int64";
|
|
23
|
+
ClickhouseTypes["FLOAT32"] = "Float32";
|
|
24
|
+
ClickhouseTypes["FLOAT64"] = "Float64";
|
|
25
|
+
ClickhouseTypes["DECIMAL"] = "Decimal";
|
|
26
|
+
ClickhouseTypes["DECIMAL32"] = "Decimal32";
|
|
27
|
+
ClickhouseTypes["DECIMAL64"] = "Decimal64";
|
|
28
|
+
ClickhouseTypes["DECIMAL128"] = "Decimal128";
|
|
29
|
+
ClickhouseTypes["DECIMAL256"] = "Decimal256";
|
|
30
|
+
ClickhouseTypes["BOOL"] = "Bool";
|
|
31
|
+
ClickhouseTypes["STRING"] = "String";
|
|
32
|
+
ClickhouseTypes["FIXEDSTRING"] = "FixedString";
|
|
33
|
+
ClickhouseTypes["UUID"] = "UUID";
|
|
34
|
+
ClickhouseTypes["DATE"] = "Date";
|
|
35
|
+
ClickhouseTypes["DATE32"] = "Date32";
|
|
36
|
+
ClickhouseTypes["DATETIME"] = "DateTime";
|
|
37
|
+
ClickhouseTypes["DATETIME64"] = "DateTime64";
|
|
38
|
+
ClickhouseTypes["ENUM8"] = "Enum8";
|
|
39
|
+
ClickhouseTypes["ENUM16"] = "Enum16";
|
|
40
|
+
ClickhouseTypes["ARRAY"] = "Array";
|
|
41
|
+
ClickhouseTypes["TUPLE"] = "Tuple";
|
|
42
|
+
ClickhouseTypes["MAP"] = "Map";
|
|
43
|
+
ClickhouseTypes["NULLABLE"] = "Nullable";
|
|
44
|
+
ClickhouseTypes["LOWCARDINALITY"] = "LowCardinality";
|
|
45
|
+
ClickhouseTypes["IPV4"] = "IPv4";
|
|
46
|
+
ClickhouseTypes["IPV6"] = "IPv6";
|
|
47
|
+
})(ClickhouseTypes || (exports.ClickhouseTypes = ClickhouseTypes = {}));
|
|
48
|
+
const convertDataTypeToDimensionType = (type) => {
|
|
49
|
+
// Remove nullable wrapper and low cardinality wrapper
|
|
50
|
+
const cleanType = type
|
|
51
|
+
.replace(/^Nullable\((.+)\)$/, '$1')
|
|
52
|
+
.replace(/^LowCardinality\((.+)\)$/, '$1')
|
|
53
|
+
.replace(/\(\d+\)/, ''); // Remove precision from decimals and fixed strings
|
|
54
|
+
switch (cleanType) {
|
|
55
|
+
case ClickhouseTypes.BOOL:
|
|
56
|
+
return common_1.DimensionType.BOOLEAN;
|
|
57
|
+
case ClickhouseTypes.UINT8:
|
|
58
|
+
case ClickhouseTypes.UINT16:
|
|
59
|
+
case ClickhouseTypes.UINT32:
|
|
60
|
+
case ClickhouseTypes.UINT64:
|
|
61
|
+
case ClickhouseTypes.INT8:
|
|
62
|
+
case ClickhouseTypes.INT16:
|
|
63
|
+
case ClickhouseTypes.INT32:
|
|
64
|
+
case ClickhouseTypes.INT64:
|
|
65
|
+
case ClickhouseTypes.FLOAT32:
|
|
66
|
+
case ClickhouseTypes.FLOAT64:
|
|
67
|
+
case ClickhouseTypes.DECIMAL:
|
|
68
|
+
case ClickhouseTypes.DECIMAL32:
|
|
69
|
+
case ClickhouseTypes.DECIMAL64:
|
|
70
|
+
case ClickhouseTypes.DECIMAL128:
|
|
71
|
+
case ClickhouseTypes.DECIMAL256:
|
|
72
|
+
return common_1.DimensionType.NUMBER;
|
|
73
|
+
case ClickhouseTypes.DATE:
|
|
74
|
+
case ClickhouseTypes.DATE32:
|
|
75
|
+
return common_1.DimensionType.DATE;
|
|
76
|
+
case ClickhouseTypes.DATETIME:
|
|
77
|
+
case ClickhouseTypes.DATETIME64:
|
|
78
|
+
return common_1.DimensionType.TIMESTAMP;
|
|
79
|
+
default:
|
|
80
|
+
return common_1.DimensionType.STRING;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const catalogToSchema = (results) => {
|
|
84
|
+
const warehouseCatalog = {};
|
|
85
|
+
results.forEach((result) => {
|
|
86
|
+
result.forEach((row) => {
|
|
87
|
+
// Map column names from snake_case to camelCase
|
|
88
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
89
|
+
const { table_catalog: database, table_schema: tableSchema, table_name: tableName, column_name: columnName, data_type: dataType, } = row;
|
|
90
|
+
warehouseCatalog[database] = warehouseCatalog[database] || {};
|
|
91
|
+
warehouseCatalog[database][tableSchema || 'default'] =
|
|
92
|
+
warehouseCatalog[database][tableSchema || 'default'] || {};
|
|
93
|
+
warehouseCatalog[database][tableSchema || 'default'][tableName] =
|
|
94
|
+
warehouseCatalog[database][tableSchema || 'default'][tableName] || {};
|
|
95
|
+
warehouseCatalog[database][tableSchema || 'default'][tableName][columnName] = convertDataTypeToDimensionType(dataType);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
return warehouseCatalog;
|
|
99
|
+
};
|
|
100
|
+
class ClickhouseSqlBuilder extends WarehouseBaseSqlBuilder_1.default {
|
|
101
|
+
constructor() {
|
|
102
|
+
super(...arguments);
|
|
103
|
+
this.type = common_1.WarehouseTypes.CLICKHOUSE;
|
|
104
|
+
}
|
|
105
|
+
getAdapterType() {
|
|
106
|
+
return common_1.SupportedDbtAdapter.CLICKHOUSE;
|
|
107
|
+
}
|
|
108
|
+
getEscapeStringQuoteChar() {
|
|
109
|
+
return "'";
|
|
110
|
+
}
|
|
111
|
+
getMetricSql(sql, metric) {
|
|
112
|
+
switch (metric.type) {
|
|
113
|
+
case common_1.MetricType.PERCENTILE:
|
|
114
|
+
return `quantile(${(metric.percentile ?? 50) / 100})(${sql})`;
|
|
115
|
+
case common_1.MetricType.MEDIAN:
|
|
116
|
+
return `median(${sql})`;
|
|
117
|
+
default:
|
|
118
|
+
return super.getMetricSql(sql, metric);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
escapeString(value) {
|
|
122
|
+
if (typeof value !== 'string') {
|
|
123
|
+
return value;
|
|
124
|
+
}
|
|
125
|
+
return ((0, sql_1.normalizeUnicode)(value)
|
|
126
|
+
// ClickHouse uses single quote doubling like PostgreSQL
|
|
127
|
+
.replaceAll("'", "''")
|
|
128
|
+
// Escape backslashes
|
|
129
|
+
.replaceAll('\\', '\\\\')
|
|
130
|
+
// Remove SQL comments
|
|
131
|
+
.replace(/--.*$/gm, '')
|
|
132
|
+
.replace(/\/\*[\s\S]*?\*\//g, '')
|
|
133
|
+
// Remove null bytes
|
|
134
|
+
.replaceAll('\0', ''));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
exports.ClickhouseSqlBuilder = ClickhouseSqlBuilder;
|
|
138
|
+
class ClickhouseWarehouseClient extends WarehouseBaseClient_1.default {
|
|
139
|
+
constructor(credentials) {
|
|
140
|
+
super(credentials, new ClickhouseSqlBuilder(credentials.startOfWeek));
|
|
141
|
+
const protocol = credentials.secure ? 'https' : 'http';
|
|
142
|
+
const url = `${protocol}://${credentials.host}:${credentials.port}`;
|
|
143
|
+
this.client = (0, client_1.createClient)({
|
|
144
|
+
url,
|
|
145
|
+
username: credentials.user,
|
|
146
|
+
password: credentials.password,
|
|
147
|
+
database: credentials.schema, // In clickhouse schema = database
|
|
148
|
+
request_timeout: (credentials.timeoutSeconds || 30) * 1000,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
async streamQuery(sql, streamCallback, options) {
|
|
152
|
+
try {
|
|
153
|
+
let alteredQuery = sql;
|
|
154
|
+
if (options?.tags) {
|
|
155
|
+
alteredQuery = `${alteredQuery}\n-- ${JSON.stringify(options?.tags)}`;
|
|
156
|
+
}
|
|
157
|
+
const resultSet = await this.client.query({
|
|
158
|
+
query: alteredQuery,
|
|
159
|
+
format: 'JSONCompactEachRowWithNamesAndTypes',
|
|
160
|
+
query_params: options?.queryParams,
|
|
161
|
+
clickhouse_settings: options?.timezone
|
|
162
|
+
? { timezone: options.timezone }
|
|
163
|
+
: undefined,
|
|
164
|
+
});
|
|
165
|
+
const columnNames = [];
|
|
166
|
+
const fields = {};
|
|
167
|
+
const stream = resultSet.stream();
|
|
168
|
+
stream.on('data', (rows) => {
|
|
169
|
+
// handle the rest of the rows with results
|
|
170
|
+
rows.forEach((r) => {
|
|
171
|
+
const row = r.json();
|
|
172
|
+
// handle first row with column names
|
|
173
|
+
if (columnNames.length === 0) {
|
|
174
|
+
row.map((c) => {
|
|
175
|
+
if (typeof c === 'string') {
|
|
176
|
+
return columnNames.push(c);
|
|
177
|
+
}
|
|
178
|
+
return columnNames.push(String(c));
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
else if (Object.keys(fields).length === 0) {
|
|
182
|
+
// handle second row with column types
|
|
183
|
+
columnNames.forEach((c, index) => {
|
|
184
|
+
fields[c] = {
|
|
185
|
+
type: convertDataTypeToDimensionType(String(row[index])),
|
|
186
|
+
};
|
|
187
|
+
});
|
|
188
|
+
streamCallback({
|
|
189
|
+
fields,
|
|
190
|
+
rows: [],
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
streamCallback({
|
|
195
|
+
fields,
|
|
196
|
+
rows: [
|
|
197
|
+
// convert value array to object
|
|
198
|
+
columnNames.reduce((acc, c, index) => {
|
|
199
|
+
acc[c] = row[index];
|
|
200
|
+
return acc;
|
|
201
|
+
}, {}),
|
|
202
|
+
],
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
await new Promise((resolve, reject) => {
|
|
208
|
+
stream.on('end', () => {
|
|
209
|
+
resolve();
|
|
210
|
+
});
|
|
211
|
+
stream.on('error', reject);
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
catch (e) {
|
|
215
|
+
throw new common_1.WarehouseQueryError((0, common_1.getErrorMessage)(e));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
async getCatalog(requests) {
|
|
219
|
+
let results;
|
|
220
|
+
const query = `SELECT
|
|
221
|
+
'' as "table_catalog",
|
|
222
|
+
database as "table_schema",
|
|
223
|
+
table as "table_name",
|
|
224
|
+
name as "column_name",
|
|
225
|
+
type as "data_type"
|
|
226
|
+
FROM system.columns
|
|
227
|
+
WHERE database = {databaseName: String}
|
|
228
|
+
AND table = {tableName: String}
|
|
229
|
+
ORDER BY position`;
|
|
230
|
+
try {
|
|
231
|
+
results = await (0, processPromisesInBatches_1.processPromisesInBatches)(requests, processPromisesInBatches_1.DEFAULT_BATCH_SIZE, async (request) => {
|
|
232
|
+
const { rows } = await this.runQuery(query, {}, undefined, undefined, {
|
|
233
|
+
databaseName: request.schema,
|
|
234
|
+
tableName: request.table,
|
|
235
|
+
});
|
|
236
|
+
return rows;
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
catch (e) {
|
|
240
|
+
throw new common_1.WarehouseQueryError((0, common_1.getErrorMessage)(e));
|
|
241
|
+
}
|
|
242
|
+
return catalogToSchema(results);
|
|
243
|
+
}
|
|
244
|
+
async getTables(schema, tags) {
|
|
245
|
+
const databaseName = schema || this.credentials.schema; // In clickhouse schema = database
|
|
246
|
+
const query = `
|
|
247
|
+
SELECT
|
|
248
|
+
'' as "table_catalog",
|
|
249
|
+
database as "table_schema",
|
|
250
|
+
name as "table_name"
|
|
251
|
+
FROM system.tables
|
|
252
|
+
WHERE database = {databaseName: String}
|
|
253
|
+
ORDER BY database, name
|
|
254
|
+
`;
|
|
255
|
+
const { rows } = await this.runQuery(query, tags, undefined, undefined, {
|
|
256
|
+
databaseName,
|
|
257
|
+
});
|
|
258
|
+
return this.parseWarehouseCatalog(rows, convertDataTypeToDimensionType);
|
|
259
|
+
}
|
|
260
|
+
async getFields(tableName, schema, database, // always empty string in clickhouse
|
|
261
|
+
tags) {
|
|
262
|
+
const dbName = schema || this.credentials.schema; // In clickhouse schema = database
|
|
263
|
+
const query = `
|
|
264
|
+
SELECT
|
|
265
|
+
'' as "table_catalog",
|
|
266
|
+
database as "table_schema",
|
|
267
|
+
table as "table_name",
|
|
268
|
+
name as "column_name",
|
|
269
|
+
type as "data_type"
|
|
270
|
+
FROM system.columns
|
|
271
|
+
WHERE database = {databaseName: String}
|
|
272
|
+
AND table = {tableName: String}
|
|
273
|
+
ORDER BY position
|
|
274
|
+
`;
|
|
275
|
+
const { rows } = await this.runQuery(query, tags, undefined, undefined, {
|
|
276
|
+
databaseName: dbName,
|
|
277
|
+
tableName,
|
|
278
|
+
});
|
|
279
|
+
return this.parseWarehouseCatalog(rows, convertDataTypeToDimensionType);
|
|
280
|
+
}
|
|
281
|
+
async getAllTables() {
|
|
282
|
+
const databaseName = this.credentials.schema; // In clickhouse schema = database
|
|
283
|
+
const query = `
|
|
284
|
+
SELECT
|
|
285
|
+
'' as "table_catalog",
|
|
286
|
+
database as "table_schema",
|
|
287
|
+
name as "table_name"
|
|
288
|
+
FROM system.tables
|
|
289
|
+
WHERE database = {databaseName: String}
|
|
290
|
+
ORDER BY database, name
|
|
291
|
+
`;
|
|
292
|
+
const { rows } = await this.runQuery(query, {}, undefined, undefined, {
|
|
293
|
+
databaseName,
|
|
294
|
+
});
|
|
295
|
+
return rows.map((row) => ({
|
|
296
|
+
database: row.table_catalog,
|
|
297
|
+
schema: row.table_schema || 'default',
|
|
298
|
+
table: row.table_name,
|
|
299
|
+
}));
|
|
300
|
+
}
|
|
301
|
+
async test() {
|
|
302
|
+
try {
|
|
303
|
+
await this.client.query({
|
|
304
|
+
query: 'SELECT 1 as test',
|
|
305
|
+
format: 'JSON',
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
catch (e) {
|
|
309
|
+
throw new common_1.WarehouseConnectionError((0, common_1.getErrorMessage)(e));
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
exports.ClickhouseWarehouseClient = ClickhouseWarehouseClient;
|
|
@@ -16,11 +16,12 @@ export default abstract class WarehouseBaseClient<T extends CreateWarehouseCrede
|
|
|
16
16
|
getAsyncQueryResults<TFormattedRow extends Record<string, unknown>>(_args: WarehouseGetAsyncQueryResultsArgs, _rowFormatter?: (row: Record<string, unknown>) => TFormattedRow): Promise<WarehouseGetAsyncQueryResults<TFormattedRow>>;
|
|
17
17
|
abstract streamQuery(query: string, streamCallback: (data: WarehouseResults) => void, options: {
|
|
18
18
|
values?: AnyType[];
|
|
19
|
+
queryParams?: Record<string, AnyType>;
|
|
19
20
|
tags?: Record<string, string>;
|
|
20
21
|
timezone?: string;
|
|
21
22
|
}): Promise<void>;
|
|
22
|
-
executeAsyncQuery({ sql, values, tags, timezone }: WarehouseExecuteAsyncQueryArgs, resultsStreamCallback: (rows: WarehouseResults['rows'], fields: WarehouseResults['fields']) => void): Promise<WarehouseExecuteAsyncQuery>;
|
|
23
|
-
runQuery(sql: string, tags?: Record<string, string>, timezone?: string, values?: AnyType[]): Promise<{
|
|
23
|
+
executeAsyncQuery({ sql, values, queryParams, tags, timezone, }: WarehouseExecuteAsyncQueryArgs, resultsStreamCallback: (rows: WarehouseResults['rows'], fields: WarehouseResults['fields']) => void): Promise<WarehouseExecuteAsyncQuery>;
|
|
24
|
+
runQuery(sql: string, tags?: Record<string, string>, timezone?: string, values?: AnyType[], queryParams?: Record<string, AnyType>): Promise<{
|
|
24
25
|
fields: Record<string, {
|
|
25
26
|
type: DimensionType;
|
|
26
27
|
}>;
|
|
@@ -21,7 +21,7 @@ class WarehouseBaseClient {
|
|
|
21
21
|
async getAsyncQueryResults(_args, _rowFormatter) {
|
|
22
22
|
throw new common_1.NotImplementedError(`Paginated query results are not supported for warehouse type: ${this.getAdapterType()}`);
|
|
23
23
|
}
|
|
24
|
-
async executeAsyncQuery({ sql, values, tags, timezone }, resultsStreamCallback) {
|
|
24
|
+
async executeAsyncQuery({ sql, values, queryParams, tags, timezone, }, resultsStreamCallback) {
|
|
25
25
|
let rowCount = 0;
|
|
26
26
|
const startTime = performance.now();
|
|
27
27
|
await this.streamQuery(sql, ({ rows, fields }) => {
|
|
@@ -29,6 +29,7 @@ class WarehouseBaseClient {
|
|
|
29
29
|
resultsStreamCallback(rows, fields);
|
|
30
30
|
}, {
|
|
31
31
|
values,
|
|
32
|
+
queryParams,
|
|
32
33
|
tags,
|
|
33
34
|
timezone,
|
|
34
35
|
});
|
|
@@ -40,7 +41,7 @@ class WarehouseBaseClient {
|
|
|
40
41
|
totalRows: rowCount,
|
|
41
42
|
};
|
|
42
43
|
}
|
|
43
|
-
async runQuery(sql, tags, timezone, values) {
|
|
44
|
+
async runQuery(sql, tags, timezone, values, queryParams) {
|
|
44
45
|
let fields = {};
|
|
45
46
|
const rows = [];
|
|
46
47
|
await this.streamQuery(sql, (data) => {
|
|
@@ -48,6 +49,7 @@ class WarehouseBaseClient {
|
|
|
48
49
|
rows.push(...data.rows);
|
|
49
50
|
}, {
|
|
50
51
|
values,
|
|
52
|
+
queryParams,
|
|
51
53
|
tags,
|
|
52
54
|
timezone,
|
|
53
55
|
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { SupportedDbtAdapter } from '@lightdash/common';
|
|
2
2
|
import { BigquerySqlBuilder } from './warehouseClients/BigqueryWarehouseClient';
|
|
3
|
+
import { ClickhouseSqlBuilder } from './warehouseClients/ClickhouseWarehouseClient';
|
|
3
4
|
import { DatabricksSqlBuilder } from './warehouseClients/DatabricksWarehouseClient';
|
|
4
5
|
import { PostgresSqlBuilder } from './warehouseClients/PostgresWarehouseClient';
|
|
5
6
|
import { SnowflakeSqlBuilder } from './warehouseClients/SnowflakeWarehouseClient';
|
|
6
7
|
import { TrinoSqlBuilder } from './warehouseClients/TrinoWarehouseClient';
|
|
7
|
-
export declare const warehouseSqlBuilderFromType: (adapterType: string | SupportedDbtAdapter, startOfWeek?: import("@lightdash/common").WeekDay | null | undefined) => BigquerySqlBuilder | DatabricksSqlBuilder | PostgresSqlBuilder | SnowflakeSqlBuilder | TrinoSqlBuilder;
|
|
8
|
+
export declare const warehouseSqlBuilderFromType: (adapterType: string | SupportedDbtAdapter, startOfWeek?: import("@lightdash/common").WeekDay | null | undefined) => BigquerySqlBuilder | ClickhouseSqlBuilder | DatabricksSqlBuilder | PostgresSqlBuilder | SnowflakeSqlBuilder | TrinoSqlBuilder;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.warehouseSqlBuilderFromType = void 0;
|
|
4
4
|
const common_1 = require("@lightdash/common");
|
|
5
5
|
const BigqueryWarehouseClient_1 = require("./warehouseClients/BigqueryWarehouseClient");
|
|
6
|
+
const ClickhouseWarehouseClient_1 = require("./warehouseClients/ClickhouseWarehouseClient");
|
|
6
7
|
const DatabricksWarehouseClient_1 = require("./warehouseClients/DatabricksWarehouseClient");
|
|
7
8
|
const PostgresWarehouseClient_1 = require("./warehouseClients/PostgresWarehouseClient");
|
|
8
9
|
const RedshiftWarehouseClient_1 = require("./warehouseClients/RedshiftWarehouseClient");
|
|
@@ -15,6 +16,8 @@ const warehouseSqlBuilderFromType = (adapterType, ...args) => {
|
|
|
15
16
|
switch (adapterType) {
|
|
16
17
|
case common_1.SupportedDbtAdapter.BIGQUERY:
|
|
17
18
|
return new BigqueryWarehouseClient_1.BigquerySqlBuilder(...args);
|
|
19
|
+
case common_1.SupportedDbtAdapter.CLICKHOUSE:
|
|
20
|
+
return new ClickhouseWarehouseClient_1.ClickhouseSqlBuilder(...args);
|
|
18
21
|
case common_1.SupportedDbtAdapter.DATABRICKS:
|
|
19
22
|
return new DatabricksWarehouseClient_1.DatabricksSqlBuilder(...args);
|
|
20
23
|
case common_1.SupportedDbtAdapter.POSTGRES:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lightdash/warehouses",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2021.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"dist/**/*"
|
|
9
9
|
],
|
|
10
10
|
"dependencies": {
|
|
11
|
+
"@clickhouse/client": "^1.12.1",
|
|
11
12
|
"@databricks/sql": "1.8.4",
|
|
12
13
|
"@google-cloud/bigquery": "^7.9.2",
|
|
13
14
|
"lodash": "^4.17.21",
|
|
@@ -16,7 +17,7 @@
|
|
|
16
17
|
"snowflake-sdk": "~2.1.3",
|
|
17
18
|
"ssh2": "^1.14.0",
|
|
18
19
|
"trino-client": "0.2.6",
|
|
19
|
-
"@lightdash/common": "0.
|
|
20
|
+
"@lightdash/common": "0.2021.0"
|
|
20
21
|
},
|
|
21
22
|
"devDependencies": {
|
|
22
23
|
"@types/pg": "^8.11.10",
|