Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgssqlexpressioncompiler.h 3 : : -------------------------- 4 : : begin : November 2015 5 : : copyright : (C) 2015 Nyall Dawson 6 : : email : nyall dot dawson at gmail dot com 7 : : *************************************************************************** 8 : : * * 9 : : * This program is free software; you can redistribute it and/or modify * 10 : : * it under the terms of the GNU General Public License as published by * 11 : : * the Free Software Foundation; either version 2 of the License, or * 12 : : * (at your option) any later version. * 13 : : * * 14 : : ***************************************************************************/ 15 : : 16 : : #ifndef QGSSQLEXPRESSIONCOMPILER_H 17 : : #define QGSSQLEXPRESSIONCOMPILER_H 18 : : 19 : : #define SIP_NO_FILE 20 : : 21 : : #include "qgis_core.h" 22 : : #include "qgsfields.h" 23 : : #include "qgsexpressionnodeimpl.h" 24 : : 25 : : class QgsExpression; 26 : : class QgsExpressionNode; 27 : : 28 : : /** 29 : : * \ingroup core 30 : : * \class QgsSqlExpressionCompiler 31 : : * \brief Generic expression compiler for translation to provider specific SQL WHERE clauses. 32 : : * 33 : : * This class is designed to be overridden by providers to take advantage of expression compilation, 34 : : * so that feature requests can take advantage of the provider's native filtering support. 35 : : * \note Not part of stable API, may change in future versions of QGIS 36 : : * \note Not available in Python bindings 37 : : * \since QGIS 2.14 38 : : */ 39 : : 40 : : class CORE_EXPORT QgsSqlExpressionCompiler 41 : : { 42 : : public: 43 : : 44 : : //! Possible results from expression compilation 45 : : enum Result 46 : : { 47 : : None, //!< No expression 48 : : Complete, //!< Expression was successfully compiled and can be completely delegated to provider 49 : : Partial, //!< Expression was partially compiled, but provider will return extra records and results must be double-checked using QGIS' expression engine 50 : : Fail //!< Provider cannot handle expression 51 : : }; 52 : : 53 : : /** 54 : : * Enumeration of flags for how provider handles SQL clauses 55 : : */ 56 : : enum Flag 57 : : { 58 : : CaseInsensitiveStringMatch = 1, //!< Provider performs case-insensitive string matching for all strings 59 : : LikeIsCaseInsensitive = 1 << 1, //!< Provider treats LIKE as case-insensitive 60 : : NoNullInBooleanLogic = 1 << 2, //!< Provider does not support using NULL with boolean logic, e.g., "(...) OR NULL" 61 : : NoUnaryMinus = 1 << 3, //!< Provider does not unary minus, e.g., " -( 100 * 2 ) = ..." 62 : : IntegerDivisionResultsInInteger = 1 << 4, //!< Dividing int by int results in int on provider. Subclass must implement the castToReal() function to allow compilation of division. 63 : : }; 64 : : Q_DECLARE_FLAGS( Flags, Flag ) 65 : : 66 : : /** 67 : : * Constructor for expression compiler. 68 : : * \param fields fields from provider 69 : : * \param flags flags which control how expression is compiled 70 : : * \param ignoreStaticNodes If an expression has been partially precalculated due to static nodes in the expression, setting this argument to FALSE 71 : : * will prevent these precalculated values from being utilized during compilation of the expression. This flag significantly limits the effectiveness 72 : : * of compilation and should be used for debugging purposes only. (Since QGIS 3.18) 73 : : */ 74 : : explicit QgsSqlExpressionCompiler( const QgsFields &fields, QgsSqlExpressionCompiler::Flags flags = Flags(), bool ignoreStaticNodes = false ); 75 : 0 : virtual ~QgsSqlExpressionCompiler() = default; 76 : : 77 : : /** 78 : : * Compiles an expression and returns the result of the compilation. 79 : : */ 80 : : virtual Result compile( const QgsExpression *exp ); 81 : : 82 : : /** 83 : : * Returns the compiled expression string for use by the provider. 84 : : */ 85 : : virtual QString result(); 86 : : 87 : : /** 88 : : * Returns TRUE if \a op is one of 89 : : * 90 : : * - LIKE 91 : : * - ILIKE 92 : : * - NOT LIKE 93 : : * - NOT ILIKE 94 : : * - ~ (regexp) 95 : : * 96 : : * In such cases the left operator will be cast to string to behave equal to 97 : : * QGIS own expression engine. 98 : : * 99 : : * \since QGIS 3.2 100 : : */ 101 : : bool opIsStringComparison( QgsExpressionNodeBinaryOperator::BinaryOperator op ); 102 : : 103 : : protected: 104 : : 105 : : /** 106 : : * Returns a quoted column identifier, in the format expected by the provider. 107 : : * Derived classes should override this if special handling of column identifiers 108 : : * is required. 109 : : * \see quotedValue() 110 : : */ 111 : : virtual QString quotedIdentifier( const QString &identifier ); 112 : : 113 : : /** 114 : : * Returns a quoted attribute value, in the format expected by the provider. 115 : : * Derived classes should override this if special handling of attribute values is required. 116 : : * \param value value to quote 117 : : * \param ok will be set to TRUE if value can be compiled 118 : : * \see quotedIdentifier() 119 : : */ 120 : : virtual QString quotedValue( const QVariant &value, bool &ok ); 121 : : 122 : : /** 123 : : * Compiles an expression node and returns the result of the compilation. 124 : : * \param node expression node to compile 125 : : * \param str string representing compiled node should be stored in this parameter 126 : : * \returns result of node compilation 127 : : */ 128 : : virtual Result compileNode( const QgsExpressionNode *node, QString &str ); 129 : : 130 : : /** 131 : : * Returns the SQL function for the expression function. 132 : : * Derived classes should override this to help compile functions 133 : : * \param fnName expression function name 134 : : * \returns the SQL function name 135 : : */ 136 : : virtual QString sqlFunctionFromFunctionName( const QString &fnName ) const; 137 : : 138 : : /** 139 : : * Returns the Arguments for SQL function for the expression function. 140 : : * Derived classes should override this to help compile functions 141 : : * \param fnName expression function name 142 : : * \param fnArgs arguments from expression 143 : : * \returns the arguments updated for SQL Function 144 : : */ 145 : : virtual QStringList sqlArgumentsFromFunctionName( const QString &fnName, const QStringList &fnArgs ) const; 146 : : 147 : : /** 148 : : * Casts a value to a real result. Subclasses which indicate the IntegerDivisionResultsInInteger 149 : : * flag must reimplement this to cast a numeric value to a real type value so that division results 150 : : * in a real value result instead of integer. 151 : : * \since QGIS 3.0 152 : : */ 153 : : virtual QString castToReal( const QString &value ) const; 154 : : 155 : : /** 156 : : * Casts a value to a text result. Subclasses that support casting to text may implement this function 157 : : * to get equal behavior to the QGIS expression engine when string comparison operators are applied 158 : : * on non-string data. 159 : : * 160 : : * ### Example 161 : : * 162 : : * 579 LIKE '5%' 163 : : * 164 : : * which on a postgres database needs to be 165 : : * 166 : : * 579::text LIKE '5%' 167 : : * 168 : : * \since QGIS 3.2 169 : : */ 170 : : virtual QString castToText( const QString &value ) const; 171 : : 172 : : /** 173 : : * Casts a value to a integer result. Subclasses must reimplement this to cast a numeric value to a integer 174 : : * type value so that integer division results in a integer value result instead of real. 175 : : * \since QGIS 3.0 176 : : */ 177 : : virtual QString castToInt( const QString &value ) const; 178 : : 179 : : /** 180 : : * Tries to replace a node by its static cached value where possible. 181 : : * 182 : : * \since QGIS 3.18 183 : : */ 184 : : virtual Result replaceNodeByStaticCachedValueIfPossible( const QgsExpressionNode *node, QString &str ); 185 : : 186 : : QString mResult; 187 : : QgsFields mFields; 188 : : 189 : : private: 190 : : 191 : : Flags mFlags; 192 : : 193 : : bool mIgnoreStaticNodes = false; 194 : : 195 : : bool nodeIsNullLiteral( const QgsExpressionNode *node ) const; 196 : : 197 : : }; 198 : : 199 : 0 : Q_DECLARE_OPERATORS_FOR_FLAGS( QgsSqlExpressionCompiler::Flags ) 200 : : 201 : : #endif // QGSSQLEXPRESSIONCOMPILER_H