28#include <QRegularExpression>
30const char *QgsExpressionNodeBinaryOperator::BINARY_OPERATOR_TEXT[] =
34 "=",
"<>",
"<=",
">=",
"<",
">",
"~",
"LIKE",
"NOT LIKE",
"ILIKE",
"NOT ILIKE",
"IS",
"IS NOT",
35 "+",
"-",
"*",
"/",
"//",
"%",
"^",
39const char *QgsExpressionNodeUnaryOperator::UNARY_OPERATOR_TEXT[] =
48 const QList< QgsExpressionNode * > nodeList = mList->
list();
50 needs |= n->needsGeometry();
61 mList.append( node->
node );
62 mNameList.append( cleanNamedNodeName( node->
name ) );
63 mHasNamedNodes =
true;
72 nl->mList.append( node->clone() );
74 nl->mNameList = mNameList;
85 if ( !first ) msg += QLatin1String(
", " );
92QString QgsExpressionNode::NodeList::cleanNamedNodeName(
const QString &name )
94 QString cleaned = name.toLower();
97 if ( cleaned == QLatin1String(
"geom" ) )
98 cleaned = QStringLiteral(
"geometry" );
99 else if ( cleaned == QLatin1String(
"val" ) )
100 cleaned = QStringLiteral(
"value" );
101 else if ( cleaned == QLatin1String(
"geometry a" ) )
102 cleaned = QStringLiteral(
"geometry1" );
103 else if ( cleaned == QLatin1String(
"geometry b" ) )
104 cleaned = QStringLiteral(
"geometry2" );
105 else if ( cleaned == QLatin1String(
"i" ) )
106 cleaned = QStringLiteral(
"vertex" );
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 QStringLiteral(
"%1 ( %2 )" ).arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
154 return QStringLiteral(
"%1 %2" ).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];
209 QVariant vL = mOpLeft->eval( parent, context );
212 if ( mOp == boAnd || mOp == boOr )
214 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent );
216 if ( mOp == boAnd && tvlL == QgsExpressionUtils::False )
218 if ( mOp == boOr && tvlL == QgsExpressionUtils::True )
222 QVariant vR = mOpRight->eval( parent, context );
228 if ( vL.type() == QVariant::String && vR.type() == QVariant::String )
230 QString sL = QgsExpressionUtils::isNull( vL ) ? QString() : QgsExpressionUtils::getStringValue( vL, parent );
232 QString sR = QgsExpressionUtils::isNull( vR ) ? QString() : QgsExpressionUtils::getStringValue( vR, parent );
234 return QVariant( sL + sR );
243 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
245 else if ( mOp != boDiv && QgsExpressionUtils::isIntSafe( vL ) && QgsExpressionUtils::isIntSafe( vR ) )
248 qlonglong iL = QgsExpressionUtils::getIntValue( vL, parent );
250 qlonglong iR = QgsExpressionUtils::getIntValue( vR, parent );
253 if ( mOp == boMod && iR == 0 )
256 return QVariant( computeInt( iL, iR ) );
258 else if ( QgsExpressionUtils::isDateTimeSafe( vL ) && QgsExpressionUtils::isIntervalSafe( vR ) )
260 QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
262 QgsInterval iL = QgsExpressionUtils::getInterval( vR, parent );
264 if ( mOp == boDiv || mOp == boMul || mOp == boMod )
266 parent->
setEvalErrorString( tr(
"Can't perform /, *, or % on DateTime and Interval" ) );
269 return QVariant( computeDateTimeFromInterval( dL, &iL ) );
271 else if ( mOp == boPlus && ( ( vL.type() == QVariant::Date && vR.type() == QVariant::Time ) ||
272 ( vR.type() == QVariant::Date && vL.type() == QVariant::Time ) ) )
274 QDate date = QgsExpressionUtils::getDateValue( vL.type() == QVariant::Date ? vL : vR, parent );
276 QTime time = QgsExpressionUtils::getTimeValue( vR.type() == QVariant::Time ? vR : vL, parent );
278 QDateTime dt = QDateTime( date, time );
279 return QVariant( dt );
281 else if ( mOp == boMinus && vL.type() == QVariant::Date && vR.type() == QVariant::Date )
283 QDate date1 = QgsExpressionUtils::getDateValue( vL, parent );
285 QDate date2 = QgsExpressionUtils::getDateValue( vR, parent );
287 return date1 - date2;
289 else if ( mOp == boMinus && vL.type() == QVariant::Time && vR.type() == QVariant::Time )
291 QTime time1 = QgsExpressionUtils::getTimeValue( vL, parent );
293 QTime time2 = QgsExpressionUtils::getTimeValue( vR, parent );
295 return time1 - time2;
297 else if ( mOp == boMinus && vL.type() == QVariant::DateTime && vR.type() == QVariant::DateTime )
299 QDateTime datetime1 = QgsExpressionUtils::getDateTimeValue( vL, parent );
301 QDateTime datetime2 = QgsExpressionUtils::getDateTimeValue( vR, parent );
308 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
310 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
312 if ( ( mOp == boDiv || mOp == boMod ) && fR == 0. )
314 return QVariant( computeDouble( fL, fR ) );
320 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
322 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
326 return QVariant( qlonglong( std::floor( fL / fR ) ) );
329 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
333 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
335 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
337 return QVariant( std::pow( fL, fR ) );
342 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
344 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::AND[tvlL][tvlR] );
349 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
351 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::OR[tvlL][tvlR] );
360 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
364 else if ( QgsExpressionUtils::isList( vL ) || QgsExpressionUtils::isList( vR ) )
367 if ( !QgsExpressionUtils::isList( vL ) || !QgsExpressionUtils::isList( vR ) )
371 QVariantList lL = vL.toList();
372 QVariantList lR = vR.toList();
373 for (
int i = 0; i < lL.length() && i < lR.length(); i++ )
375 if ( QgsExpressionUtils::isNull( lL.at( i ) ) && QgsExpressionUtils::isNull( lR.at( i ) ) )
378 if ( QgsExpressionUtils::isNull( lL.at( i ) ) || QgsExpressionUtils::isNull( lR.at( i ) ) )
388 return QgsExpressionUtils::isNull( lR.at( i ) );
391 return QgsExpressionUtils::isNull( lL.at( i ) );
401 QVariant eq = eqNode.
eval( parent, context );
403 if ( eq == TVL_False )
407 QVariant v = node.
eval( parent, context );
417 return lL.length() == lR.length();
419 return lL.length() != lR.length();
421 return lL.length() < lR.length();
423 return lL.length() > lR.length();
425 return lL.length() <= lR.length();
427 return lL.length() >= lR.length();
433 else if ( ( vL.type() == QVariant::DateTime && vR.type() == QVariant::DateTime ) )
435 QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
437 QDateTime dR = QgsExpressionUtils::getDateTimeValue( vR, parent );
444 dL.setTimeSpec( Qt::UTC );
445 dR.setTimeSpec( Qt::UTC );
447 return compare( dR.msecsTo( dL ) ) ? TVL_True : TVL_False;
449 else if ( ( vL.type() == QVariant::Date && vR.type() == QVariant::Date ) )
451 const QDate dL = QgsExpressionUtils::getDateValue( vL, parent );
453 const QDate dR = QgsExpressionUtils::getDateValue( vR, parent );
455 return compare( dR.daysTo( dL ) ) ? TVL_True : TVL_False;
457 else if ( ( vL.type() == QVariant::Time && vR.type() == QVariant::Time ) )
459 const QTime dL = QgsExpressionUtils::getTimeValue( vL, parent );
461 const QTime dR = QgsExpressionUtils::getTimeValue( vR, parent );
463 return compare( dR.msecsTo( dL ) ) ? TVL_True : TVL_False;
465 else if ( ( vL.type() != QVariant::String || vR.type() != QVariant::String ) &&
466 QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) )
470 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
472 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
474 return compare( fL - fR ) ? TVL_True : TVL_False;
477 else if ( vL.userType() == QMetaType::type(
"QgsInterval" ) && vR.userType() == QMetaType::type(
"QgsInterval" ) )
479 double fL = QgsExpressionUtils::getInterval( vL, parent ).seconds();
481 double fR = QgsExpressionUtils::getInterval( vR, parent ).seconds();
483 return compare( fL - fR ) ? TVL_True : TVL_False;
488 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
490 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
492 int diff = QString::compare( sL, sR );
493 return compare( diff ) ? TVL_True : TVL_False;
498 if ( QgsExpressionUtils::isNull( vL ) && QgsExpressionUtils::isNull( vR ) )
499 return ( mOp == boIs ? TVL_True : TVL_False );
500 else if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
501 return ( mOp == boIs ? TVL_False : TVL_True );
505 if ( QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) &&
506 ( vL.type() != QVariant::String || vR.type() != QVariant::String ) )
508 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
510 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
516 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
518 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
520 equal = QString::compare( sL, sR ) == 0;
523 return mOp == boIs ? TVL_True : TVL_False;
525 return mOp == boIs ? TVL_False : TVL_True;
533 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
537 QString
str = QgsExpressionUtils::getStringValue( vL, parent );
539 QString regexp = QgsExpressionUtils::getStringValue( vR, parent );
543 if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike )
547 if ( esc_regexp.startsWith(
'%' ) )
549 esc_regexp.replace( 0, 1, QStringLiteral(
".*" ) );
551 const thread_local QRegularExpression rx1( QStringLiteral(
"[^\\\\](%)" ) );
553 while ( ( pos = esc_regexp.indexOf( rx1, pos ) ) != -1 )
555 esc_regexp.replace( pos + 1, 1, QStringLiteral(
".*" ) );
558 const thread_local QRegularExpression rx2( QStringLiteral(
"\\\\%" ) );
559 esc_regexp.replace( rx2, QStringLiteral(
"%" ) );
560 if ( esc_regexp.startsWith(
'_' ) )
562 esc_regexp.replace( 0, 1, QStringLiteral(
"." ) );
564 const thread_local QRegularExpression rx3( QStringLiteral(
"[^\\\\](_)" ) );
566 while ( ( pos = esc_regexp.indexOf( rx3, pos ) ) != -1 )
568 esc_regexp.replace( pos + 1, 1,
'.' );
571 esc_regexp.replace( QLatin1String(
"\\\\_" ), QLatin1String(
"_" ) );
573 matches = QRegularExpression( QRegularExpression::anchoredPattern( esc_regexp ), mOp == boLike || mOp == boNotLike ? QRegularExpression::DotMatchesEverythingOption : QRegularExpression::DotMatchesEverythingOption | QRegularExpression::CaseInsensitiveOption ).match(
str ).hasMatch();
577 matches = QRegularExpression( regexp ).match(
str ).hasMatch();
580 if ( mOp == boNotLike || mOp == boNotILike )
585 return matches ? TVL_True : TVL_False;
589 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
593 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
595 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
597 return QVariant( sL + sR );
604bool QgsExpressionNodeBinaryOperator::compare(
double diff )
626qlonglong QgsExpressionNodeBinaryOperator::computeInt( qlonglong x, qlonglong y )
646QDateTime QgsExpressionNodeBinaryOperator::computeDateTimeFromInterval(
const QDateTime &d,
QgsInterval *i )
651 return d.addSecs( i->
seconds() );
653 return d.addSecs( -i->
seconds() );
660double QgsExpressionNodeBinaryOperator::computeDouble(
double x,
double y )
673 return std::fmod( x, y );
687 bool resL = mOpLeft->prepare( parent, context );
688 bool resR = mOpRight->prepare( parent, context );
734 Q_ASSERT(
false &&
"unexpected binary operator" );
770 Q_ASSERT(
false &&
"unexpected binary operator" );
780 QString rdump( mOpRight->dump() );
785 rdump.prepend(
'(' ).append(
')' );
789 if ( leftAssociative() )
791 fmt += lOp && ( lOp->
precedence() < precedence() ) ? QStringLiteral(
"(%1)" ) : QStringLiteral(
"%1" );
792 fmt += QLatin1String(
" %2 " );
793 fmt += rOp && ( rOp->
precedence() <= precedence() ) ? QStringLiteral(
"(%3)" ) : QStringLiteral(
"%3" );
797 fmt += lOp && ( lOp->
precedence() <= precedence() ) ? QStringLiteral(
"(%1)" ) : QStringLiteral(
"%1" );
798 fmt += QLatin1String(
" %2 " );
799 fmt += rOp && ( rOp->
precedence() < precedence() ) ? QStringLiteral(
"(%3)" ) : QStringLiteral(
"%3" );
802 return fmt.arg( mOpLeft->dump(), BINARY_OPERATOR_TEXT[mOp], rdump );
808 return QSet< QString >();
810 return mOpLeft->referencedColumns() + mOpRight->referencedColumns();
815 return mOpLeft->referencedVariables() + mOpRight->referencedVariables();
820 return mOpLeft->referencedFunctions() + mOpRight->referencedFunctions();
825 QList<const QgsExpressionNode *> lst;
827 lst += mOpLeft->nodes() + mOpRight->nodes();
833 return mOpLeft->needsGeometry() || mOpRight->needsGeometry();
845 const bool leftStatic = mOpLeft->isStatic( parent, context );
846 const bool rightStatic = mOpRight->isStatic( parent, context );
848 if ( leftStatic && rightStatic )
860 mOpLeft->prepare( parent, context );
861 if ( mOpLeft->hasCachedStaticValue() )
863 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
864 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
872 else if ( rightStatic )
874 mOpRight->prepare( parent, context );
875 if ( mOpRight->hasCachedStaticValue() )
877 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
878 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
896 mOpLeft->prepare( parent, context );
897 if ( mOpLeft->hasCachedStaticValue() )
899 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
900 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
908 else if ( rightStatic )
910 mOpRight->prepare( parent, context );
911 if ( mOpRight->hasCachedStaticValue() )
913 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
914 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
957 if ( mList->count() == 0 )
958 return mNotIn ? TVL_True : TVL_False;
959 QVariant v1 = mNode->eval( parent, context );
961 if ( QgsExpressionUtils::isNull( v1 ) )
964 bool listHasNull =
false;
966 const QList< QgsExpressionNode * > nodeList = mList->list();
969 QVariant v2 = n->eval( parent, context );
971 if ( QgsExpressionUtils::isNull( v2 ) )
977 if ( ( v1.type() != QVariant::String || v2.type() != QVariant::String ) &&
978 QgsExpressionUtils::isDoubleSafe( v1 ) && QgsExpressionUtils::isDoubleSafe( v2 ) )
982 double f1 = QgsExpressionUtils::getDoubleValue( v1, parent );
984 double f2 = QgsExpressionUtils::getDoubleValue( v2, parent );
990 QString s1 = QgsExpressionUtils::getStringValue( v1, parent );
992 QString s2 = QgsExpressionUtils::getStringValue( v2, parent );
994 equal = QString::compare( s1, s2 ) == 0;
998 return mNotIn ? TVL_False : TVL_True;
1006 return mNotIn ? TVL_True : TVL_False;
1022 bool res = mNode->prepare( parent, context );
1023 const QList< QgsExpressionNode * > nodeList = mList->list();
1026 res = res && n->prepare( parent, context );
1033 return QStringLiteral(
"%1 %2 IN (%3)" ).arg( mNode->dump(), mNotIn ?
"NOT" :
"", mList->dump() );
1045 if ( !mNode->isStatic( parent, context ) )
1048 const QList< QgsExpressionNode * > nodeList = mList->list();
1051 if ( !n->isStatic( parent, context ) )
1062 QString name = QgsExpression::QgsExpression::Functions()[mFnIndex]->name();
1065 QVariant res = fd->
run( mArgs, context, parent,
this );
1073 : mFnIndex( fnIndex )
1076 if ( functionParams.isEmpty() )
1097 while ( idx < args->names().size() &&
args->
names().at( idx ).isEmpty() )
1104 for ( ; idx < functionParams.count(); ++idx )
1106 int nodeIdx =
args->
names().indexOf( functionParams.at( idx ).name().toLower() );
1136 bool res = fd->
prepare(
this, parent, context );
1139 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1142 res = res && n->prepare( parent, context );
1152 return QStringLiteral(
"%1%2" ).arg( fd->
name(), fd->
name().startsWith(
'$' ) ? QString() : QStringLiteral(
"()" ) );
1154 return QStringLiteral(
"%1(%2)" ).arg( fd->
name(), mArgs ? mArgs->
dump() : QString() );
1160 return QSet< QString >();
1168 return functionColumns;
1172 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1175 if ( fd->
parameters().count() <= paramIndex || !fd->
parameters().at( paramIndex ).isSubExpression() )
1176 functionColumns.unite( n->referencedColumns() );
1180 return functionColumns;
1186 if ( fd->
name() == QLatin1String(
"var" ) )
1188 if ( !mArgs->
list().isEmpty() )
1192 return QSet<QString>() << var->
value().toString();
1194 return QSet<QString>() << QString();
1198 QSet<QString> functionVariables = QSet<QString>();
1201 return functionVariables;
1203 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1206 functionVariables.unite( n->referencedVariables() );
1209 return functionVariables;
1216 QSet<QString> functions = QSet<QString>();
1217 functions.insert( fd->
name() );
1222 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1225 functions.unite( n->referencedFunctions() );
1232 QList<const QgsExpressionNode *> lst;
1237 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1247 bool needs = QgsExpression::QgsExpression::Functions()[mFnIndex]->usesGeometry(
this );
1250 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1252 needs |= n->needsGeometry();
1275 if ( functionParams.isEmpty() )
1282 QSet< int > providedArgs;
1283 QSet< int > handledArgs;
1286 while (
args->
names().at( idx ).isEmpty() )
1288 providedArgs << idx;
1294 for ( ; idx < functionParams.count(); ++idx )
1296 int nodeIdx =
args->
names().indexOf( functionParams.at( idx ).name().toLower() );
1299 if ( !functionParams.at( idx ).optional() )
1301 error = QStringLiteral(
"No value specified for QgsExpressionFunction::Parameter '%1' for %2" ).arg( functionParams.at( idx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1307 if ( providedArgs.contains( idx ) )
1309 error = QStringLiteral(
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2" ).arg( functionParams.at( idx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1313 providedArgs << idx;
1314 handledArgs << nodeIdx;
1319 const QStringList nameList =
args->
names();
1320 for (
const QString &name : nameList )
1322 if ( !name.isEmpty() && !functionParams.contains( name ) )
1327 if ( !name.isEmpty() && !handledArgs.contains( idx ) )
1329 int functionIdx = functionParams.indexOf( name );
1330 if ( providedArgs.contains( functionIdx ) )
1332 error = QStringLiteral(
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2" ).arg( functionParams.at( functionIdx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1368 return QStringLiteral(
"NULL" );
1370 switch ( mValue.type() )
1373 return QString::number( mValue.toInt() );
1374 case QVariant::Double:
1375 return QString::number( mValue.toDouble() );
1376 case QVariant::LongLong:
1377 return QString::number( mValue.toLongLong() );
1378 case QVariant::String:
1380 case QVariant::Bool:
1381 return mValue.toBool() ? QStringLiteral(
"TRUE" ) : QStringLiteral(
"FALSE" );
1383 return tr(
"[unsupported type: %1; value: %2]" ).arg( mValue.typeName(), mValue.toString() );
1394 return QSet<QString>();
1399 return QSet<QString>();
1404 return QSet<QString>();
1409 QList<const QgsExpressionNode *> lst;
1462 parent->
setEvalErrorString( tr(
"No feature available for field '%1' evaluation" ).arg( mName ) );
1499 const thread_local QRegularExpression re( QStringLiteral(
"^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" ) );
1500 const QRegularExpressionMatch match = re.match( mName );
1506 return QSet<QString>() << mName;
1511 return QSet<QString>();
1516 return QSet<QString>();
1521 QList<const QgsExpressionNode *> result;
1548 : mConditions( *conditions )
1549 , mElseExp( elseExp )
1557 qDeleteAll( mConditions );
1567 for (
WhenThen *cond : std::as_const( mConditions ) )
1569 QVariant vWhen = cond->mWhenExp->eval( parent, context );
1570 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( vWhen, parent );
1572 if ( tvl == QgsExpressionUtils::True )
1574 QVariant vRes = cond->mThenExp->eval( parent, context );
1582 QVariant vElse = mElseExp->
eval( parent, context );
1593 bool foundAnyNonStaticConditions =
false;
1594 for (
WhenThen *cond : std::as_const( mConditions ) )
1596 const bool res = cond->mWhenExp->prepare( parent, context )
1597 && cond->mThenExp->prepare( parent, context );
1601 foundAnyNonStaticConditions |= !cond->mWhenExp->hasCachedStaticValue();
1602 if ( !foundAnyNonStaticConditions && QgsExpressionUtils::getTVLValue( cond->mWhenExp->cachedStaticValue(), parent ) == QgsExpressionUtils::True )
1606 if ( cond->mThenExp->hasCachedStaticValue() )
1625 const bool res = mElseExp->
prepare( parent, context );
1629 if ( !foundAnyNonStaticConditions )
1653 QString msg( QStringLiteral(
"CASE" ) );
1654 for (
WhenThen *cond : mConditions )
1656 msg += QStringLiteral(
" WHEN %1 THEN %2" ).arg( cond->mWhenExp->dump(), cond->mThenExp->dump() );
1659 msg += QStringLiteral(
" ELSE %1" ).arg( mElseExp->
dump() );
1660 msg += QLatin1String(
" END" );
1667 return QSet< QString >();
1670 for (
WhenThen *cond : mConditions )
1672 lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
1684 for (
WhenThen *cond : mConditions )
1686 lst += cond->mWhenExp->referencedVariables() + cond->mThenExp->referencedVariables();
1698 for (
WhenThen *cond : mConditions )
1700 lst += cond->mWhenExp->referencedFunctions() + cond->mThenExp->referencedFunctions();
1711 QList<const QgsExpressionNode *> lst;
1713 for (
WhenThen *cond : mConditions )
1715 lst += cond->mWhenExp->nodes() + cond->mThenExp->nodes();
1719 lst += mElseExp->
nodes();
1726 for (
WhenThen *cond : mConditions )
1728 if ( cond->mWhenExp->needsGeometry() ||
1729 cond->mThenExp->needsGeometry() )
1752 if ( !wt->mWhenExp->isStatic( parent, context ) || !wt->mThenExp->isStatic( parent, context ) )
1757 return mElseExp->
isStatic( parent, context );
1765 return QSet< QString >();
1768 const QList< QgsExpressionNode * > nodeList = mList->
list();
1770 lst.unite( n->referencedColumns() );
1777 const QList< QgsExpressionNode * > nodeList = mList->
list();
1779 lst.unite( n->referencedVariables() );
1786 const QList< QgsExpressionNode * > nodeList = mList->
list();
1788 lst.unite( n->referencedFunctions() );
1794 QList<const QgsExpressionNode *> lst;
1796 const QList< QgsExpressionNode * > nodeList = mList->
list();
1807 delete mHigherBound;
1817 bool res = mNode->
prepare( parent, context );
1818 res = res && mLowerBound->
prepare( parent, context );
1819 res = res && mHigherBound->
prepare( parent, context );
1825 const QVariant nodeVal = mNode->
eval( parent, context );
1834 const QVariant lowBoundValue = lowBound.
eval( parent, context );
1835 const bool lowBoundBool { lowBoundValue.toBool() };
1839 return QVariant( mNegate );
1843 const QVariant highBoundValue = highBound.
eval( parent, context );
1850 const bool highBoundBool { highBoundValue.toBool() };
1860 return QVariant( mNegate );
1870 return QVariant( mNegate );
1873 const bool res { lowBoundBool &&highBoundBool };
1874 return mNegate ? QVariant( ! res ) : QVariant( res );
1880 return QStringLiteral(
"%1 %2 %3 AND %4" ).arg( mNode->
dump(), mNegate ? QStringLiteral(
"NOT BETWEEN" ) : QStringLiteral(
"BETWEEN" ), mLowerBound->
dump(), mHigherBound->
dump() );
1901 return {
this, mLowerBound, mHigherBound };
1935 if ( !mNode->
isStatic( parent, context ) )
1938 if ( !mLowerBound->
isStatic( parent, context ) )
1941 if ( !mHigherBound->
isStatic( parent, context ) )
1954 return mHigherBound;
1963 : mWhenExp( whenExp )
1964 , mThenExp( thenExp )
1976 return new WhenThen( mWhenExp->clone(), mThenExp->clone() );
1981 return BINARY_OPERATOR_TEXT[mOp];
1988 const QVariant container = mContainer->eval( parent, context );
1990 const QVariant index = mIndex->eval( parent, context );
1993 switch ( container.type() )
1996 return QgsExpressionUtils::getMapValue( container, parent ).value( index.toString() );
1998 case QVariant::List:
1999 case QVariant::StringList:
2001 const QVariantList list = QgsExpressionUtils::getListValue( container, parent );
2002 qlonglong pos = QgsExpressionUtils::getIntValue( index, parent );
2003 if ( pos >= list.length() || pos < -list.length() )
2010 pos += list.length();
2013 return list.at( pos );
2030 bool resC = mContainer->prepare( parent, context );
2031 bool resV = mIndex->prepare( parent, context );
2032 return resC && resV;
2037 return QStringLiteral(
"%1[%2]" ).arg( mContainer->dump(), mIndex->dump() );
2043 return QSet< QString >();
2045 return mContainer->referencedColumns() + mIndex->referencedColumns();
2050 return mContainer->referencedVariables() + mIndex->referencedVariables();
2055 return mContainer->referencedFunctions() + mIndex->referencedFunctions();
2060 QList<const QgsExpressionNode *> lst;
2062 lst += mContainer->nodes() + mIndex->nodes();
2068 return mContainer->needsGeometry() || mIndex->needsGeometry();
2080 return mContainer->isStatic( parent, context ) && mIndex->isStatic( parent, context );
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
bool hasFunction(const QString &name) const
Checks whether a specified function is contained in the context.
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
static const QString EXPR_FIELDS
Inbuilt variable name for fields storage.
bool hasVariable(const QString &name) const
Check whether a variable is specified by any scope within the context.
QgsExpressionFunction * function(const QString &name) const
Fetches a matching function from the context.
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
bool hasFeature() const
Returns true if the context has a feature associated with it.
Represents a single parameter passed to a function.
A abstract base class for defining QgsExpression functions.
QList< QgsExpressionFunction::Parameter > ParameterList
List of parameters, used for function definition.
int params() const
The number of parameters this function takes.
bool lazyEval() const
true if this function should use lazy evaluation.
QString name() const
The name of the function.
virtual QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)
Evaluates the function, first evaluating all required arguments before passing them to the function's...
const QgsExpressionFunction::ParameterList & parameters() const
Returns the list of named parameters for the function, if set.
virtual QSet< QString > referencedColumns(const QgsExpressionNodeFunction *node) const
Returns a set of field names which are required for this function.
virtual bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
This will be called during the prepare step() of an expression if it is not static.
SQL-like BETWEEN and NOT BETWEEN predicates.
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.
QgsExpressionNode * clone() const override
Generate a clone of this node.
QString text() const
Returns a the name of this operator without the operands.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
An expression node which takes it value from a feature's field.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QgsExpressionNodeColumnRef(const QString &name)
Constructor for QgsExpressionNodeColumnRef, referencing the column with the specified name.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QgsExpressionNode * clone() const override
Generate a clone of this node.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
Represents a "WHEN... THEN..." portation of a CASE WHEN clause in an expression.
WhenThen(QgsExpressionNode *whenExp, QgsExpressionNode *thenExp)
A combination of when and then.
QgsExpressionNodeCondition::WhenThen * clone() const
Gets a deep copy of this WhenThen combination.
An expression node for CASE WHEN clauses.
QList< QgsExpressionNodeCondition::WhenThen * > WhenThenList
QgsExpressionNodeCondition(QgsExpressionNodeCondition::WhenThenList *conditions, QgsExpressionNode *elseExp=nullptr)
Create a new node with the given list of conditions and an optional elseExp expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QgsExpressionNode * clone() const override
Generate a clone of this node.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
WhenThenList conditions() const
The list of WHEN THEN expression parts of the expression.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
~QgsExpressionNodeCondition() override
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
An expression node for expression functions.
int fnIndex() const
Returns the index of the node's function.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
~QgsExpressionNodeFunction() override
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QgsExpressionNodeFunction(int fnIndex, QgsExpressionNode::NodeList *args)
A function node consists of an index of the function in the global function array and a list of argum...
QgsExpressionNode * clone() const override
Generate a clone of this node.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
static bool validateParams(int fnIndex, QgsExpressionNode::NodeList *args, QString &error)
Tests whether the provided argument list is valid for the matching function.
An expression node for value IN or NOT IN clauses.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
~QgsExpressionNodeInOperator() override
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QgsExpressionNode * clone() const override
Generate a clone of this node.
A indexing expression operator, which allows use of square brackets [] to reference map and array ite...
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QgsExpressionNode * clone() const override
Generate a clone of this node.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
An expression node for literal values.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QString valueAsString() const
Returns a string representation of the node's literal value.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QgsExpressionNode * clone() const override
Generate a clone of this node.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
QVariant value() const
The value of the literal.
QgsExpressionNodeLiteral(const QVariant &value)
Constructor for QgsExpressionNodeLiteral, with the specified literal value.
A unary node is either negative as in boolean (not) or as in numbers (minus).
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QgsExpressionNodeUnaryOperator::UnaryOperator op() const
Returns the unary operator.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QString text() const
Returns a the name of this operator without the operands.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
QgsExpressionNode * clone() const override
Generate a clone of this node.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
A list of expression nodes.
bool hasNamedNodes() const
Returns true if list contains any named nodes.
virtual QString dump() const
Returns a string dump of the expression node.
QStringList names() const
Returns a list of names for nodes.
QgsExpressionNode::NodeList * clone() const
Creates a deep copy of this list. Ownership is transferred to the caller.
void append(QgsExpressionNode *node)
Takes ownership of the provided node.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
Abstract base class for all nodes that can appear in an expression.
bool hasCachedStaticValue() const
Returns true if the node can be replaced by a static cached value.
virtual QString dump() const =0
Dump this node into a serialized (part) of an expression.
QVariant eval(QgsExpression *parent, const QgsExpressionContext *context)
Evaluate this node with the given context and parent.
virtual QgsExpressionNode * clone() const =0
Generate a clone of this node.
virtual bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const =0
Returns true if this node can be evaluated for a static value.
bool prepare(QgsExpression *parent, const QgsExpressionContext *context)
Prepare this node for evaluation.
virtual QSet< QString > referencedColumns() const =0
Abstract virtual method which returns a list of columns required to evaluate this node.
bool mHasCachedValue
true if the node has a static, precalculated value.
const QgsExpressionNode * effectiveNode() const
Returns a reference to the simplest node which represents this node, after any compilation optimizati...
QVariant cachedStaticValue() const
Returns the node's static cached value.
virtual QSet< QString > referencedVariables() const =0
Returns a set of all variables which are used in this expression.
QVariant mCachedStaticValue
Contains the static, precalculated value for the node if mHasCachedValue is true.
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.
virtual bool needsGeometry() const =0
Abstract virtual method which returns if the geometry is required to evaluate this expression.
virtual QList< const QgsExpressionNode * > nodes() const =0
Returns a list of all nodes which are used in this expression.
void cloneTo(QgsExpressionNode *target) const
Copies the members of this node to the node provided in target.
virtual QSet< QString > referencedFunctions() const =0
Returns a set of all functions which are used in this expression.
Class for parsing and evaluation of expressions (formerly called "search strings").
static const QList< QgsExpressionFunction * > & Functions()
static QString quotedString(QString text)
Returns a quoted version of a string (in single quotes)
void setEvalErrorString(const QString &str)
Sets evaluation error (used internally by evaluation functions)
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
int fieldNameIndex(const QString &fieldName) const
Utility method to get attribute index from name.
bool isValid() const
Returns the validity of this feature.
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Container of fields for a vector layer.
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
A representation of the interval between two datetime values.
double seconds() const
Returns the interval duration in seconds.
static QString qRegExpEscape(const QString &string)
Returns an escaped string matching the behavior of QRegExp::escape.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
#define ENSURE_NO_EVAL_ERROR
#define SET_EVAL_ERROR(x)
QgsExpressionNode * node
Node.