UNPKG

plywood

Version:
299 lines (298 loc) 13.2 kB
import { CastExpression, ConcatExpression, CustomTransformExpression, ExtractExpression, FallbackExpression, LengthExpression, LiteralExpression, LookupExpression, NumberBucketExpression, OverlapExpression, r, RefExpression, SubstrExpression, TimeBucketExpression, TimeFloorExpression, TimePartExpression, TransformCaseExpression, } from '../../expressions'; var DruidExtractionFnBuilder = (function () { function DruidExtractionFnBuilder(options) { this.customTransforms = options.customTransforms; } DruidExtractionFnBuilder.composeFns = function (f, g) { if (!f || !g) return f || g; return { type: 'cascade', extractionFns: [].concat(f.type === 'cascade' ? f.extractionFns : f, g.type === 'cascade' ? g.extractionFns : g), }; }; DruidExtractionFnBuilder.getLastFn = function (fn) { if (fn && fn.type === 'cascade') { var extractionFns = fn.extractionFns; return extractionFns[extractionFns.length - 1]; } else { return fn; } }; DruidExtractionFnBuilder.prototype.expressionToExtractionFn = function (expression) { var freeReferences = expression.getFreeReferences(); if (freeReferences.length > 1) { throw new Error("must have at most 1 reference (has ".concat(freeReferences.length, "): ").concat(expression)); } if (expression instanceof LiteralExpression) { return this.literalToExtractionFn(expression); } else if (expression instanceof RefExpression) { return this.refToExtractionFn(expression); } else if (expression instanceof ConcatExpression) { return this.concatToExtractionFn(expression); } else if (expression instanceof CustomTransformExpression) { return this.customTransformToExtractionFn(expression); } else if (expression instanceof NumberBucketExpression) { return this.numberBucketToExtractionFn(expression); } else if (expression instanceof SubstrExpression) { return this.substrToExtractionFn(expression); } else if (expression instanceof TimeBucketExpression || expression instanceof TimeFloorExpression) { return this.timeFloorToExtractionFn(expression); } else if (expression instanceof TimePartExpression) { return this.timePartToExtractionFn(expression); } else if (expression instanceof TransformCaseExpression) { return this.transformCaseToExtractionFn(expression); } else if (expression instanceof LengthExpression) { return this.lengthToExtractionFn(expression); } else if (expression instanceof ExtractExpression) { return this.extractToExtractionFn(expression); } else if (expression instanceof LookupExpression) { return this.lookupToExtractionFn(expression); } else if (expression instanceof FallbackExpression) { return this.fallbackToExtractionFn(expression); } else if (expression instanceof CastExpression) { return this.castToExtractionFn(expression); } else if (expression instanceof OverlapExpression) { return this.overlapToExtractionFn(expression); } else { throw new Error("can not convert ".concat(expression, " to extractionFn")); } }; DruidExtractionFnBuilder.prototype.literalToExtractionFn = function (expression) { return { type: 'lookup', retainMissingValue: false, replaceMissingValueWith: expression.getLiteralValue(), lookup: { type: 'map', map: {}, }, }; }; DruidExtractionFnBuilder.prototype.refToExtractionFn = function (expression) { if (expression.type === 'BOOLEAN') { return { type: 'lookup', lookup: { type: 'map', map: { '0': 'false', '1': 'true', 'false': 'false', 'true': 'true', }, }, }; } else { return null; } }; DruidExtractionFnBuilder.prototype.concatToExtractionFn = function (expression) { var innerExpression = null; var format = expression .getExpressionList() .map(function (ex) { if (ex instanceof LiteralExpression) { return ex.value.replace(/%/g, '\\%'); } if (innerExpression) { throw new Error("can not have multiple expressions in concat '".concat(expression, "'")); } innerExpression = ex; return '%s'; }) .join(''); if (!innerExpression) throw new Error("invalid concat expression '".concat(expression, "'")); return DruidExtractionFnBuilder.composeFns(this.expressionToExtractionFn(innerExpression), { type: 'stringFormat', format: format, nullHandling: 'returnNull', }); }; DruidExtractionFnBuilder.prototype.timeFloorToExtractionFn = function (expression) { var operand = expression.operand, duration = expression.duration; var timezone = expression.getTimezone(); var myExtractionFn = { type: 'timeFormat', granularity: { type: 'period', period: duration.toString(), timeZone: timezone.toString(), }, format: "yyyy-MM-dd'T'HH:mm:ss'Z", timeZone: 'Etc/UTC', }; return DruidExtractionFnBuilder.composeFns(this.expressionToExtractionFn(operand), myExtractionFn); }; DruidExtractionFnBuilder.prototype.timePartToExtractionFn = function (expression) { var operand = expression.operand, part = expression.part; var timezone = expression.getTimezone(); var myExtractionFn; var format = DruidExtractionFnBuilder.TIME_PART_TO_FORMAT[part]; if (format) { myExtractionFn = { type: 'timeFormat', format: format, locale: 'en-US', timeZone: timezone.toString(), }; } else { throw new Error("can not part on ".concat(part)); } return DruidExtractionFnBuilder.composeFns(this.expressionToExtractionFn(operand), myExtractionFn); }; DruidExtractionFnBuilder.prototype.numberBucketToExtractionFn = function (expression) { var operand = expression.operand, size = expression.size, offset = expression.offset; var bucketExtractionFn = { type: 'bucket' }; if (size !== 1) bucketExtractionFn.size = size; if (offset !== 0) bucketExtractionFn.offset = offset; return DruidExtractionFnBuilder.composeFns(this.expressionToExtractionFn(operand), bucketExtractionFn); }; DruidExtractionFnBuilder.prototype.substrToExtractionFn = function (expression) { var operand = expression.operand, position = expression.position, len = expression.len; return DruidExtractionFnBuilder.composeFns(this.expressionToExtractionFn(operand), { type: 'substring', index: position, length: len, }); }; DruidExtractionFnBuilder.prototype.transformCaseToExtractionFn = function (expression) { var operand = expression.operand, transformType = expression.transformType; var type = DruidExtractionFnBuilder.CASE_TO_DRUID[transformType]; if (!type) throw new Error("unsupported case transformation '".concat(type, "'")); return DruidExtractionFnBuilder.composeFns(this.expressionToExtractionFn(operand), { type: type, }); }; DruidExtractionFnBuilder.prototype.lengthToExtractionFn = function (expression) { var operand = expression.operand; return DruidExtractionFnBuilder.composeFns(this.expressionToExtractionFn(operand), { type: 'strlen', }); }; DruidExtractionFnBuilder.prototype.extractToExtractionFn = function (expression) { var operand = expression.operand, regexp = expression.regexp; return DruidExtractionFnBuilder.composeFns(this.expressionToExtractionFn(operand), { type: 'regex', expr: regexp, replaceMissingValue: true, }); }; DruidExtractionFnBuilder.prototype.lookupToExtractionFn = function (expression) { var operand = expression.operand, lookupFn = expression.lookupFn; var lookupExtractionFn = { type: 'registeredLookup', lookup: lookupFn, }; return DruidExtractionFnBuilder.composeFns(this.expressionToExtractionFn(operand), lookupExtractionFn); }; DruidExtractionFnBuilder.prototype.fallbackToExtractionFn = function (expression) { var operand = expression.operand, fallback = expression.expression; if (operand instanceof ExtractExpression) { var extractExtractionFn = this.extractToExtractionFn(operand); var extractExtractionFnLast = DruidExtractionFnBuilder.getLastFn(extractExtractionFn); if (fallback.isOp('ref')) { delete extractExtractionFnLast.replaceMissingValue; } else if (fallback.isOp('literal')) { extractExtractionFnLast.replaceMissingValueWith = fallback.getLiteralValue(); } else { throw new Error("unsupported fallback: ".concat(expression)); } return extractExtractionFn; } else if (operand instanceof LookupExpression) { var lookupExtractionFn = this.lookupToExtractionFn(operand); var lookupExtractionFnLast = DruidExtractionFnBuilder.getLastFn(lookupExtractionFn); if (fallback.isOp('ref')) { lookupExtractionFnLast.retainMissingValue = true; } else if (fallback.isOp('literal')) { lookupExtractionFnLast.replaceMissingValueWith = fallback.getLiteralValue(); } else { throw new Error("unsupported fallback: ".concat(expression)); } return lookupExtractionFn; } if (fallback instanceof LiteralExpression) { throw new Error("cant handle direct fallback: ".concat(expression)); } throw new Error("can not convert fallback ".concat(expression, " to extractionFn")); }; DruidExtractionFnBuilder.prototype.customTransformToExtractionFn = function (customTransform) { var operand = customTransform.operand, custom = customTransform.custom; var customExtractionFn = this.customTransforms[custom]; if (!customExtractionFn) throw new Error("could not find extraction function: '".concat(custom, "'")); var extractionFn = customExtractionFn.extractionFn; if (typeof extractionFn.type !== 'string') throw new Error("must have type in custom extraction fn '".concat(custom, "'")); try { JSON.parse(JSON.stringify(customExtractionFn)); } catch (e) { throw new Error("must have JSON extraction Fn '".concat(custom, "'")); } return DruidExtractionFnBuilder.composeFns(this.expressionToExtractionFn(operand), extractionFn); }; DruidExtractionFnBuilder.prototype.castToExtractionFn = function (cast) { if (cast.outputType === 'TIME') { throw new Error("can not convert cast ".concat(cast, " to extractionFn")); } return this.expressionToExtractionFn(cast.operand); }; DruidExtractionFnBuilder.prototype.overlapToExtractionFn = function (expression) { var freeReferences = expression.operand.getFreeReferences(); var rhsType = expression.expression.type; if (freeReferences[0] === '__time' && expression.expression instanceof LiteralExpression && (rhsType === 'TIME_RANGE' || rhsType === 'SET/TIME_RANGE')) { expression = expression.operand .cast('NUMBER') .overlap(r(expression.expression.getLiteralValue().changeToNumber())); } throw new Error("can not convert overlap ".concat(expression, " to extractionFn")); }; DruidExtractionFnBuilder.CASE_TO_DRUID = { upperCase: 'upper', lowerCase: 'lower', }; DruidExtractionFnBuilder.TIME_PART_TO_FORMAT = { SECOND_OF_MINUTE: 's', MINUTE_OF_HOUR: 'm', HOUR_OF_DAY: 'H', DAY_OF_WEEK: 'e', DAY_OF_MONTH: 'd', DAY_OF_YEAR: 'D', WEEK_OF_YEAR: 'w', MONTH_OF_YEAR: 'M', YEAR: 'Y', }; return DruidExtractionFnBuilder; }()); export { DruidExtractionFnBuilder };