UNPKG

plywood

Version:
1,217 lines (1,210 loc) 597 kB
'use strict'; var { __assign, __awaiter, __extends, __generator } = require('tslib'); var hasOwnProp = require('has-own-prop'); var toArray = require('stream-to-array'); var readableStream = require('readable-stream'); var Readable = readableStream.Readable; var Writable = readableStream.Writable; var Transform = readableStream.Transform; var PassThrough = readableStream.PassThrough; var immutableClass = require('immutable-class'); var generalArraysEqual = immutableClass.generalArraysEqual; var generalEqual = immutableClass.generalEqual; var generalLookupsEqual = immutableClass.generalLookupsEqual; var isImmutableClass = immutableClass.isImmutableClass; var immutableEqual = immutableClass.immutableEqual; var immutableArraysEqual = immutableClass.immutableArraysEqual; var immutableLookupsEqual = immutableClass.immutableLookupsEqual; var SimpleArray = immutableClass.SimpleArray; var NamedArray = immutableClass.NamedArray; var Chronoshift = require('chronoshift'); var Timezone = Chronoshift.Timezone; var Duration = Chronoshift.Duration; var moment = Chronoshift.moment; var isDate = Chronoshift.isDate; var parseISODate = Chronoshift.parseISODate; var druidQueryToolkit = require('druid-query-toolkit'); var SqlColumn = druidQueryToolkit.SqlColumn; var SqlExpression = druidQueryToolkit.SqlExpression; var SqlFunction = druidQueryToolkit.SqlFunction; var SqlCase = druidQueryToolkit.SqlCase; var SqlQuery = druidQueryToolkit.SqlQuery; var Introspect = druidQueryToolkit.Introspect; var QueryResult = druidQueryToolkit.QueryResult; var dummyObject = {}; var version = exports.version = '0.35.5'; var verboseRequesterFactory = exports.verboseRequesterFactory = function(parameters) { var requester = parameters.requester; var myName = parameters.name || 'rq' + String(Math.random()).substr(2, 5); if (parameters.preQuery) { console.warn('verboseRequesterFactory option preQuery has been renamed to onQuery'); parameters.onQuery = parameters.preQuery; } var printLine = parameters.printLine || (function (line) { console['log'](line); }); var onQuery = parameters.onQuery || (function (param) { printLine('vvvvvvvvvvvvvvvvvvvvvvvvvv'); var ctx = param.context ? " [context: ".concat(JSON.stringify(param.context), "]") : ''; printLine("Requester ".concat(param.name, " sending query ").concat(param.queryNumber, ":").concat(ctx)); printLine(JSON.stringify(param.query, null, 2)); printLine('^^^^^^^^^^^^^^^^^^^^^^^^^^'); }); var onSuccess = parameters.onSuccess || (function (param) { printLine('vvvvvvvvvvvvvvvvvvvvvvvvvv'); printLine("Requester ".concat(param.name, " got result from query ").concat(param.queryNumber, ": (in ").concat(param.time, "ms)")); printLine(JSON.stringify(param.data, null, 2)); printLine('^^^^^^^^^^^^^^^^^^^^^^^^^^'); }); var onError = parameters.onError || (function (param) { printLine('vvvvvvvvvvvvvvvvvvvvvvvvvv'); printLine("Requester ".concat(param.name, " got error in query ").concat(param.queryNumber, ": ").concat(param.error.message, " (in ").concat(param.time, "ms)")); printLine('^^^^^^^^^^^^^^^^^^^^^^^^^^'); }); var curQueryNumber = 0; return function (request) { curQueryNumber++; var myQueryNumber = curQueryNumber; onQuery({ name: myName, queryNumber: myQueryNumber, query: request.query, context: request.context, }); var startTime = Date.now(); var stream = requester(request); var errorSeen = false; stream.on('error', function (error) { errorSeen = true; onError({ name: myName, queryNumber: myQueryNumber, query: request.query, context: request.context, time: Date.now() - startTime, error: error, }); }); var data = []; stream.on('data', function (datum) { data.push(JSON.parse(JSON.stringify(datum))); }); stream.on('end', function () { if (errorSeen) return; onSuccess({ name: myName, queryNumber: myQueryNumber, query: request.query, context: request.context, time: Date.now() - startTime, data: data, }); }); return stream; }; } var retryRequesterFactory = exports.retryRequesterFactory = function(parameters) { var requester = parameters.requester; var delay = parameters.delay || 500; var retry = parameters.retry || 3; var retryOnTimeout = Boolean(parameters.retryOnTimeout); if (typeof delay !== 'number') throw new TypeError('delay should be a number'); if (typeof retry !== 'number') throw new TypeError('retry should be a number'); return function (request) { var tries = 0; var ended = false; var output = new PassThrough({ objectMode: true }); function tryRequest() { tries++; var seenData = false; var errored = false; var rs = requester(request); rs.on('error', function (e) { errored = true; if (seenData || tries > retry || (e.message === 'timeout' && !retryOnTimeout)) { rs.unpipe(output); output.emit('error', e); ended = true; output.end(); } else { setTimeout(tryRequest, delay); } }); rs.on('meta', function (m) { output.emit('meta', m); }); rs.on('data', function (_d) { seenData = true; }); rs.on('end', function () { if (ended || errored) return; output.end(); }); rs.pipe(output, { end: false }); } tryRequest(); return output; }; } var concurrentLimitRequesterFactory = exports.concurrentLimitRequesterFactory = function(parameters) { var requester = parameters.requester; var concurrentLimit = parameters.concurrentLimit || 5; if (typeof concurrentLimit !== 'number') throw new TypeError('concurrentLimit should be a number'); var requestQueue = []; var outstandingRequests = 0; function requestFinished() { outstandingRequests--; if (!(requestQueue.length && outstandingRequests < concurrentLimit)) return; var queueItem = requestQueue.shift(); outstandingRequests++; var stream = requester(queueItem.request); stream.on('error', requestFinished); stream.on('end', requestFinished); pipeWithError(stream, queueItem.stream); } return function (request) { if (outstandingRequests < concurrentLimit) { outstandingRequests++; var stream = requester(request); stream.on('error', requestFinished); stream.on('end', requestFinished); return stream; } else { var stream = new PassThrough({ objectMode: true }); requestQueue.push({ request: request, stream: stream, }); return stream; } }; } var promiseWhile = exports.promiseWhile = function(condition, action) { var loop = function () { if (!condition()) return Promise.resolve(null); return Promise.resolve(action()).then(loop); }; return Promise.resolve(null).then(loop); } var ReadableError = (function (_super) { __extends(ReadableError, _super); function ReadableError(message, options) { if (options === void 0) { options = {}; } var _this = _super.call(this, options) || this; var err = typeof message === 'string' ? new Error(message) : message; setTimeout(function () { _this.emit('error', err); }, 1); return _this; } ReadableError.prototype._read = function () { }; return ReadableError; }(Readable)); exports.ReadableError = ReadableError; var StreamConcat = (function (_super) { __extends(StreamConcat, _super); function StreamConcat(options) { var _this = _super.call(this, options) || this; _this.next = options.next; _this.currentStream = null; _this.streamIndex = 0; _this._nextStream(); return _this; } StreamConcat.prototype._nextStream = function () { var _this = this; this.currentStream = null; this.currentStream = this.next(); if (this.currentStream == null) { this.push(null); } else { this.currentStream.pipe(this, { end: false }); this.currentStream.on('error', function (e) { return _this.emit('error', e); }); this.currentStream.on('end', this._nextStream.bind(this)); } }; return StreamConcat; }(PassThrough)); exports.StreamConcat = StreamConcat; var repeat = exports.repeat = function(str, times) { return new Array(times + 1).join(str); } var indentBy = exports.indentBy = function(str, indent) { var spaces = repeat(' ', indent); return str .split('\n') .map(function (x) { return spaces + x; }) .join('\n'); } var dictEqual = exports.dictEqual = function(dictA, dictB) { if (dictA === dictB) return true; if (!dictA !== !dictB) return false; var keys = Object.keys(dictA); if (keys.length !== Object.keys(dictB).length) return false; for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { var key = keys_1[_i]; if (dictA[key] !== dictB[key]) return false; } return true; } var shallowCopy = exports.shallowCopy = function(thing) { var newThing = {}; for (var k in thing) { if (hasOwnProp(thing, k)) newThing[k] = thing[k]; } return newThing; } var deduplicateSort = exports.deduplicateSort = function(a) { a = a.sort(); var newA = []; var last = null; for (var _i = 0, a_1 = a; _i < a_1.length; _i++) { var v = a_1[_i]; if (v !== last) newA.push(v); last = v; } return newA; } var mapLookup = exports.mapLookup = function(thing, fn) { var newThing = Object.create(null); for (var k in thing) { if (hasOwnProp(thing, k)) newThing[k] = fn(thing[k]); } return newThing; } var emptyLookup = exports.emptyLookup = function(lookup) { for (var k in lookup) { if (hasOwnProp(lookup, k)) return false; } return true; } var nonEmptyLookup = exports.nonEmptyLookup = function(lookup) { return !emptyLookup(lookup); } var clip = exports.clip = function(x) { var rx = Math.round(x); return Math.abs(x - rx) < 1e-5 ? rx : x; } var safeAdd = exports.safeAdd = function(num, delta) { var stringDelta = String(delta); var dotIndex = stringDelta.indexOf('.'); if (dotIndex === -1 || stringDelta.length === 18) { return num + delta; } else { var scale = Math.pow(10, stringDelta.length - dotIndex - 1); return (num * scale + delta * scale) / scale; } } var safeRange = exports.safeRange = function(num, delta) { var stringDelta = String(delta); var dotIndex = stringDelta.indexOf('.'); if (dotIndex === -1 || stringDelta.length === 18) { return { start: num, end: num + delta, }; } else { var scale = Math.pow(10, stringDelta.length - dotIndex - 1); num = clip(num * scale) / scale; return { start: num, end: (num * scale + delta * scale) / scale, }; } } var continuousFloorExpression = exports.continuousFloorExpression = function(variable, floorFn, size, offset) { var expr = variable; if (offset !== 0) { expr = expr + ' - ' + offset; } if (offset !== 0 && size !== 1) { expr = '(' + expr + ')'; } if (size !== 1) { expr = expr + ' / ' + size; } expr = floorFn + '(' + expr + ')'; if (size !== 1) { expr = expr + ' * ' + size; } if (offset !== 0) { expr = expr + ' + ' + offset; } return expr; } var ExtendableError = (function (_super) { __extends(ExtendableError, _super); function ExtendableError(message) { var _this = _super.call(this, message) || this; _this.name = _this.constructor.name; _this.message = message; if (typeof Error.captureStackTrace === 'function') { Error.captureStackTrace(_this, _this.constructor); } else { _this.stack = new Error(message).stack; } return _this; } return ExtendableError; }(Error)); exports.ExtendableError = ExtendableError; var pluralIfNeeded = exports.pluralIfNeeded = function(n, thing) { return "".concat(n, " ").concat(thing).concat(n === 1 ? '' : 's'); } var pipeWithError = exports.pipeWithError = function(src, dest) { src.pipe(dest); src.on('error', function (e) { return dest.emit('error', e); }); return dest; } var handleNullCheckIfNeeded = exports.handleNullCheckIfNeeded = function(xs, nullCheck, andOr, fn) { if (!xs.length) { return andOr === 'AND' ? 'FALSE' : 'TRUE'; } var withoutNull = xs.filter(function (x) { return x != null; }); if (withoutNull.length === xs.length) { return fn(xs); } else if (withoutNull.length === 0) { return nullCheck; } else { return "(".concat(nullCheck, " ").concat(andOr, " ").concat(fn(withoutNull), ")"); } } var SQLDialect = (function () { function SQLDialect() { this.escapedTableName = null; } SQLDialect.prototype.setTable = function (name) { if (name) { this.escapedTableName = name.length === 1 ? name : this.escapeName(name); } else { this.escapedTableName = null; } }; SQLDialect.prototype.nullConstant = function () { return 'NULL'; }; SQLDialect.prototype.emptyGroupBy = function () { return "GROUP BY ''"; }; SQLDialect.prototype.escapeName = function (name) { name = name.replace(/"/g, '""'); return '"' + name + '"'; }; SQLDialect.prototype.maybeNamespacedName = function (name) { var escapedName = this.escapeName(name); if (this.escapedTableName) { return this.escapedTableName + '.' + escapedName; } else { return escapedName; } }; SQLDialect.prototype.escapeLiteral = function (name) { if (name === null) return this.nullConstant(); name = name.replace(/'/g, "''"); return "'" + name + "'"; }; SQLDialect.prototype.booleanToSQL = function (bool) { return ('' + bool).toUpperCase(); }; SQLDialect.prototype.ipToSQL = function (ip) { return ip.toString(); }; SQLDialect.prototype.floatDivision = function (numerator, denominator) { return "(".concat(numerator, "/").concat(denominator, ")"); }; SQLDialect.prototype.numberOrTimeToSQL = function (x) { if (x === null) return this.nullConstant(); if (x.toISOString) { return this.timeToSQL(x); } else { return this.numberToSQL(x); } }; SQLDialect.prototype.numberToSQL = function (num) { if (num === null) return this.nullConstant(); return '' + num; }; SQLDialect.prototype.dateToSQLDateString = function (date) { return date .toISOString() .replace('T', ' ') .replace('Z', '') .replace(/\.000$/, '') .replace(/ 00:00:00$/, ''); }; SQLDialect.prototype.aggregateFilterIfNeeded = function (inputSQL, expressionSQL, elseSQL) { if (elseSQL === void 0) { elseSQL = null; } var whereIndex = inputSQL.indexOf(' WHERE '); if (whereIndex === -1) return expressionSQL; var filterSQL = inputSQL.substr(whereIndex + 7); return this.ifThenElseExpression(filterSQL, expressionSQL, elseSQL); }; SQLDialect.prototype.concatExpression = function (_a, _b) { throw new Error('must implement'); }; SQLDialect.prototype.containsExpression = function (_a, _b, _insensitive) { throw new Error('must implement'); }; SQLDialect.prototype.mvContainsExpression = function (_a, _b) { throw new Error('must implement'); }; SQLDialect.prototype.mvFilterOnlyExpression = function (_a, _b) { throw new Error('must implement'); }; SQLDialect.prototype.mvOverlapExpression = function (_a, _b) { throw new Error('must implement'); }; SQLDialect.prototype.substrExpression = function (a, position, length) { return "SUBSTR(".concat(a, ",").concat(position + 1, ",").concat(length, ")"); }; SQLDialect.prototype.coalesceExpression = function (a, b) { return "COALESCE(".concat(a, ", ").concat(b, ")"); }; SQLDialect.prototype.countDistinctExpression = function (a, _parameterAttributeName) { return "COUNT(DISTINCT ".concat(a, ")"); }; SQLDialect.prototype.ifThenElseExpression = function (a, b, c) { var elsePart = typeof c === 'string' ? " ELSE ".concat(c) : ''; return "CASE WHEN ".concat(a, " THEN ").concat(b).concat(elsePart, " END"); }; SQLDialect.prototype.filterAggregatorExpression = function (aggregate, whereFilter) { var whereIndex = whereFilter.indexOf('WHERE'); return "".concat(aggregate).concat(whereIndex !== -1 ? "FILTER (".concat(whereFilter.substr(whereIndex), ")") : ''); }; SQLDialect.prototype.isNotDistinctFromExpression = function (a, b) { var nullConst = this.nullConstant(); if (a === nullConst) return "".concat(b, " IS ").concat(nullConst); if (b === nullConst) return "".concat(a, " IS ").concat(nullConst); return "(".concat(a, " IS NOT DISTINCT FROM ").concat(b, ")"); }; SQLDialect.prototype.regexpExpression = function (expression, regexp) { return "(".concat(expression, " REGEXP ").concat(this.escapeLiteral(regexp), ")"); }; SQLDialect.prototype.inExpression = function (operand, start, end, bounds) { if (start === end && bounds === '[]') return "".concat(operand, "=").concat(start); var startSQL = null; if (start !== this.nullConstant()) { startSQL = start + (bounds[0] === '[' ? '<=' : '<') + operand; } var endSQL = null; if (end !== this.nullConstant()) { endSQL = operand + (bounds[1] === ']' ? '<=' : '<') + end; } if (startSQL) { return endSQL ? "(".concat(startSQL, " AND ").concat(endSQL, ")") : startSQL; } else { return endSQL ? endSQL : 'TRUE'; } }; SQLDialect.prototype.lengthExpression = function (a) { return "CHAR_LENGTH(".concat(a, ")"); }; SQLDialect.prototype.quantileExpression = function (_str, _quantile, _parameterAttributeName) { throw new Error('dialect does not implement quantile'); }; SQLDialect.prototype.logExpression = function (base, operand) { if (base === String(Math.E)) return "LN(".concat(operand, ")"); return "LOG(".concat(base, ",").concat(operand, ")"); }; SQLDialect.prototype.lookupExpression = function (_base, _lookup) { throw new Error('can not express a lookup as a function'); }; SQLDialect.prototype.ipMatchExpression = function (_colName, _searchString, _ipSearchType) { throw new Error('must implement'); }; SQLDialect.prototype.ipSearchExpression = function (_colName, _searchString, _ipSearchType) { throw new Error('must implement'); }; SQLDialect.prototype.ipStringifyExpression = function (_operand) { throw new Error('must implement'); }; return SQLDialect; }()); exports.SQLDialect = SQLDialect; var MySQLDialect = (function (_super) { __extends(MySQLDialect, _super); function MySQLDialect() { return _super.call(this) || this; } MySQLDialect.prototype.escapeName = function (name) { name = name.replace(/`/g, '``'); return '`' + name + '`'; }; MySQLDialect.prototype.escapeLiteral = function (name) { if (name === null) return this.nullConstant(); return JSON.stringify(name); }; MySQLDialect.prototype.timeToSQL = function (date) { if (!date) return this.nullConstant(); return "TIMESTAMP('".concat(this.dateToSQLDateString(date), "')"); }; MySQLDialect.prototype.stringArrayToSQL = function (_value) { throw new Error('must implement'); }; MySQLDialect.prototype.concatExpression = function (a, b) { return "CONCAT(".concat(a, ",").concat(b, ")"); }; MySQLDialect.prototype.containsExpression = function (a, b, insensitive) { if (insensitive) { a = "LOWER(".concat(a, ")"); b = "LOWER(".concat(b, ")"); } return "LOCATE(".concat(b, ",").concat(a, ")>0"); }; MySQLDialect.prototype.isNotDistinctFromExpression = function (a, b) { return "(".concat(a, "<=>").concat(b, ")"); }; MySQLDialect.prototype.castExpression = function (inputType, operand, targetType) { var castFunction = MySQLDialect.CAST_TO_FUNCTION[targetType][inputType]; if (!castFunction) { throw new Error("unsupported cast from ".concat(inputType, " to ").concat(targetType, " in MySQL dialect")); } return castFunction.replace(/\$\$/g, operand); }; MySQLDialect.prototype.utcToWalltime = function (operand, timezone) { if (timezone.isUTC()) return operand; return "CONVERT_TZ(".concat(operand, ",'+0:00','").concat(timezone, "')"); }; MySQLDialect.prototype.walltimeToUTC = function (operand, timezone) { if (timezone.isUTC()) return operand; return "CONVERT_TZ(".concat(operand, ",'").concat(timezone, "','+0:00')"); }; MySQLDialect.prototype.timeFloorExpression = function (operand, duration, timezone) { var bucketFormat = MySQLDialect.TIME_BUCKETING[duration.toString()]; if (!bucketFormat) throw new Error("unsupported duration '".concat(duration, "'")); return this.walltimeToUTC("DATE_FORMAT(".concat(this.utcToWalltime(operand, timezone), ",'").concat(bucketFormat, "')"), timezone); }; MySQLDialect.prototype.timeBucketExpression = function (operand, duration, timezone) { return this.timeFloorExpression(operand, duration, timezone); }; MySQLDialect.prototype.timePartExpression = function (operand, part, timezone) { var timePartFunction = MySQLDialect.TIME_PART_TO_FUNCTION[part]; if (!timePartFunction) throw new Error("unsupported part ".concat(part, " in MySQL dialect")); return timePartFunction.replace(/\$\$/g, this.utcToWalltime(operand, timezone)); }; MySQLDialect.prototype.timeShiftExpression = function (operand, duration, step, _timezone) { if (step === 0) return operand; var sqlFn = step > 0 ? 'DATE_ADD(' : 'DATE_SUB('; var spans = duration.multiply(Math.abs(step)).valueOf(); if (spans.week) { return sqlFn + operand + ', INTERVAL ' + String(spans.week) + ' WEEK)'; } if (spans.year || spans.month) { var expr = String(spans.year || 0) + '-' + String(spans.month || 0); operand = sqlFn + operand + ", INTERVAL '" + expr + "' YEAR_MONTH)"; } if (spans.day || spans.hour || spans.minute || spans.second) { var expr = String(spans.day || 0) + ' ' + [spans.hour || 0, spans.minute || 0, spans.second || 0].join(':'); operand = sqlFn + operand + ", INTERVAL '" + expr + "' DAY_SECOND)"; } return operand; }; MySQLDialect.prototype.extractExpression = function (_operand, _regexp) { throw new Error('MySQL must implement extractExpression (https://github.com/mysqludf/lib_mysqludf_preg)'); }; MySQLDialect.prototype.indexOfExpression = function (str, substr) { return "LOCATE(".concat(substr, ", ").concat(str, ") - 1"); }; MySQLDialect.TIME_BUCKETING = { PT1S: '%Y-%m-%d %H:%i:%SZ', PT1M: '%Y-%m-%d %H:%i:00Z', PT1H: '%Y-%m-%d %H:00:00Z', P1D: '%Y-%m-%d 00:00:00Z', P1M: '%Y-%m-01 00:00:00Z', P1Y: '%Y-01-01 00:00:00Z', }; MySQLDialect.TIME_PART_TO_FUNCTION = { SECOND_OF_MINUTE: 'SECOND($$)', SECOND_OF_HOUR: '(MINUTE($$)*60+SECOND($$))', SECOND_OF_DAY: '((HOUR($$)*60+MINUTE($$))*60+SECOND($$))', SECOND_OF_WEEK: '(((WEEKDAY($$)*24)+HOUR($$)*60+MINUTE($$))*60+SECOND($$))', SECOND_OF_MONTH: '((((DAYOFMONTH($$)-1)*24)+HOUR($$)*60+MINUTE($$))*60+SECOND($$))', SECOND_OF_YEAR: '((((DAYOFYEAR($$)-1)*24)+HOUR($$)*60+MINUTE($$))*60+SECOND($$))', MINUTE_OF_HOUR: 'MINUTE($$)', MINUTE_OF_DAY: 'HOUR($$)*60+MINUTE($$)', MINUTE_OF_WEEK: '(WEEKDAY($$)*24)+HOUR($$)*60+MINUTE($$)', MINUTE_OF_MONTH: '((DAYOFMONTH($$)-1)*24)+HOUR($$)*60+MINUTE($$)', MINUTE_OF_YEAR: '((DAYOFYEAR($$)-1)*24)+HOUR($$)*60+MINUTE($$)', HOUR_OF_DAY: 'HOUR($$)', HOUR_OF_WEEK: '(WEEKDAY($$)*24+HOUR($$))', HOUR_OF_MONTH: '((DAYOFMONTH($$)-1)*24+HOUR($$))', HOUR_OF_YEAR: '((DAYOFYEAR($$)-1)*24+HOUR($$))', DAY_OF_WEEK: '(WEEKDAY($$)+1)', DAY_OF_MONTH: 'DAYOFMONTH($$)', DAY_OF_YEAR: 'DAYOFYEAR($$)', WEEK_OF_YEAR: 'WEEK($$)', MONTH_OF_YEAR: 'MONTH($$)', YEAR: 'YEAR($$)', }; MySQLDialect.CAST_TO_FUNCTION = { TIME: { NUMBER: 'FROM_UNIXTIME($$ / 1000)', }, NUMBER: { TIME: 'UNIX_TIMESTAMP($$) * 1000', STRING: 'CAST($$ AS SIGNED)', }, STRING: { NUMBER: 'CAST($$ AS CHAR)', }, }; return MySQLDialect; }(SQLDialect)); exports.MySQLDialect = MySQLDialect; var PostgresDialect = (function (_super) { __extends(PostgresDialect, _super); function PostgresDialect() { return _super.call(this) || this; } PostgresDialect.prototype.emptyGroupBy = function () { return "GROUP BY ''=''"; }; PostgresDialect.prototype.timeToSQL = function (date) { if (!date) return this.nullConstant(); return "TIMESTAMP '".concat(this.dateToSQLDateString(date), "'"); }; PostgresDialect.prototype.stringArrayToSQL = function (_value) { throw new Error('must implement'); }; PostgresDialect.prototype.concatExpression = function (a, b) { return "(".concat(a, "||").concat(b, ")"); }; PostgresDialect.prototype.containsExpression = function (a, b, insensitive) { if (insensitive) { a = "LOWER(".concat(a, ")"); b = "LOWER(".concat(b, ")"); } return "POSITION(".concat(b, " IN ").concat(a, ")>0"); }; PostgresDialect.prototype.regexpExpression = function (expression, regexp) { return "(".concat(expression, " ~ '").concat(regexp, "')"); }; PostgresDialect.prototype.castExpression = function (inputType, operand, targetType) { var castFunction = PostgresDialect.CAST_TO_FUNCTION[targetType][inputType]; if (!castFunction) { throw new Error("unsupported cast from ".concat(inputType, " to ").concat(targetType, " in Postgres dialect")); } return castFunction.replace(/\$\$/g, operand); }; PostgresDialect.prototype.utcToWalltime = function (operand, timezone) { if (timezone.isUTC()) return operand; return "(".concat(operand, " AT TIME ZONE 'UTC' AT TIME ZONE '").concat(timezone, "')"); }; PostgresDialect.prototype.walltimeToUTC = function (operand, timezone) { if (timezone.isUTC()) return operand; return "(".concat(operand, " AT TIME ZONE '").concat(timezone, "' AT TIME ZONE 'UTC')"); }; PostgresDialect.prototype.timeFloorExpression = function (operand, duration, timezone) { var bucketFormat = PostgresDialect.TIME_BUCKETING[duration.toString()]; if (!bucketFormat) throw new Error("unsupported duration '".concat(duration, "'")); return this.walltimeToUTC("DATE_TRUNC('".concat(bucketFormat, "',").concat(this.utcToWalltime(operand, timezone), ")"), timezone); }; PostgresDialect.prototype.timeBucketExpression = function (operand, duration, timezone) { return this.timeFloorExpression(operand, duration, timezone); }; PostgresDialect.prototype.timePartExpression = function (operand, part, timezone) { var timePartFunction = PostgresDialect.TIME_PART_TO_FUNCTION[part]; if (!timePartFunction) throw new Error("unsupported part ".concat(part, " in Postgres dialect")); return timePartFunction.replace(/\$\$/g, this.utcToWalltime(operand, timezone)); }; PostgresDialect.prototype.timeShiftExpression = function (operand, duration, step, _timezone) { if (step === 0) return operand; var sqlFn = step > 0 ? 'DATE_ADD(' : 'DATE_SUB('; var spans = duration.multiply(Math.abs(step)).valueOf(); if (spans.week) { return sqlFn + operand + ', INTERVAL ' + String(spans.week) + ' WEEK)'; } if (spans.year || spans.month) { var expr = String(spans.year || 0) + '-' + String(spans.month || 0); operand = sqlFn + operand + ", INTERVAL '" + expr + "' YEAR_MONTH)"; } if (spans.day || spans.hour || spans.minute || spans.second) { var expr = String(spans.day || 0) + ' ' + [spans.hour || 0, spans.minute || 0, spans.second || 0].join(':'); operand = sqlFn + operand + ", INTERVAL '" + expr + "' DAY_SECOND)"; } return operand; }; PostgresDialect.prototype.extractExpression = function (operand, regexp) { return "(SELECT (REGEXP_MATCHES(".concat(operand, ", '").concat(regexp, "'))[1])"); }; PostgresDialect.prototype.indexOfExpression = function (str, substr) { return "POSITION(".concat(substr, " IN ").concat(str, ") - 1"); }; PostgresDialect.TIME_BUCKETING = { PT1S: 'second', PT1M: 'minute', PT1H: 'hour', P1D: 'day', P1W: 'week', P1M: 'month', P3M: 'quarter', P1Y: 'year', }; PostgresDialect.TIME_PART_TO_FUNCTION = { SECOND_OF_MINUTE: "DATE_PART('second',$$)", SECOND_OF_HOUR: "(DATE_PART('minute',$$)*60+DATE_PART('second',$$))", SECOND_OF_DAY: "((DATE_PART('hour',$$)*60+DATE_PART('minute',$$))*60+DATE_PART('second',$$))", SECOND_OF_WEEK: "((((CAST((DATE_PART('dow',$$)+6) AS int)%7)*24)+DATE_PART('hour',$$)*60+DATE_PART('minute',$$))*60+DATE_PART('second',$$))", SECOND_OF_MONTH: "((((DATE_PART('day',$$)-1)*24)+DATE_PART('hour',$$)*60+DATE_PART('minute',$$))*60+DATE_PART('second',$$))", SECOND_OF_YEAR: "((((DATE_PART('doy',$$)-1)*24)+DATE_PART('hour',$$)*60+DATE_PART('minute',$$))*60+DATE_PART('second',$$))", MINUTE_OF_HOUR: "DATE_PART('minute',$$)", MINUTE_OF_DAY: "DATE_PART('hour',$$)*60+DATE_PART('minute',$$)", MINUTE_OF_WEEK: "((CAST((DATE_PART('dow',$$)+6) AS int)%7)*24)+DATE_PART('hour',$$)*60+DATE_PART('minute',$$)", MINUTE_OF_MONTH: "((DATE_PART('day',$$)-1)*24)+DATE_PART('hour',$$)*60+DATE_PART('minute',$$)", MINUTE_OF_YEAR: "((DATE_PART('doy',$$)-1)*24)+DATE_PART('hour',$$)*60+DATE_PART('minute',$$)", HOUR_OF_DAY: "DATE_PART('hour',$$)", HOUR_OF_WEEK: "((CAST((DATE_PART('dow',$$)+6) AS int)%7)*24+DATE_PART('hour',$$))", HOUR_OF_MONTH: "((DATE_PART('day',$$)-1)*24+DATE_PART('hour',$$))", HOUR_OF_YEAR: "((DATE_PART('doy',$$)-1)*24+DATE_PART('hour',$$))", DAY_OF_WEEK: "(CAST((DATE_PART('dow',$$)+6) AS int)%7)+1", DAY_OF_MONTH: "DATE_PART('day',$$)", DAY_OF_YEAR: "DATE_PART('doy',$$)", WEEK_OF_YEAR: "DATE_PART('week',$$)", MONTH_OF_YEAR: "DATE_PART('month',$$)", YEAR: "DATE_PART('year',$$)", }; PostgresDialect.CAST_TO_FUNCTION = { TIME: { NUMBER: 'TO_TIMESTAMP($$::double precision / 1000)', }, NUMBER: { TIME: 'EXTRACT(EPOCH FROM $$) * 1000', STRING: '$$::float', }, STRING: { NUMBER: '$$::text', }, }; return PostgresDialect; }(SQLDialect)); exports.PostgresDialect = PostgresDialect; var DruidDialect = (function (_super) { __extends(DruidDialect, _super); function DruidDialect(options) { if (options === void 0) { options = {}; } var _this = _super.call(this) || this; _this.attributes = options.attributes; return _this; } DruidDialect.prototype.dateToSQLDateString = function (date) { return date .toISOString() .replace('T', ' ') .replace('Z', '') .replace(/\.000$/, ''); }; DruidDialect.prototype.floatDivision = function (numerator, denominator) { return "(".concat(numerator, "*1.0/").concat(denominator, ")"); }; DruidDialect.prototype.emptyGroupBy = function () { return 'GROUP BY ()'; }; DruidDialect.prototype.timeToSQL = function (date) { if (!date) return this.nullConstant(); return "TIMESTAMP '".concat(this.dateToSQLDateString(date), "'"); }; DruidDialect.prototype.stringArrayToSQL = function (value) { var _this = this; var arr = value.map(function (v) { return _this.escapeLiteral(v); }); return "ARRAY[".concat(arr.join(','), "]"); }; DruidDialect.prototype.ipParse = function (value) { return "IP_PARSE(".concat(value, ")"); }; DruidDialect.prototype.ipPrefixParse = function (value) { return "IP_PREFIX_PARSE(".concat(value, ")"); }; DruidDialect.prototype.concatExpression = function (a, b) { return "(".concat(a, "||").concat(b, ")"); }; DruidDialect.prototype.containsExpression = function (a, b, insensitive) { return "".concat(insensitive ? 'ICONTAINS_STRING' : 'CONTAINS_STRING', "(CAST(").concat(a, " AS VARCHAR),").concat(b, ")"); }; DruidDialect.prototype.mvContainsExpression = function (a, b) { return "MV_CONTAINS(".concat(a, ", ").concat(this.stringArrayToSQL(b), ")"); }; DruidDialect.prototype.mvFilterOnlyExpression = function (a, b) { return "MV_FILTER_ONLY(".concat(a, ", ").concat(this.stringArrayToSQL(b), ")"); }; DruidDialect.prototype.mvOverlapExpression = function (a, b) { return "MV_OVERLAP(".concat(a, ", ").concat(this.stringArrayToSQL(b), ")"); }; DruidDialect.prototype.substrExpression = function (a, position, length) { return "SUBSTRING(".concat(a, ",").concat(position + 1, ",").concat(length, ")"); }; DruidDialect.prototype.countDistinctExpression = function (a, parameterAttributeName) { var attribute = NamedArray.findByName(this.attributes || [], parameterAttributeName); var nativeType = attribute ? attribute.nativeType : undefined; switch (nativeType) { case 'HLLSketch': return "APPROX_COUNT_DISTINCT_DS_HLL(".concat(a, ")"); case 'thetaSketch': return "APPROX_COUNT_DISTINCT_DS_THETA(".concat(a, ")"); case 'hyperUnique': return "APPROX_COUNT_DISTINCT(".concat(a, ")"); default: return "COUNT(DISTINCT ".concat(a, ")"); } }; DruidDialect.prototype.isNotDistinctFromExpression = function (a, b) { var nullConst = this.nullConstant(); if (a === nullConst) return "".concat(b, " IS ").concat(nullConst); if (b === nullConst) return "".concat(a, " IS ").concat(nullConst); return "(".concat(a, "=").concat(b, ")"); }; DruidDialect.prototype.castExpression = function (inputType, operand, targetType) { if (targetType === 'SET/STRING') targetType = 'STRING'; if (inputType === targetType) return operand; var castForInput = DruidDialect.CAST_TO_FUNCTION[targetType]; var castFunction = castForInput[inputType || '_'] || castForInput['_']; if (!castFunction) { throw new Error("unsupported cast from ".concat(inputType || 'unknown', " to ").concat(targetType, " in Druid dialect")); } return castFunction.replace(/\$\$/g, operand); }; DruidDialect.prototype.operandAsTimestamp = function (operand) { return operand.includes('__time') ? operand : "CAST(".concat(operand, " AS TIMESTAMP)"); }; DruidDialect.prototype.timeFloorExpression = function (operand, duration, timezone) { return "TIME_FLOOR(".concat(this.operandAsTimestamp(operand), ", ").concat(this.escapeLiteral(duration.toString()), ", NULL, ").concat(this.escapeLiteral(timezone.toString()), ")"); }; DruidDialect.prototype.timeBucketExpression = function (operand, duration, timezone) { return this.timeFloorExpression(operand, duration, timezone); }; DruidDialect.prototype.timePartExpression = function (operand, part, timezone) { var timePartFunction = DruidDialect.TIME_PART_TO_FUNCTION[part]; if (!timePartFunction) throw new Error("unsupported part ".concat(part, " in Druid dialect")); return timePartFunction .replace(/\$\$/g, this.operandAsTimestamp(operand)) .replace(/##/g, this.escapeLiteral(timezone.toString())); }; DruidDialect.prototype.timeShiftExpression = function (operand, duration, step, timezone) { return "TIME_SHIFT(".concat(this.operandAsTimestamp(operand), ", ").concat(this.escapeLiteral(duration.toString()), ", ").concat(step, ", ").concat(this.escapeLiteral(timezone.toString()), ")"); }; DruidDialect.prototype.extractExpression = function (operand, regexp) { return "REGEXP_EXTRACT(CAST(".concat(operand, " AS VARCHAR), ").concat(this.escapeLiteral(regexp), ", 1)"); }; DruidDialect.prototype.regexpExpression = function (expression, regexp) { return "REGEXP_LIKE(CAST(".concat(expression, " AS VARCHAR), ").concat(this.escapeLiteral(regexp), ")"); }; DruidDialect.prototype.indexOfExpression = function (str, substr) { return "POSITION(".concat(substr, " IN ").concat(str, ") - 1"); }; DruidDialect.prototype.quantileExpression = function (str, quantile, parameterAttributeName) { var attribute = NamedArray.findByName(this.attributes || [], parameterAttributeName); var nativeType = attribute ? attribute.nativeType : undefined; switch (nativeType) { case 'approximateHistogram': return "APPROX_QUANTILE(".concat(str, ", ").concat(quantile, ")"); default: return "APPROX_QUANTILE_DS(".concat(str, ", ").concat(quantile, ")"); } }; DruidDialect.prototype.logExpression = function (base, operand) { if (base === String(Math.E)) return "LN(".concat(operand, ")"); if (base === '10') return "LOG10(".concat(operand, ")"); return "LN(".concat(operand, ")/LN(").concat(base, ")"); }; DruidDialect.prototype.lookupExpression = function (base, lookup) { return "LOOKUP(".concat(base, ", ").concat(this.escapeLiteral(lookup), ")"); }; DruidDialect.prototype.ipMatchExpression = function (columnName, searchString, ipSearchType) { return ipSearchType === 'ipPrefix' ? "IP_MATCH(".concat(this.escapeLiteral(searchString.toString()), ", ").concat(columnName, ")") : "IP_MATCH(".concat(columnName, ", ").concat(this.escapeLiteral(searchString.toString()), ")"); }; DruidDialect.prototype.ipSearchExpression = function (columnName, searchString, ipSearchType) { return ipSearchType === 'ipPrefix' ? "IP_SEARCH(".concat(this.escapeLiteral(searchString.toString()), ", ").concat(columnName, ")") : "IP_SEARCH(".concat(columnName, ", ").concat(this.escapeLiteral(searchString.toString()), ")"); }; DruidDialect.prototype.ipStringifyExpression = function (operand) { return "IP_STRINGIFY(".concat(operand, ")"); }; DruidDialect.TIME_PART_TO_FUNCTION = { SECOND_OF_MINUTE: "TIME_EXTRACT($$,'SECOND',##)", SECOND_OF_HOUR: "(TIME_EXTRACT($$,'MINUTE',##)*60+TIME_EXTRACT($$,'SECOND',##))", SECOND_OF_DAY: "((TIME_EXTRACT($$,'HOUR',##)*60+TIME_EXTRACT($$,'MINUTE',##))*60+TIME_EXTRACT($$,'SECOND',##))", SECOND_OF_WEEK: "(((MOD(CAST((TIME_EXTRACT($$,'DOW',##)+6) AS int),7)*24)+TIME_EXTRACT($$,'HOUR',##)*60+TIME_EXTRACT($$,'MINUTE',##))*60+TIME_EXTRACT($$,'SECOND',##))", SECOND_OF_MONTH: "((((TIME_EXTRACT($$,'DAY',##)-1)*24)+TIME_EXTRACT($$,'HOUR',##)*60+TIME_EXTRACT($$,'MINUTE',##))*60+TIME_EXTRACT($$,'SECOND',##))", SECOND_OF_YEAR: "((((TIME_EXTRACT($$,'DOY',##)-1)*24)+TIME_EXTRACT($$,'HOUR',##)*60+TIME_EXTRACT($$,'MINUTE',##))*60+TIME_EXTRACT($$,'SECOND',##))", MINUTE_OF_HOUR: "TIME_EXTRACT($$,'MINUTE',##)", MINUTE_OF_DAY: "TIME_EXTRACT($$,'HOUR',##)*60+TIME_EXTRACT($$,'MINUTE',##)", MINUTE_OF_WEEK: "(MOD(CAST((TIME_EXTRACT($$,'DOW',##)+6) AS int),7)*24)+TIME_EXTRACT($$,'HOUR',##)*60+TIME_EXTRACT($$,'MINUTE',##)", MINUTE_OF_MONTH: "((TIME_EXTRACT($$,'DAY',##)-1)*24)+TIME_EXTRACT($$,'HOUR',##)*60+TIME_EXTRACT($$,'MINUTE',##)", MINUTE_OF_YEAR: "((TIME_EXTRACT($$,'DOY',##)-1)*24)+TIME_EXTRACT($$,'HOUR',##)*60+TIME_EXTRACT($$,'MINUTE',##)", HOUR_OF_DAY: "TIME_EXTRACT($$,'HOUR',##)", HOUR_OF_WEEK: "(MOD(CAST((TIME_EXTRACT($$,'DOW',##)+6) AS int),7)*24+TIME_EXTRACT($$,'HOUR',##))", HOUR_OF_MONTH: "((TIME_EXTRACT($$,'DAY',##)-1)*24+TIME_EXTRACT($$,'HOUR',##))", HOUR_OF_YEAR: "((TIME_EXTRACT($$,'DOY',##)-1)*24+TIME_EXTRACT($$,'HOUR',##))", DAY_OF_WEEK: "MOD(CAST((TIME_EXTRACT($$,'DOW',##)+6) AS int),7)+1", DAY_OF_MONTH: "TIME_EXTRACT($$,'DAY',##)", DAY_OF_YEAR: "TIME_EXTRACT($$,'DOY',##)", WEEK_OF_YEAR: "TIME_EXTRACT($$,'WEEK',##)", MONTH_OF_YEAR: "TIME_EXTRACT($$,'MONTH',##)", YEAR: "TIME_EXTRACT($$,'YEAR',##)", }; DruidDialect.CAST_TO_FUNCTION = { TIME: { NUMBER: 'MILLIS_TO_TIMESTAMP(CAST($$ AS BIGINT))', _: 'CAST($$ AS TIMESTAMP)', }, NUMBER: { TIME: 'CAST($$ AS BIGINT)', STRING: 'CAST($$ AS DOUBLE)', _: 'CAST($$ AS DOUBLE)', }, STRING: { NUMBER: 'CAST($$ AS VARCHAR)', _: 'CAST($$ AS VARCHAR)', }, BOOLEAN: { NUMBER: '($$ = 1)', STRING: "($$ = 'true')", _: "(CAST($$ AS VARCHAR) IN ('1','true'))", }, }; return DruidDialect; }(SQLDialect)); exports.DruidDialect = DruidDialect; var getValueType = exports.getValueType = function(value) { var typeofValue = typeof value; if (typeofValue === 'object') { if (value === null) { return 'NULL'; } else if (isDate(value)) { return 'TIME'; } else if (hasOwnProp(value, 'ip') && Ip.isIp(value.ip)) { return 'IP'; } else if (hasOwnProp(value, 'start') && hasOwnProp(value, 'end')) { if (isDate(value.start) || isDate(value.end)) return 'TIME_RANGE'; if (typeof value.start === 'number' || typeof value.end === 'number') return 'NUMBER_RANGE'; if (typeof value.start === 'string' || typeof value.end === 'string') return 'STRING_RANGE'; throw new Error('unrecognizable range'); } else { var ctrType = value.constructor.type; if (!ctrType) { if (value instanceof Expression) { throw new Error("expression used as datum value ".concat(value)); } else { throw new Error("can not have an object without a type: ".concat(JSON.stringify(value))); } } if (ctrType === 'SET') ctrType += '/' + value.setType; return ctrType; } } else { if (typeofValue !== 'boolean' && typeofValue !== 'number' && typeofValue !== 'string') { throw new TypeError('unsupported JS type ' + typeofValue); } return typeofValue.toUpperCase(); } } var getFullType = exports.getFullType = function(value) { var myType = getValueType(value); return myType === 'DATASET' ? value.getFullType() : { type: myType }; } var getFullTypeFromDatum = exports.getFullTypeFromDatum = function(datum) { var datasetType = {}; for (var k in datum) { if (!hasOwnProp(datum, k)) continue; datasetType[k] = getFullType(datum[k]); } return { type: 'DATASET', datasetType: datasetType, }; } function timeFromJS(v) { switch (typeof v) { case 'string': case 'number': return new Date(v); case 'object': if (v.toISOString) return v; if (v === null) return null; if (v.value) return new Date(v.value); throw new Error("can not interpret ".concat(JSON.stringify(v), " as TIME")); default: throw new Error("can not interpret ".concat(v, " as TIME")); } } var valueFromJS = exports.valueFromJS = function(v, typeOverride) { if (typeOverride === void 0) { typeOverride = null; } if (v == null) { return null; } else if (Array.isArray(v)) { if (v.length && typeof v[0] !== 'object') { return Set.fromJS(v); } else { return Dataset.fromJS(v); } } else { var typeofV = typeof v; if (typeofV === 'object') { switch (typeOverride || v.type) { case 'NUMBER': { var n = Number(v.value); if (isNaN(n)) throw new Error("bad number value '".concat(v.value, "'")); return n; } case 'NUMBER_RANGE': return NumberRange.fromJS(v); case 'STRING_RANGE': return StringRange.fromJS(v); case 'IP': return Ip.fromJS(v); case 'TIME': return timeFromJS(v); case 'TIME_RANGE': return TimeRange.fromJS(v); case 'SET': return Set.fromJS(v); case 'DATASET': return Dataset.fromJS(v); default: if (String(typeOverride).indexOf('SET') === 0 || Array.isArray(v.elements)) { return Set.fromJS(v); } if (v.toISOString) { return v; } if (typeOverride) { throw new Error("unknown type ".concat(typeOverride, " on ").concat(JSON.stringify(v))); } else { throw new Error("can not have an object without a 'type' as a datum value: ".concat(JSON.stringify(v))); } } } else if (typeofV === 'string' && typeOverride === 'TIME') { return new Date(v); } else if (typeofV === 'number' && isNaN(v)) { return null; } } return v; } var valueToJS = exports.valueToJS = function(v) { if (v == null) { return null; } else { var typeofV = typeof v; if (typeofV === 'object') { if (v.toISOString) { return v; } else if (v.toJS) { return v.toJS(); } else { throw new Error("can not convert ".concat(JSON.stringify(v), " to JS")); } } else if (typeofV === 'number' && !isFinite(v)) { return String(v); } } return v; } var datumHasExternal = exports.datumHasExternal = function(datum) { for (var name_1 in datum) { var value = datum[name_1]; if (value instanceof External) return true; if (value instanceof Dataset && value.hasExternal()) return true; } return false; } var introspectDatum = exports.introspectDatum = function(datum) { var promises = []; var newDatum = Object.create(null); Object.keys(datum).forEach(function (name) { var v = datum[name]; if (v instanceof External && v.needsIntrospect()) { promises.push(v.introspect().then(function (introspectedExter