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::QDateTime && vR.userType() == QMetaType::Type::QString ) || ( vL.userType() == QMetaType::Type::QString && vR.userType() == QMetaType::Type::QDateTime ) )
300 if ( vL.userType() == QMetaType::Type::QDateTime )
302 dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
306 dL = QDateTime::fromString( vL.toString(), Qt::ISODate );
310 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to DateTime" ).arg( vL.toString() ) );
317 if ( vR.userType() == QMetaType::Type::QDateTime )
319 dR = QgsExpressionUtils::getDateTimeValue( vR, parent );
323 dR = QDateTime::fromString( vR.toString(), Qt::ISODate );
327 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to DateTime" ).arg( vR.toString() ) );
337 dL.setTimeSpec( Qt::UTC );
338 dR.setTimeSpec( Qt::UTC );
342 else if ( ( vL.userType() == QMetaType::Type::QDate && vR.userType() == QMetaType::Type::QString ) || ( vL.userType() == QMetaType::Type::QString && vR.userType() == QMetaType::Type::QDate ) )
346 if ( vL.userType() == QMetaType::Type::QDate )
348 dL = QgsExpressionUtils::getDateValue( vL, parent );
352 dL = QDate::fromString( vL.toString(), Qt::ISODate );
356 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Date" ).arg( vL.toString() ) );
363 if ( vR.userType() == QMetaType::Type::QDate )
365 dR = QgsExpressionUtils::getDateValue( vR, parent );
369 dR = QDate::fromString( vR.toString(), Qt::ISODate );
373 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Date" ).arg( vR.toString() ) );
381 else if ( ( vL.userType() == QMetaType::Type::QTime && vR.userType() == QMetaType::Type::QString ) || ( vL.userType() == QMetaType::Type::QString && vR.userType() == QMetaType::Type::QTime ) )
385 if ( vL.userType() == QMetaType::Type::QTime )
387 dL = QgsExpressionUtils::getTimeValue( vL, parent );
391 dL = QTime::fromString( vL.toString(), Qt::ISODate );
395 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Time" ).arg( vL.toString() ) );
402 if ( vR.userType() == QMetaType::Type::QTime )
404 dR = QgsExpressionUtils::getTimeValue( vR, parent );
408 dR = QTime::fromString( vR.toString(), Qt::ISODate );
412 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Time" ).arg( vR.toString() ) );
418 return compareOp<int>( dR.msecsTo( dL ), op ) ? TVL_True : TVL_False;
420 else if ( ( vL.userType() == QMetaType::Type::QDate && vR.userType() == QMetaType::Type::QDate ) )
422 const QDate dL = QgsExpressionUtils::getDateValue( vL, parent );
424 const QDate dR = QgsExpressionUtils::getDateValue( vR, parent );
428 else if ( ( vL.userType() == QMetaType::Type::QTime && vR.userType() == QMetaType::Type::QTime ) )
430 const QTime dL = QgsExpressionUtils::getTimeValue( vL, parent );
432 const QTime dR = QgsExpressionUtils::getTimeValue( vR, parent );
434 return compareOp<int>( dR.msecsTo( dL ), op ) ? TVL_True : TVL_False;
436 else if ( ( vL.userType() != QMetaType::Type::QString || vR.userType() != QMetaType::Type::QString ) && QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) )
440 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
442 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
447 else if ( vL.userType() == QMetaType::Type::Bool || vR.userType() == QMetaType::Type::Bool )
469 const bool vLBool = vL.toBool();
470 const bool vRBool = vR.toBool();
474 return vLBool == vRBool ? TVL_True : TVL_False;
476 return vLBool != vRBool ? TVL_True : TVL_False;
478 return vLBool < vRBool ? TVL_True : TVL_False;
480 return vLBool <= vRBool ? TVL_True : TVL_False;
482 return vLBool > vRBool ? TVL_True : TVL_False;
484 return vLBool >= vRBool ? TVL_True : TVL_False;
509 else if ( vL.userType() == qMetaTypeId< QgsInterval>() && vR.userType() == qMetaTypeId< QgsInterval>() )
511 double fL = QgsExpressionUtils::getInterval( vL, parent ).seconds();
513 double fR = QgsExpressionUtils::getInterval( vR, parent ).seconds();
520 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
522 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
524 int diff = QString::compare( sL, sR );
531 QVariant vL = mOpLeft->eval( parent, context );
536 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent );
538 if ( mOp ==
boAnd && tvlL == QgsExpressionUtils::False )
540 if ( mOp ==
boOr && tvlL == QgsExpressionUtils::True )
544 QVariant vR = mOpRight->eval( parent, context );
550 if ( vL.userType() == QMetaType::Type::QString && vR.userType() == QMetaType::Type::QString )
552 QString sL = QgsExpressionUtils::isNull( vL ) ? QString() : QgsExpressionUtils::getStringValue( vL, parent );
554 QString sR = QgsExpressionUtils::isNull( vR ) ? QString() : QgsExpressionUtils::getStringValue( vR, parent );
556 return QVariant( sL + sR );
565 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
567 else if ( mOp !=
boDiv && QgsExpressionUtils::isIntSafe( vL ) && QgsExpressionUtils::isIntSafe( vR ) )
570 qlonglong iL = QgsExpressionUtils::getIntValue( vL, parent );
572 qlonglong iR = QgsExpressionUtils::getIntValue( vR, parent );
575 if ( mOp ==
boMod && iR == 0 )
578 return QVariant( computeInt( iL, iR ) );
580 else if ( QgsExpressionUtils::isDateTimeSafe( vL ) && QgsExpressionUtils::isIntervalSafe( vR ) )
582 QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
584 QgsInterval iL = QgsExpressionUtils::getInterval( vR, parent );
588 parent->
setEvalErrorString( tr(
"Can't perform /, *, or % on DateTime and Interval" ) );
591 return QVariant( computeDateTimeFromInterval( dL, &iL ) );
594 && ( ( vL.userType() == QMetaType::Type::QDate && vR.userType() == QMetaType::Type::QTime ) || ( vR.userType() == QMetaType::Type::QDate && vL.userType() == QMetaType::Type::QTime ) ) )
596 QDate date = QgsExpressionUtils::getDateValue( vL.userType() == QMetaType::Type::QDate ? vL : vR, parent );
598 QTime time = QgsExpressionUtils::getTimeValue( vR.userType() == QMetaType::Type::QTime ? vR : vL, parent );
600 QDateTime dt = QDateTime( date, time );
601 return QVariant( dt );
603 else if ( mOp ==
boMinus && vL.userType() == QMetaType::Type::QDate && vR.userType() == QMetaType::Type::QDate )
605 QDate date1 = QgsExpressionUtils::getDateValue( vL, parent );
607 QDate date2 = QgsExpressionUtils::getDateValue( vR, parent );
609 return date1 - date2;
611 else if ( mOp ==
boMinus && vL.userType() == QMetaType::Type::QTime && vR.userType() == QMetaType::Type::QTime )
613 QTime time1 = QgsExpressionUtils::getTimeValue( vL, parent );
615 QTime time2 = QgsExpressionUtils::getTimeValue( vR, parent );
617 return time1 - time2;
619 else if ( mOp ==
boMinus && vL.userType() == QMetaType::Type::QDateTime && vR.userType() == QMetaType::Type::QDateTime )
621 QDateTime datetime1 = QgsExpressionUtils::getDateTimeValue( vL, parent );
623 QDateTime datetime2 = QgsExpressionUtils::getDateTimeValue( vR, parent );
627 else if ( ( mOp ==
boPlus || mOp ==
boMinus || mOp ==
boMul || mOp ==
boDiv ) && vL.userType() == QMetaType::Type::QColor && vR.userType() == QMetaType::Type::QColor )
629 bool isQColor =
false;
630 const QColor colorL = QgsExpressionUtils::getColorValue( vL, parent, isQColor );
632 const QColor colorR = QgsExpressionUtils::getColorValue( vR, parent, isQColor );
635 if ( !colorL.isValid() || !colorR.isValid() )
641 QColor::Spec colorLSpec = colorL.spec();
642 QColor::Spec colorRSpec = colorR.spec();
644 switch ( colorLSpec )
648 if ( colorRSpec != QColor::Cmyk )
650 parent->
setEvalErrorString( tr(
"Cannot combine a CMYK color with a non-CMYK color" ) );
654 float lc, lm, ly, lk, la, rc, rm, ry, rk, ra;
655 colorL.getCmykF( &lc, &lm, &ly, &lk, &la );
656 colorR.getCmykF( &rc, &rm, &ry, &rk, &ra );
657 return QColor::fromCmykF(
658 static_cast<float>( std::clamp( computeDouble( lc, rc ), 0.0, 1.0 ) ),
659 static_cast<float>( std::clamp( computeDouble( lm, rm ), 0.0, 1.0 ) ),
660 static_cast<float>( std::clamp( computeDouble( ly, ry ), 0.0, 1.0 ) ),
661 static_cast<float>( std::clamp( computeDouble( lk, rk ), 0.0, 1.0 ) ),
668 case QColor::ExtendedRgb:
670 if ( colorRSpec == QColor::Cmyk )
672 parent->
setEvalErrorString( tr(
"Cannot combine a non-CMYK color with a CMYK color" ) );
676 float lr, lg, lb, la, rr, rg, rb, ra;
677 colorL.getRgbF( &lr, &lg, &lb, &la );
678 colorR.getRgbF( &rr, &rg, &rb, &ra );
679 QColor result = QColor::
680 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 );
688 && ( ( ( vL.userType() == QMetaType::Type::QColor ) && QgsExpressionUtils::isDoubleSafe( vR ) ) || ( ( vR.userType() == QMetaType::Type::QColor ) && QgsExpressionUtils::isDoubleSafe( vL ) ) ) )
690 const bool colorLeft = vL.userType() == QMetaType::Type::QColor;
691 bool isQColor =
false;
692 const QColor color = QgsExpressionUtils::getColorValue( colorLeft ? vL : vR, parent, isQColor );
695 if ( !color.isValid() )
701 const double value = QgsExpressionUtils::getDoubleValue( colorLeft ? vR : vL, parent );
704 if ( mOp ==
boDiv && value == 0.0 )
710 if ( !colorLeft && mOp ==
boDiv )
712 parent->
setEvalErrorString( tr(
"Can't perform / with a color value on the right" ) );
716 switch ( color.spec() )
721 color.getCmykF( &
c, &m, &y, &k, &a );
722 const double dc =
static_cast<double>(
c );
723 const double dm =
static_cast<double>( m );
724 const double dy =
static_cast<double>( y );
725 const double dk =
static_cast<double>( k );
727 return QColor::fromCmykF(
728 static_cast<float>( std::clamp( computeDouble( colorLeft ? dc : value, colorLeft ? value : dc ), 0.0, 1.0 ) ),
729 static_cast<float>( std::clamp( computeDouble( colorLeft ? dm : value, colorLeft ? value : dm ), 0.0, 1.0 ) ),
730 static_cast<float>( std::clamp( computeDouble( colorLeft ? dy : value, colorLeft ? value : dy ), 0.0, 1.0 ) ),
731 static_cast<float>( std::clamp( computeDouble( colorLeft ? dk : value, colorLeft ? value : dk ), 0.0, 1.0 ) ),
738 case QColor::ExtendedRgb:
741 color.getRgbF( &r, &g, &b, &a );
742 const double dr =
static_cast<double>( r );
743 const double dg =
static_cast<double>( g );
744 const double db =
static_cast<double>( b );
746 return QColor::fromRgbF(
747 static_cast<float>( std::clamp( computeDouble( colorLeft ? dr : value, colorLeft ? value : dr ), 0.0, 1.0 ) ),
748 static_cast<float>( std::clamp( computeDouble( colorLeft ? dg : value, colorLeft ? value : dg ), 0.0, 1.0 ) ),
749 static_cast<float>( std::clamp( computeDouble( colorLeft ? db : value, colorLeft ? value : db ), 0.0, 1.0 ) ),
760 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
762 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
764 if ( ( mOp ==
boDiv || mOp ==
boMod ) && fR == 0. )
766 return QVariant( computeDouble( fL, fR ) );
772 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
774 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
778 return QVariant( qlonglong( std::floor( fL / fR ) ) );
781 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
785 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
787 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
789 return QVariant( std::pow( fL, fR ) );
794 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
796 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::AND[tvlL][tvlR] );
801 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
803 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::OR[tvlL][tvlR] );
812 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
816 else if ( QgsExpressionUtils::isList( vL ) || QgsExpressionUtils::isList( vR ) )
819 if ( !QgsExpressionUtils::isList( vL ) || !QgsExpressionUtils::isList( vR ) )
823 QVariantList lL = vL.toList();
824 QVariantList lR = vR.toList();
825 for (
int i = 0; i < lL.length() && i < lR.length(); i++ )
827 if ( QgsExpressionUtils::isNull( lL.at( i ) ) && QgsExpressionUtils::isNull( lR.at( i ) ) )
830 if ( QgsExpressionUtils::isNull( lL.at( i ) ) || QgsExpressionUtils::isNull( lR.at( i ) ) )
840 return QgsExpressionUtils::isNull( lR.at( i ) );
843 return QgsExpressionUtils::isNull( lL.at( i ) );
853 QVariant eq = eqNode.
eval( parent, context );
855 if ( eq == TVL_False )
859 QVariant v = node.
eval( parent, context );
869 return lL.length() == lR.length();
871 return lL.length() != lR.length();
873 return lL.length() < lR.length();
875 return lL.length() > lR.length();
877 return lL.length() <= lR.length();
879 return lL.length() >= lR.length();
887 return compareNonNullValues( parent, context, vL, vR, mOp );
893 const bool vLNull = QgsExpressionUtils::isNull( vL );
894 const bool vRNull = QgsExpressionUtils::isNull( vR );
895 if ( vLNull && vRNull )
896 return ( mOp ==
boIs ? TVL_True : TVL_False );
897 else if ( vLNull || vRNull )
898 return ( mOp ==
boIs ? TVL_False : TVL_True );
901 return compareNonNullValues( parent, context, vL, vR, mOp ==
boIs ?
boEQ :
boNE );
910 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
914 const QString str = QgsExpressionUtils::getStringValue( vL, parent );
916 const QString regexp = QgsExpressionUtils::getStringValue( vR, parent );
919 QRegularExpression re;
920 const QString cachedRegExKey = u
"re_bo_%1_%2"_s.arg( mOp ).arg( regexp );
923 re = context->
cachedValue( cachedRegExKey ).value< QRegularExpression >();
926 bool matches =
false;
927 if ( re.pattern().isEmpty() )
933 if ( esc_regexp.startsWith(
'%' ) )
935 esc_regexp.replace( 0, 1, u
".*"_s );
937 const thread_local QRegularExpression rx1( u
"[^\\\\](%)"_s );
939 while ( ( pos = esc_regexp.indexOf( rx1, pos ) ) != -1 )
941 esc_regexp.replace( pos + 1, 1, u
".*"_s );
944 const thread_local QRegularExpression rx2( u
"\\\\%"_s );
945 esc_regexp.replace( rx2, u
"%"_s );
946 if ( esc_regexp.startsWith(
'_' ) )
948 esc_regexp.replace( 0, 1, u
"."_s );
950 const thread_local QRegularExpression rx3( u
"[^\\\\](_)"_s );
952 while ( ( pos = esc_regexp.indexOf( rx3, pos ) ) != -1 )
954 esc_regexp.replace( pos + 1, 1,
'.' );
957 esc_regexp.replace(
"\\\\_"_L1,
"_"_L1 );
959 re = QRegularExpression( QRegularExpression::anchoredPattern( esc_regexp ), mOp ==
boLike || mOp ==
boNotLike ? QRegularExpression::DotMatchesEverythingOption : QRegularExpression::DotMatchesEverythingOption | QRegularExpression::CaseInsensitiveOption );
963 re = QRegularExpression( regexp );
971 matches = re.match( str ).hasMatch();
978 return matches ? TVL_True : TVL_False;
982 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
986 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
988 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
990 return QVariant( sL + sR );
997qlonglong QgsExpressionNodeBinaryOperator::computeInt( qlonglong x, qlonglong y )
1017QDateTime QgsExpressionNodeBinaryOperator::computeDateTimeFromInterval(
const QDateTime &d, QgsInterval *i )
1022 return d.addSecs( i->
seconds() );
1024 return d.addSecs( -i->
seconds() );
1031double QgsExpressionNodeBinaryOperator::computeDouble(
double x,
double y )
1044 return std::fmod( x, y );
1062 QMap<QString, QgsExpressionNode::NodeList> orValuesMap;
1063 QList<QString> orFieldNames;
1079 const QString fieldName =
op->opLeft()->dump();
1080 if ( !orValuesMap.contains( fieldName ) )
1082 orFieldNames.append( fieldName );
1085 orValuesMap[fieldName].append(
op->opRight()->clone() );
1090 const QString fieldName =
op->opRight()->dump();
1091 if ( !orValuesMap.contains( fieldName ) )
1093 orFieldNames.append( fieldName );
1096 orValuesMap[fieldName].append(
op->opLeft()->clone() );
1102 if ( visitOrNodes(
op->opLeft() ) && visitOrNodes(
op->opRight() ) )
1114 const QString fieldName = inOp->node()->dump();
1117 const auto nodes = inOp->list()->list();
1118 for (
const auto &valueNode : std::as_const(
nodes ) )
1126 auto orValuesMapIt = orValuesMap.find( fieldName );
1127 if ( orValuesMapIt == orValuesMap.end() )
1129 orFieldNames.append( fieldName );
1132 for (
const auto &valueNode : std::as_const(
nodes ) )
1134 orValuesMapIt->append( valueNode->clone() );
1144 if ( visitOrNodes(
this ) && !orValuesMap.empty() )
1146 std::unique_ptr<QgsExpressionNode> currentNode;
1147 for (
const auto &fieldName : std::as_const( orFieldNames ) )
1149 auto orValuesIt = orValuesMap.find( fieldName );
1150 if ( orValuesIt.value().count() == 1 )
1155 currentNode = std::make_unique<QgsExpressionNodeBinaryOperator>(
boOr, currentNode.release(), eqNode.release() );
1159 currentNode = std::move( eqNode );
1167 currentNode = std::make_unique<QgsExpressionNodeBinaryOperator>(
boOr, currentNode.release(), inNode.release() );
1171 currentNode = std::move( inNode );
1184 bool resL = mOpLeft->prepare( parent, context );
1185 bool resR = mOpRight->prepare( parent, context );
1186 return resL && resR;
1231 Q_ASSERT(
false &&
"unexpected binary operator" );
1267 Q_ASSERT(
false &&
"unexpected binary operator" );
1277 QString rdump( mOpRight->dump() );
1282 rdump.prepend(
'(' ).append(
')' );
1299 return fmt.arg( mOpLeft->dump(), BINARY_OPERATOR_TEXT[mOp], rdump );
1305 return QSet< QString >();
1307 return mOpLeft->referencedColumns() + mOpRight->referencedColumns();
1312 return mOpLeft->referencedVariables() + mOpRight->referencedVariables();
1317 return mOpLeft->referencedFunctions() + mOpRight->referencedFunctions();
1322 QList<const QgsExpressionNode *> lst;
1324 lst += mOpLeft->nodes() + mOpRight->nodes();
1330 return mOpLeft->needsGeometry() || mOpRight->needsGeometry();
1342 const bool leftStatic = mOpLeft->
isStatic( parent, context );
1343 const bool rightStatic = mOpRight->isStatic( parent, context );
1345 if ( leftStatic && rightStatic )
1357 mOpLeft->prepare( parent, context );
1358 if ( mOpLeft->hasCachedStaticValue() )
1360 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
1361 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
1369 else if ( rightStatic )
1371 mOpRight->prepare( parent, context );
1372 if ( mOpRight->hasCachedStaticValue() )
1374 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
1375 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
1393 mOpLeft->prepare( parent, context );
1394 if ( mOpLeft->hasCachedStaticValue() )
1396 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
1397 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
1405 else if ( rightStatic )
1407 mOpRight->prepare( parent, context );
1408 if ( mOpRight->hasCachedStaticValue() )
1410 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
1411 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
1452 std::unique_ptr< QgsExpressionNode >
opLeft( mOpLeft->simplifiedNode() );
1453 std::unique_ptr< QgsExpressionNode >
opRight( mOpRight->simplifiedNode() );
1460 QVariant result = tempNode.
eval( &parentExp,
nullptr );
1474 if ( mList->count() == 0 )
1475 return mNotIn ? TVL_True : TVL_False;
1476 QVariant v1 = mNode->eval( parent, context );
1478 if ( QgsExpressionUtils::isNull( v1 ) )
1481 bool listHasNull =
false;
1483 const QList< QgsExpressionNode * > nodeList = mList->list();
1486 QVariant v2 = n->eval( parent, context );
1488 if ( QgsExpressionUtils::isNull( v2 ) )
1494 if ( ( v1.userType() != QMetaType::Type::QString || v2.userType() != QMetaType::Type::QString ) && QgsExpressionUtils::isDoubleSafe( v1 ) && QgsExpressionUtils::isDoubleSafe( v2 ) )
1498 double f1 = QgsExpressionUtils::getDoubleValue( v1, parent );
1500 double f2 = QgsExpressionUtils::getDoubleValue( v2, parent );
1506 QString s1 = QgsExpressionUtils::getStringValue( v1, parent );
1508 QString s2 = QgsExpressionUtils::getStringValue( v2, parent );
1510 equal = QString::compare( s1, s2 ) == 0;
1514 return mNotIn ? TVL_False : TVL_True;
1522 return mNotIn ? TVL_True : TVL_False;
1535 bool res = mNode->prepare( parent, context );
1536 const QList< QgsExpressionNode * > nodeList = mList->list();
1539 res = res && n->prepare( parent, context );
1546 return u
"%1 %2 IN (%3)"_s.arg( mNode->dump(), mNotIn ?
"NOT" :
"", mList->dump() );
1558 if ( !mNode->isStatic( parent, context ) )
1561 const QList< QgsExpressionNode * > nodeList = mList->
list();
1564 if ( !n->isStatic( parent, context ) )
1573 std::unique_ptr< QgsExpressionNode > simplifiedTargetNode( mNode->simplifiedNode() );
1574 bool allLiterals = simplifiedTargetNode->nodeType() ==
ntLiteral;
1576 auto simplifiedList = std::make_unique< QgsExpressionNode::NodeList >();
1577 simplifiedList->reserve( mList->count() );
1580 std::unique_ptr< QgsExpressionNode > simplifiedItem(
node->simplifiedNode() );
1581 if ( simplifiedItem->nodeType() !=
ntLiteral )
1583 allLiterals =
false;
1586 if ( simplifiedTargetNode->nodeType() ==
ntLiteral
1587 && simplifiedItem->nodeType() ==
ntLiteral
1588 && qgis::down_cast< QgsExpressionNodeLiteral *>( simplifiedTargetNode.get() )->value() == qgis::down_cast< QgsExpressionNodeLiteral * >( simplifiedItem.get() )->value() )
1593 simplifiedList->append( simplifiedItem.release() );
1601 QVariant result = tempNode.
eval( &parentExp,
nullptr );
1616 const QString name = func->name();
1622 res = fd->
run( mArgs.get(), context, parent,
this );
1626 res = func->run( mArgs.get(), context, parent,
this );
1642 const qsizetype functionParamsSize = functionParams.size();
1643 if ( functionParams.isEmpty() )
1646 mArgs.reset( args );
1651 mArgs = std::make_unique<NodeList>();
1652 mArgs->reserve( functionParamsSize );
1661 mArgs = std::make_unique<NodeList>();
1662 mArgs->reserve( functionParamsSize );
1665 const QStringList argNames =
args->names();
1666 const QList<QgsExpressionNode *> argList =
args->list();
1669 const qsizetype argNamesSize = argNames.size();
1670 while ( idx < argNamesSize && argNames.at( idx ).isEmpty() )
1672 mArgs->append( argList.at( idx )->clone() );
1678 for ( ; idx < functionParamsSize; ++idx )
1681 qsizetype nodeIdx = argNames.indexOf( parameter.
name().toLower() );
1689 mArgs->append( argList.at( nodeIdx )->clone() );
1704 return functions->functionIndex( mFunction->name() );
1720 bool res = func->prepare(
this, parent, context );
1721 if ( mArgs && !func->lazyEval() )
1723 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1726 res = res && n->prepare( parent, context );
1735 if ( func->params() == 0 )
1736 return u
"%1%2"_s.arg( func->name(), func->name().startsWith(
'$' ) ? QString() : u
"()"_s );
1738 return u
"%1(%2)"_s.arg( func->name(), mArgs ? mArgs->dump() : QString() );
1744 return QSet< QString >();
1747 QSet<QString> functionColumns = func->referencedColumns(
this );
1752 return functionColumns;
1756 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1759 if ( func->parameters().count() <= paramIndex || !func->parameters().at( paramIndex ).isSubExpression() )
1760 functionColumns.unite( n->referencedColumns() );
1764 return functionColumns;
1770 if ( func->name() ==
"var"_L1 )
1772 if ( !mArgs->list().isEmpty() )
1776 return QSet<QString>() << var->
value().toString();
1778 return QSet<QString>() << QString();
1782 QSet<QString> functionVariables = QSet<QString>();
1785 return functionVariables;
1787 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1790 functionVariables.unite( n->referencedVariables() );
1793 return functionVariables;
1800 QSet<QString> functions = QSet<QString>();
1801 functions.insert( func->name() );
1806 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1809 functions.unite( n->referencedFunctions() );
1816 QList<const QgsExpressionNode *> lst;
1821 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1832 bool needs = func->usesGeometry(
this );
1835 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1837 needs |= n->needsGeometry();
1853 return func->isStatic(
this, parent, context );
1858 auto simplifiedArgs = std::make_unique< QgsExpressionNode::NodeList >();
1861 simplifiedArgs->reserve( mArgs->count() );
1864 std::unique_ptr< QgsExpressionNode > simplifiedArg( arg->simplifiedNode() );
1865 simplifiedArgs->append( simplifiedArg.release() );
1875 if ( !
args || !
args->hasNamedNodes() )
1882 if ( functionParams.isEmpty() )
1884 error = u
"%1 does not support named QgsExpressionFunction::Parameters"_s.arg( fd->name() );
1889 QSet< int > providedArgs;
1890 QSet< int > handledArgs;
1893 while (
args->names().at( idx ).isEmpty() )
1895 providedArgs << idx;
1901 for ( ; idx < functionParams.count(); ++idx )
1903 int nodeIdx =
args->names().indexOf( functionParams.at( idx ).name().toLower() );
1906 if ( !functionParams.at( idx ).optional() )
1908 error = u
"No value specified for QgsExpressionFunction::Parameter '%1' for %2"_s.arg( functionParams.at( idx ).name(), fd->name() );
1914 if ( providedArgs.contains( idx ) )
1916 error = u
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2"_s.arg( functionParams.at( idx ).name(), fd->name() );
1920 providedArgs << idx;
1921 handledArgs << nodeIdx;
1926 const QStringList nameList =
args->names();
1927 for (
const QString &name : nameList )
1929 if ( !name.isEmpty() && !functionParams.contains( name ) )
1931 error = u
"Invalid QgsExpressionFunction::Parameter name '%1' for %2"_s.arg( name, fd->name() );
1934 if ( !name.isEmpty() && !handledArgs.contains( idx ) )
1936 int functionIdx = functionParams.indexOf( name );
1937 if ( providedArgs.contains( functionIdx ) )
1939 error = u
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2"_s.arg( functionParams.at( functionIdx ).name(), fd->name() );
1976 switch ( mValue.userType() )
1978 case QMetaType::Type::Int:
1979 return QString::number( mValue.toInt() );
1980 case QMetaType::Type::Double:
1982 case QMetaType::Type::LongLong:
1983 return QString::number( mValue.toLongLong() );
1984 case QMetaType::Type::QString:
1986 case QMetaType::Type::QTime:
1988 case QMetaType::Type::QDate:
1990 case QMetaType::Type::QDateTime:
1992 case QMetaType::Type::Bool:
1993 return mValue.toBool() ? u
"TRUE"_s : u
"FALSE"_s;
1995 return tr(
"[unsupported type: %1; value: %2]" ).arg( mValue.typeName(), mValue.toString() );
2006 return QSet<QString>();
2011 return QSet<QString>();
2016 return QSet<QString>();
2021 QList<const QgsExpressionNode *> lst;
2074 parent->
setEvalErrorString( tr(
"No feature available for field '%1' evaluation" ).arg( mName ) );
2111 const thread_local QRegularExpression re( u
"^[A-Za-z_\\x80-\\xff][A-Za-z0-9_\\x80-\\xff]*$"_s );
2112 const QRegularExpressionMatch match = re.match( mName );
2118 return QSet<QString>() << mName;
2123 return QSet<QString>();
2128 return QSet<QString>();
2133 QList<const QgsExpressionNode *> result;
2168 qDeleteAll( mConditions );
2178 for (
WhenThen *cond : std::as_const( mConditions ) )
2180 QVariant vWhen = cond->mWhenExp->eval( parent, context );
2181 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( vWhen, parent );
2183 if ( tvl == QgsExpressionUtils::True )
2185 QVariant vRes = cond->mThenExp->eval( parent, context );
2193 QVariant vElse = mElseExp->eval( parent, context );
2204 bool foundAnyNonStaticConditions =
false;
2205 for (
WhenThen *cond : std::as_const( mConditions ) )
2207 const bool res = cond->mWhenExp->prepare( parent, context ) && cond->mThenExp->prepare( parent, context );
2211 foundAnyNonStaticConditions |= !cond->mWhenExp->hasCachedStaticValue();
2212 if ( !foundAnyNonStaticConditions && QgsExpressionUtils::getTVLValue( cond->mWhenExp->cachedStaticValue(), parent ) == QgsExpressionUtils::True )
2216 if ( cond->mThenExp->hasCachedStaticValue() )
2235 const bool res = mElseExp->prepare( parent, context );
2239 if ( !foundAnyNonStaticConditions )
2242 if ( mElseExp->hasCachedStaticValue() )
2263 QString msg( u
"CASE"_s );
2264 for (
WhenThen *cond : mConditions )
2266 msg += u
" WHEN %1 THEN %2"_s.arg( cond->mWhenExp->dump(), cond->mThenExp->dump() );
2269 msg += u
" ELSE %1"_s.arg( mElseExp->dump() );
2277 return QSet< QString >();
2280 for (
WhenThen *cond : mConditions )
2282 lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
2286 lst += mElseExp->referencedColumns();
2294 for (
WhenThen *cond : mConditions )
2296 lst += cond->mWhenExp->referencedVariables() + cond->mThenExp->referencedVariables();
2300 lst += mElseExp->referencedVariables();
2308 for (
WhenThen *cond : mConditions )
2310 lst += cond->mWhenExp->referencedFunctions() + cond->mThenExp->referencedFunctions();
2314 lst += mElseExp->referencedFunctions();
2321 QList<const QgsExpressionNode *> lst;
2323 for (
WhenThen *cond : mConditions )
2325 lst += cond->mWhenExp->nodes() + cond->mThenExp->nodes();
2329 lst += mElseExp->nodes();
2336 for (
WhenThen *cond : mConditions )
2338 if ( cond->mWhenExp->needsGeometry() || cond->mThenExp->needsGeometry() )
2342 return mElseExp && mElseExp->needsGeometry();
2361 if ( !wt->mWhenExp->isStatic( parent, context ) || !wt->mThenExp->isStatic( parent, context ) )
2366 return mElseExp->
isStatic( parent, context );
2373 auto simplifiedWhenThenList = std::make_unique< QgsExpressionNodeCondition::WhenThenList >();
2376 std::unique_ptr< QgsExpressionNode > simplifiedWhen( clause->whenExp()->simplifiedNode() );
2377 std::unique_ptr< QgsExpressionNode > simplifiedThen( clause->thenExp()->simplifiedNode() );
2380 if ( simplifiedWhenThenList->isEmpty() && simplifiedWhen->nodeType() ==
ntLiteral && simplifiedWhen->eval(
nullptr,
nullptr ).toBool() )
2382 return simplifiedThen.release();
2385 else if ( simplifiedWhen->nodeType() ==
ntLiteral && !simplifiedWhen->eval(
nullptr,
nullptr ).toBool() )
2393 std::unique_ptr< QgsExpressionNode > simplifiedElse( mElseExp ? mElseExp->simplifiedNode() :
nullptr );
2394 if ( simplifiedWhenThenList->isEmpty() )
2405 return QSet< QString >();
2407 QSet<QString> lst( mNode->referencedColumns() );
2408 const QList< QgsExpressionNode * > nodeList = mList->list();
2410 lst.unite( n->referencedColumns() );
2416 QSet<QString> lst( mNode->referencedVariables() );
2417 const QList< QgsExpressionNode * > nodeList = mList->list();
2419 lst.unite( n->referencedVariables() );
2425 QSet<QString> lst( mNode->referencedFunctions() );
2426 const QList< QgsExpressionNode * > nodeList = mList->list();
2428 lst.unite( n->referencedFunctions() );
2434 QList<const QgsExpressionNode *> lst;
2437 const QList< QgsExpressionNode * > nodeList = mList->list();
2454 bool res = mNode->prepare( parent, context );
2455 res = res && mLowerBound->prepare( parent, context );
2456 res = res && mHigherBound->prepare( parent, context );
2462 const QVariant nodeVal = mNode->eval( parent, context );
2471 const QVariant lowBoundValue = lowBound.
eval( parent, context );
2472 const bool lowBoundBool { lowBoundValue.toBool() };
2476 return QVariant( mNegate );
2480 const QVariant highBoundValue = highBound.
eval( parent, context );
2487 const bool highBoundBool { highBoundValue.toBool() };
2495 return QVariant( mNegate );
2504 return QVariant( mNegate );
2507 const bool res { lowBoundBool && highBoundBool };
2508 return mNegate ? QVariant( !res ) : QVariant( res );
2513 return u
"%1 %2 %3 AND %4"_s.arg( mNode->dump(), mNegate ? u
"NOT BETWEEN"_s : u
"BETWEEN"_s, mLowerBound->dump(), mHigherBound->dump() );
2518 QSet<QString> lst( mNode->referencedVariables() );
2519 lst.unite( mLowerBound->referencedVariables() );
2520 lst.unite( mHigherBound->referencedVariables() );
2526 QSet<QString> lst( mNode->referencedFunctions() );
2527 lst.unite( mLowerBound->referencedFunctions() );
2528 lst.unite( mHigherBound->referencedFunctions() );
2534 return {
this, mLowerBound.get(), mHigherBound.get() };
2539 QSet<QString> lst( mNode->referencedColumns() );
2540 lst.unite( mLowerBound->referencedColumns() );
2541 lst.unite( mHigherBound->referencedColumns() );
2547 if ( mNode->needsGeometry() )
2550 if ( mLowerBound->needsGeometry() )
2553 if ( mHigherBound->needsGeometry() )
2568 if ( !mNode->isStatic( parent, context ) )
2571 if ( !mLowerBound->isStatic( parent, context ) )
2574 if ( !mHigherBound->isStatic( parent, context ) )
2582 return mLowerBound.get();
2587 return mHigherBound.get();
2605 return new WhenThen( mWhenExp->clone(), mThenExp->clone() );
2610 return BINARY_OPERATOR_TEXT[mOp];
2617 const QVariant
container = mContainer->eval( parent, context );
2619 const QVariant
index = mIndex->eval( parent, context );
2624 case QMetaType::Type::QVariantMap:
2625 return QgsExpressionUtils::getMapValue(
container, parent ).value(
index.toString() );
2627 case QMetaType::Type::QVariantList:
2628 case QMetaType::Type::QStringList:
2630 const QVariantList list = QgsExpressionUtils::getListValue(
container, parent );
2631 qlonglong pos = QgsExpressionUtils::getIntValue(
index, parent );
2632 if ( pos >= list.length() || pos < -list.length() )
2639 pos += list.length();
2642 return list.at( pos );
2647 parent->
setEvalErrorString( tr(
"[] can only be used with map or array values, not %1" ).arg( QMetaType::typeName(
static_cast<QMetaType::Type
>(
container.userType() ) ) ) );
2659 bool resC = mContainer->prepare( parent, context );
2660 bool resV = mIndex->prepare( parent, context );
2661 return resC && resV;
2666 return u
"%1[%2]"_s.arg( mContainer->dump(), mIndex->dump() );
2672 return QSet< QString >();
2674 return mContainer->referencedColumns() + mIndex->referencedColumns();
2679 return mContainer->referencedVariables() + mIndex->referencedVariables();
2684 return mContainer->referencedFunctions() + mIndex->referencedFunctions();
2689 QList<const QgsExpressionNode *> lst;
2691 lst += mContainer->nodes() + mIndex->nodes();
2697 return mContainer->needsGeometry() || mIndex->needsGeometry();
2709 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.
void setCachedValue(const QString &key, const QVariant &value) const
Sets a value to cache within the expression 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.
QVariant cachedValue(const QString &key) const
Returns the matching cached value, if set.
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.
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...
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.
std::shared_ptr< QgsExpressionFunction > function() const
Returns a reference to the node's function.
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 QString quotedString(QString text)
Returns a quoted version of a string (in single quotes).
std::shared_ptr< const SharedFunctionPtrList > FunctionListSnapshot
static const FunctionListSnapshot getFunctionsSnapshot()
Returns a thread-safe snapshot of all registered functions.
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.
std::shared_ptr< QgsExpressionFunction > SharedFunctionPtr
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.