"use strict"; const NoChange = require("./util/no-change"); const deriveNode = require("../derive-node"); const operations = require("../operations"); module.exports = { name: "test-context", category: [ "testing" ], visitors: { columnName: (node, { setState }) => { setState("seenColumn", node.name); return NoChange; }, select: (node, { registerStateHandler, defer }) => { let seenColumns = new Set(); registerStateHandler("seenColumnsInWhere", (names) => { for (let name of names) { seenColumns = seenColumns.add(name); } }); // FIXME: Definitely need better AST modification/derivation tools... probably some sort of deep-modifying utility, for starters. Maybe merge-by-template can be of use here? With a custom AST node merger? It probably doesn't support non-enumerable properties correctly right now, though... return defer(() => { console.log("Seen columns in WHERE in SELECT:", seenColumns); let onlyColumnsClause = node.clauses.find((clause) => clause.type === "onlyColumns"); let columnsAlreadyAdded = onlyColumnsClause != null && Array.from(seenColumns).every((column) => { return onlyColumnsClause.columns.some((existingColumn) => existingColumn.name === column); }); if (!columnsAlreadyAdded) { // NOTE: This is a good test case for optimizer stability! Just returning a derived node in every case. let newOnlyColumnsClause = (onlyColumnsClause == null) ? operations.onlyColumns(Array.from(seenColumns)) : deriveNode(onlyColumnsClause, { columns: onlyColumnsClause.columns.concat(Array.from(seenColumns).map((columnName) => { return operations.column(columnName); })) }); return deriveNode(node, { clauses: node.clauses .filter((clause) => clause.type !== "onlyColumns") .concat([ newOnlyColumnsClause ]) }); } else { return NoChange; } }); }, where: (node, { registerStateHandler, defer, setState }) => { let seenColumns = []; registerStateHandler("seenColumn", (name) => seenColumns.push(name)); return defer(() => { setState("seenColumnsInWhere", seenColumns); return NoChange; }); // let seenColumns = []; // let id = Math.random(); // registerStateHandler("seenColumn", (name) => { // seenColumns.push(name); // }); // console.log("Scheduling defer", id); // return defer(() => { // console.log("Defer called", id); // // MARKER: This gets called twice, but should only be called once! // // console.log("Seen columns in WHERE:", seenColumns, require("util").inspect(node, {colors:true,depth:null})); // console.log("Seen columns in WHERE:", seenColumns); // return NoChange; // }); } } };