UNPKG

ddl-manager

Version:

store postgres procedures and triggers in files

302 lines 11.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Expression = void 0; const Operator_1 = require("./Operator"); const FuncCall_1 = require("./FuncCall"); const AbstractExpressionElement_1 = require("./AbstractExpressionElement"); const UnknownExpressionElement_1 = require("./UnknownExpressionElement"); const ColumnReference_1 = require("./ColumnReference"); const Exists_1 = require("./Exists"); class Expression extends AbstractExpressionElement_1.AbstractExpressionElement { constructor(elements = [], brackets = false) { super(); this.elements = elements; this.brackets = brackets; } static and(conditions) { return Expression.condition("and", conditions); } static or(conditions) { return Expression.condition("or", conditions); } static unknown(sql, columnsMap = {}) { const unknownElement = UnknownExpressionElement_1.UnknownExpressionElement.fromSql(sql, columnsMap); return new Expression([unknownElement]); } static funcCall(name, args) { const funcElem = new FuncCall_1.FuncCall(name, args); return new Expression([funcElem]); } static condition(operator, conditions) { const elements = []; for (let i = 0, n = conditions.length; i < n; i++) { if (i > 0) { elements.push(new Operator_1.Operator(operator)); } const sql = conditions[i]; if (typeof sql === "string") { elements.push(UnknownExpressionElement_1.UnknownExpressionElement.fromSql(sql)); } else { elements.push(sql); } } return new Expression(elements).extrude(); } children() { return this.elements; } and(otherExpression) { if (!otherExpression) { return this; } const canCombineToPlainCondition = (this.onlyOperators("and") && otherExpression.onlyOperators("and")); if (canCombineToPlainCondition) { return new Expression([ ...this.elements, new Operator_1.Operator("and"), ...otherExpression.elements ]); } return new Expression([ this, new Operator_1.Operator("and"), otherExpression ]); } getExplicitCastType() { const twoLastElements = this.elements.slice(-2); const isCasting = (twoLastElements.length === 2 && twoLastElements[0].toString() === "::"); if (isCasting) { return twoLastElements[1].toString(); } } isCoalesce() { if (!this.isFuncCall()) { return false; } const funcCall = this.getFuncCalls()[0]; return funcCall.name === "coalesce"; } isFuncCall() { const elements = this.getElementsWithoutCasts(); const firstElem = elements[0]; return (elements.length === 1 && (firstElem instanceof FuncCall_1.FuncCall || firstElem instanceof Expression && firstElem.isFuncCall())); } isThatFuncCall(funcName) { const elements = this.getElementsWithoutCasts(); const firstElem = elements[0]; return (elements.length === 1 && (firstElem instanceof FuncCall_1.FuncCall && firstElem.name === funcName || firstElem instanceof Expression && firstElem.isThatFuncCall(funcName))); } isColumnReference() { return (this.elements.length === 1 && this.elements[0] instanceof ColumnReference_1.ColumnReference); } isArrayItemOfColumnReference() { return (this.elements.length === 2 && this.elements[0] instanceof ColumnReference_1.ColumnReference && /^\[\s*\d+\s*\]$/.test(this.elements[1].toString().trim())); } isIn() { return (this.elements.length === 2 && /^\s*in\s*\([^\)]+\)\s*$/.test(this.elements[1].toString())); } isNotExists() { return (this.elements.length === 2 && this.elements[0].toString() === "not" && this.elements[1] instanceof Exists_1.Exists); } isPrimitive() { const elements = this.getElementsWithoutCasts(); return (elements.length === 1 && elements[0] instanceof UnknownExpressionElement_1.UnknownExpressionElement && /^(\d+|'.*')$/.test(elements[0].toString())); } hasArraySearchOperator() { return this.elements.some(element => element instanceof Operator_1.Operator && element.toString() === "&&"); } isBinary(operator) { const elems = (operator === "::" ? this.elements : this.getElementsWithoutCasts()); const isBinaryExpression = (elems.length === 3 && elems[1] instanceof Operator_1.Operator && elems[1].toString() === operator); return isBinaryExpression; } isEqualAny() { const elems = this.getElementsWithoutCasts(); const isEqualAnyExpression = (elems.length === 3 && elems[1] instanceof Operator_1.Operator && elems[1].toString() === "=" && /^\s*any\s*\(/i.test(elems[2].toString())); return isEqualAnyExpression; } getOperands() { const operands = []; for (let i = 0, n = this.elements.length; i < n; i++) { const elem = this.elements[i]; const nextElem = this.elements[i + 1]; if (nextElem instanceof Operator_1.Operator && nextElem.toString() === "::") { const castOperator = nextElem; const castType = this.elements[i + 2]; const elemWithCasting = new Expression([ elem, castOperator, castType ]); operands.push(elemWithCasting); i += 2; continue; } if (elem instanceof Operator_1.Operator) { continue; } operands.push(elem); } return operands; } getElementsWithoutCasts() { const expressionElementsWithoutCasts = this.elements.slice(); for (let i = 0, n = expressionElementsWithoutCasts.length; i < n; i++) { const elem = expressionElementsWithoutCasts[i]; if (elem instanceof Operator_1.Operator && elem.toString() === "::") { expressionElementsWithoutCasts.splice(i, 2); n -= 2; i--; } } return expressionElementsWithoutCasts; } isEmpty() { if (this.elements.length === 0) { return true; } if (this.elements.length === 1) { const firstElem = this.elements[0]; if (firstElem instanceof Expression) { return firstElem.isEmpty(); } } return false; } replaceFuncCall(replaceFunc, toSql) { const newElements = this.elements.map(elem => elem.replaceFuncCall(replaceFunc, toSql)); return this.clone(newElements); } replaceTable(replaceTable, toTable) { const newElements = this.elements.map(elem => elem.replaceTable(replaceTable, toTable)); return this.clone(newElements); } replaceColumn(replaceColumn, toSql) { const newElements = this.elements.map(elem => elem.replaceColumn(replaceColumn, toSql)); return this.clone(newElements); } splitBy(operator) { const conditions = []; let currentCondition = []; for (const element of this.elements) { if (element instanceof Operator_1.Operator) { if (element.toString() === operator) { if (currentCondition.length) { const condition = new Expression(currentCondition); conditions.push(condition); } currentCondition = []; continue; } } currentCondition.push(element); } if (currentCondition.length) { const condition = new Expression(currentCondition); conditions.push(condition); } return conditions; } extrude() { const singleElement = this.elements[0]; if (this.elements.length === 1 && singleElement instanceof Expression) { return singleElement.extrude(); } return this; } clone(newElements) { return new Expression(newElements || this.elements.map(elem => elem.clone()), this.brackets); } needWrapToBrackets() { return (/^case\s/.test(this.toString().trim())); } template(spaces) { let lines = []; let line = ""; for (let i = 0, n = this.elements.length; i < n; i++) { const elem = this.elements[i]; if (elem instanceof Operator_1.Operator && elem.toString() === "::") { const nextElem = this.elements[i + 1]; line += "::" + nextElem.toString(); i++; continue; } const isConditionOperator = (elem instanceof Operator_1.Operator && ["and", "or"].includes(elem.toString())); if (isConditionOperator) { lines.push(spaces + line.trim()); lines.push(spaces + elem.toString()); line = ""; continue; } if (elem instanceof Expression) { if (line.trim()) { lines.push(spaces + line.trim()); } line = ""; if (elem.hasOperator("or")) { lines.push(spaces + "("); lines.push(...elem.template(spaces.plusOneLevel())); lines.push(spaces + ")"); } else { lines.push(...elem.template(spaces)); } continue; } else { line += " " + elem.toSQL(spaces); } } if (line.trim()) { lines.push(spaces + line.trim()); } lines = lines.filter(someLine => !!someLine.trim()); if (this.brackets) { const n = lines.length; lines[0] = spaces + "(" + lines[0].trim(); lines[n - 1] = lines[n - 1] + ")"; } return lines; } onlyOperators(onlyOperator) { const operators = this.elements.filter(elem => elem instanceof Operator_1.Operator); return (operators.length && operators.every(operator => operator.toString() === onlyOperator)); } hasOperator(operator) { return this.elements.some(elem => elem instanceof Operator_1.Operator && elem.toString() === operator); } } exports.Expression = Expression; //# sourceMappingURL=Expression.js.map