/* * 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 "../common/common.h" #include "../dsql/dsql.h" #include "../dsql/node.h" #include "../common/classes/array.h" #include "../common/classes/auto.h" #include "../common/classes/NestConst.h" namespace Jrd { class CompilerScratch; class dsql_nod; class ExprNode; class FieldNode; class MapNode; class MessageNode; 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 ***/ }; // Base class to call a visitor of an ExprNode. class VisitorCaller { public: virtual bool call(ExprNode* exprNode) = 0; }; // Implementation class to call a visitor of an ExprNode. template class VisitorCallerImpl : public VisitorCaller { public: VisitorCallerImpl(T& aVisitor, bool (ExprNode::*aVisitFunction)(T&)) : visitor(aVisitor), visitFunction(aVisitFunction) { } virtual bool call(ExprNode* exprNode) { return (exprNode->*visitFunction)(visitor); } private: T& visitor; bool (ExprNode::*visitFunction)(T&); }; template class DsqlNodeVisitor { public: template DsqlNodeVisitor(bool aAssertOnOthers, bool aReturnOnOthers, bool (ExprNode::*aVisitFunction)(Self&)) : assertOnOthers(aAssertOnOthers), returnOnOthers(aReturnOnOthers), currentNode(NULL) { caller = FB_NEW(*getDefaultMemoryPool()) VisitorCallerImpl( static_cast(*this), aVisitFunction); } public: T getCurrentNode() { return *currentNode; } void replaceNode(T 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: bool call(ExprNode* exprNode) { return caller->call(exprNode); } private: const bool assertOnOthers; const bool returnOnOthers; Firebird::AutoPtr caller; 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