24 #include <QRegularExpression> 
   26 const char *QgsExpressionNodeBinaryOperator::BINARY_OPERATOR_TEXT[] =
 
   30   "=", 
"<>", 
"<=", 
">=", 
"<", 
">", 
"~", 
"LIKE", 
"NOT LIKE", 
"ILIKE", 
"NOT ILIKE", 
"IS", 
"IS NOT",
 
   31   "+", 
"-", 
"*", 
"/", 
"//", 
"%", 
"^",
 
   35 const char *QgsExpressionNodeUnaryOperator::UNARY_OPERATOR_TEXT[] =
 
   44   const QList< QgsExpressionNode * > nodeList = mList->
list();
 
   46     needs |= n->needsGeometry();
 
   57   mList.append( node->
node );
 
   58   mNameList.append( cleanNamedNodeName( node->
name ) );
 
   59   mHasNamedNodes = 
true;
 
   68     nl->mList.append( node->clone() );
 
   70   nl->mNameList = mNameList;
 
   81     if ( !first ) msg += QLatin1String( 
", " );
 
   88 QString QgsExpressionNode::NodeList::cleanNamedNodeName( 
const QString &name )
 
   90   QString cleaned = name.toLower();
 
   93   if ( cleaned == QLatin1String( 
"geom" ) )
 
   94     cleaned = QStringLiteral( 
"geometry" );
 
   95   else if ( cleaned == QLatin1String( 
"val" ) )
 
   96     cleaned = QStringLiteral( 
"value" );
 
   97   else if ( cleaned == QLatin1String( 
"geometry a" ) )
 
   98     cleaned = QStringLiteral( 
"geometry1" );
 
   99   else if ( cleaned == QLatin1String( 
"geometry b" ) )
 
  100     cleaned = QStringLiteral( 
"geometry2" );
 
  110   QVariant val = mOperand->eval( parent, context );
 
  117       QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( val, parent );
 
  119       return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::NOT[tvl] );
 
  123       if ( QgsExpressionUtils::isIntSafe( val ) )
 
  124         return QVariant( - QgsExpressionUtils::getIntValue( val, parent ) );
 
  125       else if ( QgsExpressionUtils::isDoubleSafe( val ) )
 
  126         return QVariant( - QgsExpressionUtils::getDoubleValue( val, parent ) );
 
  140   return mOperand->prepare( parent, context );
 
  146     return QStringLiteral( 
"%1 ( %2 )" ).arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
 
  148     return QStringLiteral( 
"%1 %2" ).arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
 
  154     return QSet< QString >();
 
  156   return mOperand->referencedColumns();
 
  161   return mOperand->referencedVariables();
 
  166   return mOperand->referencedFunctions();
 
  171   QList<const QgsExpressionNode *> lst;
 
  173   lst += mOperand->nodes();
 
  179   return mOperand->needsGeometry();
 
  191   return mOperand->isStatic( parent, context );
 
  196   return UNARY_OPERATOR_TEXT[mOp];
 
  203   QVariant vL = mOpLeft->eval( parent, context );
 
  206   if ( mOp == boAnd || mOp == boOr )
 
  208     QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent );
 
  210     if ( mOp == boAnd && tvlL == QgsExpressionUtils::False )
 
  212     if ( mOp == boOr && tvlL == QgsExpressionUtils::True )
 
  216   QVariant vR = mOpRight->eval( parent, context );
 
  222       if ( vL.type() == QVariant::String && vR.type() == QVariant::String )
 
  224         QString sL = QgsExpressionUtils::isNull( vL ) ? QString() : QgsExpressionUtils::getStringValue( vL, parent );
 
  226         QString sR = QgsExpressionUtils::isNull( vR ) ? QString() : QgsExpressionUtils::getStringValue( vR, parent );
 
  228         return QVariant( sL + sR );
 
  237       if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
 
  239       else if ( mOp != boDiv && QgsExpressionUtils::isIntSafe( vL ) && QgsExpressionUtils::isIntSafe( vR ) )
 
  242         qlonglong iL = QgsExpressionUtils::getIntValue( vL, parent );
 
  244         qlonglong iR = QgsExpressionUtils::getIntValue( vR, parent );
 
  247         if ( mOp == boMod && iR == 0 )
 
  250         return QVariant( computeInt( iL, iR ) );
 
  252       else if ( QgsExpressionUtils::isDateTimeSafe( vL ) && QgsExpressionUtils::isIntervalSafe( vR ) )
 
  254         QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
 
  256         QgsInterval iL = QgsExpressionUtils::getInterval( vR, parent );
 
  258         if ( mOp == boDiv || mOp == boMul || mOp == boMod )
 
  260           parent->
setEvalErrorString( tr( 
"Can't perform /, *, or % on DateTime and Interval" ) );
 
  263         return QVariant( computeDateTimeFromInterval( dL, &iL ) );
 
  265       else if ( mOp == boPlus && ( ( vL.type() == QVariant::Date && vR.type() == QVariant::Time ) ||
 
  266                                    ( vR.type() == QVariant::Date && vL.type() == QVariant::Time ) ) )
 
  268         QDate date = QgsExpressionUtils::getDateValue( vL.type() == QVariant::Date ? vL : vR, parent );
 
  270         QTime time = QgsExpressionUtils::getTimeValue( vR.type() == QVariant::Time ? vR : vL, parent );
 
  272         QDateTime dt = QDateTime( date, time );
 
  273         return QVariant( dt );
 
  275       else if ( mOp == boMinus && vL.type() == QVariant::Date && vR.type() == QVariant::Date )
 
  277         QDate date1 = QgsExpressionUtils::getDateValue( vL, parent );
 
  279         QDate date2 = QgsExpressionUtils::getDateValue( vR, parent );
 
  281         return date1 - date2;
 
  283       else if ( mOp == boMinus && vL.type() == QVariant::Time && vR.type() == QVariant::Time )
 
  285         QTime time1 = QgsExpressionUtils::getTimeValue( vL, parent );
 
  287         QTime time2 = QgsExpressionUtils::getTimeValue( vR, parent );
 
  289         return time1 - time2;
 
  291       else if ( mOp == boMinus && vL.type() == QVariant::DateTime && vR.type() == QVariant::DateTime )
 
  293         QDateTime datetime1 = QgsExpressionUtils::getDateTimeValue( vL, parent );
 
  295         QDateTime datetime2 = QgsExpressionUtils::getDateTimeValue( vR, parent );
 
  297         return datetime1 - datetime2;
 
  302         double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
 
  304         double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
 
  306         if ( ( mOp == boDiv || mOp == boMod ) && fR == 0. )
 
  308         return QVariant( computeDouble( fL, fR ) );
 
  314       double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
 
  316       double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
 
  320       return QVariant( qlonglong( std::floor( fL / fR ) ) );
 
  323       if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
 
  327         double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
 
  329         double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
 
  331         return QVariant( std::pow( fL, fR ) );
 
  336       QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
 
  338       return  QgsExpressionUtils::tvl2variant( QgsExpressionUtils::AND[tvlL][tvlR] );
 
  343       QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
 
  345       return  QgsExpressionUtils::tvl2variant( QgsExpressionUtils::OR[tvlL][tvlR] );
 
  354       if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
 
  358       else if ( QgsExpressionUtils::isList( vL ) || QgsExpressionUtils::isList( vR ) )
 
  361         if ( !QgsExpressionUtils::isList( vL ) || !QgsExpressionUtils::isList( vR ) )
 
  365         QVariantList lL = vL.toList();
 
  366         QVariantList lR = vR.toList();
 
  367         for ( 
int i = 0; i < lL.length() && i < lR.length(); i++ )
 
  369           if ( QgsExpressionUtils::isNull( lL.at( i ) ) && QgsExpressionUtils::isNull( lR.at( i ) ) )
 
  372           if ( QgsExpressionUtils::isNull( lL.at( i ) ) || QgsExpressionUtils::isNull( lR.at( i ) ) )
 
  382                 return QgsExpressionUtils::isNull( lR.at( i ) );
 
  385                 return QgsExpressionUtils::isNull( lL.at( i ) );
 
  395           QVariant eq = eqNode.
eval( parent, context );
 
  397           if ( eq == TVL_False )
 
  401             QVariant v = node.
eval( parent, context );
 
  411             return lL.length() == lR.length();
 
  413             return lL.length() != lR.length();
 
  415             return lL.length() < lR.length();
 
  417             return lL.length() > lR.length();
 
  419             return lL.length() <= lR.length();
 
  421             return lL.length() >= lR.length();
 
  427       else if ( ( vL.type() == QVariant::DateTime && vR.type() == QVariant::DateTime ) )
 
  429         QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
 
  431         QDateTime dR = QgsExpressionUtils::getDateTimeValue( vR, parent );
 
  438         dL.setTimeSpec( Qt::UTC );
 
  439         dR.setTimeSpec( Qt::UTC );
 
  441         return compare( dR.msecsTo( dL ) ) ? TVL_True : TVL_False;
 
  443       else if ( ( vL.type() == QVariant::Date && vR.type() == QVariant::Date ) )
 
  445         const QDate dL = QgsExpressionUtils::getDateValue( vL, parent );
 
  447         const QDate dR = QgsExpressionUtils::getDateValue( vR, parent );
 
  449         return compare( dR.daysTo( dL ) ) ? TVL_True : TVL_False;
 
  451       else if ( ( vL.type() == QVariant::Time && vR.type() == QVariant::Time ) )
 
  453         const QTime dL = QgsExpressionUtils::getTimeValue( vL, parent );
 
  455         const QTime dR = QgsExpressionUtils::getTimeValue( vR, parent );
 
  457         return compare( dR.msecsTo( dL ) ) ? TVL_True : TVL_False;
 
  459       else if ( ( vL.type() != QVariant::String || vR.type() != QVariant::String ) &&
 
  460                 QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) )
 
  464         double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
 
  466         double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
 
  468         return compare( fL - fR ) ? TVL_True : TVL_False;
 
  473         double fL = QgsExpressionUtils::getInterval( vL, parent ).seconds();
 
  475         double fR = QgsExpressionUtils::getInterval( vR, parent ).seconds();
 
  477         return compare( fL - fR ) ? TVL_True : TVL_False;
 
  482         QString sL = QgsExpressionUtils::getStringValue( vL, parent );
 
  484         QString sR = QgsExpressionUtils::getStringValue( vR, parent );
 
  486         int diff = QString::compare( sL, sR );
 
  487         return compare( diff ) ? TVL_True : TVL_False;
 
  492       if ( QgsExpressionUtils::isNull( vL ) && QgsExpressionUtils::isNull( vR ) ) 
 
  493         return ( mOp == boIs ? TVL_True : TVL_False );
 
  494       else if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) ) 
 
  495         return ( mOp == boIs ? TVL_False : TVL_True );
 
  499         if ( QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) &&
 
  500              ( vL.type() != QVariant::String || vR.type() != QVariant::String ) )
 
  502           double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
 
  504           double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
 
  510           QString sL = QgsExpressionUtils::getStringValue( vL, parent );
 
  512           QString sR = QgsExpressionUtils::getStringValue( vR, parent );
 
  514           equal = QString::compare( sL, sR ) == 0;
 
  517           return mOp == boIs ? TVL_True : TVL_False;
 
  519           return mOp == boIs ? TVL_False : TVL_True;
 
  527       if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
 
  531         QString 
str    = QgsExpressionUtils::getStringValue( vL, parent );
 
  533         QString regexp = QgsExpressionUtils::getStringValue( vR, parent );
 
  537         if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike ) 
 
  541           if ( esc_regexp.startsWith( 
'%' ) )
 
  543             esc_regexp.replace( 0, 1, QStringLiteral( 
".*" ) );
 
  545           const thread_local QRegularExpression rx1( QStringLiteral( 
"[^\\\\](%)" ) );
 
  547           while ( ( pos = esc_regexp.indexOf( rx1, pos ) ) != -1 )
 
  549             esc_regexp.replace( pos + 1, 1, QStringLiteral( 
".*" ) );
 
  552           const thread_local QRegularExpression rx2( QStringLiteral( 
"\\\\%" ) );
 
  553           esc_regexp.replace( rx2, QStringLiteral( 
"%" ) );
 
  554           if ( esc_regexp.startsWith( 
'_' ) )
 
  556             esc_regexp.replace( 0, 1, QStringLiteral( 
"." ) );
 
  558           const thread_local QRegularExpression rx3( QStringLiteral( 
"[^\\\\](_)" ) );
 
  560           while ( ( pos = esc_regexp.indexOf( rx3, pos ) ) != -1 )
 
  562             esc_regexp.replace( pos + 1, 1, 
'.' );
 
  565           esc_regexp.replace( QLatin1String( 
"\\\\_" ), QLatin1String( 
"_" ) );
 
  567           matches = QRegularExpression( QRegularExpression::anchoredPattern( esc_regexp ), mOp == boLike || mOp == boNotLike ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption ).match( 
str ).hasMatch();
 
  571           matches = QRegularExpression( regexp ).match( 
str ).hasMatch();
 
  574         if ( mOp == boNotLike || mOp == boNotILike )
 
  579         return matches ? TVL_True : TVL_False;
 
  583       if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
 
  587         QString sL = QgsExpressionUtils::getStringValue( vL, parent );
 
  589         QString sR = QgsExpressionUtils::getStringValue( vR, parent );
 
  591         return QVariant( sL + sR );
 
  598 bool QgsExpressionNodeBinaryOperator::compare( 
double diff )
 
  620 qlonglong QgsExpressionNodeBinaryOperator::computeInt( qlonglong x, qlonglong y )
 
  640 QDateTime QgsExpressionNodeBinaryOperator::computeDateTimeFromInterval( 
const QDateTime &d, 
QgsInterval *i )
 
  645       return d.addSecs( i->
seconds() );
 
  647       return d.addSecs( -i->
seconds() );
 
  654 double QgsExpressionNodeBinaryOperator::computeDouble( 
double x, 
double y )
 
  667       return std::fmod( x, y );
 
  681   bool resL = mOpLeft->prepare( parent, context );
 
  682   bool resR = mOpRight->prepare( parent, context );
 
  728   Q_ASSERT( 
false && 
"unexpected binary operator" );
 
  764   Q_ASSERT( 
false && 
"unexpected binary operator" );
 
  774   QString rdump( mOpRight->dump() );
 
  779     rdump.prepend( 
'(' ).append( 
')' );
 
  783   if ( leftAssociative() )
 
  785     fmt += lOp && ( lOp->
precedence() < precedence() ) ? QStringLiteral( 
"(%1)" ) : QStringLiteral( 
"%1" );
 
  786     fmt += QLatin1String( 
" %2 " );
 
  787     fmt += rOp && ( rOp->
precedence() <= precedence() ) ? QStringLiteral( 
"(%3)" ) : QStringLiteral( 
"%3" );
 
  791     fmt += lOp && ( lOp->
precedence() <= precedence() ) ? QStringLiteral( 
"(%1)" ) : QStringLiteral( 
"%1" );
 
  792     fmt += QLatin1String( 
" %2 " );
 
  793     fmt += rOp && ( rOp->
precedence() < precedence() ) ? QStringLiteral( 
"(%3)" ) : QStringLiteral( 
"%3" );
 
  796   return fmt.arg( mOpLeft->dump(), BINARY_OPERATOR_TEXT[mOp], rdump );
 
  802     return QSet< QString >();
 
  804   return mOpLeft->referencedColumns() + mOpRight->referencedColumns();
 
  809   return mOpLeft->referencedVariables() + mOpRight->referencedVariables();
 
  814   return mOpLeft->referencedFunctions() + mOpRight->referencedFunctions();
 
  819   QList<const QgsExpressionNode *> lst;
 
  821   lst += mOpLeft->nodes() + mOpRight->nodes();
 
  827   return mOpLeft->needsGeometry() || mOpRight->needsGeometry();
 
  839   const bool leftStatic = mOpLeft->isStatic( parent, context );
 
  840   const bool rightStatic = mOpRight->isStatic( parent, context );
 
  842   if ( leftStatic && rightStatic )
 
  854         mOpLeft->prepare( parent, context );
 
  855         if ( mOpLeft->hasCachedStaticValue() )
 
  857           QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
 
  858           if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
 
  866       else if ( rightStatic )
 
  868         mOpRight->prepare( parent, context );
 
  869         if ( mOpRight->hasCachedStaticValue() )
 
  871           QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
 
  872           if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
 
  890         mOpLeft->prepare( parent, context );
 
  891         if ( mOpLeft->hasCachedStaticValue() )
 
  893           QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
 
  894           if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
 
  902       else if ( rightStatic )
 
  904         mOpRight->prepare( parent, context );
 
  905         if ( mOpRight->hasCachedStaticValue() )
 
  907           QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
 
  908           if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
 
  951   if ( mList->count() == 0 )
 
  952     return mNotIn ? TVL_True : TVL_False;
 
  953   QVariant v1 = mNode->eval( parent, context );
 
  955   if ( QgsExpressionUtils::isNull( v1 ) )
 
  958   bool listHasNull = 
false;
 
  960   const QList< QgsExpressionNode * > nodeList = mList->list();
 
  963     QVariant v2 = n->eval( parent, context );
 
  965     if ( QgsExpressionUtils::isNull( v2 ) )
 
  971       if ( ( v1.type() != QVariant::String || v2.type() != QVariant::String ) &&
 
  972            QgsExpressionUtils::isDoubleSafe( v1 ) && QgsExpressionUtils::isDoubleSafe( v2 ) )
 
  976         double f1 = QgsExpressionUtils::getDoubleValue( v1, parent );
 
  978         double f2 = QgsExpressionUtils::getDoubleValue( v2, parent );
 
  984         QString s1 = QgsExpressionUtils::getStringValue( v1, parent );
 
  986         QString s2 = QgsExpressionUtils::getStringValue( v2, parent );
 
  988         equal = QString::compare( s1, s2 ) == 0;
 
  992         return mNotIn ? TVL_False : TVL_True;
 
 1000     return mNotIn ? TVL_True : TVL_False;
 
 1016   bool res = mNode->prepare( parent, context );
 
 1017   const QList< QgsExpressionNode * > nodeList = mList->list();
 
 1020     res = res && n->prepare( parent, context );
 
 1027   return QStringLiteral( 
"%1 %2 IN (%3)" ).arg( mNode->dump(), mNotIn ? 
"NOT" : 
"", mList->dump() );
 
 1039   if ( !mNode->isStatic( parent, context ) )
 
 1042   const QList< QgsExpressionNode * > nodeList = mList->list();
 
 1045     if ( !n->isStatic( parent, context ) )
 
 1056   QString name = QgsExpression::QgsExpression::Functions()[mFnIndex]->name();
 
 1059   QVariant res = fd->
run( mArgs, context, parent, 
this );
 
 1067   : mFnIndex( fnIndex )
 
 1070   if ( functionParams.isEmpty() )
 
 1091     while ( idx < args->names().size() && 
args->
names().at( idx ).isEmpty() )
 
 1098     for ( ; idx < functionParams.count(); ++idx )
 
 1100       int nodeIdx = 
args->
names().indexOf( functionParams.at( idx ).name().toLower() );
 
 1130   bool res = fd->
prepare( 
this, parent, context );
 
 1133     const QList< QgsExpressionNode * > nodeList = mArgs->
list();
 
 1136       res = res && n->prepare( parent, context );
 
 1146     return QStringLiteral( 
"%1%2" ).arg( fd->
name(), fd->
name().startsWith( 
'$' ) ? QString() : QStringLiteral( 
"()" ) ); 
 
 1148     return QStringLiteral( 
"%1(%2)" ).arg( fd->
name(), mArgs ? mArgs->
dump() : QString() ); 
 
 1154     return QSet< QString >();
 
 1162     return functionColumns;
 
 1166   const QList< QgsExpressionNode * > nodeList = mArgs->
list();
 
 1169     if ( fd->
parameters().count() <= paramIndex || !fd->
parameters().at( paramIndex ).isSubExpression() )
 
 1170       functionColumns.unite( n->referencedColumns() );
 
 1174   return functionColumns;
 
 1180   if ( fd->
name() == QLatin1String( 
"var" ) )
 
 1182     if ( !mArgs->
list().isEmpty() )
 
 1186         return QSet<QString>() << var->
value().toString();
 
 1188     return QSet<QString>() << QString();
 
 1192     QSet<QString> functionVariables = QSet<QString>();
 
 1195       return functionVariables;
 
 1197     const QList< QgsExpressionNode * > nodeList = mArgs->
list();
 
 1200       functionVariables.unite( n->referencedVariables() );
 
 1203     return functionVariables;
 
 1210   QSet<QString> functions = QSet<QString>();
 
 1211   functions.insert( fd->
name() );
 
 1216   const QList< QgsExpressionNode * > nodeList = mArgs->
list();
 
 1219     functions.unite( n->referencedFunctions() );
 
 1226   QList<const QgsExpressionNode *> lst;
 
 1231   const QList< QgsExpressionNode * > nodeList = mArgs->
list();
 
 1241   bool needs = QgsExpression::QgsExpression::Functions()[mFnIndex]->usesGeometry( 
this );
 
 1244     const QList< QgsExpressionNode * > nodeList = mArgs->
list();
 
 1246       needs |= n->needsGeometry();
 
 1269   if ( functionParams.isEmpty() )
 
 1276     QSet< int > providedArgs;
 
 1277     QSet< int > handledArgs;
 
 1280     while ( 
args->
names().at( idx ).isEmpty() )
 
 1282       providedArgs << idx;
 
 1288     for ( ; idx < functionParams.count(); ++idx )
 
 1290       int nodeIdx = 
args->
names().indexOf( functionParams.at( idx ).name().toLower() );
 
 1293         if ( !functionParams.at( idx ).optional() )
 
 1295           error = QStringLiteral( 
"No value specified for QgsExpressionFunction::Parameter '%1' for %2" ).arg( functionParams.at( idx ).name(), 
QgsExpression::Functions()[
fnIndex]->name() );
 
 1301         if ( providedArgs.contains( idx ) )
 
 1303           error = QStringLiteral( 
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2" ).arg( functionParams.at( idx ).name(), 
QgsExpression::Functions()[
fnIndex]->name() );
 
 1307       providedArgs << idx;
 
 1308       handledArgs << nodeIdx;
 
 1313     const QStringList nameList = 
args->
names();
 
 1314     for ( 
const QString &name : nameList )
 
 1316       if ( !name.isEmpty() && !functionParams.contains( name ) )
 
 1321       if ( !name.isEmpty() && !handledArgs.contains( idx ) )
 
 1323         int functionIdx = functionParams.indexOf( name );
 
 1324         if ( providedArgs.contains( functionIdx ) )
 
 1326           error = QStringLiteral( 
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2" ).arg( functionParams.at( functionIdx ).name(), 
QgsExpression::Functions()[
fnIndex]->name() );
 
 1361   if ( mValue.isNull() )
 
 1362     return QStringLiteral( 
"NULL" );
 
 1364   switch ( mValue.type() )
 
 1367       return QString::number( mValue.toInt() );
 
 1368     case QVariant::Double:
 
 1369       return QString::number( mValue.toDouble() );
 
 1370     case QVariant::LongLong:
 
 1371       return QString::number( mValue.toLongLong() );
 
 1372     case QVariant::String:
 
 1374     case QVariant::Bool:
 
 1375       return mValue.toBool() ? QStringLiteral( 
"TRUE" ) : QStringLiteral( 
"FALSE" );
 
 1377       return tr( 
"[unsupported type: %1; value: %2]" ).arg( mValue.typeName(), mValue.toString() );
 
 1388   return QSet<QString>();
 
 1393   return QSet<QString>();
 
 1398   return QSet<QString>();
 
 1403   QList<const QgsExpressionNode *> lst;
 
 1456       parent->
setEvalErrorString( tr( 
"No feature available for field '%1' evaluation" ).arg( mName ) );
 
 1493   const thread_local QRegularExpression re( QStringLiteral( 
"^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" ) );
 
 1494   const QRegularExpressionMatch match = re.match( mName );
 
 1500   return QSet<QString>() << mName;
 
 1505   return QSet<QString>();
 
 1510   return QSet<QString>();
 
 1515   QList<const QgsExpressionNode *> result;
 
 1542   : mConditions( *conditions )
 
 1543   , mElseExp( elseExp )
 
 1551   qDeleteAll( mConditions );
 
 1561   for ( 
WhenThen *cond : std::as_const( mConditions ) )
 
 1563     QVariant vWhen = cond->mWhenExp->eval( parent, context );
 
 1564     QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( vWhen, parent );
 
 1566     if ( tvl == QgsExpressionUtils::True )
 
 1568       QVariant vRes = cond->mThenExp->eval( parent, context );
 
 1576     QVariant vElse = mElseExp->
eval( parent, context );
 
 1587   bool foundAnyNonStaticConditions = 
false;
 
 1588   for ( 
WhenThen *cond : std::as_const( mConditions ) )
 
 1590     const bool res = cond->mWhenExp->prepare( parent, context )
 
 1591                      && cond->mThenExp->prepare( parent, context );
 
 1595     foundAnyNonStaticConditions |= !cond->mWhenExp->hasCachedStaticValue();
 
 1596     if ( !foundAnyNonStaticConditions && QgsExpressionUtils::getTVLValue( cond->mWhenExp->cachedStaticValue(), parent ) == QgsExpressionUtils::True )
 
 1600       if ( cond->mThenExp->hasCachedStaticValue() )
 
 1619     const bool res = mElseExp->
prepare( parent, context );
 
 1623     if ( !foundAnyNonStaticConditions )
 
 1647   QString msg( QStringLiteral( 
"CASE" ) );
 
 1648   for ( 
WhenThen *cond : mConditions )
 
 1650     msg += QStringLiteral( 
" WHEN %1 THEN %2" ).arg( cond->mWhenExp->dump(), cond->mThenExp->dump() );
 
 1653     msg += QStringLiteral( 
" ELSE %1" ).arg( mElseExp->
dump() );
 
 1654   msg += QLatin1String( 
" END" );
 
 1661     return QSet< QString >();
 
 1664   for ( 
WhenThen *cond : mConditions )
 
 1666     lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
 
 1678   for ( 
WhenThen *cond : mConditions )
 
 1680     lst += cond->mWhenExp->referencedVariables() + cond->mThenExp->referencedVariables();
 
 1692   for ( 
WhenThen *cond : mConditions )
 
 1694     lst += cond->mWhenExp->referencedFunctions() + cond->mThenExp->referencedFunctions();
 
 1705   QList<const QgsExpressionNode *> lst;
 
 1707   for ( 
WhenThen *cond : mConditions )
 
 1709     lst += cond->mWhenExp->nodes() + cond->mThenExp->nodes();
 
 1713     lst += mElseExp->
nodes();
 
 1720   for ( 
WhenThen *cond : mConditions )
 
 1722     if ( cond->mWhenExp->needsGeometry() ||
 
 1723          cond->mThenExp->needsGeometry() )
 
 1746     if ( !wt->mWhenExp->isStatic( parent, context ) || !wt->mThenExp->isStatic( parent, context ) )
 
 1751     return mElseExp->
isStatic( parent, context );
 
 1759     return QSet< QString >();
 
 1762   const QList< QgsExpressionNode * > nodeList = mList->
list();
 
 1764     lst.unite( n->referencedColumns() );
 
 1771   const QList< QgsExpressionNode * > nodeList = mList->
list();
 
 1773     lst.unite( n->referencedVariables() );
 
 1780   const QList< QgsExpressionNode * > nodeList = mList->
list();
 
 1782     lst.unite( n->referencedFunctions() );
 
 1788   QList<const QgsExpressionNode *> lst;
 
 1790   const QList< QgsExpressionNode * > nodeList = mList->
list();
 
 1797   : mWhenExp( whenExp )
 
 1798   , mThenExp( thenExp )
 
 1810   return new WhenThen( mWhenExp->clone(), mThenExp->clone() );
 
 1815   return BINARY_OPERATOR_TEXT[mOp];
 
 1822   const QVariant container = mContainer->eval( parent, context );
 
 1824   const QVariant index = mIndex->eval( parent, context );
 
 1827   switch ( container.type() )
 
 1830       return QgsExpressionUtils::getMapValue( container, parent ).value( index.toString() );
 
 1832     case QVariant::List:
 
 1833     case QVariant::StringList:
 
 1835       const QVariantList list = QgsExpressionUtils::getListValue( container, parent );
 
 1836       qlonglong pos = QgsExpressionUtils::getIntValue( index, parent );
 
 1837       if ( pos >= list.length() || pos < -list.length() )
 
 1844         pos += list.length();
 
 1847       return list.at( pos );
 
 1851       if ( !container.isNull() )
 
 1864   bool resC = mContainer->prepare( parent, context );
 
 1865   bool resV = mIndex->prepare( parent, context );
 
 1866   return resC && resV;
 
 1871   return QStringLiteral( 
"%1[%2]" ).arg( mContainer->dump(), mIndex->dump() );
 
 1877     return QSet< QString >();
 
 1879   return mContainer->referencedColumns() + mIndex->referencedColumns();
 
 1884   return mContainer->referencedVariables() + mIndex->referencedVariables();
 
 1889   return mContainer->referencedFunctions() + mIndex->referencedFunctions();
 
 1894   QList<const QgsExpressionNode *> lst;
 
 1896   lst += mContainer->nodes() + mIndex->nodes();
 
 1902   return mContainer->needsGeometry() || mIndex->needsGeometry();
 
 1914   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.
Represents a single parameter passed to a function.
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.
static QString qRegExpEscape(const QString &string)
Returns an escaped string matching the behavior of QRegExp::escape.
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.