Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgsogrexpressioncompiler.cpp 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 : : #include "qgsogrexpressioncompiler.h" 17 : : ///@cond PRIVATE 18 : : 19 : : #include "qgsexpressionnodeimpl.h" 20 : : #include "qgsogrprovider.h" 21 : : 22 : 0 : QgsOgrExpressionCompiler::QgsOgrExpressionCompiler( QgsOgrFeatureSource *source, bool ignoreStaticNodes ) 23 : 0 : : QgsSqlExpressionCompiler( source->mFields, QgsSqlExpressionCompiler::CaseInsensitiveStringMatch | QgsSqlExpressionCompiler::NoNullInBooleanLogic 24 : 0 : | QgsSqlExpressionCompiler::NoUnaryMinus | QgsSqlExpressionCompiler::IntegerDivisionResultsInInteger, ignoreStaticNodes ) 25 : 0 : , mSource( source ) 26 : 0 : { 27 : 0 : } 28 : : 29 : : 30 : 0 : QgsSqlExpressionCompiler::Result QgsOgrExpressionCompiler::compile( const QgsExpression *exp ) 31 : : { 32 : : //for certain driver types, OGR forwards SQL through to the underlying provider. In these cases 33 : : //the syntax may differ from OGR SQL, so we don't support compilation for these drivers 34 : : //see http://www.gdal.org/ogr_sql.html 35 : 0 : if ( mSource->mDriverName == QLatin1String( "MySQL" ) ) 36 : 0 : return Fail; 37 : 0 : else if ( mSource->mDriverName == QLatin1String( "PostgreSQL" ) ) 38 : 0 : return Fail; 39 : 0 : else if ( mSource->mDriverName == QLatin1String( "OCI" ) ) 40 : 0 : return Fail; 41 : 0 : else if ( mSource->mDriverName == QLatin1String( "ODBC" ) ) 42 : 0 : return Fail; 43 : 0 : else if ( mSource->mDriverName == QLatin1String( "PGeo" ) ) 44 : 0 : return Fail; 45 : 0 : else if ( mSource->mDriverName == QLatin1String( "MSSQLSpatial" ) ) 46 : 0 : return Fail; 47 : : 48 : 0 : return QgsSqlExpressionCompiler::compile( exp ); 49 : 0 : } 50 : : 51 : 0 : QgsSqlExpressionCompiler::Result QgsOgrExpressionCompiler::compileNode( const QgsExpressionNode *node, QString &result ) 52 : : { 53 : 0 : QgsSqlExpressionCompiler::Result staticRes = replaceNodeByStaticCachedValueIfPossible( node, result ); 54 : 0 : if ( staticRes != Fail ) 55 : 0 : return staticRes; 56 : : 57 : 0 : switch ( node->nodeType() ) 58 : : { 59 : : case QgsExpressionNode::ntBinaryOperator: 60 : : { 61 : 0 : switch ( static_cast<const QgsExpressionNodeBinaryOperator *>( node )->op() ) 62 : : { 63 : : case QgsExpressionNodeBinaryOperator::boILike: 64 : : case QgsExpressionNodeBinaryOperator::boNotILike: 65 : 0 : return Fail; //disabled until https://trac.osgeo.org/gdal/ticket/5132 is fixed 66 : : 67 : : case QgsExpressionNodeBinaryOperator::boMod: 68 : : case QgsExpressionNodeBinaryOperator::boConcat: 69 : : case QgsExpressionNodeBinaryOperator::boPow: 70 : : case QgsExpressionNodeBinaryOperator::boRegexp: 71 : 0 : return Fail; //not supported by OGR 72 : : 73 : : default: 74 : : //fallback to default handling 75 : 0 : return QgsSqlExpressionCompiler::compileNode( node, result ); 76 : : } 77 : : } 78 : : 79 : : case QgsExpressionNode::ntFunction: 80 : : { 81 : 0 : const QgsExpressionNodeFunction *n = static_cast<const QgsExpressionNodeFunction *>( node ); 82 : 0 : QgsExpressionFunction *fd = QgsExpression::Functions()[n->fnIndex()]; 83 : : 84 : 0 : if ( fd->name() == QLatin1String( "make_datetime" ) || fd->name() == QLatin1String( "make_date" ) || fd->name() == QLatin1String( "make_time" ) ) 85 : : { 86 : 0 : const auto constList = n->args()->list(); 87 : 0 : for ( const QgsExpressionNode *ln : constList ) 88 : : { 89 : 0 : if ( ln->nodeType() != QgsExpressionNode::ntLiteral ) 90 : 0 : return Fail; 91 : : } 92 : 0 : return QgsSqlExpressionCompiler::compileNode( node, result ); 93 : 0 : } 94 : : //generally not support by OGR 95 : 0 : return Fail; 96 : : } 97 : : 98 : : case QgsExpressionNode::ntCondition: 99 : : //not support by OGR 100 : 0 : return Fail; 101 : : 102 : : case QgsExpressionNode::ntUnaryOperator: 103 : : case QgsExpressionNode::ntColumnRef: 104 : : case QgsExpressionNode::ntInOperator: 105 : : case QgsExpressionNode::ntLiteral: 106 : : case QgsExpressionNode::ntIndexOperator: 107 : 0 : break; 108 : : } 109 : : 110 : 0 : return QgsSqlExpressionCompiler::compileNode( node, result ); 111 : 0 : } 112 : : 113 : 0 : QString QgsOgrExpressionCompiler::sqlFunctionFromFunctionName( const QString &fnName ) const 114 : : { 115 : 0 : static const QMap<QString, QString> FN_NAMES 116 : 0 : { 117 : 0 : { "make_datetime", "" }, 118 : 0 : { "make_date", "" }, 119 : 0 : { "make_time", "" }, 120 : : }; 121 : : 122 : 0 : return FN_NAMES.value( fnName, QString() ); 123 : 0 : } 124 : : 125 : 0 : QStringList QgsOgrExpressionCompiler::sqlArgumentsFromFunctionName( const QString &fnName, const QStringList &fnArgs ) const 126 : : { 127 : 0 : QStringList args( fnArgs ); 128 : 0 : if ( fnName == QLatin1String( "make_datetime" ) ) 129 : : { 130 : 0 : args = QStringList( QStringLiteral( "'%1-%2-%3T%4:%5:%6Z'" ).arg( args[0].rightJustified( 4, '0' ) ) 131 : 0 : .arg( args[1].rightJustified( 2, '0' ) ) 132 : 0 : .arg( args[2].rightJustified( 2, '0' ) ) 133 : 0 : .arg( args[3].rightJustified( 2, '0' ) ) 134 : 0 : .arg( args[4].rightJustified( 2, '0' ) ) 135 : 0 : .arg( args[5].rightJustified( 2, '0' ) ) ); 136 : 0 : } 137 : 0 : else if ( fnName == QLatin1String( "make_date" ) ) 138 : : { 139 : 0 : args = QStringList( QStringLiteral( "'%1-%2-%3'" ).arg( args[0].rightJustified( 4, '0' ) ) 140 : 0 : .arg( args[1].rightJustified( 2, '0' ) ) 141 : 0 : .arg( args[2].rightJustified( 2, '0' ) ) ); 142 : 0 : } 143 : 0 : else if ( fnName == QLatin1String( "make_time" ) ) 144 : : { 145 : 0 : args = QStringList( QStringLiteral( "'%1:%2:%3'" ).arg( args[0].rightJustified( 2, '0' ) ) 146 : 0 : .arg( args[1].rightJustified( 2, '0' ) ) 147 : 0 : .arg( args[2].rightJustified( 2, '0' ) ) ); 148 : 0 : } 149 : 0 : return args; 150 : 0 : } 151 : : 152 : 0 : QString QgsOgrExpressionCompiler::quotedIdentifier( const QString &identifier ) 153 : : { 154 : 0 : return QgsOgrProviderUtils::quotedIdentifier( identifier.toUtf8(), mSource->mDriverName ); 155 : 0 : } 156 : : 157 : 0 : QString QgsOgrExpressionCompiler::quotedValue( const QVariant &value, bool &ok ) 158 : : { 159 : 0 : ok = true; 160 : : 161 : 0 : if ( value.type() == QVariant::Bool ) 162 : : { 163 : : // No support for boolean literals, so fake them 164 : 0 : return value.toBool() ? "(1=1)" : "(1=0)"; 165 : : } 166 : : 167 : 0 : return QgsOgrProviderUtils::quotedValue( value ); 168 : 0 : } 169 : : 170 : 0 : QString QgsOgrExpressionCompiler::castToReal( const QString &value ) const 171 : : { 172 : 0 : return QStringLiteral( "CAST((%1) AS float)" ).arg( value ); 173 : 0 : } 174 : : 175 : 0 : QString QgsOgrExpressionCompiler::castToInt( const QString &value ) const 176 : : { 177 : 0 : return QStringLiteral( "CAST((%1) AS integer)" ).arg( value ); 178 : 0 : } 179 : : 180 : : ///@endcond