UNPKG

@enzedd/stimulsoft-clickhouse-data-adapter

Version:

Stimulsoft clickhouse data adapter

143 lines (130 loc) 4.73 kB
/* Stimulsoft.Reports.JS Clickhouse adapter */ require('isomorphic-fetch'); const ADAPTER_VERSION = "2022.3.1"; const CLICKHOUSE_TO_JS_TYPES = { // Possible js values: string, number, int, boolean, array, datetime, datetimeZ, time, timeZ, datetimeoffset 'Array': 'array', 'Bool': 'boolean', 'IPv6': 'string', 'IPv4': 'string', 'Enum': 'string', 'FixedString': 'string', 'String': 'string', 'Float64': 'number', 'UInt8': 'int', 'UInt16': 'int', 'DateTime': 'datetime', 'DateTime64': 'datetime', 'Decimal': 'number', 'Int64': 'int', 'Float32': 'number', 'UInt64': 'int', 'UInt32': 'int', 'Int16': 'int', 'Int32': 'int', 'Int8': 'int', 'UUID': 'string', } let DEFAULT_TYPE = 'string'; class ClickhouseClient { constructor(params) { this.protocol = params.protocol || (params.port && params.port === 8443) ? 'https' : 'http' this.host = params.host || 'localhost' this.port = params.port || (params.protocol && params.protocol === 'https') ? 8443 : 8123 this.database = params.database || 'default' this.user = params.user || 'default' this.password = params.password || '' } static getConnectionParams(connectionString) { const params = {}; for (let propertyIndex in connectionString.split(";")) { let property = connectionString.split(";")[propertyIndex]; if (property) { let match = property.split(new RegExp('=|:')); if (match && match.length >= 2) { match[0] = match[0].trim().toLowerCase(); match[1] = match[1].trim(); switch (match[0]) { case "data source": case "server": case "host": params["host"] = match[1]; break; case "port": params["port"] = match[1]; break; case "database": case "location": params["database"] = match[1]; break; case "uid": case "user": case "user id": params["user"] = match[1]; break; case "pwd": case "password": params["password"] = match[1]; break; case "ssl": params["protocol"] = match[1] ? 'https' : 'http'; break; case "sslmode": if (match[1] === "require") params["protocol"] = 'https'; else if (match[1] === "disable") params["protocol"] = 'http'; break; } } } } return params; }; getColumnType(val) { val = val.split('(')[0]; return CLICKHOUSE_TO_JS_TYPES[val] || DEFAULT_TYPE } query(sql) { return fetch(`http://${this.host}:${this.port}?database=${this.database}&query=${sql} FORMAT JSONCompact`, { headers: { "X-Clickhouse-User": this.user, "X-Clickhouse-Key": this.password, } }).then(response => { return response.json() }).then(data => { const columns = data.meta.map(item => item.name); const types = data.meta.map(item => this.getColumnType(item.type)); return { success: true, columns: columns, rows: data.data, types: types, }; }).catch(error => { console.error('There has been an issue with your fetch operation:', error) return { success: false, notice: error.message, } }); } } exports.process = function (command, onResult) { try { const connectionParams = ClickhouseClient.getConnectionParams(command.connectionString); const client = new ClickhouseClient(connectionParams) client.query(command.queryString).then(result => { result.adapterVersion = ADAPTER_VERSION; onResult(result) }) } catch (error) { console.error('Failed to process:', error) onResult({ success: false, notice: error.stack, adapterVersion: ADAPTER_VERSION, }) } }