/* * The contents of this file are subject to the Interbase Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy * of the License at http://www.Inprise.com/IPL.html * * Software distributed under the License is distributed on an * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express * or implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code was created by Inprise Corporation * and its predecessors. Portions created by Inprise Corporation are * Copyright (C) Inprise Corporation. * * All Rights Reserved. * Contributor(s): ______________________________________. * Adriano dos Santos Fernandes - refactored from pass1.cpp */ #ifndef DSQL_VISITORS_H #define DSQL_VISITORS_H #include "../jrd/common.h" #include "../dsql/dsql.h" #include "../dsql/node.h" #include "../common/classes/array.h" #include "../common/classes/auto.h" namespace Jrd { class CompilerScratch; class dsql_nod; class ExprNode; class jrd_nod; class JrdNodeVisitor; enum FieldMatchType { FIELD_MATCH_TYPE_EQUAL = 0, FIELD_MATCH_TYPE_LOWER = 1, FIELD_MATCH_TYPE_LOWER_EQUAL = 2 /*** , FIELD_MATCH_TYPE_HIGHER = 3, FIELD_MATCH_TYPE_HIGHER_EQUAL = 4 ***/ }; template class DsqlNodeVisitor { private: typedef bool (ExprNode::*Callback)(DsqlNodeVisitor& visitor); public: template DsqlNodeVisitor(bool aAssertOnOthers, bool aReturnOnOthers, bool (ExprNode::*aExprVisit)(T3& visitor)) : assertOnOthers(aAssertOnOthers), returnOnOthers(aReturnOnOthers), exprVisit(reinterpret_cast(aExprVisit)), currentNode(NULL) { } public: dsql_nod* getCurrentNode() { return *currentNode; } void replaceNode(dsql_nod* node) { *currentNode = node; } bool visit(T2 nodePtr) { Firebird::AutoSetRestore autoInsideHigherMap(¤tNode, nodePtr); return internalVisit(*nodePtr); } bool visitChildren(T node); virtual bool internalVisit(T node) = 0; private: const bool assertOnOthers; const bool returnOnOthers; const Callback exprVisit; T2 currentNode; }; typedef DsqlNodeVisitor ConstDsqlNodeVisitor; typedef DsqlNodeVisitor NonConstDsqlNodeVisitor; // Check for an aggregate expression in an expression. It could be buried in an expression // tree and therefore call itselfs again. The level parameters (currentLevel & deepestLevel) // are used to see how deep we are with passing sub-queries (= scope_level). class AggregateFinder : public ConstDsqlNodeVisitor { public: AggregateFinder(const DsqlCompilerScratch* aDsqlScratch, bool aWindow); static bool find(const DsqlCompilerScratch* dsqlScratch, bool window, const dsql_nod* node) { return AggregateFinder(dsqlScratch, window).visit(&node); } virtual bool internalVisit(const dsql_nod* node); public: const DsqlCompilerScratch* const dsqlScratch; bool window; USHORT currentLevel; USHORT deepestLevel; bool ignoreSubSelects; }; // Check the fields inside an aggregate and check if the field scope_level meets the specified // conditions. // // The SQL 2008 standard says: // ::= // WHERE // Syntax Rules // 1) If a directly contained in the is a // , then the shall be contained in a // or