23 #include <QRegularExpression> 
   25 const char *QgsExpressionNodeBinaryOperator::BINARY_OPERATOR_TEXT[] =
 
   29   "=", 
"<>", 
"<=", 
">=", 
"<", 
">", 
"~", 
"LIKE", 
"NOT LIKE", 
"ILIKE", 
"NOT ILIKE", 
"IS", 
"IS NOT",
 
   30   "+", 
"-", 
"*", 
"/", 
"//", 
"%", 
"^",
 
   34 const char *QgsExpressionNodeUnaryOperator::UNARY_OPERATOR_TEXT[] =
 
   43   const QList< QgsExpressionNode * > nodeList = mList->
list();
 
   45     needs |= n->needsGeometry();
 
   56   mList.append( node->
node );
 
   57   mNameList.append( cleanNamedNodeName( node->
name ) );
 
   58   mHasNamedNodes = 
true;
 
   67     nl->mList.append( node->clone() );
 
   69   nl->mNameList = mNameList;
 
   80     if ( !first ) msg += QLatin1String( 
", " );
 
   87 QString QgsExpressionNode::NodeList::cleanNamedNodeName( 
const QString &name )
 
   89   QString cleaned = name.toLower();
 
   92   if ( cleaned == QLatin1String( 
"geom" ) )
 
   93     cleaned = QStringLiteral( 
"geometry" );
 
   94   else if ( cleaned == QLatin1String( 
"val" ) )
 
   95     cleaned = QStringLiteral( 
"value" );
 
   96   else if ( cleaned == QLatin1String( 
"geometry a" ) )
 
   97     cleaned = QStringLiteral( 
"geometry1" );
 
   98   else if ( cleaned == QLatin1String( 
"geometry b" ) )
 
   99     cleaned = QStringLiteral( 
"geometry2" );
 
  109   QVariant val = mOperand->eval( parent, context );
 
  116       QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( val, parent );
 
  118       return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::NOT[tvl] );
 
  122       if ( QgsExpressionUtils::isIntSafe( val ) )
 
  123         return QVariant( - QgsExpressionUtils::getIntValue( val, parent ) );
 
  124       else if ( QgsExpressionUtils::isDoubleSafe( val ) )
 
  125         return QVariant( - QgsExpressionUtils::getDoubleValue( val, parent ) );
 
  139   return mOperand->prepare( parent, context );
 
  145     return QStringLiteral( 
"%1 ( %2 )" ).arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
 
  147     return QStringLiteral( 
"%1 %2" ).arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
 
  153     return QSet< QString >();
 
  155   return mOperand->referencedColumns();
 
  160   return mOperand->referencedVariables();
 
  165   return mOperand->referencedFunctions();
 
  170   QList<const QgsExpressionNode *> lst;
 
  172   lst += mOperand->nodes();
 
  178   return mOperand->needsGeometry();
 
  190   return mOperand->isStatic( parent, context );
 
  195   return UNARY_OPERATOR_TEXT[mOp];
 
  202   QVariant vL = mOpLeft->eval( parent, context );
 
  205   if ( mOp == boAnd || mOp == boOr )
 
  207     QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent );
 
  209     if ( mOp == boAnd && tvlL == QgsExpressionUtils::False )
 
  211     if ( mOp == boOr && tvlL == QgsExpressionUtils::True )
 
  215   QVariant vR = mOpRight->eval( parent, context );
 
  221       if ( vL.type() == QVariant::String && vR.type() == QVariant::String )
 
  223         QString sL = QgsExpressionUtils::isNull( vL ) ? QString() : QgsExpressionUtils::getStringValue( vL, parent );
 
  225         QString sR = QgsExpressionUtils::isNull( vR ) ? QString() : QgsExpressionUtils::getStringValue( vR, parent );
 
  227         return QVariant( sL + sR );
 
  236       if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
 
  238       else if ( mOp != boDiv && QgsExpressionUtils::isIntSafe( vL ) && QgsExpressionUtils::isIntSafe( vR ) )
 
  241         qlonglong iL = QgsExpressionUtils::getIntValue( vL, parent );
 
  243         qlonglong iR = QgsExpressionUtils::getIntValue( vR, parent );
 
  246         if ( mOp == boMod && iR == 0 )
 
  249         return QVariant( computeInt( iL, iR ) );
 
  251       else if ( QgsExpressionUtils::isDateTimeSafe( vL ) && QgsExpressionUtils::isIntervalSafe( vR ) )
 
  253         QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
 
  255         QgsInterval iL = QgsExpressionUtils::getInterval( vR, parent );
 
  257         if ( mOp == boDiv || mOp == boMul || mOp == boMod )
 
  259           parent->
setEvalErrorString( tr( 
"Can't perform /, *, or % on DateTime and Interval" ) );
 
  262         return QVariant( computeDateTimeFromInterval( dL, &iL ) );
 
  264       else if ( mOp == boPlus && ( ( vL.type() == QVariant::Date && vR.type() == QVariant::Time ) ||
 
  265                                    ( vR.type() == QVariant::Date && vL.type() == QVariant::Time ) ) )
 
  267         QDate date = QgsExpressionUtils::getDateValue( vL.type() == QVariant::Date ? vL : vR, parent );
 
  269         QTime time = QgsExpressionUtils::getTimeValue( vR.type() == QVariant::Time ? vR : vL, parent );
 
  271         QDateTime dt = QDateTime( date, time );
 
  272         return QVariant( dt );
 
  274       else if ( mOp == boMinus && vL.type() == QVariant::Date && vR.type() == QVariant::Date )
 
  276         QDate date1 = QgsExpressionUtils::getDateValue( vL, parent );
 
  278         QDate date2 = QgsExpressionUtils::getDateValue( vR, parent );
 
  280         return date1 - date2;
 
  282       else if ( mOp == boMinus && vL.type() == QVariant::Time && vR.type() == QVariant::Time )
 
  284         QTime time1 = QgsExpressionUtils::getTimeValue( vL, parent );
 
  286         QTime time2 = QgsExpressionUtils::getTimeValue( vR, parent );
 
  288         return time1 - time2;
 
  290       else if ( mOp == boMinus && vL.type() == QVariant::DateTime && vR.type() == QVariant::DateTime )
 
  292         QDateTime datetime1 = QgsExpressionUtils::getDateTimeValue( vL, parent );
 
  294         QDateTime datetime2 = QgsExpressionUtils::getDateTimeValue( vR, parent );
 
  296         return datetime1 - datetime2;
 
  301         double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
 
  303         double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
 
  305         if ( ( mOp == boDiv || mOp == boMod ) && fR == 0. )
 
  307         return QVariant( computeDouble( fL, fR ) );
 
  313       double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
 
  315       double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
 
  319       return QVariant( qlonglong( std::floor( fL / fR ) ) );
 
  322       if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
 
  326         double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
 
  328         double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
 
  330         return QVariant( std::pow( fL, fR ) );
 
  335       QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
 
  337       return  QgsExpressionUtils::tvl2variant( QgsExpressionUtils::AND[tvlL][tvlR] );
 
  342       QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
 
  344       return  QgsExpressionUtils::tvl2variant( QgsExpressionUtils::OR[tvlL][tvlR] );
 
  353       if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
 
  357       else if ( QgsExpressionUtils::isList( vL ) || QgsExpressionUtils::isList( vR ) )
 
  360         if ( !QgsExpressionUtils::isList( vL ) || !QgsExpressionUtils::isList( vR ) )
 
  364         QVariantList lL = vL.toList();
 
  365         QVariantList lR = vR.toList();
 
  366         for ( 
int i = 0; i < lL.length() && i < lR.length(); i++ )
 
  368           if ( QgsExpressionUtils::isNull( lL.at( i ) ) && QgsExpressionUtils::isNull( lR.at( i ) ) )
 
  371           if ( QgsExpressionUtils::isNull( lL.at( i ) ) || QgsExpressionUtils::isNull( lR.at( i ) ) )
 
  381                 return QgsExpressionUtils::isNull( lR.at( i ) );
 
  384                 return QgsExpressionUtils::isNull( lL.at( i ) );
 
  394           QVariant eq = eqNode.
eval( parent, context );
 
  396           if ( eq == TVL_False )
 
  400             QVariant v = node.
eval( parent, context );
 
  410             return lL.length() == lR.length();
 
  412             return lL.length() != lR.length();
 
  414             return lL.length() < lR.length();
 
  416             return lL.length() > lR.length();
 
  418             return lL.length() <= lR.length();
 
  420             return lL.length() >= lR.length();
 
  426       else if ( ( vL.type() == QVariant::DateTime && vR.type() == QVariant::DateTime ) )
 
  428         QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
 
  430         QDateTime dR = QgsExpressionUtils::getDateTimeValue( vR, parent );
 
  437         dL.setTimeSpec( Qt::UTC );
 
  438         dR.setTimeSpec( Qt::UTC );
 
  440         return compare( dR.msecsTo( dL ) ) ? TVL_True : TVL_False;
 
  442       else if ( ( vL.type() == QVariant::Date && vR.type() == QVariant::Date ) )
 
  444         const QDate dL = QgsExpressionUtils::getDateValue( vL, parent );
 
  446         const QDate dR = QgsExpressionUtils::getDateValue( vR, parent );
 
  448         return compare( dR.daysTo( dL ) ) ? TVL_True : TVL_False;
 
  450       else if ( ( vL.type() == QVariant::Time && vR.type() == QVariant::Time ) )
 
  452         const QTime dL = QgsExpressionUtils::getTimeValue( vL, parent );
 
  454         const QTime dR = QgsExpressionUtils::getTimeValue( vR, parent );
 
  456         return compare( dR.msecsTo( dL ) ) ? TVL_True : TVL_False;
 
  458       else if ( ( vL.type() != QVariant::String || vR.type() != QVariant::String ) &&
 
  459                 QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) )
 
  463         double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
 
  465         double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
 
  467         return compare( fL - fR ) ? TVL_True : TVL_False;
 
  472         double fL = QgsExpressionUtils::getInterval( vL, parent ).seconds();
 
  474         double fR = QgsExpressionUtils::getInterval( vR, parent ).seconds();
 
  476         return compare( fL - fR ) ? TVL_True : TVL_False;
 
  481         QString sL = QgsExpressionUtils::getStringValue( vL, parent );
 
  483         QString sR = QgsExpressionUtils::getStringValue( vR, parent );
 
  485         int diff = QString::compare( sL, sR );
 
  486         return compare( diff ) ? TVL_True : TVL_False;
 
  491       if ( QgsExpressionUtils::isNull( vL ) && QgsExpressionUtils::isNull( vR ) ) 
 
  492         return ( mOp == boIs ? TVL_True : TVL_False );
 
  493       else if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) ) 
 
  494         return ( mOp == boIs ? TVL_False : TVL_True );
 
  498         if ( QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) &&
 
  499              ( vL.type() != QVariant::String || vR.type() != QVariant::String ) )
 
  501           double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
 
  503           double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
 
  509           QString sL = QgsExpressionUtils::getStringValue( vL, parent );
 
  511           QString sR = QgsExpressionUtils::getStringValue( vR, parent );
 
  513           equal = QString::compare( sL, sR ) == 0;
 
  516           return mOp == boIs ? TVL_True : TVL_False;
 
  518           return mOp == boIs ? TVL_False : TVL_True;
 
  526       if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
 
  530         QString 
str    = QgsExpressionUtils::getStringValue( vL, parent );
 
  532         QString regexp = QgsExpressionUtils::getStringValue( vR, parent );
 
  536         if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike ) 
 
  538           QString esc_regexp = QRegExp::escape( regexp );
 
  540           if ( esc_regexp.startsWith( 
'%' ) )
 
  542             esc_regexp.replace( 0, 1, QStringLiteral( 
".*" ) );
 
  544           thread_local QRegExp rx1( QStringLiteral( 
"[^\\\\](%)" ) );
 
  546           while ( ( pos = rx1.indexIn( esc_regexp, pos ) ) != -1 )
 
  548             esc_regexp.replace( pos + 1, 1, QStringLiteral( 
".*" ) );
 
  551           thread_local QRegExp rx2( QStringLiteral( 
"\\\\%" ) );
 
  552           esc_regexp.replace( rx2, QStringLiteral( 
"%" ) );
 
  553           if ( esc_regexp.startsWith( 
'_' ) )
 
  555             esc_regexp.replace( 0, 1, QStringLiteral( 
"." ) );
 
  557           thread_local QRegExp rx3( QStringLiteral( 
"[^\\\\](_)" ) );
 
  559           while ( ( pos = rx3.indexIn( esc_regexp, pos ) ) != -1 )
 
  561             esc_regexp.replace( pos + 1, 1, 
'.' );
 
  564           esc_regexp.replace( QLatin1String( 
"\\\\_" ), QLatin1String( 
"_" ) );
 
  566           matches = QRegExp( esc_regexp, mOp == boLike || mOp == boNotLike ? Qt::CaseSensitive : Qt::CaseInsensitive ).exactMatch( 
str );
 
  570           matches = QRegularExpression( regexp ).match( 
str ).hasMatch();
 
  573         if ( mOp == boNotLike || mOp == boNotILike )
 
  578         return matches ? TVL_True : TVL_False;
 
  582       if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
 
  586         QString sL = QgsExpressionUtils::getStringValue( vL, parent );
 
  588         QString sR = QgsExpressionUtils::getStringValue( vR, parent );
 
  590         return QVariant( sL + sR );
 
  597 bool QgsExpressionNodeBinaryOperator::compare( 
double diff )
 
  619 qlonglong QgsExpressionNodeBinaryOperator::computeInt( qlonglong x, qlonglong y )
 
  639 QDateTime QgsExpressionNodeBinaryOperator::computeDateTimeFromInterval( 
const QDateTime &d, 
QgsInterval *i )
 
  644       return d.addSecs( i->
seconds() );
 
  646       return d.addSecs( -i->
seconds() );
 
  653 double QgsExpressionNodeBinaryOperator::computeDouble( 
double x, 
double y )
 
  666       return std::fmod( x, y );
 
  680   bool resL = mOpLeft->prepare( parent, context );
 
  681   bool resR = mOpRight->prepare( parent, context );
 
  727   Q_ASSERT( 
false && 
"unexpected binary operator" );
 
  763   Q_ASSERT( 
false && 
"unexpected binary operator" );
 
  773   QString rdump( mOpRight->dump() );
 
  778     rdump.prepend( 
'(' ).append( 
')' );
 
  782   if ( leftAssociative() )
 
  784     fmt += lOp && ( lOp->
precedence() < precedence() ) ? QStringLiteral( 
"(%1)" ) : QStringLiteral( 
"%1" );
 
  785     fmt += QLatin1String( 
" %2 " );
 
  786     fmt += rOp && ( rOp->
precedence() <= precedence() ) ? QStringLiteral( 
"(%3)" ) : QStringLiteral( 
"%3" );
 
  790     fmt += lOp && ( lOp->
precedence() <= precedence() ) ? QStringLiteral( 
"(%1)" ) : QStringLiteral( 
"%1" );
 
  791     fmt += QLatin1String( 
" %2 " );
 
  792     fmt += rOp && ( rOp->
precedence() < precedence() ) ? QStringLiteral( 
"(%3)" ) : QStringLiteral( 
"%3" );
 
  795   return fmt.arg( mOpLeft->dump(), BINARY_OPERATOR_TEXT[mOp], rdump );
 
  801     return QSet< QString >();
 
  803   return mOpLeft->referencedColumns() + mOpRight->referencedColumns();
 
  808   return mOpLeft->referencedVariables() + mOpRight->referencedVariables();
 
  813   return mOpLeft->referencedFunctions() + mOpRight->referencedFunctions();
 
  818   QList<const QgsExpressionNode *> lst;
 
  820   lst += mOpLeft->nodes() + mOpRight->nodes();
 
  826   return mOpLeft->needsGeometry() || mOpRight->needsGeometry();
 
  838   const bool leftStatic = mOpLeft->isStatic( parent, context );
 
  839   const bool rightStatic = mOpRight->isStatic( parent, context );
 
  841   if ( leftStatic && rightStatic )
 
  853         mOpLeft->prepare( parent, context );
 
  854         if ( mOpLeft->hasCachedStaticValue() )
 
  856           QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
 
  857           if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
 
  865       else if ( rightStatic )
 
  867         mOpRight->prepare( parent, context );
 
  868         if ( mOpRight->hasCachedStaticValue() )
 
  870           QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
 
  871           if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
 
  889         mOpLeft->prepare( parent, context );
 
  890         if ( mOpLeft->hasCachedStaticValue() )
 
  892           QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
 
  893           if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
 
  901       else if ( rightStatic )
 
  903         mOpRight->prepare( parent, context );
 
  904         if ( mOpRight->hasCachedStaticValue() )
 
  906           QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
 
  907           if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
 
  950   if ( mList->count() == 0 )
 
  951     return mNotIn ? TVL_True : TVL_False;
 
  952   QVariant v1 = mNode->eval( parent, context );
 
  954   if ( QgsExpressionUtils::isNull( v1 ) )
 
  957   bool listHasNull = 
false;
 
  959   const QList< QgsExpressionNode * > nodeList = mList->list();
 
  962     QVariant v2 = n->eval( parent, context );
 
  964     if ( QgsExpressionUtils::isNull( v2 ) )
 
  970       if ( ( v1.type() != QVariant::String || v2.type() != QVariant::String ) &&
 
  971            QgsExpressionUtils::isDoubleSafe( v1 ) && QgsExpressionUtils::isDoubleSafe( v2 ) )
 
  975         double f1 = QgsExpressionUtils::getDoubleValue( v1, parent );
 
  977         double f2 = QgsExpressionUtils::getDoubleValue( v2, parent );
 
  983         QString s1 = QgsExpressionUtils::getStringValue( v1, parent );
 
  985         QString s2 = QgsExpressionUtils::getStringValue( v2, parent );
 
  987         equal = QString::compare( s1, s2 ) == 0;
 
  991         return mNotIn ? TVL_False : TVL_True;
 
  999     return mNotIn ? TVL_True : TVL_False;
 
 1015   bool res = mNode->prepare( parent, context );
 
 1016   const QList< QgsExpressionNode * > nodeList = mList->list();
 
 1019     res = res && n->prepare( parent, context );
 
 1026   return QStringLiteral( 
"%1 %2 IN (%3)" ).arg( mNode->dump(), mNotIn ? 
"NOT" : 
"", mList->dump() );
 
 1038   if ( !mNode->isStatic( parent, context ) )
 
 1041   const QList< QgsExpressionNode * > nodeList = mList->list();
 
 1044     if ( !n->isStatic( parent, context ) )
 
 1055   QString name = QgsExpression::QgsExpression::Functions()[mFnIndex]->name();
 
 1058   QVariant res = fd->
run( mArgs, context, parent, 
this );
 
 1066   : mFnIndex( fnIndex )
 
 1069   if ( !
args || functionParams.isEmpty() )
 
 1080     while ( idx < args->names().size() && 
args->
names().at( idx ).isEmpty() )
 
 1087     for ( ; idx < functionParams.count(); ++idx )
 
 1089       int nodeIdx = 
args->
names().indexOf( functionParams.at( idx ).name().toLower() );
 
 1119   bool res = fd->
prepare( 
this, parent, context );
 
 1122     const QList< QgsExpressionNode * > nodeList = mArgs->
list();
 
 1125       res = res && n->prepare( parent, context );
 
 1135     return QStringLiteral( 
"%1%2" ).arg( fd->
name(), fd->
name().startsWith( 
'$' ) ? QString() : QStringLiteral( 
"()" ) ); 
 
 1137     return QStringLiteral( 
"%1(%2)" ).arg( fd->
name(), mArgs ? mArgs->
dump() : QString() ); 
 
 1143     return QSet< QString >();
 
 1151     return functionColumns;
 
 1155   const QList< QgsExpressionNode * > nodeList = mArgs->
list();
 
 1158     if ( fd->
parameters().count() <= paramIndex || !fd->
parameters().at( paramIndex ).isSubExpression() )
 
 1159       functionColumns.unite( n->referencedColumns() );
 
 1163   return functionColumns;
 
 1169   if ( fd->
name() == QLatin1String( 
"var" ) )
 
 1171     if ( !mArgs->
list().isEmpty() )
 
 1175         return QSet<QString>() << var->
value().toString();
 
 1177     return QSet<QString>() << QString();
 
 1181     QSet<QString> functionVariables = QSet<QString>();
 
 1184       return functionVariables;
 
 1186     const QList< QgsExpressionNode * > nodeList = mArgs->
list();
 
 1189       functionVariables.unite( n->referencedVariables() );
 
 1192     return functionVariables;
 
 1199   QSet<QString> functions = QSet<QString>();
 
 1200   functions.insert( fd->
name() );
 
 1205   const QList< QgsExpressionNode * > nodeList = mArgs->
list();
 
 1208     functions.unite( n->referencedFunctions() );
 
 1215   QList<const QgsExpressionNode *> lst;
 
 1220   const QList< QgsExpressionNode * > nodeList = mArgs->
list();
 
 1230   bool needs = QgsExpression::QgsExpression::Functions()[mFnIndex]->usesGeometry( 
this );
 
 1233     const QList< QgsExpressionNode * > nodeList = mArgs->
list();
 
 1235       needs |= n->needsGeometry();
 
 1258   if ( functionParams.isEmpty() )
 
 1265     QSet< int > providedArgs;
 
 1266     QSet< int > handledArgs;
 
 1269     while ( 
args->
names().at( idx ).isEmpty() )
 
 1271       providedArgs << idx;
 
 1277     for ( ; idx < functionParams.count(); ++idx )
 
 1279       int nodeIdx = 
args->
names().indexOf( functionParams.at( idx ).name().toLower() );
 
 1282         if ( !functionParams.at( idx ).optional() )
 
 1284           error = QStringLiteral( 
"No value specified for QgsExpressionFunction::Parameter '%1' for %2" ).arg( functionParams.at( idx ).name(), 
QgsExpression::Functions()[
fnIndex]->name() );
 
 1290         if ( providedArgs.contains( idx ) )
 
 1292           error = QStringLiteral( 
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2" ).arg( functionParams.at( idx ).name(), 
QgsExpression::Functions()[
fnIndex]->name() );
 
 1296       providedArgs << idx;
 
 1297       handledArgs << nodeIdx;
 
 1302     const QStringList nameList = 
args->
names();
 
 1303     for ( 
const QString &name : nameList )
 
 1305       if ( !name.isEmpty() && !functionParams.contains( name ) )
 
 1310       if ( !name.isEmpty() && !handledArgs.contains( idx ) )
 
 1312         int functionIdx = functionParams.indexOf( name );
 
 1313         if ( providedArgs.contains( functionIdx ) )
 
 1315           error = QStringLiteral( 
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2" ).arg( functionParams.at( functionIdx ).name(), 
QgsExpression::Functions()[
fnIndex]->name() );
 
 1350   if ( mValue.isNull() )
 
 1351     return QStringLiteral( 
"NULL" );
 
 1353   switch ( mValue.type() )
 
 1356       return QString::number( mValue.toInt() );
 
 1357     case QVariant::Double:
 
 1358       return QString::number( mValue.toDouble() );
 
 1359     case QVariant::LongLong:
 
 1360       return QString::number( mValue.toLongLong() );
 
 1361     case QVariant::String:
 
 1363     case QVariant::Bool:
 
 1364       return mValue.toBool() ? QStringLiteral( 
"TRUE" ) : QStringLiteral( 
"FALSE" );
 
 1366       return tr( 
"[unsupported type: %1; value: %2]" ).arg( mValue.typeName(), mValue.toString() );
 
 1377   return QSet<QString>();
 
 1382   return QSet<QString>();
 
 1387   return QSet<QString>();
 
 1392   QList<const QgsExpressionNode *> lst;
 
 1445       parent->
setEvalErrorString( tr( 
"No feature available for field '%1' evaluation" ).arg( mName ) );
 
 1482   const thread_local QRegExp re( QStringLiteral( 
"^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" ) );
 
 1488   return QSet<QString>() << mName;
 
 1493   return QSet<QString>();
 
 1498   return QSet<QString>();
 
 1503   QList<const QgsExpressionNode *> result;
 
 1530   : mConditions( *conditions )
 
 1531   , mElseExp( elseExp )
 
 1539   qDeleteAll( mConditions );
 
 1549   for ( 
WhenThen *cond : std::as_const( mConditions ) )
 
 1551     QVariant vWhen = cond->mWhenExp->eval( parent, context );
 
 1552     QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( vWhen, parent );
 
 1554     if ( tvl == QgsExpressionUtils::True )
 
 1556       QVariant vRes = cond->mThenExp->eval( parent, context );
 
 1564     QVariant vElse = mElseExp->
eval( parent, context );
 
 1575   bool foundAnyNonStaticConditions = 
false;
 
 1576   for ( 
WhenThen *cond : std::as_const( mConditions ) )
 
 1578     const bool res = cond->mWhenExp->prepare( parent, context )
 
 1579                      && cond->mThenExp->prepare( parent, context );
 
 1583     foundAnyNonStaticConditions |= !cond->mWhenExp->hasCachedStaticValue();
 
 1584     if ( !foundAnyNonStaticConditions && QgsExpressionUtils::getTVLValue( cond->mWhenExp->cachedStaticValue(), parent ) == QgsExpressionUtils::True )
 
 1588       if ( cond->mThenExp->hasCachedStaticValue() )
 
 1607     const bool res = mElseExp->
prepare( parent, context );
 
 1611     if ( !foundAnyNonStaticConditions )
 
 1635   QString msg( QStringLiteral( 
"CASE" ) );
 
 1636   for ( 
WhenThen *cond : mConditions )
 
 1638     msg += QStringLiteral( 
" WHEN %1 THEN %2" ).arg( cond->mWhenExp->dump(), cond->mThenExp->dump() );
 
 1641     msg += QStringLiteral( 
" ELSE %1" ).arg( mElseExp->
dump() );
 
 1642   msg += QLatin1String( 
" END" );
 
 1649     return QSet< QString >();
 
 1652   for ( 
WhenThen *cond : mConditions )
 
 1654     lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
 
 1666   for ( 
WhenThen *cond : mConditions )
 
 1668     lst += cond->mWhenExp->referencedVariables() + cond->mThenExp->referencedVariables();
 
 1680   for ( 
WhenThen *cond : mConditions )
 
 1682     lst += cond->mWhenExp->referencedFunctions() + cond->mThenExp->referencedFunctions();
 
 1693   QList<const QgsExpressionNode *> lst;
 
 1695   for ( 
WhenThen *cond : mConditions )
 
 1697     lst += cond->mWhenExp->nodes() + cond->mThenExp->nodes();
 
 1701     lst += mElseExp->
nodes();
 
 1708   for ( 
WhenThen *cond : mConditions )
 
 1710     if ( cond->mWhenExp->needsGeometry() ||
 
 1711          cond->mThenExp->needsGeometry() )
 
 1734     if ( !wt->mWhenExp->isStatic( parent, context ) || !wt->mThenExp->isStatic( parent, context ) )
 
 1739     return mElseExp->
isStatic( parent, context );
 
 1747     return QSet< QString >();
 
 1750   const QList< QgsExpressionNode * > nodeList = mList->
list();
 
 1752     lst.unite( n->referencedColumns() );
 
 1759   const QList< QgsExpressionNode * > nodeList = mList->
list();
 
 1761     lst.unite( n->referencedVariables() );
 
 1768   const QList< QgsExpressionNode * > nodeList = mList->
list();
 
 1770     lst.unite( n->referencedFunctions() );
 
 1776   QList<const QgsExpressionNode *> lst;
 
 1778   const QList< QgsExpressionNode * > nodeList = mList->
list();
 
 1785   : mWhenExp( whenExp )
 
 1786   , mThenExp( thenExp )
 
 1798   return new WhenThen( mWhenExp->clone(), mThenExp->clone() );
 
 1803   return BINARY_OPERATOR_TEXT[mOp];
 
 1810   const QVariant container = mContainer->eval( parent, context );
 
 1812   const QVariant index = mIndex->eval( parent, context );
 
 1815   switch ( container.type() )
 
 1818       return QgsExpressionUtils::getMapValue( container, parent ).value( index.toString() );
 
 1820     case QVariant::List:
 
 1821     case QVariant::StringList:
 
 1823       const QVariantList list = QgsExpressionUtils::getListValue( container, parent );
 
 1824       qlonglong pos = QgsExpressionUtils::getIntValue( index, parent );
 
 1825       if ( pos >= list.length() || pos < -list.length() )
 
 1832         pos += list.length();
 
 1835       return list.at( pos );
 
 1839       if ( !container.isNull() )
 
 1852   bool resC = mContainer->prepare( parent, context );
 
 1853   bool resV = mIndex->prepare( parent, context );
 
 1854   return resC && resV;
 
 1859   return QStringLiteral( 
"%1[%2]" ).arg( mContainer->dump(), mIndex->dump() );
 
 1865     return QSet< QString >();
 
 1867   return mContainer->referencedColumns() + mIndex->referencedColumns();
 
 1872   return mContainer->referencedVariables() + mIndex->referencedVariables();
 
 1877   return mContainer->referencedFunctions() + mIndex->referencedFunctions();
 
 1882   QList<const QgsExpressionNode *> lst;
 
 1884   lst += mContainer->nodes() + mIndex->nodes();
 
 1890   return mContainer->needsGeometry() || mIndex->needsGeometry();
 
 1902   return mContainer->isStatic( parent, context ) && mIndex->isStatic( parent, context );
 
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
bool hasFunction(const QString &name) const
Checks whether a specified function is contained in the context.
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
static const QString EXPR_FIELDS
Inbuilt variable name for fields storage.
bool hasVariable(const QString &name) const
Check whether a variable is specified by any scope within the context.
QgsExpressionFunction * function(const QString &name) const
Fetches a matching function from the context.
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
bool hasFeature() const
Returns true if the context has a feature associated with it.
A abstract base class for defining QgsExpression functions.
QList< QgsExpressionFunction::Parameter > ParameterList
List of parameters, used for function definition.
int params() const
The number of parameters this function takes.
bool lazyEval() const
true if this function should use lazy evaluation.
QString name() const
The name of the function.
virtual QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)
Evaluates the function, first evaluating all required arguments before passing them to the function's...
const QgsExpressionFunction::ParameterList & parameters() const
Returns the list of named parameters for the function, if set.
virtual QSet< QString > referencedColumns(const QgsExpressionNodeFunction *node) const
Returns a set of field names which are required for this function.
virtual bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
This will be called during the prepare step() of an expression if it is not static.
A binary expression operator, which operates on two values.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
bool leftAssociative() const
Returns true if the operator is left-associative.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
int precedence() const
Returns the precedence index for the operator.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
QgsExpressionNode * clone() const override
Generate a clone of this node.
QString text() const
Returns a the name of this operator without the operands.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
An expression node which takes it value from a feature's field.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QgsExpressionNodeColumnRef(const QString &name)
Constructor for QgsExpressionNodeColumnRef, referencing the column with the specified name.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QgsExpressionNode * clone() const override
Generate a clone of this node.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
Represents a "WHEN... THEN..." portation of a CASE WHEN clause in an expression.
WhenThen(QgsExpressionNode *whenExp, QgsExpressionNode *thenExp)
A combination of when and then.
QgsExpressionNodeCondition::WhenThen * clone() const
Gets a deep copy of this WhenThen combination.
An expression node for CASE WHEN clauses.
QList< QgsExpressionNodeCondition::WhenThen * > WhenThenList
QgsExpressionNodeCondition(QgsExpressionNodeCondition::WhenThenList *conditions, QgsExpressionNode *elseExp=nullptr)
Create a new node with the given list of conditions and an optional elseExp expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QgsExpressionNode * clone() const override
Generate a clone of this node.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
WhenThenList conditions() const
The list of WHEN THEN expression parts of the expression.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
~QgsExpressionNodeCondition() override
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
An expression node for expression functions.
int fnIndex() const
Returns the index of the node's function.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
~QgsExpressionNodeFunction() override
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QgsExpressionNodeFunction(int fnIndex, QgsExpressionNode::NodeList *args)
A function node consists of an index of the function in the global function array and a list of argum...
QgsExpressionNode * clone() const override
Generate a clone of this node.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
static bool validateParams(int fnIndex, QgsExpressionNode::NodeList *args, QString &error)
Tests whether the provided argument list is valid for the matching function.
An expression node for value IN or NOT IN clauses.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
~QgsExpressionNodeInOperator() override
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QgsExpressionNode * clone() const override
Generate a clone of this node.
A indexing expression operator, which allows use of square brackets [] to reference map and array ite...
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QgsExpressionNode * clone() const override
Generate a clone of this node.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
An expression node for literal values.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QString valueAsString() const
Returns a string representation of the node's literal value.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QgsExpressionNode * clone() const override
Generate a clone of this node.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
QVariant value() const
The value of the literal.
QgsExpressionNodeLiteral(const QVariant &value)
Constructor for QgsExpressionNodeLiteral, with the specified literal value.
A unary node is either negative as in boolean (not) or as in numbers (minus).
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QgsExpressionNodeUnaryOperator::UnaryOperator op() const
Returns the unary operator.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QString text() const
Returns a the name of this operator without the operands.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
QgsExpressionNode * clone() const override
Generate a clone of this node.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
A list of expression nodes.
bool hasNamedNodes() const
Returns true if list contains any named nodes.
virtual QString dump() const
Returns a string dump of the expression node.
QStringList names() const
Returns a list of names for nodes.
QgsExpressionNode::NodeList * clone() const
Creates a deep copy of this list. Ownership is transferred to the caller.
void append(QgsExpressionNode *node)
Takes ownership of the provided node.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
Abstract base class for all nodes that can appear in an expression.
virtual QList< const QgsExpressionNode * > nodes() const =0
Returns a list of all nodes which are used in this expression.
bool hasCachedStaticValue() const
Returns true if the node can be replaced by a static cached value.
virtual QString dump() const =0
Dump this node into a serialized (part) of an expression.
QVariant eval(QgsExpression *parent, const QgsExpressionContext *context)
Evaluate this node with the given context and parent.
virtual bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const =0
Returns true if this node can be evaluated for a static value.
bool prepare(QgsExpression *parent, const QgsExpressionContext *context)
Prepare this node for evaluation.
bool mHasCachedValue
true if the node has a static, precalculated value.
const QgsExpressionNode * effectiveNode() const
Returns a reference to the simplest node which represents this node, after any compilation optimizati...
QVariant cachedStaticValue() const
Returns the node's static cached value.
QVariant mCachedStaticValue
Contains the static, precalculated value for the node if mHasCachedValue is true.
virtual QSet< QString > referencedColumns() const =0
Abstract virtual method which returns a list of columns required to evaluate this node.
std::unique_ptr< QgsExpressionNode > mCompiledSimplifiedNode
Contains a compiled node which represents a simplified version of this node as a result of compilatio...
NodeType
Known node types.
@ ntIndexOperator
Index operator.
virtual bool needsGeometry() const =0
Abstract virtual method which returns if the geometry is required to evaluate this expression.
void cloneTo(QgsExpressionNode *target) const
Copies the members of this node to the node provided in target.
virtual QSet< QString > referencedFunctions() const =0
Returns a set of all functions which are used in this expression.
virtual QSet< QString > referencedVariables() const =0
Returns a set of all variables which are used in this expression.
virtual QgsExpressionNode * clone() const =0
Generate a clone of this node.
Class for parsing and evaluation of expressions (formerly called "search strings").
static const QList< QgsExpressionFunction * > & Functions()
static QString quotedString(QString text)
Returns a quoted version of a string (in single quotes)
void setEvalErrorString(const QString &str)
Sets evaluation error (used internally by evaluation functions)
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
int fieldNameIndex(const QString &fieldName) const
Utility method to get attribute index from name.
bool isValid() const
Returns the validity of this feature.
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Container of fields for a vector layer.
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
A representation of the interval between two datetime values.
double seconds() const
Returns the interval duration in seconds.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
#define ENSURE_NO_EVAL_ERROR
#define SET_EVAL_ERROR(x)
QgsExpressionNode * node
Node.