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;
116 QVariant val = mOperand->eval( parent, context );
123 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( val, parent );
125 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::NOT[tvl] );
129 if ( QgsExpressionUtils::isIntSafe( val ) )
130 return QVariant( -QgsExpressionUtils::getIntValue( val, parent ) );
131 else if ( QgsExpressionUtils::isDoubleSafe( val ) )
132 return QVariant( -QgsExpressionUtils::getDoubleValue( val, parent ) );
146 return mOperand->prepare( parent, context );
152 return u
"%1 ( %2 )"_s.arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
154 return u
"%1 %2"_s.arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
160 return QSet< QString >();
162 return mOperand->referencedColumns();
167 return mOperand->referencedVariables();
172 return mOperand->referencedFunctions();
177 QList<const QgsExpressionNode *> lst;
179 lst += mOperand->nodes();
185 return mOperand->needsGeometry();
197 return mOperand->
isStatic( parent, context );
202 return UNARY_OPERATOR_TEXT[mOp];
251QVariant QgsExpressionNodeBinaryOperator::compareNonNullValues( QgsExpression *parent,
const QgsExpressionContext *,
const QVariant &vL,
const QVariant &vR, BinaryOperator op )
253 if ( ( vL.userType() == QMetaType::Type::QDateTime && vR.userType() == QMetaType::Type::QDateTime ) )
255 QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
257 QDateTime dR = QgsExpressionUtils::getDateTimeValue( vR, parent );
264 dL.setTimeSpec( Qt::UTC );
265 dR.setTimeSpec( Qt::UTC );
269 else if ( ( vL.userType() == QMetaType::Type::QDate && vR.userType() == QMetaType::Type::QDate ) )
271 const QDate dL = QgsExpressionUtils::getDateValue( vL, parent );
273 const QDate dR = QgsExpressionUtils::getDateValue( vR, parent );
277 else if ( ( vL.userType() == QMetaType::Type::QTime && vR.userType() == QMetaType::Type::QTime ) )
279 const QTime dL = QgsExpressionUtils::getTimeValue( vL, parent );
281 const QTime dR = QgsExpressionUtils::getTimeValue( vR, parent );
283 return compareOp<int>( dR.msecsTo( dL ), op ) ? TVL_True : TVL_False;
285 else if ( ( vL.userType() != QMetaType::Type::QString || vR.userType() != QMetaType::Type::QString ) && QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) )
289 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
291 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
296 else if ( vL.userType() == QMetaType::Type::Bool || vR.userType() == QMetaType::Type::Bool )
318 const bool vLBool = vL.toBool();
319 const bool vRBool = vR.toBool();
323 return vLBool == vRBool ? TVL_True : TVL_False;
325 return vLBool != vRBool ? TVL_True : TVL_False;
327 return vLBool < vRBool ? TVL_True : TVL_False;
329 return vLBool <= vRBool ? TVL_True : TVL_False;
331 return vLBool > vRBool ? TVL_True : TVL_False;
333 return vLBool >= vRBool ? TVL_True : TVL_False;
358 else if ( vL.userType() == qMetaTypeId< QgsInterval>() && vR.userType() == qMetaTypeId< QgsInterval>() )
360 double fL = QgsExpressionUtils::getInterval( vL, parent ).seconds();
362 double fR = QgsExpressionUtils::getInterval( vR, parent ).seconds();
369 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
371 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
373 int diff = QString::compare( sL, sR );
380 QVariant vL = mOpLeft->eval( parent, context );
385 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent );
387 if ( mOp ==
boAnd && tvlL == QgsExpressionUtils::False )
389 if ( mOp ==
boOr && tvlL == QgsExpressionUtils::True )
393 QVariant vR = mOpRight->eval( parent, context );
399 if ( vL.userType() == QMetaType::Type::QString && vR.userType() == QMetaType::Type::QString )
401 QString sL = QgsExpressionUtils::isNull( vL ) ? QString() : QgsExpressionUtils::getStringValue( vL, parent );
403 QString sR = QgsExpressionUtils::isNull( vR ) ? QString() : QgsExpressionUtils::getStringValue( vR, parent );
405 return QVariant( sL + sR );
414 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
416 else if ( mOp !=
boDiv && QgsExpressionUtils::isIntSafe( vL ) && QgsExpressionUtils::isIntSafe( vR ) )
419 qlonglong iL = QgsExpressionUtils::getIntValue( vL, parent );
421 qlonglong iR = QgsExpressionUtils::getIntValue( vR, parent );
424 if ( mOp ==
boMod && iR == 0 )
427 return QVariant( computeInt( iL, iR ) );
429 else if ( QgsExpressionUtils::isDateTimeSafe( vL ) && QgsExpressionUtils::isIntervalSafe( vR ) )
431 QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
433 QgsInterval iL = QgsExpressionUtils::getInterval( vR, parent );
437 parent->
setEvalErrorString( tr(
"Can't perform /, *, or % on DateTime and Interval" ) );
440 return QVariant( computeDateTimeFromInterval( dL, &iL ) );
443 && ( ( vL.userType() == QMetaType::Type::QDate && vR.userType() == QMetaType::Type::QTime ) || ( vR.userType() == QMetaType::Type::QDate && vL.userType() == QMetaType::Type::QTime ) ) )
445 QDate date = QgsExpressionUtils::getDateValue( vL.userType() == QMetaType::Type::QDate ? vL : vR, parent );
447 QTime time = QgsExpressionUtils::getTimeValue( vR.userType() == QMetaType::Type::QTime ? vR : vL, parent );
449 QDateTime dt = QDateTime( date, time );
450 return QVariant( dt );
452 else if ( mOp ==
boMinus && vL.userType() == QMetaType::Type::QDate && vR.userType() == QMetaType::Type::QDate )
454 QDate date1 = QgsExpressionUtils::getDateValue( vL, parent );
456 QDate date2 = QgsExpressionUtils::getDateValue( vR, parent );
458 return date1 - date2;
460 else if ( mOp ==
boMinus && vL.userType() == QMetaType::Type::QTime && vR.userType() == QMetaType::Type::QTime )
462 QTime time1 = QgsExpressionUtils::getTimeValue( vL, parent );
464 QTime time2 = QgsExpressionUtils::getTimeValue( vR, parent );
466 return time1 - time2;
468 else if ( mOp ==
boMinus && vL.userType() == QMetaType::Type::QDateTime && vR.userType() == QMetaType::Type::QDateTime )
470 QDateTime datetime1 = QgsExpressionUtils::getDateTimeValue( vL, parent );
472 QDateTime datetime2 = QgsExpressionUtils::getDateTimeValue( vR, parent );
476 else if ( ( mOp ==
boPlus || mOp ==
boMinus || mOp ==
boMul || mOp ==
boDiv ) && vL.userType() == QMetaType::Type::QColor && vR.userType() == QMetaType::Type::QColor )
478 bool isQColor =
false;
479 const QColor colorL = QgsExpressionUtils::getColorValue( vL, parent, isQColor );
481 const QColor colorR = QgsExpressionUtils::getColorValue( vR, parent, isQColor );
484 if ( !colorL.isValid() || !colorR.isValid() )
490 QColor::Spec colorLSpec = colorL.spec();
491 QColor::Spec colorRSpec = colorR.spec();
493 switch ( colorLSpec )
497 if ( colorRSpec != QColor::Cmyk )
499 parent->
setEvalErrorString( tr(
"Cannot combine a CMYK color with a non-CMYK color" ) );
503 float lc, lm, ly, lk, la, rc, rm, ry, rk, ra;
504 colorL.getCmykF( &lc, &lm, &ly, &lk, &la );
505 colorR.getCmykF( &rc, &rm, &ry, &rk, &ra );
506 return QColor::fromCmykF(
507 static_cast<float>( std::clamp( computeDouble( lc, rc ), 0.0, 1.0 ) ),
508 static_cast<float>( std::clamp( computeDouble( lm, rm ), 0.0, 1.0 ) ),
509 static_cast<float>( std::clamp( computeDouble( ly, ry ), 0.0, 1.0 ) ),
510 static_cast<float>( std::clamp( computeDouble( lk, rk ), 0.0, 1.0 ) ),
517 case QColor::ExtendedRgb:
519 if ( colorRSpec == QColor::Cmyk )
521 parent->
setEvalErrorString( tr(
"Cannot combine a non-CMYK color with a CMYK color" ) );
525 float lr, lg, lb, la, rr, rg, rb, ra;
526 colorL.getRgbF( &lr, &lg, &lb, &la );
527 colorR.getRgbF( &rr, &rg, &rb, &ra );
528 QColor result = QColor::
529 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 );
537 && ( ( ( vL.userType() == QMetaType::Type::QColor ) && QgsExpressionUtils::isDoubleSafe( vR ) ) || ( ( vR.userType() == QMetaType::Type::QColor ) && QgsExpressionUtils::isDoubleSafe( vL ) ) ) )
539 const bool colorLeft = vL.userType() == QMetaType::Type::QColor;
540 bool isQColor =
false;
541 const QColor color = QgsExpressionUtils::getColorValue( colorLeft ? vL : vR, parent, isQColor );
544 if ( !color.isValid() )
550 const double value = QgsExpressionUtils::getDoubleValue( colorLeft ? vR : vL, parent );
553 if ( mOp ==
boDiv && value == 0.0 )
559 if ( !colorLeft && mOp ==
boDiv )
561 parent->
setEvalErrorString( tr(
"Can't perform / with a color value on the right" ) );
565 switch ( color.spec() )
570 color.getCmykF( &
c, &m, &y, &k, &a );
571 const double dc =
static_cast<double>(
c );
572 const double dm =
static_cast<double>( m );
573 const double dy =
static_cast<double>( y );
574 const double dk =
static_cast<double>( k );
576 return QColor::fromCmykF(
577 static_cast<float>( std::clamp( computeDouble( colorLeft ? dc : value, colorLeft ? value : dc ), 0.0, 1.0 ) ),
578 static_cast<float>( std::clamp( computeDouble( colorLeft ? dm : value, colorLeft ? value : dm ), 0.0, 1.0 ) ),
579 static_cast<float>( std::clamp( computeDouble( colorLeft ? dy : value, colorLeft ? value : dy ), 0.0, 1.0 ) ),
580 static_cast<float>( std::clamp( computeDouble( colorLeft ? dk : value, colorLeft ? value : dk ), 0.0, 1.0 ) ),
587 case QColor::ExtendedRgb:
590 color.getRgbF( &r, &g, &b, &a );
591 const double dr =
static_cast<double>( r );
592 const double dg =
static_cast<double>( g );
593 const double db =
static_cast<double>( b );
595 return QColor::fromRgbF(
596 static_cast<float>( std::clamp( computeDouble( colorLeft ? dr : value, colorLeft ? value : dr ), 0.0, 1.0 ) ),
597 static_cast<float>( std::clamp( computeDouble( colorLeft ? dg : value, colorLeft ? value : dg ), 0.0, 1.0 ) ),
598 static_cast<float>( std::clamp( computeDouble( colorLeft ? db : value, colorLeft ? value : db ), 0.0, 1.0 ) ),
609 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
611 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
613 if ( ( mOp ==
boDiv || mOp ==
boMod ) && fR == 0. )
615 return QVariant( computeDouble( fL, fR ) );
621 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
623 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
627 return QVariant( qlonglong( std::floor( fL / fR ) ) );
630 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
634 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
636 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
638 return QVariant( std::pow( fL, fR ) );
643 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
645 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::AND[tvlL][tvlR] );
650 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
652 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::OR[tvlL][tvlR] );
661 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
665 else if ( QgsExpressionUtils::isList( vL ) || QgsExpressionUtils::isList( vR ) )
668 if ( !QgsExpressionUtils::isList( vL ) || !QgsExpressionUtils::isList( vR ) )
672 QVariantList lL = vL.toList();
673 QVariantList lR = vR.toList();
674 for (
int i = 0; i < lL.length() && i < lR.length(); i++ )
676 if ( QgsExpressionUtils::isNull( lL.at( i ) ) && QgsExpressionUtils::isNull( lR.at( i ) ) )
679 if ( QgsExpressionUtils::isNull( lL.at( i ) ) || QgsExpressionUtils::isNull( lR.at( i ) ) )
689 return QgsExpressionUtils::isNull( lR.at( i ) );
692 return QgsExpressionUtils::isNull( lL.at( i ) );
702 QVariant eq = eqNode.
eval( parent, context );
704 if ( eq == TVL_False )
708 QVariant v = node.
eval( parent, context );
718 return lL.length() == lR.length();
720 return lL.length() != lR.length();
722 return lL.length() < lR.length();
724 return lL.length() > lR.length();
726 return lL.length() <= lR.length();
728 return lL.length() >= lR.length();
736 return compareNonNullValues( parent, context, vL, vR, mOp );
742 const bool vLNull = QgsExpressionUtils::isNull( vL );
743 const bool vRNull = QgsExpressionUtils::isNull( vR );
744 if ( vLNull && vRNull )
745 return ( mOp ==
boIs ? TVL_True : TVL_False );
746 else if ( vLNull || vRNull )
747 return ( mOp ==
boIs ? TVL_False : TVL_True );
750 return compareNonNullValues( parent, context, vL, vR, mOp ==
boIs ?
boEQ :
boNE );
759 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
763 QString str = QgsExpressionUtils::getStringValue( vL, parent );
765 QString regexp = QgsExpressionUtils::getStringValue( vR, parent );
773 if ( esc_regexp.startsWith(
'%' ) )
775 esc_regexp.replace( 0, 1, u
".*"_s );
777 const thread_local QRegularExpression rx1( u
"[^\\\\](%)"_s );
779 while ( ( pos = esc_regexp.indexOf( rx1, pos ) ) != -1 )
781 esc_regexp.replace( pos + 1, 1, u
".*"_s );
784 const thread_local QRegularExpression rx2( u
"\\\\%"_s );
785 esc_regexp.replace( rx2, u
"%"_s );
786 if ( esc_regexp.startsWith(
'_' ) )
788 esc_regexp.replace( 0, 1, u
"."_s );
790 const thread_local QRegularExpression rx3( u
"[^\\\\](_)"_s );
792 while ( ( pos = esc_regexp.indexOf( rx3, pos ) ) != -1 )
794 esc_regexp.replace( pos + 1, 1,
'.' );
797 esc_regexp.replace(
"\\\\_"_L1,
"_"_L1 );
800 = QRegularExpression( QRegularExpression::anchoredPattern( esc_regexp ), mOp ==
boLike || mOp ==
boNotLike ? QRegularExpression::DotMatchesEverythingOption : QRegularExpression::DotMatchesEverythingOption | QRegularExpression::CaseInsensitiveOption )
806 matches = QRegularExpression( regexp ).match( str ).hasMatch();
814 return matches ? TVL_True : TVL_False;
818 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
822 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
824 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
826 return QVariant( sL + sR );
833qlonglong QgsExpressionNodeBinaryOperator::computeInt( qlonglong x, qlonglong y )
853QDateTime QgsExpressionNodeBinaryOperator::computeDateTimeFromInterval(
const QDateTime &d, QgsInterval *i )
858 return d.addSecs( i->
seconds() );
860 return d.addSecs( -i->
seconds() );
867double QgsExpressionNodeBinaryOperator::computeDouble(
double x,
double y )
880 return std::fmod( x, y );
898 QMap<QString, QgsExpressionNode::NodeList> orValuesMap;
899 QList<QString> orFieldNames;
915 const QString fieldName =
op->opLeft()->dump();
916 if ( !orValuesMap.contains( fieldName ) )
918 orFieldNames.append( fieldName );
921 orValuesMap[fieldName].append(
op->opRight()->clone() );
926 const QString fieldName =
op->opRight()->dump();
927 if ( !orValuesMap.contains( fieldName ) )
929 orFieldNames.append( fieldName );
932 orValuesMap[fieldName].append(
op->opLeft()->clone() );
938 if ( visitOrNodes(
op->opLeft() ) && visitOrNodes(
op->opRight() ) )
950 const QString fieldName = inOp->node()->dump();
953 const auto nodes = inOp->list()->list();
954 for (
const auto &valueNode : std::as_const(
nodes ) )
962 if ( !orValuesMap.contains( fieldName ) )
964 orFieldNames.append( fieldName );
965 orValuesMap.insert( fieldName, *inOp->list()->clone() );
969 for (
const auto &valueNode : std::as_const(
nodes ) )
971 orValuesMap[fieldName].append( valueNode->clone() );
982 if ( visitOrNodes(
this ) && !orValuesMap.empty() )
984 std::unique_ptr<QgsExpressionNode> currentNode;
985 for (
const auto &fieldName : std::as_const( orFieldNames ) )
987 auto orValuesIt = orValuesMap.find( fieldName );
988 if ( orValuesIt.value().count() == 1 )
993 currentNode = std::make_unique<QgsExpressionNodeBinaryOperator>(
boOr, currentNode.release(), eqNode.release() );
997 currentNode = std::move( eqNode );
1005 currentNode = std::make_unique<QgsExpressionNodeBinaryOperator>(
boOr, currentNode.release(), inNode.release() );
1009 currentNode = std::move( inNode );
1022 bool resL = mOpLeft->prepare( parent, context );
1023 bool resR = mOpRight->prepare( parent, context );
1024 return resL && resR;
1069 Q_ASSERT(
false &&
"unexpected binary operator" );
1105 Q_ASSERT(
false &&
"unexpected binary operator" );
1115 QString rdump( mOpRight->dump() );
1120 rdump.prepend(
'(' ).append(
')' );
1137 return fmt.arg( mOpLeft->dump(), BINARY_OPERATOR_TEXT[mOp], rdump );
1143 return QSet< QString >();
1145 return mOpLeft->referencedColumns() + mOpRight->referencedColumns();
1150 return mOpLeft->referencedVariables() + mOpRight->referencedVariables();
1155 return mOpLeft->referencedFunctions() + mOpRight->referencedFunctions();
1160 QList<const QgsExpressionNode *> lst;
1162 lst += mOpLeft->nodes() + mOpRight->nodes();
1168 return mOpLeft->needsGeometry() || mOpRight->needsGeometry();
1180 const bool leftStatic = mOpLeft->
isStatic( parent, context );
1181 const bool rightStatic = mOpRight->isStatic( parent, context );
1183 if ( leftStatic && rightStatic )
1195 mOpLeft->prepare( parent, context );
1196 if ( mOpLeft->hasCachedStaticValue() )
1198 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
1199 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
1207 else if ( rightStatic )
1209 mOpRight->prepare( parent, context );
1210 if ( mOpRight->hasCachedStaticValue() )
1212 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
1213 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
1231 mOpLeft->prepare( parent, context );
1232 if ( mOpLeft->hasCachedStaticValue() )
1234 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
1235 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
1243 else if ( rightStatic )
1245 mOpRight->prepare( parent, context );
1246 if ( mOpRight->hasCachedStaticValue() )
1248 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
1249 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
1292 if ( mList->count() == 0 )
1293 return mNotIn ? TVL_True : TVL_False;
1294 QVariant v1 = mNode->eval( parent, context );
1296 if ( QgsExpressionUtils::isNull( v1 ) )
1299 bool listHasNull =
false;
1301 const QList< QgsExpressionNode * > nodeList = mList->list();
1304 QVariant v2 = n->eval( parent, context );
1306 if ( QgsExpressionUtils::isNull( v2 ) )
1312 if ( ( v1.userType() != QMetaType::Type::QString || v2.userType() != QMetaType::Type::QString ) && QgsExpressionUtils::isDoubleSafe( v1 ) && QgsExpressionUtils::isDoubleSafe( v2 ) )
1316 double f1 = QgsExpressionUtils::getDoubleValue( v1, parent );
1318 double f2 = QgsExpressionUtils::getDoubleValue( v2, parent );
1324 QString s1 = QgsExpressionUtils::getStringValue( v1, parent );
1326 QString s2 = QgsExpressionUtils::getStringValue( v2, parent );
1328 equal = QString::compare( s1, s2 ) == 0;
1332 return mNotIn ? TVL_False : TVL_True;
1340 return mNotIn ? TVL_True : TVL_False;
1353 bool res = mNode->prepare( parent, context );
1354 const QList< QgsExpressionNode * > nodeList = mList->list();
1357 res = res && n->prepare( parent, context );
1364 return u
"%1 %2 IN (%3)"_s.arg( mNode->dump(), mNotIn ?
"NOT" :
"", mList->dump() );
1376 if ( !mNode->isStatic( parent, context ) )
1379 const QList< QgsExpressionNode * > nodeList = mList->
list();
1382 if ( !n->isStatic( parent, context ) )
1393 QString name = QgsExpression::QgsExpression::Functions()[mFnIndex]->name();
1396 QVariant res = fd->
run( mArgs.get(), context, parent,
this );
1409 QMutexLocker locker( &QgsExpression::QgsExpression::sFunctionsMutex );
1412 const int functionParamsSize = functionParams.size();
1413 if ( functionParams.isEmpty() )
1416 mArgs.reset(
args );
1421 mArgs = std::make_unique<NodeList>();
1422 mArgs->reserve( functionParamsSize );
1431 mArgs = std::make_unique<NodeList>();
1432 mArgs->reserve( functionParamsSize );
1435 const QStringList argNames =
args->names();
1436 const QList<QgsExpressionNode *> argList =
args->list();
1439 const int argNamesSize = argNames.size();
1440 while ( idx < argNamesSize && argNames.at( idx ).isEmpty() )
1442 mArgs->append( argList.at( idx )->clone() );
1448 for ( ; idx < functionParamsSize; ++idx )
1451 int nodeIdx = argNames.indexOf( parameter.
name().toLower() );
1459 mArgs->append( argList.at( nodeIdx )->clone() );
1479 bool res = fd->
prepare(
this, parent, context );
1482 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1485 res = res && n->prepare( parent, context );
1495 return u
"%1%2"_s.arg( fd->
name(), fd->
name().startsWith(
'$' ) ? QString() : u
"()"_s );
1497 return u
"%1(%2)"_s.arg( fd->
name(), mArgs ? mArgs->dump() : QString() );
1503 return QSet< QString >();
1511 return functionColumns;
1515 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1518 if ( fd->
parameters().count() <= paramIndex || !fd->
parameters().at( paramIndex ).isSubExpression() )
1519 functionColumns.unite( n->referencedColumns() );
1523 return functionColumns;
1529 if ( fd->
name() ==
"var"_L1 )
1531 if ( !mArgs->list().isEmpty() )
1535 return QSet<QString>() << var->
value().toString();
1537 return QSet<QString>() << QString();
1541 QSet<QString> functionVariables = QSet<QString>();
1544 return functionVariables;
1546 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1549 functionVariables.unite( n->referencedVariables() );
1552 return functionVariables;
1559 QSet<QString> functions = QSet<QString>();
1560 functions.insert( fd->
name() );
1565 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1568 functions.unite( n->referencedFunctions() );
1575 QList<const QgsExpressionNode *> lst;
1580 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1590 bool needs = QgsExpression::QgsExpression::Functions()[mFnIndex]->usesGeometry(
this );
1593 const QList< QgsExpressionNode * > nodeList = mArgs->list();
1595 needs |= n->needsGeometry();
1614 if ( !
args || !
args->hasNamedNodes() )
1618 if ( functionParams.isEmpty() )
1625 QSet< int > providedArgs;
1626 QSet< int > handledArgs;
1629 while (
args->names().at( idx ).isEmpty() )
1631 providedArgs << idx;
1637 for ( ; idx < functionParams.count(); ++idx )
1639 int nodeIdx =
args->names().indexOf( functionParams.at( idx ).name().toLower() );
1642 if ( !functionParams.at( idx ).optional() )
1644 error = u
"No value specified for QgsExpressionFunction::Parameter '%1' for %2"_s.arg( functionParams.at( idx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1650 if ( providedArgs.contains( idx ) )
1652 error = u
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2"_s.arg( functionParams.at( idx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1656 providedArgs << idx;
1657 handledArgs << nodeIdx;
1662 const QStringList nameList =
args->names();
1663 for (
const QString &name : nameList )
1665 if ( !name.isEmpty() && !functionParams.contains( name ) )
1670 if ( !name.isEmpty() && !handledArgs.contains( idx ) )
1672 int functionIdx = functionParams.indexOf( name );
1673 if ( providedArgs.contains( functionIdx ) )
1675 error = u
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2"_s.arg( functionParams.at( functionIdx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1712 switch ( mValue.userType() )
1714 case QMetaType::Type::Int:
1715 return QString::number( mValue.toInt() );
1716 case QMetaType::Type::Double:
1718 case QMetaType::Type::LongLong:
1719 return QString::number( mValue.toLongLong() );
1720 case QMetaType::Type::QString:
1722 case QMetaType::Type::QTime:
1724 case QMetaType::Type::QDate:
1726 case QMetaType::Type::QDateTime:
1728 case QMetaType::Type::Bool:
1729 return mValue.toBool() ? u
"TRUE"_s : u
"FALSE"_s;
1731 return tr(
"[unsupported type: %1; value: %2]" ).arg( mValue.typeName(), mValue.toString() );
1742 return QSet<QString>();
1747 return QSet<QString>();
1752 return QSet<QString>();
1757 QList<const QgsExpressionNode *> lst;
1810 parent->
setEvalErrorString( tr(
"No feature available for field '%1' evaluation" ).arg( mName ) );
1847 const thread_local QRegularExpression re( u
"^[A-Za-z_\\x80-\\xff][A-Za-z0-9_\\x80-\\xff]*$"_s );
1848 const QRegularExpressionMatch match = re.match( mName );
1854 return QSet<QString>() << mName;
1859 return QSet<QString>();
1864 return QSet<QString>();
1869 QList<const QgsExpressionNode *> result;
1904 qDeleteAll( mConditions );
1914 for (
WhenThen *cond : std::as_const( mConditions ) )
1916 QVariant vWhen = cond->mWhenExp->eval( parent, context );
1917 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( vWhen, parent );
1919 if ( tvl == QgsExpressionUtils::True )
1921 QVariant vRes = cond->mThenExp->eval( parent, context );
1929 QVariant vElse = mElseExp->eval( parent, context );
1940 bool foundAnyNonStaticConditions =
false;
1941 for (
WhenThen *cond : std::as_const( mConditions ) )
1943 const bool res = cond->mWhenExp->prepare( parent, context ) && cond->mThenExp->prepare( parent, context );
1947 foundAnyNonStaticConditions |= !cond->mWhenExp->hasCachedStaticValue();
1948 if ( !foundAnyNonStaticConditions && QgsExpressionUtils::getTVLValue( cond->mWhenExp->cachedStaticValue(), parent ) == QgsExpressionUtils::True )
1952 if ( cond->mThenExp->hasCachedStaticValue() )
1971 const bool res = mElseExp->prepare( parent, context );
1975 if ( !foundAnyNonStaticConditions )
1978 if ( mElseExp->hasCachedStaticValue() )
1999 QString msg( u
"CASE"_s );
2000 for (
WhenThen *cond : mConditions )
2002 msg += u
" WHEN %1 THEN %2"_s.arg( cond->mWhenExp->dump(), cond->mThenExp->dump() );
2005 msg += u
" ELSE %1"_s.arg( mElseExp->dump() );
2013 return QSet< QString >();
2016 for (
WhenThen *cond : mConditions )
2018 lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
2022 lst += mElseExp->referencedColumns();
2030 for (
WhenThen *cond : mConditions )
2032 lst += cond->mWhenExp->referencedVariables() + cond->mThenExp->referencedVariables();
2036 lst += mElseExp->referencedVariables();
2044 for (
WhenThen *cond : mConditions )
2046 lst += cond->mWhenExp->referencedFunctions() + cond->mThenExp->referencedFunctions();
2050 lst += mElseExp->referencedFunctions();
2057 QList<const QgsExpressionNode *> lst;
2059 for (
WhenThen *cond : mConditions )
2061 lst += cond->mWhenExp->nodes() + cond->mThenExp->nodes();
2065 lst += mElseExp->nodes();
2072 for (
WhenThen *cond : mConditions )
2074 if ( cond->mWhenExp->needsGeometry() || cond->mThenExp->needsGeometry() )
2078 return mElseExp && mElseExp->needsGeometry();
2097 if ( !wt->mWhenExp->isStatic( parent, context ) || !wt->mThenExp->isStatic( parent, context ) )
2102 return mElseExp->
isStatic( parent, context );
2110 return QSet< QString >();
2112 QSet<QString> lst( mNode->referencedColumns() );
2113 const QList< QgsExpressionNode * > nodeList = mList->list();
2115 lst.unite( n->referencedColumns() );
2121 QSet<QString> lst( mNode->referencedVariables() );
2122 const QList< QgsExpressionNode * > nodeList = mList->list();
2124 lst.unite( n->referencedVariables() );
2130 QSet<QString> lst( mNode->referencedFunctions() );
2131 const QList< QgsExpressionNode * > nodeList = mList->list();
2133 lst.unite( n->referencedFunctions() );
2139 QList<const QgsExpressionNode *> lst;
2141 const QList< QgsExpressionNode * > nodeList = mList->list();
2158 bool res = mNode->prepare( parent, context );
2159 res = res && mLowerBound->prepare( parent, context );
2160 res = res && mHigherBound->prepare( parent, context );
2166 const QVariant nodeVal = mNode->eval( parent, context );
2175 const QVariant lowBoundValue = lowBound.
eval( parent, context );
2176 const bool lowBoundBool { lowBoundValue.toBool() };
2180 return QVariant( mNegate );
2184 const QVariant highBoundValue = highBound.
eval( parent, context );
2191 const bool highBoundBool { highBoundValue.toBool() };
2199 return QVariant( mNegate );
2208 return QVariant( mNegate );
2211 const bool res { lowBoundBool && highBoundBool };
2212 return mNegate ? QVariant( !res ) : QVariant( res );
2217 return u
"%1 %2 %3 AND %4"_s.arg( mNode->dump(), mNegate ? u
"NOT BETWEEN"_s : u
"BETWEEN"_s, mLowerBound->dump(), mHigherBound->dump() );
2222 QSet<QString> lst( mNode->referencedVariables() );
2223 lst.unite( mLowerBound->referencedVariables() );
2224 lst.unite( mHigherBound->referencedVariables() );
2230 QSet<QString> lst( mNode->referencedFunctions() );
2231 lst.unite( mLowerBound->referencedFunctions() );
2232 lst.unite( mHigherBound->referencedFunctions() );
2238 return {
this, mLowerBound.get(), mHigherBound.get() };
2243 QSet<QString> lst( mNode->referencedColumns() );
2244 lst.unite( mLowerBound->referencedColumns() );
2245 lst.unite( mHigherBound->referencedColumns() );
2251 if ( mNode->needsGeometry() )
2254 if ( mLowerBound->needsGeometry() )
2257 if ( mHigherBound->needsGeometry() )
2272 if ( !mNode->isStatic( parent, context ) )
2275 if ( !mLowerBound->isStatic( parent, context ) )
2278 if ( !mHigherBound->isStatic( parent, context ) )
2286 return mLowerBound.get();
2291 return mHigherBound.get();
2309 return new WhenThen( mWhenExp->clone(), mThenExp->clone() );
2314 return BINARY_OPERATOR_TEXT[mOp];
2321 const QVariant
container = mContainer->eval( parent, context );
2323 const QVariant
index = mIndex->eval( parent, context );
2328 case QMetaType::Type::QVariantMap:
2329 return QgsExpressionUtils::getMapValue(
container, parent ).value(
index.toString() );
2331 case QMetaType::Type::QVariantList:
2332 case QMetaType::Type::QStringList:
2334 const QVariantList list = QgsExpressionUtils::getListValue(
container, parent );
2335 qlonglong pos = QgsExpressionUtils::getIntValue(
index, parent );
2336 if ( pos >= list.length() || pos < -list.length() )
2343 pos += list.length();
2346 return list.at( pos );
2351 parent->
setEvalErrorString( tr(
"[] can only be used with map or array values, not %1" ).arg( QMetaType::typeName(
static_cast<QMetaType::Type
>(
container.userType() ) ) ) );
2363 bool resC = mContainer->prepare( parent, context );
2364 bool resV = mIndex->prepare( parent, context );
2365 return resC && resV;
2370 return u
"%1[%2]"_s.arg( mContainer->dump(), mIndex->dump() );
2376 return QSet< QString >();
2378 return mContainer->referencedColumns() + mIndex->referencedColumns();
2383 return mContainer->referencedVariables() + mIndex->referencedVariables();
2388 return mContainer->referencedFunctions() + mIndex->referencedFunctions();
2393 QList<const QgsExpressionNode *> lst;
2395 lst += mContainer->nodes() + mIndex->nodes();
2401 return mContainer->needsGeometry() || mIndex->needsGeometry();
2413 return mContainer->
isStatic( parent, context ) && mIndex->isStatic( parent, context );
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
bool hasFunction(const QString &name) const
Checks whether a specified function is contained in the context.
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
static const QString EXPR_FIELDS
Inbuilt variable name for fields storage.
bool hasVariable(const QString &name) const
Check whether a variable is specified by any scope within the context.
QgsExpressionFunction * function(const QString &name) const
Fetches a matching function from the context.
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
bool hasFeature() const
Returns true if the context has a feature associated with it.
Represents a single parameter passed to a function.
QVariant defaultValue() const
Returns the default value for the parameter.
QString name() const
Returns the name of the parameter.
An abstract base class for defining QgsExpression functions.
QList< QgsExpressionFunction::Parameter > ParameterList
List of parameters, used for function definition.
int params() const
The number of parameters this function takes.
bool lazyEval() const
true if this function should use lazy evaluation.
QString name() const
The name of the function.
virtual QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)
Evaluates the function, first evaluating all required arguments before passing them to the function's...
const QgsExpressionFunction::ParameterList & parameters() const
Returns the list of named parameters for the function, if set.
virtual QSet< QString > referencedColumns(const QgsExpressionNodeFunction *node) const
Returns a set of field names which are required for this function.
virtual bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
This will be called during the prepare step() of an expression if it is not static.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
bool negate() const
Returns true if the predicate is an exclusion test (NOT BETWEEN).
QgsExpressionNode * lowerBound() const
Returns the lower bound expression node of the range.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QgsExpressionNode * clone() const override
Generate a clone of this node.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QgsExpressionNode * higherBound() const
Returns the higher bound expression node of the range.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
~QgsExpressionNodeBetweenOperator() override
QgsExpressionNodeBetweenOperator(QgsExpressionNode *node, QgsExpressionNode *nodeLowerBound, QgsExpressionNode *nodeHigherBound, bool negate=false)
This node tests if the result of node is between the result of nodeLowerBound and nodeHigherBound nod...
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
A binary expression operator, which operates on two values.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
bool leftAssociative() const
Returns true if the operator is left-associative.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
int precedence() const
Returns the precedence index for the operator.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
QgsExpressionNodeBinaryOperator::BinaryOperator op() const
Returns the binary operator.
QgsExpressionNode * clone() const override
Generate a clone of this node.
QString text() const
Returns a the name of this operator without the operands.
QgsExpressionNodeBinaryOperator(QgsExpressionNodeBinaryOperator::BinaryOperator op, QgsExpressionNode *opLeft, QgsExpressionNode *opRight)
Binary combination of the left and the right with op.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
BinaryOperator
list of binary operators
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
An expression node which takes its value from a feature's field.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QgsExpressionNodeColumnRef(const QString &name)
Constructor for QgsExpressionNodeColumnRef, referencing the column with the specified name.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QgsExpressionNode * clone() const override
Generate a clone of this node.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
Represents a "WHEN... THEN..." portation of a CASE WHEN clause in an expression.
WhenThen(QgsExpressionNode *whenExp, QgsExpressionNode *thenExp)
A combination of when and then.
QgsExpressionNode * thenExp() const
The expression node that makes the THEN result part of the condition.
QgsExpressionNode * whenExp() const
The expression that makes the WHEN part of the condition.
QgsExpressionNodeCondition::WhenThen * clone() const
Gets a deep copy of this WhenThen combination.
QList< QgsExpressionNodeCondition::WhenThen * > WhenThenList
QgsExpressionNodeCondition(QgsExpressionNodeCondition::WhenThenList *conditions, QgsExpressionNode *elseExp=nullptr)
Create a new node with the given list of conditions and an optional elseExp expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
QgsExpressionNode * elseExp() const
The ELSE expression used for the condition.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QgsExpressionNode * clone() const override
Generate a clone of this node.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
WhenThenList conditions() const
The list of WHEN THEN expression parts of the expression.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
~QgsExpressionNodeCondition() override
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
int fnIndex() const
Returns the index of the node's function.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
~QgsExpressionNodeFunction() override
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QgsExpressionNodeFunction(int fnIndex, QgsExpressionNode::NodeList *args)
A function node consists of an index of the function in the global function array and a list of argum...
QgsExpressionNode * clone() const override
Generate a clone of this node.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
static bool validateParams(int fnIndex, QgsExpressionNode::NodeList *args, QString &error)
Tests whether the provided argument list is valid for the matching function.
An expression node for value IN or NOT IN clauses.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QgsExpressionNodeInOperator(QgsExpressionNode *node, QgsExpressionNode::NodeList *list, bool notin=false)
This node tests if the result of node is in the result of list.
~QgsExpressionNodeInOperator() override
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QgsExpressionNode * clone() const override
Generate a clone of this node.
QgsExpressionNode::NodeList * list() const
Returns the list of nodes to search for matching values within.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
QgsExpressionNodeIndexOperator(QgsExpressionNode *container, QgsExpressionNode *index)
Constructor for QgsExpressionNodeIndexOperator.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QgsExpressionNode * clone() const override
Generate a clone of this node.
QgsExpressionNode * index() const
Returns the index node, representing an array element index or map key.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QgsExpressionNode * container() const
Returns the container node, representing an array or map value.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
An expression node for literal values.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QString valueAsString() const
Returns a string representation of the node's literal value.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QgsExpressionNode * clone() const override
Generate a clone of this node.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
QVariant value() const
The value of the literal.
QgsExpressionNodeLiteral(const QVariant &value)
Constructor for QgsExpressionNodeLiteral, with the specified literal value.
A unary node is either negative as in boolean (not) or as in numbers (minus).
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QgsExpressionNodeUnaryOperator::UnaryOperator op() const
Returns the unary operator.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QgsExpressionNodeUnaryOperator(QgsExpressionNodeUnaryOperator::UnaryOperator op, QgsExpressionNode *operand)
A node unary operator is modifying the value of operand by negating it with op.
QString text() const
Returns a the name of this operator without the operands.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
QgsExpressionNode * clone() const override
Generate a clone of this node.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
A list of expression nodes.
virtual QString dump() const
Returns a string dump of the expression node.
QgsExpressionNode::NodeList * clone() const
Creates a deep copy of this list. Ownership is transferred to the caller.
void append(QgsExpressionNode *node)
Takes ownership of the provided node.
bool hasCachedStaticValue() const
Returns true if the node can be replaced by a static cached value.
QVariant eval(QgsExpression *parent, const QgsExpressionContext *context)
Evaluate this node with the given context and parent.
virtual QgsExpressionNode * clone() const =0
Generate a clone of this node.
bool mHasCachedValue
true if the node has a static, precalculated value.
QVariant mCachedStaticValue
Contains the static, precalculated value for the node if mHasCachedValue is true.
QgsExpressionNode()=default
std::unique_ptr< QgsExpressionNode > mCompiledSimplifiedNode
Contains a compiled node which represents a simplified version of this node as a result of compilatio...
NodeType
Known node types.
@ ntBetweenOperator
Between operator.
@ ntIndexOperator
Index operator.
void cloneTo(QgsExpressionNode *target) const
Copies the members of this node to the node provided in target.
Handles parsing and evaluation of expressions (formerly called "search strings").
static const QList< QgsExpressionFunction * > & Functions()
static QString quotedString(QString text)
Returns a quoted version of a string (in single quotes).
void setEvalErrorString(const QString &str)
Sets evaluation error (used internally by evaluation functions).
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes).
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
int fieldNameIndex(const QString &fieldName) const
Utility method to get attribute index from name.
bool isValid() const
Returns the validity of this feature.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Container of fields for a vector layer.
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
A representation of the interval between two datetime values.
double seconds() const
Returns the interval duration in seconds.
static QString qRegExpEscape(const QString &string)
Returns an escaped string matching the behavior of QRegExp::escape.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
bool compareOp(T diff, QgsExpressionNodeBinaryOperator::BinaryOperator op)
#define ENSURE_NO_EVAL_ERROR
#define SET_EVAL_ERROR(x)
QgsExpressionNode * node
Node.