"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 : {
field : ( node , { setState } ) => {
setState ( "seenField" , node . name ) ;
return NoChange ;
} ,
select : ( node , { registerStateHandler , defer } ) => {
let seenFields = new Set ( ) ;
registerStateHandler ( "seenFieldsInWhere" , ( names ) => {
for ( let name of names ) {
seenFields = seenFields . 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 fields in WHERE in SELECT:", seenFields);
let onlyFieldsClause = node . clauses . find ( ( clause ) => clause . type === "onlyFields" ) ;
let fieldsAlreadyAdded = onlyFieldsClause != null && Array . from ( seenFields ) . every ( ( field ) => {
return onlyFieldsClause . fields . some ( ( existingField ) => existingField . name === field ) ;
} ) ;
if ( ! fieldsAlreadyAdded ) {
// NOTE: This is a good test case for optimizer stability! Just returning a derived node in every case.
let newOnlyFieldsClause = ( onlyFieldsClause == null )
? operations . onlyFields ( Array . from ( seenFields ) )
: deriveNode ( onlyFieldsClause , {
fields : onlyFieldsClause . fields . concat ( Array . from ( seenFields ) . map ( ( fieldName ) => {
return operations . field ( fieldName ) ;
} ) )
} ) ;
return deriveNode ( node , {
clauses : node . clauses
. filter ( ( clause ) => clause . type !== "onlyFields" )
. concat ( [ newOnlyFieldsClause ] )
} ) ;
} else {
return NoChange ;
}
} ) ;
} ,
where : ( node , { registerStateHandler , defer , setState } ) => {
let seenFields = [ ] ;
registerStateHandler ( "seenField" , ( name ) => seenFields . push ( name ) ) ;
return defer ( ( ) => {
setState ( "seenFieldsInWhere" , seenFields ) ;
return NoChange ;
} ) ;
// let seenFields = [];
// let id = Math.random();
// registerStateHandler("seenField", (name) => {
// seenFields.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 fields in WHERE:", seenFields, require("util").inspect(node, {colors:true,depth:null}));
// console.log("Seen fields in WHERE:", seenFields);
// return NoChange;
// });
}
}
} ;