26#include <QRegularExpression>
30using namespace Qt::StringLiterals;
32const char *QgsExpressionNodeBinaryOperator::BINARY_OPERATOR_TEXT[] = {
34 "OR",
"AND",
"=",
"<>",
"<=",
">=",
"<",
">",
"~",
"LIKE",
"NOT LIKE",
"ILIKE",
"NOT ILIKE",
"IS",
"IS NOT",
"+",
"-",
"*",
"/",
"//",
"%",
"^",
"||"
37const char *QgsExpressionNodeUnaryOperator::UNARY_OPERATOR_TEXT[] = {
46 const QList< QgsExpressionNode * > nodeList = mList->list();
48 needs |= n->needsGeometry();
59 mList.append( node->
node );
60 mNameList.append( cleanNamedNodeName( node->
name ) );
61 mHasNamedNodes =
true;
70 nl->mList.append( node->clone() );
72 nl->mNameList = mNameList;
92QString QgsExpressionNode::NodeList::cleanNamedNodeName(
const QString &name )
94 QString cleaned = name.toLower();
97 if ( cleaned ==
"geom"_L1 )
98 cleaned = u
"geometry"_s;
99 else if ( cleaned ==
"val"_L1 )
100 cleaned = u
"value"_s;
101 else if ( cleaned ==
"geometry a"_L1 )
102 cleaned = u
"geometry1"_s;
103 else if ( cleaned ==
"geometry b"_L1 )
104 cleaned = u
"geometry2"_s;
105 else if ( cleaned ==
"i"_L1 )
106 cleaned = u
"vertex"_s;
107 else if ( cleaned ==
"array_a"_L1 )
108 cleaned = u
"array1"_s;
109 else if ( cleaned ==
"array_b"_L1 )
110 cleaned = u
"array2"_s;
111 else if ( cleaned ==
"point_a"_L1 )
112 cleaned = u
"point1"_s;
113 else if ( cleaned ==
"point_b"_L1 )
114 cleaned = u
"point2"_s;
115 else if ( cleaned ==
"array_prioritize"_L1 )
116 cleaned = u
"priority"_s;
126 QVariant val = mOperand->eval( parent, context );
133 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( val, parent );
135 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::NOT[tvl] );
139 if ( QgsExpressionUtils::isIntSafe( val ) )
140 return QVariant( -QgsExpressionUtils::getIntValue( val, parent ) );
141 else if ( QgsExpressionUtils::isDoubleSafe( val ) )
142 return QVariant( -QgsExpressionUtils::getDoubleValue( val, parent ) );
156 return mOperand->prepare( parent, context );
162 return u
"%1 ( %2 )"_s.arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
164 return u
"%1 %2"_s.arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
170 return QSet< QString >();
172 return mOperand->referencedColumns();
177 return mOperand->referencedVariables();
182 return mOperand->referencedFunctions();
187 QList<const QgsExpressionNode *> lst;
189 lst += mOperand->nodes();
195 return mOperand->needsGeometry();
207 return mOperand->
isStatic( parent, context );
212 return UNARY_OPERATOR_TEXT[mOp];
261QVariant QgsExpressionNodeBinaryOperator::compareNonNullValues( QgsExpression *parent,
const QgsExpressionContext *,
const QVariant &vL,
const QVariant &vR, BinaryOperator op )
263 if ( ( vL.userType() == QMetaType::Type::QDateTime && vR.userType() == QMetaType::Type::QDateTime ) )
265 QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
267 QDateTime dR = QgsExpressionUtils::getDateTimeValue( vR, parent );
274 dL.setTimeSpec( Qt::UTC );
275 dR.setTimeSpec( Qt::UTC );
279 else if ( ( vL.userType() == QMetaType::Type::QDate && vR.userType() == QMetaType::Type::QDate ) )
281 const QDate dL = QgsExpressionUtils::getDateValue( vL, parent );
283 const QDate dR = QgsExpressionUtils::getDateValue( vR, parent );
287 else if ( ( vL.userType() == QMetaType::Type::QTime && vR.userType() == QMetaType::Type::QTime ) )
289 const QTime dL = QgsExpressionUtils::getTimeValue( vL, parent );
291 const QTime dR = QgsExpressionUtils::getTimeValue( vR, parent );
293 return compareOp<int>( dR.msecsTo( dL ), op ) ? TVL_True : TVL_False;
295 else if ( ( vL.userType() != QMetaType::Type::QString || vR.userType() != QMetaType::Type::QString ) && QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) )
299 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
301 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
306 else if ( vL.userType() == QMetaType::Type::Bool || vR.userType() == QMetaType::Type::Bool )
328 const bool vLBool = vL.toBool();
329 const bool vRBool = vR.toBool();
333 return vLBool == vRBool ? TVL_True : TVL_False;
335 return vLBool != vRBool ? TVL_True : TVL_False;
337 return vLBool < vRBool ? TVL_True : TVL_False;
339 return vLBool <= vRBool ? TVL_True : TVL_False;
341 return vLBool > vRBool ? TVL_True : TVL_False;
343 return vLBool >= vRBool ? TVL_True : TVL_False;
368 else if ( vL.userType() == qMetaTypeId< QgsInterval>() && vR.userType() == qMetaTypeId< QgsInterval>() )
370 double fL = QgsExpressionUtils::getInterval( vL, parent ).seconds();
372 double fR = QgsExpressionUtils::getInterval( vR, parent ).seconds();
379 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
381 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
383 int diff = QString::compare( sL, sR );
390 QVariant vL = mOpLeft->eval( parent, context );
395 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent );
397 if ( mOp ==
boAnd && tvlL == QgsExpressionUtils::False )
399 if ( mOp ==
boOr && tvlL == QgsExpressionUtils::True )
403 QVariant vR = mOpRight->eval( parent, context );
409 if ( vL.userType() == QMetaType::Type::QString && vR.userType() == QMetaType::Type::QString )
411 QString sL = QgsExpressionUtils::isNull( vL ) ? QString() : QgsExpressionUtils::getStringValue( vL, parent );
413 QString sR = QgsExpressionUtils::isNull( vR ) ? QString() : QgsExpressionUtils::getStringValue( vR, parent );
415 return QVariant( sL + sR );
424 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
426 else if ( mOp !=
boDiv && QgsExpressionUtils::isIntSafe( vL ) && QgsExpressionUtils::isIntSafe( vR ) )
429 qlonglong iL = QgsExpressionUtils::getIntValue( vL, parent );
431 qlonglong iR = QgsExpressionUtils::getIntValue( vR, parent );
434 if ( mOp ==
boMod && iR == 0 )
437 return QVariant( computeInt( iL, iR ) );
439 else if ( QgsExpressionUtils::isDateTimeSafe( vL ) && QgsExpressionUtils::isIntervalSafe( vR ) )
441 QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
443 QgsInterval iL = QgsExpressionUtils::getInterval( vR, parent );
447 parent->
setEvalErrorString( tr(
"Can't perform /, *, or % on DateTime and Interval" ) );
450 return QVariant( computeDateTimeFromInterval( dL, &iL ) );
453 && ( ( vL.userType() == QMetaType::Type::QDate && vR.userType() == QMetaType::Type::QTime ) || ( vR.userType() == QMetaType::Type::QDate && vL.userType() == QMetaType::Type::QTime ) ) )
455 QDate date = QgsExpressionUtils::getDateValue( vL.userType() == QMetaType::Type::QDate ? vL : vR, parent );
457 QTime time = QgsExpressionUtils::getTimeValue( vR.userType() == QMetaType::Type::QTime ? vR : vL, parent );
459 QDateTime dt = QDateTime( date, time );
460 return QVariant( dt );
462 else if ( mOp ==
boMinus && vL.userType() == QMetaType::Type::QDate && vR.userType() == QMetaType::Type::QDate )
464 QDate date1 = QgsExpressionUtils::getDateValue( vL, parent );
466 QDate date2 = QgsExpressionUtils::getDateValue( vR, parent );
468 return date1 - date2;
470 else if ( mOp ==
boMinus && vL.userType() == QMetaType::Type::QTime && vR.userType() == QMetaType::Type::QTime )
472 QTime time1 = QgsExpressionUtils::getTimeValue( vL, parent );
474 QTime time2 = QgsExpressionUtils::getTimeValue( vR, parent );
476 return time1 - time2;
478 else if ( mOp ==
boMinus && vL.userType() == QMetaType::Type::QDateTime && vR.userType() == QMetaType::Type::QDateTime )
480 QDateTime datetime1 = QgsExpressionUtils::getDateTimeValue( vL, parent );
482 QDateTime datetime2 = QgsExpressionUtils::getDateTimeValue( vR, parent );
486 else if ( ( mOp ==
boPlus || mOp ==
boMinus || mOp ==
boMul || mOp ==
boDiv ) && vL.userType() == QMetaType::Type::QColor && vR.userType() == QMetaType::Type::QColor )
488 bool isQColor =
false;
489 const QColor colorL = QgsExpressionUtils::getColorValue( vL, parent, isQColor );
491 const QColor colorR = QgsExpressionUtils::getColorValue( vR, parent, isQColor );
494 if ( !colorL.isValid() || !colorR.isValid() )
500 QColor::Spec colorLSpec = colorL.spec();
501 QColor::Spec colorRSpec = colorR.spec();
503 switch ( colorLSpec )
507 if ( colorRSpec != QColor::Cmyk )
509 parent->
setEvalErrorString( tr(
"Cannot combine a CMYK color with a non-CMYK color" ) );
513 float lc, lm, ly, lk, la, rc, rm, ry, rk, ra;
514 colorL.getCmykF( &lc, &lm, &ly, &lk, &la );
515 colorR.getCmykF( &rc, &rm, &ry, &rk, &ra );
516 return QColor::fromCmykF(
517 static_cast<float>( std::clamp( computeDouble( lc, rc ), 0.0, 1.0 ) ),
518 static_cast<float>( std::clamp( computeDouble( lm, rm ), 0.0, 1.0 ) ),
519 static_cast<float>( std::clamp( computeDouble( ly, ry ), 0.0, 1.0 ) ),
520 static_cast<float>( std::clamp( computeDouble( lk, rk ), 0.0, 1.0 ) ),
527 case QColor::ExtendedRgb:
529 if ( colorRSpec == QColor::Cmyk )
531 parent->
setEvalErrorString( tr(
"Cannot combine a non-CMYK color with a CMYK color" ) );
535 float lr, lg, lb, la, rr, rg, rb, ra;
536 colorL.getRgbF( &lr, &lg, &lb, &la );
537 colorR.getRgbF( &rr, &rg, &rb, &ra );
538 QColor result = QColor::
539 fromRgbF(
static_cast<float>( std::clamp( computeDouble( lr, rr ), 0.0, 1.0 ) ),
static_cast<float>( std::clamp( computeDouble( lg, rg ), 0.0, 1.0 ) ),
static_cast<float>( std::clamp( computeDouble( lb, rb ), 0.0, 1.0 ) ), la );
547 && ( ( ( vL.userType() == QMetaType::Type::QColor ) && QgsExpressionUtils::isDoubleSafe( vR ) ) || ( ( vR.userType() == QMetaType::Type::QColor ) && QgsExpressionUtils::isDoubleSafe( vL ) ) ) )
549 const bool colorLeft = vL.userType() == QMetaType::Type::QColor;
550 bool isQColor =
false;
551 const QColor color = QgsExpressionUtils::getColorValue( colorLeft ? vL : vR, parent, isQColor );
554 if ( !color.isValid() )
560 const double value = QgsExpressionUtils::getDoubleValue( colorLeft ? vR : vL, parent );
563 if ( mOp ==
boDiv && value == 0.0 )
569 if ( !colorLeft && mOp ==
boDiv )
571 parent->
setEvalErrorString( tr(
"Can't perform / with a color value on the right" ) );
575 switch ( color.spec() )
580 color.getCmykF( &
c, &m, &y, &k, &a );
581 const double dc =
static_cast<double>(
c );
582 const double dm =
static_cast<double>( m );
583 const double dy =
static_cast<double>( y );
584 const double dk =
static_cast<double>( k );
586 return QColor::fromCmykF(
587 static_cast<float>( std::clamp( computeDouble( colorLeft ? dc : value, colorLeft ? value : dc ), 0.0, 1.0 ) ),
588 static_cast<float>( std::clamp( computeDouble( colorLeft ? dm : value, colorLeft ? value : dm ), 0.0, 1.0 ) ),
589 static_cast<float>( std::clamp( computeDouble( colorLeft ? dy : value, colorLeft ? value : dy ), 0.0, 1.0 ) ),
590 static_cast<float>( std::clamp( computeDouble( colorLeft ? dk : value, colorLeft ? value : dk ), 0.0, 1.0 ) ),
597 case QColor::ExtendedRgb:
600 color.getRgbF( &r, &g, &b, &a );
601 const double dr =
static_cast<double>( r );
602 const double dg =
static_cast<double>( g );
603 const double db =
static_cast<double>( b );
605 return QColor::fromRgbF(
606 static_cast<float>( std::clamp( computeDouble( colorLeft ? dr : value, colorLeft ? value : dr ), 0.0, 1.0 ) ),
607 static_cast<float>( std::clamp( computeDouble( colorLeft ? dg : value, colorLeft ? value : dg ), 0.0, 1.0 ) ),
608 static_cast<float>( std::clamp( computeDouble( colorLeft ? db : value, colorLeft ? value : db ), 0.0, 1.0 ) ),
619 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
621 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
623 if ( ( mOp ==
boDiv || mOp ==
boMod ) && fR == 0. )
625 return QVariant( computeDouble( fL, fR ) );
631 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
633 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
637 return QVariant( qlonglong( std::floor( fL / fR ) ) );
640 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
644 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
646 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
648 return QVariant( std::pow( fL, fR ) );
653 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
655 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::AND[tvlL][tvlR] );
660 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
662 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::OR[tvlL][tvlR] );
671 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
675 else if ( QgsExpressionUtils::isList( vL ) || QgsExpressionUtils::isList( vR ) )
678 if ( !QgsExpressionUtils::isList( vL ) || !QgsExpressionUtils::isList( vR ) )
682 QVariantList lL = vL.toList();
683 QVariantList lR = vR.toList();
684 for (
int i = 0; i < lL.length() && i < lR.length(); i++ )
686 if ( QgsExpressionUtils::isNull( lL.at( i ) ) && QgsExpressionUtils::isNull( lR.at( i ) ) )
689 if ( QgsExpressionUtils::isNull( lL.at( i ) ) || QgsExpressionUtils::isNull( lR.at( i ) ) )
699 return QgsExpressionUtils::isNull( lR.at( i ) );
702 return QgsExpressionUtils::isNull( lL.at( i ) );
712 QVariant eq = eqNode.
eval( parent, context );
714 if ( eq == TVL_False )
718 QVariant v = node.
eval( parent, context );
728 return lL.length() == lR.length();
730 return lL.length() != lR.length();
732 return lL.length() < lR.length();
734 return lL.length() > lR.length();
736 return lL.length() <= lR.length();
738 return lL.length() >= lR.length();
746 return compareNonNullValues( parent, context, vL, vR, mOp );
752 const bool vLNull = QgsExpressionUtils::isNull( vL );
753 const bool vRNull = QgsExpressionUtils::isNull( vR );
754 if ( vLNull && vRNull )
755 return ( mOp ==
boIs ? TVL_True : TVL_False );
756 else if ( vLNull || vRNull )
757 return ( mOp ==
boIs ? TVL_False : TVL_True );
760 return compareNonNullValues( parent, context, vL, vR, mOp ==
boIs ?
boEQ :
boNE );
769 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
773 QString str = QgsExpressionUtils::getStringValue( vL, parent );
775 QString regexp = QgsExpressionUtils::getStringValue( vR, parent );
783 if ( esc_regexp.startsWith(
'%' ) )
785 esc_regexp.replace( 0, 1, u
".*"_s );
787 const thread_local QRegularExpression rx1( u
"[^\\\\](%)"_s );
789 while ( ( pos = esc_regexp.indexOf( rx1, pos ) ) != -1 )
791 esc_regexp.replace( pos + 1, 1, u
".*"_s );
794 const thread_local QRegularExpression rx2( u
"\\\\%"_s );
795 esc_regexp.replace( rx2, u
"%"_s );
796 if ( esc_regexp.startsWith(
'_' ) )
798 esc_regexp.replace( 0, 1, u
"."_s );
800 const thread_local QRegularExpression rx3( u
"[^\\\\](_)"_s );
802 while ( ( pos = esc_regexp.indexOf( rx3, pos ) ) != -1 )
804 esc_regexp.replace( pos + 1, 1,
'.' );
807 esc_regexp.replace(
"\\\\_"_L1,
"_"_L1 );
810 = QRegularExpression( QRegularExpression::anchoredPattern( esc_regexp ), mOp ==
boLike || mOp ==
boNotLike ? QRegularExpression::DotMatchesEverythingOption : QRegularExpression::DotMatchesEverythingOption | QRegularExpression::CaseInsensitiveOption )
816 matches = QRegularExpression( regexp ).match( str ).hasMatch();
824 return matches ? TVL_True : TVL_False;
828 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
832 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
834 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
836 return QVariant( sL + sR );
843qlonglong QgsExpressionNodeBinaryOperator::computeInt( qlonglong x, qlonglong y )
863QDateTime QgsExpressionNodeBinaryOperator::computeDateTimeFromInterval(
const QDateTime &d, QgsInterval *i )
868 return d.addSecs( i->
seconds() );
870 return d.addSecs( -i->
seconds() );
877double QgsExpressionNodeBinaryOperator::computeDouble(
double x,
double y )
890 return std::fmod( x, y );
908 QMap<QString, QgsExpressionNode::NodeList> orValuesMap;
909 QList<QString> orFieldNames;
925 const QString fieldName =
op->opLeft()->dump();
926 if ( !orValuesMap.contains( fieldName ) )
928 orFieldNames.append( fieldName );
931 orValuesMap[fieldName].append(
op->opRight()->clone() );
936 const QString fieldName =
op->opRight()->dump();
937 if ( !orValuesMap.contains( fieldName ) )
939 orFieldNames.append( fieldName );
942 orValuesMap[fieldName].append(
op->opLeft()->clone() );
948 if ( visitOrNodes(
op->opLeft() ) && visitOrNodes(
op->opRight() ) )
960 const QString fieldName = inOp->node()->dump();
963 const auto nodes = inOp->list()->list();
964 for (
const auto &valueNode : std::as_const(
nodes ) )
972 if ( !orValuesMap.contains( fieldName ) )
974 orFieldNames.append( fieldName );
975 orValuesMap.insert( fieldName, *inOp->list()->clone() );
979 for (
const auto &valueNode : std::as_const(
nodes ) )
981 orValuesMap[fieldName].append( valueNode->clone() );
992 if ( visitOrNodes(
this ) && !orValuesMap.empty() )
994 std::unique_ptr<QgsExpressionNode> currentNode;
995 for (
const auto &fieldName : std::as_const( orFieldNames ) )
997 auto orValuesIt = orValuesMap.find( fieldName );
998 if ( orValuesIt.value().count() == 1 )
1003 currentNode = std::make_unique<QgsExpressionNodeBinaryOperator>(
boOr, currentNode.release(), eqNode.release() );
1007 currentNode = std::move( eqNode );
1015 currentNode = std::make_unique<QgsExpressionNodeBinaryOperator>(
boOr, currentNode.release(), inNode.release() );
1019 currentNode = std::move( inNode );
1032 bool resL = mOpLeft->prepare( parent, context );
1033 bool resR = mOpRight->prepare( parent, context );
1034 return resL && resR;
1079 Q_ASSERT(
false &&
"unexpected binary operator" );
1115 Q_ASSERT(
false &&
"unexpected binary operator" );
1125 QString rdump( mOpRight->dump() );
1130 rdump.prepend(
'(' ).append(
')' );
1147 return fmt.arg( mOpLeft->dump(), BINARY_OPERATOR_TEXT[mOp], rdump );
1153 return QSet< QString >();
1155 return mOpLeft->referencedColumns() + mOpRight->referencedColumns();
1160 return mOpLeft->referencedVariables() + mOpRight->referencedVariables();
1165 return mOpLeft->referencedFunctions() + mOpRight->referencedFunctions();
1170 QList<const QgsExpressionNode *> lst;
1172 lst += mOpLeft->nodes() + mOpRight->nodes();
1178 return mOpLeft->needsGeometry() || mOpRight->needsGeometry();
1190 const bool leftStatic = mOpLeft->
isStatic( parent, context );
1191 const bool rightStatic = mOpRight->isStatic( parent, context );
1193 if ( leftStatic && rightStatic )
1205 mOpLeft->prepare( parent, context );
1206 if ( mOpLeft->hasCachedStaticValue() )
1208 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
1209 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
1217 else if ( rightStatic )
1219 mOpRight->prepare( parent, context );
1220 if ( mOpRight->hasCachedStaticValue() )
1222 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
1223 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
1241 mOpLeft->prepare( parent, context );
1242 if ( mOpLeft->hasCachedStaticValue() )
1244 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
1245 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
1253 else if ( rightStatic )
1255 mOpRight->prepare( parent, context );
1256 if ( mOpRight->hasCachedStaticValue() )
1258 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
1259 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
1302 if ( mList->count() == 0 )
1303 return mNotIn ? TVL_True : TVL_False;
1304 QVariant v1 = mNode->eval( parent, context );
1306 if ( QgsExpressionUtils::isNull( v1 ) )
1309 bool listHasNull =
false;
1311 const QList< QgsExpressionNode * > nodeList = mList->list();
1314 QVariant v2 = n->eval( parent, context );
1316 if ( QgsExpressionUtils::isNull( v2 ) )
1322 if ( ( v1.userType() != QMetaType::Type::QString || v2.userType() != QMetaType::Type::QString ) && QgsExpressionUtils::isDoubleSafe( v1 ) && QgsExpressionUtils::isDoubleSafe( v2 ) )
1326 double f1 = QgsExpressionUtils::getDoubleValue( v1, parent );
1328 double f2 = QgsExpressionUtils::getDoubleValue( v2, parent );
1334 QString s1 = QgsExpressionUtils::getStringValue( v1, parent );
1336 QString s2 = QgsExpressionUtils::getStringValue( v2, parent );
1338 equal = QString::compare( s1, s2 ) == 0;
1342 return mNotIn ? TVL_False : TVL_True;
1350 return mNotIn ? TVL_True : TVL_False;
1363 bool res = mNode->prepare( parent, context );
1364 const QList< QgsExpressionNode * > nodeList = mList->list();
1367 res = res && n->prepare( parent, context );
1374 return u
"%1 %2 IN (%3)"_s.arg( mNode->dump(), mNotIn ?
"NOT" :
"", mList->dump() );
1386 if ( !mNode->isStatic( parent, context ) )
1389 const QList< QgsExpressionNode * > nodeList = mList->
list();
1392 if ( !n->isStatic( parent, context ) )
1403 QString name = QgsExpression::QgsExpression::Functions()[mFnIndex]->name();
1406 QVariant res = fd->
run( mArgs.get(), context, parent,
this );
1419 QMutexLocker locker( &QgsExpression::QgsExpression::sFunctionsMutex );
1422 const int functionParamsSize = functionParams.size();
1423 if ( functionParams.isEmpty() )
1426 mArgs.reset(
args );
1431 mArgs = std::make_unique<NodeList>();
1432 mArgs->reserve( functionParamsSize );
1441 mArgs = std::make_unique<NodeList>();
1442 mArgs->reserve( functionParamsSize );
1445 const QStringList argNames =
args->names();
1446 const QList<QgsExpressionNode *> argList =
args->list();
1449 const int argNamesSize = argNames.size();
1450 while ( idx < argNamesSize && argNames.at( idx ).isEmpty() )
1452 mArgs->append( argList.at( idx )->clone() );
1458 for ( ; idx < functionParamsSize; ++idx )
1461 int nodeIdx = argNames.indexOf( parameter.
name().toLower() );
1469 mArgs->append( argList.at( nodeIdx )->clone() );
1489 bool res = fd->
prepare(
this, parent, context );
1492 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1495 res = res && n->prepare( parent, context );
1505 return u
"%1%2"_s.arg( fd->
name(), fd->
name().startsWith(
'$' ) ? QString() : u
"()"_s );
1507 return u
"%1(%2)"_s.arg( fd->
name(), mArgs ? mArgs->dump() : QString() );
1513 return QSet< QString >();
1521 return functionColumns;
1525 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1528 if ( fd->
parameters().count() <= paramIndex || !fd->
parameters().at( paramIndex ).isSubExpression() )
1529 functionColumns.unite( n->referencedColumns() );
1533 return functionColumns;
1539 if ( fd->
name() ==
"var"_L1 )
1541 if ( !mArgs->list().isEmpty() )
1545 return QSet<QString>() << var->
value().toString();
1547 return QSet<QString>() << QString();
1551 QSet<QString> functionVariables = QSet<QString>();
1554 return functionVariables;
1556 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1559 functionVariables.unite( n->referencedVariables() );
1562 return functionVariables;
1569 QSet<QString> functions = QSet<QString>();
1570 functions.insert( fd->
name() );
1575 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1578 functions.unite( n->referencedFunctions() );
1585 QList<const QgsExpressionNode *> lst;
1590 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1600 bool needs = QgsExpression::QgsExpression::Functions()[mFnIndex]->usesGeometry(
this );
1603 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1605 needs |= n->needsGeometry();
1624 if ( !
args || !
args->hasNamedNodes() )
1628 if ( functionParams.isEmpty() )
1635 QSet< int > providedArgs;
1636 QSet< int > handledArgs;
1639 while (
args->names().at( idx ).isEmpty() )
1641 providedArgs << idx;
1647 for ( ; idx < functionParams.count(); ++idx )
1649 int nodeIdx =
args->names().indexOf( functionParams.at( idx ).name().toLower() );
1652 if ( !functionParams.at( idx ).optional() )
1654 error = u
"No value specified for QgsExpressionFunction::Parameter '%1' for %2"_s.arg( functionParams.at( idx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1660 if ( providedArgs.contains( idx ) )
1662 error = u
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2"_s.arg( functionParams.at( idx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1666 providedArgs << idx;
1667 handledArgs << nodeIdx;
1672 const QStringList nameList =
args->names();
1673 for (
const QString &name : nameList )
1675 if ( !name.isEmpty() && !functionParams.contains( name ) )
1680 if ( !name.isEmpty() && !handledArgs.contains( idx ) )
1682 int functionIdx = functionParams.indexOf( name );
1683 if ( providedArgs.contains( functionIdx ) )
1685 error = u
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2"_s.arg( functionParams.at( functionIdx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1722 switch ( mValue.userType() )
1724 case QMetaType::Type::Int:
1725 return QString::number( mValue.toInt() );
1726 case QMetaType::Type::Double:
1728 case QMetaType::Type::LongLong:
1729 return QString::number( mValue.toLongLong() );
1730 case QMetaType::Type::QString:
1732 case QMetaType::Type::QTime:
1734 case QMetaType::Type::QDate:
1736 case QMetaType::Type::QDateTime:
1738 case QMetaType::Type::Bool:
1739 return mValue.toBool() ? u
"TRUE"_s : u
"FALSE"_s;
1741 return tr(
"[unsupported type: %1; value: %2]" ).arg( mValue.typeName(), mValue.toString() );
1752 return QSet<QString>();
1757 return QSet<QString>();
1762 return QSet<QString>();
1767 QList<const QgsExpressionNode *> lst;
1820 parent->
setEvalErrorString( tr(
"No feature available for field '%1' evaluation" ).arg( mName ) );
1857 const thread_local QRegularExpression re( u
"^[A-Za-z_\\x80-\\xff][A-Za-z0-9_\\x80-\\xff]*$"_s );
1858 const QRegularExpressionMatch match = re.match( mName );
1864 return QSet<QString>() << mName;
1869 return QSet<QString>();
1874 return QSet<QString>();
1879 QList<const QgsExpressionNode *> result;
1914 qDeleteAll( mConditions );
1924 for (
WhenThen *cond : std::as_const( mConditions ) )
1926 QVariant vWhen = cond->mWhenExp->eval( parent, context );
1927 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( vWhen, parent );
1929 if ( tvl == QgsExpressionUtils::True )
1931 QVariant vRes = cond->mThenExp->eval( parent, context );
1939 QVariant vElse = mElseExp->eval( parent, context );
1950 bool foundAnyNonStaticConditions =
false;
1951 for (
WhenThen *cond : std::as_const( mConditions ) )
1953 const bool res = cond->mWhenExp->prepare( parent, context ) && cond->mThenExp->prepare( parent, context );
1957 foundAnyNonStaticConditions |= !cond->mWhenExp->hasCachedStaticValue();
1958 if ( !foundAnyNonStaticConditions && QgsExpressionUtils::getTVLValue( cond->mWhenExp->cachedStaticValue(), parent ) == QgsExpressionUtils::True )
1962 if ( cond->mThenExp->hasCachedStaticValue() )
1981 const bool res = mElseExp->prepare( parent, context );
1985 if ( !foundAnyNonStaticConditions )
1988 if ( mElseExp->hasCachedStaticValue() )
2009 QString msg( u
"CASE"_s );
2010 for (
WhenThen *cond : mConditions )
2012 msg += u
" WHEN %1 THEN %2"_s.arg( cond->mWhenExp->dump(), cond->mThenExp->dump() );
2015 msg += u
" ELSE %1"_s.arg( mElseExp->dump() );
2023 return QSet< QString >();
2026 for (
WhenThen *cond : mConditions )
2028 lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
2032 lst += mElseExp->referencedColumns();
2040 for (
WhenThen *cond : mConditions )
2042 lst += cond->mWhenExp->referencedVariables() + cond->mThenExp->referencedVariables();
2046 lst += mElseExp->referencedVariables();
2054 for (
WhenThen *cond : mConditions )
2056 lst += cond->mWhenExp->referencedFunctions() + cond->mThenExp->referencedFunctions();
2060 lst += mElseExp->referencedFunctions();
2067 QList<const QgsExpressionNode *> lst;
2069 for (
WhenThen *cond : mConditions )
2071 lst += cond->mWhenExp->nodes() + cond->mThenExp->nodes();
2075 lst += mElseExp->nodes();
2082 for (
WhenThen *cond : mConditions )
2084 if ( cond->mWhenExp->needsGeometry() || cond->mThenExp->needsGeometry() )
2088 return mElseExp && mElseExp->needsGeometry();
2107 if ( !wt->mWhenExp->isStatic( parent, context ) || !wt->mThenExp->isStatic( parent, context ) )
2112 return mElseExp->
isStatic( parent, context );
2120 return QSet< QString >();
2122 QSet<QString> lst( mNode->referencedColumns() );
2123 const QList< QgsExpressionNode * > nodeList = mList->list();
2125 lst.unite( n->referencedColumns() );
2131 QSet<QString> lst( mNode->referencedVariables() );
2132 const QList< QgsExpressionNode * > nodeList = mList->list();
2134 lst.unite( n->referencedVariables() );
2140 QSet<QString> lst( mNode->referencedFunctions() );
2141 const QList< QgsExpressionNode * > nodeList = mList->list();
2143 lst.unite( n->referencedFunctions() );
2149 QList<const QgsExpressionNode *> lst;
2151 const QList< QgsExpressionNode * > nodeList = mList->list();
2168 bool res = mNode->prepare( parent, context );
2169 res = res && mLowerBound->prepare( parent, context );
2170 res = res && mHigherBound->prepare( parent, context );
2176 const QVariant nodeVal = mNode->eval( parent, context );
2185 const QVariant lowBoundValue = lowBound.
eval( parent, context );
2186 const bool lowBoundBool { lowBoundValue.toBool() };
2190 return QVariant( mNegate );
2194 const QVariant highBoundValue = highBound.
eval( parent, context );
2201 const bool highBoundBool { highBoundValue.toBool() };
2209 return QVariant( mNegate );
2218 return QVariant( mNegate );
2221 const bool res { lowBoundBool && highBoundBool };
2222 return mNegate ? QVariant( !res ) : QVariant( res );
2227 return u
"%1 %2 %3 AND %4"_s.arg( mNode->dump(), mNegate ? u
"NOT BETWEEN"_s : u
"BETWEEN"_s, mLowerBound->dump(), mHigherBound->dump() );
2232 QSet<QString> lst( mNode->referencedVariables() );
2233 lst.unite( mLowerBound->referencedVariables() );
2234 lst.unite( mHigherBound->referencedVariables() );
2240 QSet<QString> lst( mNode->referencedFunctions() );
2241 lst.unite( mLowerBound->referencedFunctions() );
2242 lst.unite( mHigherBound->referencedFunctions() );
2248 return {
this, mLowerBound.get(), mHigherBound.get() };
2253 QSet<QString> lst( mNode->referencedColumns() );
2254 lst.unite( mLowerBound->referencedColumns() );
2255 lst.unite( mHigherBound->referencedColumns() );
2261 if ( mNode->needsGeometry() )
2264 if ( mLowerBound->needsGeometry() )
2267 if ( mHigherBound->needsGeometry() )
2282 if ( !mNode->isStatic( parent, context ) )
2285 if ( !mLowerBound->isStatic( parent, context ) )
2288 if ( !mHigherBound->isStatic( parent, context ) )
2296 return mLowerBound.get();
2301 return mHigherBound.get();
2319 return new WhenThen( mWhenExp->clone(), mThenExp->clone() );
2324 return BINARY_OPERATOR_TEXT[mOp];
2331 const QVariant
container = mContainer->eval( parent, context );
2333 const QVariant
index = mIndex->eval( parent, context );
2338 case QMetaType::Type::QVariantMap:
2339 return QgsExpressionUtils::getMapValue(
container, parent ).value(
index.toString() );
2341 case QMetaType::Type::QVariantList:
2342 case QMetaType::Type::QStringList:
2344 const QVariantList list = QgsExpressionUtils::getListValue(
container, parent );
2345 qlonglong pos = QgsExpressionUtils::getIntValue(
index, parent );
2346 if ( pos >= list.length() || pos < -list.length() )
2353 pos += list.length();
2356 return list.at( pos );
2361 parent->
setEvalErrorString( tr(
"[] can only be used with map or array values, not %1" ).arg( QMetaType::typeName(
static_cast<QMetaType::Type
>(
container.userType() ) ) ) );
2373 bool resC = mContainer->prepare( parent, context );
2374 bool resV = mIndex->prepare( parent, context );
2375 return resC && resV;
2380 return u
"%1[%2]"_s.arg( mContainer->dump(), mIndex->dump() );
2386 return QSet< QString >();
2388 return mContainer->referencedColumns() + mIndex->referencedColumns();
2393 return mContainer->referencedVariables() + mIndex->referencedVariables();
2398 return mContainer->referencedFunctions() + mIndex->referencedFunctions();
2403 QList<const QgsExpressionNode *> lst;
2405 lst += mContainer->nodes() + mIndex->nodes();
2411 return mContainer->needsGeometry() || mIndex->needsGeometry();
2423 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.
QVariant defaultValue() const
Returns the default value for the parameter.
QString name() const
Returns the name of the parameter.
An 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.
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.
bool negate() const
Returns true if the predicate is an exclusion test (NOT BETWEEN).
QgsExpressionNode * lowerBound() const
Returns the lower bound expression node of the range.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in 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 > 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 * higherBound() const
Returns the higher bound expression node of the range.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
~QgsExpressionNodeBetweenOperator() override
QgsExpressionNodeBetweenOperator(QgsExpressionNode *node, QgsExpressionNode *nodeLowerBound, QgsExpressionNode *nodeHigherBound, bool negate=false)
This node tests if the result of node is between the result of nodeLowerBound and nodeHigherBound nod...
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.
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.
QgsExpressionNodeBinaryOperator::BinaryOperator op() const
Returns the binary operator.
QgsExpressionNode * clone() const override
Generate a clone of this node.
QString text() const
Returns a the name of this operator without the operands.
QgsExpressionNodeBinaryOperator(QgsExpressionNodeBinaryOperator::BinaryOperator op, QgsExpressionNode *opLeft, QgsExpressionNode *opRight)
Binary combination of the left and the right with op.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
BinaryOperator
list of binary operators
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
An expression node which takes its 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.
QgsExpressionNode * thenExp() const
The expression node that makes the THEN result part of the condition.
QgsExpressionNode * whenExp() const
The expression that makes the WHEN part of the condition.
QgsExpressionNodeCondition::WhenThen * clone() const
Gets a deep copy of this WhenThen combination.
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.
QgsExpressionNode * elseExp() const
The ELSE expression used for the condition.
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.
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(QgsExpressionNode *node, QgsExpressionNode::NodeList *list, bool notin=false)
This node tests if the result of node is in the result of list.
~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.
QgsExpressionNode::NodeList * list() const
Returns the list of nodes to search for matching values within.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
QgsExpressionNodeIndexOperator(QgsExpressionNode *container, QgsExpressionNode *index)
Constructor for QgsExpressionNodeIndexOperator.
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.
QgsExpressionNode * index() const
Returns the index node, representing an array element index or map key.
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.
QgsExpressionNode * container() const
Returns the container node, representing an array or map value.
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.
QgsExpressionNodeUnaryOperator(QgsExpressionNodeUnaryOperator::UnaryOperator op, QgsExpressionNode *operand)
A node unary operator is modifying the value of operand by negating it with op.
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.
virtual QString dump() const
Returns a string dump of the expression node.
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.
bool hasCachedStaticValue() const
Returns true if the node can be replaced by a static cached value.
QVariant eval(QgsExpression *parent, const QgsExpressionContext *context)
Evaluate this node with the given context and parent.
virtual QgsExpressionNode * clone() const =0
Generate a clone of this node.
bool mHasCachedValue
true if the node has a static, precalculated value.
QVariant mCachedStaticValue
Contains the static, precalculated value for the node if mHasCachedValue is true.
QgsExpressionNode()=default
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.
@ ntBetweenOperator
Between operator.
@ ntIndexOperator
Index operator.
void cloneTo(QgsExpressionNode *target) const
Copies the members of this node to the node provided in target.
Handles 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.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Container of fields for a vector layer.
Q_INVOKABLE 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.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
bool compareOp(T diff, QgsExpressionNodeBinaryOperator::BinaryOperator op)
#define ENSURE_NO_EVAL_ERROR
#define SET_EVAL_ERROR(x)
QgsExpressionNode * node
Node.