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 std::unique_ptr< QgsExpressionNode > simplifiedOperand( mOperand->simplifiedNode() );
208 if ( simplifiedOperand->nodeType() ==
ntLiteral )
212 QVariant result = tempNode.
eval( &parentExp,
nullptr );
224 return mOperand->isStatic( parent, context );
229 return UNARY_OPERATOR_TEXT[mOp];
278QVariant QgsExpressionNodeBinaryOperator::compareNonNullValues( QgsExpression *parent,
const QgsExpressionContext *,
const QVariant &vL,
const QVariant &vR, BinaryOperator op )
280 if ( ( vL.userType() == QMetaType::Type::QDateTime && vR.userType() == QMetaType::Type::QDateTime ) )
282 QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
284 QDateTime dR = QgsExpressionUtils::getDateTimeValue( vR, parent );
291 dL.setTimeSpec( Qt::UTC );
292 dR.setTimeSpec( Qt::UTC );
296 else if ( ( vL.userType() == QMetaType::Type::QDate && vR.userType() == QMetaType::Type::QDate ) )
298 const QDate dL = QgsExpressionUtils::getDateValue( vL, parent );
300 const QDate dR = QgsExpressionUtils::getDateValue( vR, parent );
304 else if ( ( vL.userType() == QMetaType::Type::QTime && vR.userType() == QMetaType::Type::QTime ) )
306 const QTime dL = QgsExpressionUtils::getTimeValue( vL, parent );
308 const QTime dR = QgsExpressionUtils::getTimeValue( vR, parent );
310 return compareOp<int>( dR.msecsTo( dL ), op ) ? TVL_True : TVL_False;
312 else if ( ( vL.userType() != QMetaType::Type::QString || vR.userType() != QMetaType::Type::QString ) && QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) )
316 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
318 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
323 else if ( vL.userType() == QMetaType::Type::Bool || vR.userType() == QMetaType::Type::Bool )
345 const bool vLBool = vL.toBool();
346 const bool vRBool = vR.toBool();
350 return vLBool == vRBool ? TVL_True : TVL_False;
352 return vLBool != vRBool ? TVL_True : TVL_False;
354 return vLBool < vRBool ? TVL_True : TVL_False;
356 return vLBool <= vRBool ? TVL_True : TVL_False;
358 return vLBool > vRBool ? TVL_True : TVL_False;
360 return vLBool >= vRBool ? TVL_True : TVL_False;
385 else if ( vL.userType() == qMetaTypeId< QgsInterval>() && vR.userType() == qMetaTypeId< QgsInterval>() )
387 double fL = QgsExpressionUtils::getInterval( vL, parent ).seconds();
389 double fR = QgsExpressionUtils::getInterval( vR, parent ).seconds();
396 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
398 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
400 int diff = QString::compare( sL, sR );
407 QVariant vL = mOpLeft->eval( parent, context );
412 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent );
414 if ( mOp ==
boAnd && tvlL == QgsExpressionUtils::False )
416 if ( mOp ==
boOr && tvlL == QgsExpressionUtils::True )
420 QVariant vR = mOpRight->eval( parent, context );
426 if ( vL.userType() == QMetaType::Type::QString && vR.userType() == QMetaType::Type::QString )
428 QString sL = QgsExpressionUtils::isNull( vL ) ? QString() : QgsExpressionUtils::getStringValue( vL, parent );
430 QString sR = QgsExpressionUtils::isNull( vR ) ? QString() : QgsExpressionUtils::getStringValue( vR, parent );
432 return QVariant( sL + sR );
441 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
443 else if ( mOp !=
boDiv && QgsExpressionUtils::isIntSafe( vL ) && QgsExpressionUtils::isIntSafe( vR ) )
446 qlonglong iL = QgsExpressionUtils::getIntValue( vL, parent );
448 qlonglong iR = QgsExpressionUtils::getIntValue( vR, parent );
451 if ( mOp ==
boMod && iR == 0 )
454 return QVariant( computeInt( iL, iR ) );
456 else if ( QgsExpressionUtils::isDateTimeSafe( vL ) && QgsExpressionUtils::isIntervalSafe( vR ) )
458 QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
460 QgsInterval iL = QgsExpressionUtils::getInterval( vR, parent );
464 parent->
setEvalErrorString( tr(
"Can't perform /, *, or % on DateTime and Interval" ) );
467 return QVariant( computeDateTimeFromInterval( dL, &iL ) );
470 && ( ( vL.userType() == QMetaType::Type::QDate && vR.userType() == QMetaType::Type::QTime ) || ( vR.userType() == QMetaType::Type::QDate && vL.userType() == QMetaType::Type::QTime ) ) )
472 QDate date = QgsExpressionUtils::getDateValue( vL.userType() == QMetaType::Type::QDate ? vL : vR, parent );
474 QTime time = QgsExpressionUtils::getTimeValue( vR.userType() == QMetaType::Type::QTime ? vR : vL, parent );
476 QDateTime dt = QDateTime( date, time );
477 return QVariant( dt );
479 else if ( mOp ==
boMinus && vL.userType() == QMetaType::Type::QDate && vR.userType() == QMetaType::Type::QDate )
481 QDate date1 = QgsExpressionUtils::getDateValue( vL, parent );
483 QDate date2 = QgsExpressionUtils::getDateValue( vR, parent );
485 return date1 - date2;
487 else if ( mOp ==
boMinus && vL.userType() == QMetaType::Type::QTime && vR.userType() == QMetaType::Type::QTime )
489 QTime time1 = QgsExpressionUtils::getTimeValue( vL, parent );
491 QTime time2 = QgsExpressionUtils::getTimeValue( vR, parent );
493 return time1 - time2;
495 else if ( mOp ==
boMinus && vL.userType() == QMetaType::Type::QDateTime && vR.userType() == QMetaType::Type::QDateTime )
497 QDateTime datetime1 = QgsExpressionUtils::getDateTimeValue( vL, parent );
499 QDateTime datetime2 = QgsExpressionUtils::getDateTimeValue( vR, parent );
503 else if ( ( mOp ==
boPlus || mOp ==
boMinus || mOp ==
boMul || mOp ==
boDiv ) && vL.userType() == QMetaType::Type::QColor && vR.userType() == QMetaType::Type::QColor )
505 bool isQColor =
false;
506 const QColor colorL = QgsExpressionUtils::getColorValue( vL, parent, isQColor );
508 const QColor colorR = QgsExpressionUtils::getColorValue( vR, parent, isQColor );
511 if ( !colorL.isValid() || !colorR.isValid() )
517 QColor::Spec colorLSpec = colorL.spec();
518 QColor::Spec colorRSpec = colorR.spec();
520 switch ( colorLSpec )
524 if ( colorRSpec != QColor::Cmyk )
526 parent->
setEvalErrorString( tr(
"Cannot combine a CMYK color with a non-CMYK color" ) );
530 float lc, lm, ly, lk, la, rc, rm, ry, rk, ra;
531 colorL.getCmykF( &lc, &lm, &ly, &lk, &la );
532 colorR.getCmykF( &rc, &rm, &ry, &rk, &ra );
533 return QColor::fromCmykF(
534 static_cast<float>( std::clamp( computeDouble( lc, rc ), 0.0, 1.0 ) ),
535 static_cast<float>( std::clamp( computeDouble( lm, rm ), 0.0, 1.0 ) ),
536 static_cast<float>( std::clamp( computeDouble( ly, ry ), 0.0, 1.0 ) ),
537 static_cast<float>( std::clamp( computeDouble( lk, rk ), 0.0, 1.0 ) ),
544 case QColor::ExtendedRgb:
546 if ( colorRSpec == QColor::Cmyk )
548 parent->
setEvalErrorString( tr(
"Cannot combine a non-CMYK color with a CMYK color" ) );
552 float lr, lg, lb, la, rr, rg, rb, ra;
553 colorL.getRgbF( &lr, &lg, &lb, &la );
554 colorR.getRgbF( &rr, &rg, &rb, &ra );
555 QColor result = QColor::
556 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 );
564 && ( ( ( vL.userType() == QMetaType::Type::QColor ) && QgsExpressionUtils::isDoubleSafe( vR ) ) || ( ( vR.userType() == QMetaType::Type::QColor ) && QgsExpressionUtils::isDoubleSafe( vL ) ) ) )
566 const bool colorLeft = vL.userType() == QMetaType::Type::QColor;
567 bool isQColor =
false;
568 const QColor color = QgsExpressionUtils::getColorValue( colorLeft ? vL : vR, parent, isQColor );
571 if ( !color.isValid() )
577 const double value = QgsExpressionUtils::getDoubleValue( colorLeft ? vR : vL, parent );
580 if ( mOp ==
boDiv && value == 0.0 )
586 if ( !colorLeft && mOp ==
boDiv )
588 parent->
setEvalErrorString( tr(
"Can't perform / with a color value on the right" ) );
592 switch ( color.spec() )
597 color.getCmykF( &
c, &m, &y, &k, &a );
598 const double dc =
static_cast<double>(
c );
599 const double dm =
static_cast<double>( m );
600 const double dy =
static_cast<double>( y );
601 const double dk =
static_cast<double>( k );
603 return QColor::fromCmykF(
604 static_cast<float>( std::clamp( computeDouble( colorLeft ? dc : value, colorLeft ? value : dc ), 0.0, 1.0 ) ),
605 static_cast<float>( std::clamp( computeDouble( colorLeft ? dm : value, colorLeft ? value : dm ), 0.0, 1.0 ) ),
606 static_cast<float>( std::clamp( computeDouble( colorLeft ? dy : value, colorLeft ? value : dy ), 0.0, 1.0 ) ),
607 static_cast<float>( std::clamp( computeDouble( colorLeft ? dk : value, colorLeft ? value : dk ), 0.0, 1.0 ) ),
614 case QColor::ExtendedRgb:
617 color.getRgbF( &r, &g, &b, &a );
618 const double dr =
static_cast<double>( r );
619 const double dg =
static_cast<double>( g );
620 const double db =
static_cast<double>( b );
622 return QColor::fromRgbF(
623 static_cast<float>( std::clamp( computeDouble( colorLeft ? dr : value, colorLeft ? value : dr ), 0.0, 1.0 ) ),
624 static_cast<float>( std::clamp( computeDouble( colorLeft ? dg : value, colorLeft ? value : dg ), 0.0, 1.0 ) ),
625 static_cast<float>( std::clamp( computeDouble( colorLeft ? db : value, colorLeft ? value : db ), 0.0, 1.0 ) ),
636 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
638 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
640 if ( ( mOp ==
boDiv || mOp ==
boMod ) && fR == 0. )
642 return QVariant( computeDouble( fL, fR ) );
648 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
650 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
654 return QVariant( qlonglong( std::floor( fL / fR ) ) );
657 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
661 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
663 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
665 return QVariant( std::pow( fL, fR ) );
670 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
672 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::AND[tvlL][tvlR] );
677 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
679 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::OR[tvlL][tvlR] );
688 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
692 else if ( QgsExpressionUtils::isList( vL ) || QgsExpressionUtils::isList( vR ) )
695 if ( !QgsExpressionUtils::isList( vL ) || !QgsExpressionUtils::isList( vR ) )
699 QVariantList lL = vL.toList();
700 QVariantList lR = vR.toList();
701 for (
int i = 0; i < lL.length() && i < lR.length(); i++ )
703 if ( QgsExpressionUtils::isNull( lL.at( i ) ) && QgsExpressionUtils::isNull( lR.at( i ) ) )
706 if ( QgsExpressionUtils::isNull( lL.at( i ) ) || QgsExpressionUtils::isNull( lR.at( i ) ) )
716 return QgsExpressionUtils::isNull( lR.at( i ) );
719 return QgsExpressionUtils::isNull( lL.at( i ) );
729 QVariant eq = eqNode.
eval( parent, context );
731 if ( eq == TVL_False )
735 QVariant v = node.
eval( parent, context );
745 return lL.length() == lR.length();
747 return lL.length() != lR.length();
749 return lL.length() < lR.length();
751 return lL.length() > lR.length();
753 return lL.length() <= lR.length();
755 return lL.length() >= lR.length();
763 return compareNonNullValues( parent, context, vL, vR, mOp );
769 const bool vLNull = QgsExpressionUtils::isNull( vL );
770 const bool vRNull = QgsExpressionUtils::isNull( vR );
771 if ( vLNull && vRNull )
772 return ( mOp ==
boIs ? TVL_True : TVL_False );
773 else if ( vLNull || vRNull )
774 return ( mOp ==
boIs ? TVL_False : TVL_True );
777 return compareNonNullValues( parent, context, vL, vR, mOp ==
boIs ?
boEQ :
boNE );
786 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
790 QString str = QgsExpressionUtils::getStringValue( vL, parent );
792 QString regexp = QgsExpressionUtils::getStringValue( vR, parent );
800 if ( esc_regexp.startsWith(
'%' ) )
802 esc_regexp.replace( 0, 1, u
".*"_s );
804 const thread_local QRegularExpression rx1( u
"[^\\\\](%)"_s );
806 while ( ( pos = esc_regexp.indexOf( rx1, pos ) ) != -1 )
808 esc_regexp.replace( pos + 1, 1, u
".*"_s );
811 const thread_local QRegularExpression rx2( u
"\\\\%"_s );
812 esc_regexp.replace( rx2, u
"%"_s );
813 if ( esc_regexp.startsWith(
'_' ) )
815 esc_regexp.replace( 0, 1, u
"."_s );
817 const thread_local QRegularExpression rx3( u
"[^\\\\](_)"_s );
819 while ( ( pos = esc_regexp.indexOf( rx3, pos ) ) != -1 )
821 esc_regexp.replace( pos + 1, 1,
'.' );
824 esc_regexp.replace(
"\\\\_"_L1,
"_"_L1 );
827 = QRegularExpression( QRegularExpression::anchoredPattern( esc_regexp ), mOp ==
boLike || mOp ==
boNotLike ? QRegularExpression::DotMatchesEverythingOption : QRegularExpression::DotMatchesEverythingOption | QRegularExpression::CaseInsensitiveOption )
833 matches = QRegularExpression( regexp ).match( str ).hasMatch();
841 return matches ? TVL_True : TVL_False;
845 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
849 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
851 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
853 return QVariant( sL + sR );
860qlonglong QgsExpressionNodeBinaryOperator::computeInt( qlonglong x, qlonglong y )
880QDateTime QgsExpressionNodeBinaryOperator::computeDateTimeFromInterval(
const QDateTime &d, QgsInterval *i )
885 return d.addSecs( i->
seconds() );
887 return d.addSecs( -i->
seconds() );
894double QgsExpressionNodeBinaryOperator::computeDouble(
double x,
double y )
907 return std::fmod( x, y );
925 QMap<QString, QgsExpressionNode::NodeList> orValuesMap;
926 QList<QString> orFieldNames;
942 const QString fieldName =
op->opLeft()->dump();
943 if ( !orValuesMap.contains( fieldName ) )
945 orFieldNames.append( fieldName );
948 orValuesMap[fieldName].append(
op->opRight()->clone() );
953 const QString fieldName =
op->opRight()->dump();
954 if ( !orValuesMap.contains( fieldName ) )
956 orFieldNames.append( fieldName );
959 orValuesMap[fieldName].append(
op->opLeft()->clone() );
965 if ( visitOrNodes(
op->opLeft() ) && visitOrNodes(
op->opRight() ) )
977 const QString fieldName = inOp->node()->dump();
980 const auto nodes = inOp->list()->list();
981 for (
const auto &valueNode : std::as_const(
nodes ) )
989 if ( !orValuesMap.contains( fieldName ) )
991 orFieldNames.append( fieldName );
992 orValuesMap.insert( fieldName, *inOp->list()->clone() );
996 for (
const auto &valueNode : std::as_const(
nodes ) )
998 orValuesMap[fieldName].append( valueNode->clone() );
1009 if ( visitOrNodes(
this ) && !orValuesMap.empty() )
1011 std::unique_ptr<QgsExpressionNode> currentNode;
1012 for (
const auto &fieldName : std::as_const( orFieldNames ) )
1014 auto orValuesIt = orValuesMap.find( fieldName );
1015 if ( orValuesIt.value().count() == 1 )
1020 currentNode = std::make_unique<QgsExpressionNodeBinaryOperator>(
boOr, currentNode.release(), eqNode.release() );
1024 currentNode = std::move( eqNode );
1032 currentNode = std::make_unique<QgsExpressionNodeBinaryOperator>(
boOr, currentNode.release(), inNode.release() );
1036 currentNode = std::move( inNode );
1049 bool resL = mOpLeft->prepare( parent, context );
1050 bool resR = mOpRight->prepare( parent, context );
1051 return resL && resR;
1096 Q_ASSERT(
false &&
"unexpected binary operator" );
1132 Q_ASSERT(
false &&
"unexpected binary operator" );
1142 QString rdump( mOpRight->dump() );
1147 rdump.prepend(
'(' ).append(
')' );
1164 return fmt.arg( mOpLeft->dump(), BINARY_OPERATOR_TEXT[mOp], rdump );
1170 return QSet< QString >();
1172 return mOpLeft->referencedColumns() + mOpRight->referencedColumns();
1177 return mOpLeft->referencedVariables() + mOpRight->referencedVariables();
1182 return mOpLeft->referencedFunctions() + mOpRight->referencedFunctions();
1187 QList<const QgsExpressionNode *> lst;
1189 lst += mOpLeft->nodes() + mOpRight->nodes();
1195 return mOpLeft->needsGeometry() || mOpRight->needsGeometry();
1207 const bool leftStatic = mOpLeft->
isStatic( parent, context );
1208 const bool rightStatic = mOpRight->isStatic( parent, context );
1210 if ( leftStatic && rightStatic )
1222 mOpLeft->prepare( parent, context );
1223 if ( mOpLeft->hasCachedStaticValue() )
1225 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
1226 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
1234 else if ( rightStatic )
1236 mOpRight->prepare( parent, context );
1237 if ( mOpRight->hasCachedStaticValue() )
1239 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
1240 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
1258 mOpLeft->prepare( parent, context );
1259 if ( mOpLeft->hasCachedStaticValue() )
1261 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
1262 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
1270 else if ( rightStatic )
1272 mOpRight->prepare( parent, context );
1273 if ( mOpRight->hasCachedStaticValue() )
1275 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
1276 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
1317 std::unique_ptr< QgsExpressionNode >
opLeft( mOpLeft->simplifiedNode() );
1318 std::unique_ptr< QgsExpressionNode >
opRight( mOpRight->simplifiedNode() );
1325 QVariant result = tempNode.
eval( &parentExp,
nullptr );
1339 if ( mList->count() == 0 )
1340 return mNotIn ? TVL_True : TVL_False;
1341 QVariant v1 = mNode->eval( parent, context );
1343 if ( QgsExpressionUtils::isNull( v1 ) )
1346 bool listHasNull =
false;
1348 const QList< QgsExpressionNode * > nodeList = mList->list();
1351 QVariant v2 = n->eval( parent, context );
1353 if ( QgsExpressionUtils::isNull( v2 ) )
1359 if ( ( v1.userType() != QMetaType::Type::QString || v2.userType() != QMetaType::Type::QString ) && QgsExpressionUtils::isDoubleSafe( v1 ) && QgsExpressionUtils::isDoubleSafe( v2 ) )
1363 double f1 = QgsExpressionUtils::getDoubleValue( v1, parent );
1365 double f2 = QgsExpressionUtils::getDoubleValue( v2, parent );
1371 QString s1 = QgsExpressionUtils::getStringValue( v1, parent );
1373 QString s2 = QgsExpressionUtils::getStringValue( v2, parent );
1375 equal = QString::compare( s1, s2 ) == 0;
1379 return mNotIn ? TVL_False : TVL_True;
1387 return mNotIn ? TVL_True : TVL_False;
1400 bool res = mNode->prepare( parent, context );
1401 const QList< QgsExpressionNode * > nodeList = mList->list();
1404 res = res && n->prepare( parent, context );
1411 return u
"%1 %2 IN (%3)"_s.arg( mNode->dump(), mNotIn ?
"NOT" :
"", mList->dump() );
1423 if ( !mNode->isStatic( parent, context ) )
1426 const QList< QgsExpressionNode * > nodeList = mList->
list();
1429 if ( !n->isStatic( parent, context ) )
1438 std::unique_ptr< QgsExpressionNode > simplifiedTargetNode( mNode->simplifiedNode() );
1439 bool allLiterals = simplifiedTargetNode->nodeType() ==
ntLiteral;
1441 auto simplifiedList = std::make_unique< QgsExpressionNode::NodeList >();
1442 simplifiedList->reserve( mList->count() );
1445 std::unique_ptr< QgsExpressionNode > simplifiedItem(
node->simplifiedNode() );
1446 if ( simplifiedItem->nodeType() !=
ntLiteral )
1448 allLiterals =
false;
1451 if ( simplifiedTargetNode->nodeType() ==
ntLiteral
1452 && simplifiedItem->nodeType() ==
ntLiteral
1453 && qgis::down_cast< QgsExpressionNodeLiteral *>( simplifiedTargetNode.get() )->value() == qgis::down_cast< QgsExpressionNodeLiteral * >( simplifiedItem.get() )->value() )
1458 simplifiedList->append( simplifiedItem.release() );
1466 QVariant result = tempNode.
eval( &parentExp,
nullptr );
1480 QString name = QgsExpression::QgsExpression::Functions()[mFnIndex]->name();
1483 QVariant res = fd->
run( mArgs.get(), context, parent,
this );
1496 QMutexLocker locker( &QgsExpression::QgsExpression::sFunctionsMutex );
1499 const int functionParamsSize = functionParams.size();
1500 if ( functionParams.isEmpty() )
1503 mArgs.reset(
args );
1508 mArgs = std::make_unique<NodeList>();
1509 mArgs->reserve( functionParamsSize );
1518 mArgs = std::make_unique<NodeList>();
1519 mArgs->reserve( functionParamsSize );
1522 const QStringList argNames =
args->names();
1523 const QList<QgsExpressionNode *> argList =
args->list();
1526 const int argNamesSize = argNames.size();
1527 while ( idx < argNamesSize && argNames.at( idx ).isEmpty() )
1529 mArgs->append( argList.at( idx )->clone() );
1535 for ( ; idx < functionParamsSize; ++idx )
1538 int nodeIdx = argNames.indexOf( parameter.
name().toLower() );
1546 mArgs->append( argList.at( nodeIdx )->clone() );
1566 bool res = fd->
prepare(
this, parent, context );
1569 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1572 res = res && n->prepare( parent, context );
1582 return u
"%1%2"_s.arg( fd->
name(), fd->
name().startsWith(
'$' ) ? QString() : u
"()"_s );
1584 return u
"%1(%2)"_s.arg( fd->
name(), mArgs ? mArgs->dump() : QString() );
1590 return QSet< QString >();
1598 return functionColumns;
1602 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1605 if ( fd->
parameters().count() <= paramIndex || !fd->
parameters().at( paramIndex ).isSubExpression() )
1606 functionColumns.unite( n->referencedColumns() );
1610 return functionColumns;
1616 if ( fd->
name() ==
"var"_L1 )
1618 if ( !mArgs->list().isEmpty() )
1622 return QSet<QString>() << var->
value().toString();
1624 return QSet<QString>() << QString();
1628 QSet<QString> functionVariables = QSet<QString>();
1631 return functionVariables;
1633 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1636 functionVariables.unite( n->referencedVariables() );
1639 return functionVariables;
1646 QSet<QString> functions = QSet<QString>();
1647 functions.insert( fd->
name() );
1652 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1655 functions.unite( n->referencedFunctions() );
1662 QList<const QgsExpressionNode *> lst;
1667 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1677 bool needs = QgsExpression::QgsExpression::Functions()[mFnIndex]->usesGeometry(
this );
1680 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1682 needs |= n->needsGeometry();
1701 auto simplifiedArgs = std::make_unique< QgsExpressionNode::NodeList >();
1704 simplifiedArgs->reserve( mArgs->count() );
1707 std::unique_ptr< QgsExpressionNode > simplifiedArg( arg->simplifiedNode() );
1708 simplifiedArgs->append( simplifiedArg.release() );
1718 if ( !
args || !
args->hasNamedNodes() )
1722 if ( functionParams.isEmpty() )
1729 QSet< int > providedArgs;
1730 QSet< int > handledArgs;
1733 while (
args->names().at( idx ).isEmpty() )
1735 providedArgs << idx;
1741 for ( ; idx < functionParams.count(); ++idx )
1743 int nodeIdx =
args->names().indexOf( functionParams.at( idx ).name().toLower() );
1746 if ( !functionParams.at( idx ).optional() )
1748 error = u
"No value specified for QgsExpressionFunction::Parameter '%1' for %2"_s.arg( functionParams.at( idx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1754 if ( providedArgs.contains( idx ) )
1756 error = u
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2"_s.arg( functionParams.at( idx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1760 providedArgs << idx;
1761 handledArgs << nodeIdx;
1766 const QStringList nameList =
args->names();
1767 for (
const QString &name : nameList )
1769 if ( !name.isEmpty() && !functionParams.contains( name ) )
1774 if ( !name.isEmpty() && !handledArgs.contains( idx ) )
1776 int functionIdx = functionParams.indexOf( name );
1777 if ( providedArgs.contains( functionIdx ) )
1779 error = u
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2"_s.arg( functionParams.at( functionIdx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1816 switch ( mValue.userType() )
1818 case QMetaType::Type::Int:
1819 return QString::number( mValue.toInt() );
1820 case QMetaType::Type::Double:
1822 case QMetaType::Type::LongLong:
1823 return QString::number( mValue.toLongLong() );
1824 case QMetaType::Type::QString:
1826 case QMetaType::Type::QTime:
1828 case QMetaType::Type::QDate:
1830 case QMetaType::Type::QDateTime:
1832 case QMetaType::Type::Bool:
1833 return mValue.toBool() ? u
"TRUE"_s : u
"FALSE"_s;
1835 return tr(
"[unsupported type: %1; value: %2]" ).arg( mValue.typeName(), mValue.toString() );
1846 return QSet<QString>();
1851 return QSet<QString>();
1856 return QSet<QString>();
1861 QList<const QgsExpressionNode *> lst;
1914 parent->
setEvalErrorString( tr(
"No feature available for field '%1' evaluation" ).arg( mName ) );
1951 const thread_local QRegularExpression re( u
"^[A-Za-z_\\x80-\\xff][A-Za-z0-9_\\x80-\\xff]*$"_s );
1952 const QRegularExpressionMatch match = re.match( mName );
1958 return QSet<QString>() << mName;
1963 return QSet<QString>();
1968 return QSet<QString>();
1973 QList<const QgsExpressionNode *> result;
2008 qDeleteAll( mConditions );
2018 for (
WhenThen *cond : std::as_const( mConditions ) )
2020 QVariant vWhen = cond->mWhenExp->eval( parent, context );
2021 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( vWhen, parent );
2023 if ( tvl == QgsExpressionUtils::True )
2025 QVariant vRes = cond->mThenExp->eval( parent, context );
2033 QVariant vElse = mElseExp->eval( parent, context );
2044 bool foundAnyNonStaticConditions =
false;
2045 for (
WhenThen *cond : std::as_const( mConditions ) )
2047 const bool res = cond->mWhenExp->prepare( parent, context ) && cond->mThenExp->prepare( parent, context );
2051 foundAnyNonStaticConditions |= !cond->mWhenExp->hasCachedStaticValue();
2052 if ( !foundAnyNonStaticConditions && QgsExpressionUtils::getTVLValue( cond->mWhenExp->cachedStaticValue(), parent ) == QgsExpressionUtils::True )
2056 if ( cond->mThenExp->hasCachedStaticValue() )
2075 const bool res = mElseExp->prepare( parent, context );
2079 if ( !foundAnyNonStaticConditions )
2082 if ( mElseExp->hasCachedStaticValue() )
2103 QString msg( u
"CASE"_s );
2104 for (
WhenThen *cond : mConditions )
2106 msg += u
" WHEN %1 THEN %2"_s.arg( cond->mWhenExp->dump(), cond->mThenExp->dump() );
2109 msg += u
" ELSE %1"_s.arg( mElseExp->dump() );
2117 return QSet< QString >();
2120 for (
WhenThen *cond : mConditions )
2122 lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
2126 lst += mElseExp->referencedColumns();
2134 for (
WhenThen *cond : mConditions )
2136 lst += cond->mWhenExp->referencedVariables() + cond->mThenExp->referencedVariables();
2140 lst += mElseExp->referencedVariables();
2148 for (
WhenThen *cond : mConditions )
2150 lst += cond->mWhenExp->referencedFunctions() + cond->mThenExp->referencedFunctions();
2154 lst += mElseExp->referencedFunctions();
2161 QList<const QgsExpressionNode *> lst;
2163 for (
WhenThen *cond : mConditions )
2165 lst += cond->mWhenExp->nodes() + cond->mThenExp->nodes();
2169 lst += mElseExp->nodes();
2176 for (
WhenThen *cond : mConditions )
2178 if ( cond->mWhenExp->needsGeometry() || cond->mThenExp->needsGeometry() )
2182 return mElseExp && mElseExp->needsGeometry();
2201 if ( !wt->mWhenExp->isStatic( parent, context ) || !wt->mThenExp->isStatic( parent, context ) )
2206 return mElseExp->
isStatic( parent, context );
2213 auto simplifiedWhenThenList = std::make_unique< QgsExpressionNodeCondition::WhenThenList >();
2216 std::unique_ptr< QgsExpressionNode > simplifiedWhen( clause->whenExp()->simplifiedNode() );
2217 std::unique_ptr< QgsExpressionNode > simplifiedThen( clause->thenExp()->simplifiedNode() );
2220 if ( simplifiedWhenThenList->isEmpty() && simplifiedWhen->nodeType() ==
ntLiteral && simplifiedWhen->eval(
nullptr,
nullptr ).toBool() )
2222 return simplifiedThen.release();
2225 else if ( simplifiedWhen->nodeType() ==
ntLiteral && !simplifiedWhen->eval(
nullptr,
nullptr ).toBool() )
2233 std::unique_ptr< QgsExpressionNode > simplifiedElse( mElseExp ? mElseExp->simplifiedNode() :
nullptr );
2234 if ( simplifiedWhenThenList->isEmpty() )
2245 return QSet< QString >();
2247 QSet<QString> lst( mNode->referencedColumns() );
2248 const QList< QgsExpressionNode * > nodeList = mList->list();
2250 lst.unite( n->referencedColumns() );
2256 QSet<QString> lst( mNode->referencedVariables() );
2257 const QList< QgsExpressionNode * > nodeList = mList->list();
2259 lst.unite( n->referencedVariables() );
2265 QSet<QString> lst( mNode->referencedFunctions() );
2266 const QList< QgsExpressionNode * > nodeList = mList->list();
2268 lst.unite( n->referencedFunctions() );
2274 QList<const QgsExpressionNode *> lst;
2277 const QList< QgsExpressionNode * > nodeList = mList->list();
2294 bool res = mNode->prepare( parent, context );
2295 res = res && mLowerBound->prepare( parent, context );
2296 res = res && mHigherBound->prepare( parent, context );
2302 const QVariant nodeVal = mNode->eval( parent, context );
2311 const QVariant lowBoundValue = lowBound.
eval( parent, context );
2312 const bool lowBoundBool { lowBoundValue.toBool() };
2316 return QVariant( mNegate );
2320 const QVariant highBoundValue = highBound.
eval( parent, context );
2327 const bool highBoundBool { highBoundValue.toBool() };
2335 return QVariant( mNegate );
2344 return QVariant( mNegate );
2347 const bool res { lowBoundBool && highBoundBool };
2348 return mNegate ? QVariant( !res ) : QVariant( res );
2353 return u
"%1 %2 %3 AND %4"_s.arg( mNode->dump(), mNegate ? u
"NOT BETWEEN"_s : u
"BETWEEN"_s, mLowerBound->dump(), mHigherBound->dump() );
2358 QSet<QString> lst( mNode->referencedVariables() );
2359 lst.unite( mLowerBound->referencedVariables() );
2360 lst.unite( mHigherBound->referencedVariables() );
2366 QSet<QString> lst( mNode->referencedFunctions() );
2367 lst.unite( mLowerBound->referencedFunctions() );
2368 lst.unite( mHigherBound->referencedFunctions() );
2374 return {
this, mLowerBound.get(), mHigherBound.get() };
2379 QSet<QString> lst( mNode->referencedColumns() );
2380 lst.unite( mLowerBound->referencedColumns() );
2381 lst.unite( mHigherBound->referencedColumns() );
2387 if ( mNode->needsGeometry() )
2390 if ( mLowerBound->needsGeometry() )
2393 if ( mHigherBound->needsGeometry() )
2408 if ( !mNode->isStatic( parent, context ) )
2411 if ( !mLowerBound->isStatic( parent, context ) )
2414 if ( !mHigherBound->isStatic( parent, context ) )
2422 return mLowerBound.get();
2427 return mHigherBound.get();
2445 return new WhenThen( mWhenExp->clone(), mThenExp->clone() );
2450 return BINARY_OPERATOR_TEXT[mOp];
2457 const QVariant
container = mContainer->eval( parent, context );
2459 const QVariant
index = mIndex->eval( parent, context );
2464 case QMetaType::Type::QVariantMap:
2465 return QgsExpressionUtils::getMapValue(
container, parent ).value(
index.toString() );
2467 case QMetaType::Type::QVariantList:
2468 case QMetaType::Type::QStringList:
2470 const QVariantList list = QgsExpressionUtils::getListValue(
container, parent );
2471 qlonglong pos = QgsExpressionUtils::getIntValue(
index, parent );
2472 if ( pos >= list.length() || pos < -list.length() )
2479 pos += list.length();
2482 return list.at( pos );
2487 parent->
setEvalErrorString( tr(
"[] can only be used with map or array values, not %1" ).arg( QMetaType::typeName(
static_cast<QMetaType::Type
>(
container.userType() ) ) ) );
2499 bool resC = mContainer->prepare( parent, context );
2500 bool resV = mIndex->prepare( parent, context );
2501 return resC && resV;
2506 return u
"%1[%2]"_s.arg( mContainer->dump(), mIndex->dump() );
2512 return QSet< QString >();
2514 return mContainer->referencedColumns() + mIndex->referencedColumns();
2519 return mContainer->referencedVariables() + mIndex->referencedVariables();
2524 return mContainer->referencedFunctions() + mIndex->referencedFunctions();
2529 QList<const QgsExpressionNode *> lst;
2531 lst += mContainer->nodes() + mIndex->nodes();
2537 return mContainer->needsGeometry() || mIndex->needsGeometry();
2549 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.
QgsExpressionNode * opLeft() const
Returns the node to the left of the operator.
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.
QgsExpressionNode * opRight() const
Returns the node to the right of 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.
QgsExpressionNode * simplifiedNode() const override
Returns a new node, which is the simplest node which represents this node before any compilation opti...
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.
QgsExpressionNode * simplifiedNode() const override
Returns a new node, which is the simplest node which represents this node before any compilation opti...
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.
QgsExpressionNode * simplifiedNode() const override
Returns a new node, which is the simplest node which represents this node before any compilation opti...
~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.
QgsExpressionNode * node() const
Returns the expression node.
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.
QgsExpressionNode * simplifiedNode() const override
Returns a new node, which is the simplest node which represents this node before any compilation opti...
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.
QgsExpressionNode * simplifiedNode() const override
Returns a new node, which is the simplest node which represents this node before any compilation opti...
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.