ddl-manager
Version:
store postgres procedures and triggers in files
100 lines • 3.68 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.replaceAmpArrayToAny = void 0;
const assert_1 = __importDefault(require("assert"));
const ast_1 = require("../../../ast");
// try using btree-index scan
// input (cannot use btree-index):
// from companies where new.companies_ids && array[ companies.id ]
// from companies where new.companies_ids @> array[ companies.id ]
// output (can use btree-index):
// from companies where companies.id = any( new.companies_ids )
function replaceAmpArrayToAny(cacheFor, input) {
if (!input.isBinary("&&") && !input.isBinary("@>") && !input.isBinary("<@")) {
return input;
}
const [leftOperand, rightOperand] = input.getOperands();
const columnOperand = detectColumnOperand(leftOperand, rightOperand);
const arrOperand = detectArrOperand(leftOperand, rightOperand);
if (!columnOperand || !arrOperand) {
return input;
}
const columnRefs = arrOperand.getColumnReferences();
const isCacheId = (columnRefs.length === 1 &&
columnRefs[0].name === "id" &&
columnRefs[0].tableReference.equal(cacheFor));
if (!isCacheId) {
return input;
}
// cannot optimize
if (input.isBinary("<@")) {
if (columnOperand === leftOperand) {
return input;
}
}
if (input.isBinary("@>")) {
if (columnOperand === rightOperand) {
return input;
}
}
const arrContent = executeArrayContent(arrOperand);
const castingSQL = executeArrayCasting(arrOperand);
const output = new ast_1.Expression([
arrContent,
new ast_1.Operator("="),
ast_1.UnknownExpressionElement.fromSql(`any( ${columnOperand}${castingSQL} )`, { [columnOperand.toString()]: columnOperand })
]);
return output;
}
exports.replaceAmpArrayToAny = replaceAmpArrayToAny;
function detectColumnOperand(leftOperand, rightOperand) {
if (leftOperand instanceof ast_1.ColumnReference) {
return leftOperand;
}
if (rightOperand instanceof ast_1.ColumnReference) {
return rightOperand;
}
}
function detectArrOperand(leftOperand, rightOperand) {
if (isArrayExpression(leftOperand)) {
return leftOperand;
}
if (isArrayExpression(rightOperand)) {
return rightOperand;
}
}
function isArrayExpression(operand) {
const operandSQL = operand.toString().trim().toLowerCase();
return (/^array\s*\[.*\](\s*::\s*(\w+)\[\])?$/.test(operandSQL));
}
function executeArrayContent(anyOperand) {
const matchResult = anyOperand.toString().match(/\[([^\]]+)\]/);
assert_1.default.ok(matchResult && matchResult[1]);
const columnsMap = {};
if (anyOperand instanceof ast_1.UnknownExpressionElement) {
Object.assign(columnsMap, anyOperand.columnsMap);
}
else if (anyOperand instanceof ast_1.Expression) {
for (const subElem of anyOperand.elements) {
const subMap = subElem.columnsMap || {};
Object.assign(columnsMap, subMap);
}
}
const arrContentSQL = matchResult[1].trim();
const arrContentElem = ast_1.UnknownExpressionElement.fromSql(arrContentSQL, columnsMap);
return arrContentElem;
}
function executeArrayCasting(anyOperand) {
if (!(anyOperand instanceof ast_1.Expression)) {
return "";
}
if (anyOperand.isBinary("::")) {
const castType = anyOperand.elements[2];
return `::${castType}`;
}
return "";
}
//# sourceMappingURL=replaceAmpArrayToAny.js.map