25#include <QRegularExpression>
27const char *QgsExpressionNodeBinaryOperator::BINARY_OPERATOR_TEXT[] =
31 "=",
"<>",
"<=",
">=",
"<",
">",
"~",
"LIKE",
"NOT LIKE",
"ILIKE",
"NOT ILIKE",
"IS",
"IS NOT",
32 "+",
"-",
"*",
"/",
"//",
"%",
"^",
36const char *QgsExpressionNodeUnaryOperator::UNARY_OPERATOR_TEXT[] =
45 const QList< QgsExpressionNode * > nodeList = mList->
list();
47 needs |= n->needsGeometry();
58 mList.append( node->
node );
59 mNameList.append( cleanNamedNodeName( node->
name ) );
60 mHasNamedNodes =
true;
69 nl->mList.append( node->clone() );
71 nl->mNameList = mNameList;
82 if ( !first ) msg += QLatin1String(
", " );
89QString QgsExpressionNode::NodeList::cleanNamedNodeName(
const QString &name )
91 QString cleaned = name.toLower();
94 if ( cleaned == QLatin1String(
"geom" ) )
95 cleaned = QStringLiteral(
"geometry" );
96 else if ( cleaned == QLatin1String(
"val" ) )
97 cleaned = QStringLiteral(
"value" );
98 else if ( cleaned == QLatin1String(
"geometry a" ) )
99 cleaned = QStringLiteral(
"geometry1" );
100 else if ( cleaned == QLatin1String(
"geometry b" ) )
101 cleaned = QStringLiteral(
"geometry2" );
111 QVariant val = mOperand->eval( parent, context );
118 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( val, parent );
120 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::NOT[tvl] );
124 if ( QgsExpressionUtils::isIntSafe( val ) )
125 return QVariant( - QgsExpressionUtils::getIntValue( val, parent ) );
126 else if ( QgsExpressionUtils::isDoubleSafe( val ) )
127 return QVariant( - QgsExpressionUtils::getDoubleValue( val, parent ) );
141 return mOperand->prepare( parent, context );
147 return QStringLiteral(
"%1 ( %2 )" ).arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
149 return QStringLiteral(
"%1 %2" ).arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
155 return QSet< QString >();
157 return mOperand->referencedColumns();
162 return mOperand->referencedVariables();
167 return mOperand->referencedFunctions();
172 QList<const QgsExpressionNode *> lst;
174 lst += mOperand->nodes();
180 return mOperand->needsGeometry();
192 return mOperand->isStatic( parent, context );
197 return UNARY_OPERATOR_TEXT[mOp];
204 QVariant vL = mOpLeft->eval( parent, context );
207 if ( mOp == boAnd || mOp == boOr )
209 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent );
211 if ( mOp == boAnd && tvlL == QgsExpressionUtils::False )
213 if ( mOp == boOr && tvlL == QgsExpressionUtils::True )
217 QVariant vR = mOpRight->eval( parent, context );
223 if ( vL.type() == QVariant::String && vR.type() == QVariant::String )
225 QString sL = QgsExpressionUtils::isNull( vL ) ? QString() : QgsExpressionUtils::getStringValue( vL, parent );
227 QString sR = QgsExpressionUtils::isNull( vR ) ? QString() : QgsExpressionUtils::getStringValue( vR, parent );
229 return QVariant( sL + sR );
238 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
240 else if ( mOp != boDiv && QgsExpressionUtils::isIntSafe( vL ) && QgsExpressionUtils::isIntSafe( vR ) )
243 qlonglong iL = QgsExpressionUtils::getIntValue( vL, parent );
245 qlonglong iR = QgsExpressionUtils::getIntValue( vR, parent );
248 if ( mOp == boMod && iR == 0 )
251 return QVariant( computeInt( iL, iR ) );
253 else if ( QgsExpressionUtils::isDateTimeSafe( vL ) && QgsExpressionUtils::isIntervalSafe( vR ) )
255 QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
257 QgsInterval iL = QgsExpressionUtils::getInterval( vR, parent );
259 if ( mOp == boDiv || mOp == boMul || mOp == boMod )
261 parent->
setEvalErrorString( tr(
"Can't perform /, *, or % on DateTime and Interval" ) );
264 return QVariant( computeDateTimeFromInterval( dL, &iL ) );
266 else if ( mOp == boPlus && ( ( vL.type() == QVariant::Date && vR.type() == QVariant::Time ) ||
267 ( vR.type() == QVariant::Date && vL.type() == QVariant::Time ) ) )
269 QDate date = QgsExpressionUtils::getDateValue( vL.type() == QVariant::Date ? vL : vR, parent );
271 QTime time = QgsExpressionUtils::getTimeValue( vR.type() == QVariant::Time ? vR : vL, parent );
273 QDateTime dt = QDateTime( date, time );
274 return QVariant( dt );
276 else if ( mOp == boMinus && vL.type() == QVariant::Date && vR.type() == QVariant::Date )
278 QDate date1 = QgsExpressionUtils::getDateValue( vL, parent );
280 QDate date2 = QgsExpressionUtils::getDateValue( vR, parent );
282 return date1 - date2;
284 else if ( mOp == boMinus && vL.type() == QVariant::Time && vR.type() == QVariant::Time )
286 QTime time1 = QgsExpressionUtils::getTimeValue( vL, parent );
288 QTime time2 = QgsExpressionUtils::getTimeValue( vR, parent );
290 return time1 - time2;
292 else if ( mOp == boMinus && vL.type() == QVariant::DateTime && vR.type() == QVariant::DateTime )
294 QDateTime datetime1 = QgsExpressionUtils::getDateTimeValue( vL, parent );
296 QDateTime datetime2 = QgsExpressionUtils::getDateTimeValue( vR, parent );
298 return datetime1 - datetime2;
303 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
305 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
307 if ( ( mOp == boDiv || mOp == boMod ) && fR == 0. )
309 return QVariant( computeDouble( fL, fR ) );
315 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
317 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
321 return QVariant( qlonglong( std::floor( fL / fR ) ) );
324 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
328 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
330 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
332 return QVariant( std::pow( fL, fR ) );
337 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
339 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::AND[tvlL][tvlR] );
344 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
346 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::OR[tvlL][tvlR] );
355 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
359 else if ( QgsExpressionUtils::isList( vL ) || QgsExpressionUtils::isList( vR ) )
362 if ( !QgsExpressionUtils::isList( vL ) || !QgsExpressionUtils::isList( vR ) )
366 QVariantList lL = vL.toList();
367 QVariantList lR = vR.toList();
368 for (
int i = 0; i < lL.length() && i < lR.length(); i++ )
370 if ( QgsExpressionUtils::isNull( lL.at( i ) ) && QgsExpressionUtils::isNull( lR.at( i ) ) )
373 if ( QgsExpressionUtils::isNull( lL.at( i ) ) || QgsExpressionUtils::isNull( lR.at( i ) ) )
383 return QgsExpressionUtils::isNull( lR.at( i ) );
386 return QgsExpressionUtils::isNull( lL.at( i ) );
396 QVariant eq = eqNode.
eval( parent, context );
398 if ( eq == TVL_False )
402 QVariant v = node.
eval( parent, context );
412 return lL.length() == lR.length();
414 return lL.length() != lR.length();
416 return lL.length() < lR.length();
418 return lL.length() > lR.length();
420 return lL.length() <= lR.length();
422 return lL.length() >= lR.length();
428 else if ( ( vL.type() == QVariant::DateTime && vR.type() == QVariant::DateTime ) )
430 QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
432 QDateTime dR = QgsExpressionUtils::getDateTimeValue( vR, parent );
439 dL.setTimeSpec( Qt::UTC );
440 dR.setTimeSpec( Qt::UTC );
442 return compare( dR.msecsTo( dL ) ) ? TVL_True : TVL_False;
444 else if ( ( vL.type() == QVariant::Date && vR.type() == QVariant::Date ) )
446 const QDate dL = QgsExpressionUtils::getDateValue( vL, parent );
448 const QDate dR = QgsExpressionUtils::getDateValue( vR, parent );
450 return compare( dR.daysTo( dL ) ) ? TVL_True : TVL_False;
452 else if ( ( vL.type() == QVariant::Time && vR.type() == QVariant::Time ) )
454 const QTime dL = QgsExpressionUtils::getTimeValue( vL, parent );
456 const QTime dR = QgsExpressionUtils::getTimeValue( vR, parent );
458 return compare( dR.msecsTo( dL ) ) ? TVL_True : TVL_False;
460 else if ( ( vL.type() != QVariant::String || vR.type() != QVariant::String ) &&
461 QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) )
465 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
467 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
469 return compare( fL - fR ) ? TVL_True : TVL_False;
472 else if ( vL.userType() == QMetaType::type(
"QgsInterval" ) && vR.userType() == QMetaType::type(
"QgsInterval" ) )
474 double fL = QgsExpressionUtils::getInterval( vL, parent ).seconds();
476 double fR = QgsExpressionUtils::getInterval( vR, parent ).seconds();
478 return compare( fL - fR ) ? TVL_True : TVL_False;
483 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
485 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
487 int diff = QString::compare( sL, sR );
488 return compare( diff ) ? TVL_True : TVL_False;
493 if ( QgsExpressionUtils::isNull( vL ) && QgsExpressionUtils::isNull( vR ) )
494 return ( mOp == boIs ? TVL_True : TVL_False );
495 else if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
496 return ( mOp == boIs ? TVL_False : TVL_True );
500 if ( QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) &&
501 ( vL.type() != QVariant::String || vR.type() != QVariant::String ) )
503 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
505 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
511 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
513 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
515 equal = QString::compare( sL, sR ) == 0;
518 return mOp == boIs ? TVL_True : TVL_False;
520 return mOp == boIs ? TVL_False : TVL_True;
528 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
532 QString
str = QgsExpressionUtils::getStringValue( vL, parent );
534 QString regexp = QgsExpressionUtils::getStringValue( vR, parent );
538 if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike )
542 if ( esc_regexp.startsWith(
'%' ) )
544 esc_regexp.replace( 0, 1, QStringLiteral(
".*" ) );
546 const thread_local QRegularExpression rx1( QStringLiteral(
"[^\\\\](%)" ) );
548 while ( ( pos = esc_regexp.indexOf( rx1, pos ) ) != -1 )
550 esc_regexp.replace( pos + 1, 1, QStringLiteral(
".*" ) );
553 const thread_local QRegularExpression rx2( QStringLiteral(
"\\\\%" ) );
554 esc_regexp.replace( rx2, QStringLiteral(
"%" ) );
555 if ( esc_regexp.startsWith(
'_' ) )
557 esc_regexp.replace( 0, 1, QStringLiteral(
"." ) );
559 const thread_local QRegularExpression rx3( QStringLiteral(
"[^\\\\](_)" ) );
561 while ( ( pos = esc_regexp.indexOf( rx3, pos ) ) != -1 )
563 esc_regexp.replace( pos + 1, 1,
'.' );
566 esc_regexp.replace( QLatin1String(
"\\\\_" ), QLatin1String(
"_" ) );
568 matches = QRegularExpression( QRegularExpression::anchoredPattern( esc_regexp ), mOp == boLike || mOp == boNotLike ? QRegularExpression::DotMatchesEverythingOption : QRegularExpression::DotMatchesEverythingOption | QRegularExpression::CaseInsensitiveOption ).match(
str ).hasMatch();
572 matches = QRegularExpression( regexp ).match(
str ).hasMatch();
575 if ( mOp == boNotLike || mOp == boNotILike )
580 return matches ? TVL_True : TVL_False;
584 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
588 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
590 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
592 return QVariant( sL + sR );
599bool QgsExpressionNodeBinaryOperator::compare(
double diff )
621qlonglong QgsExpressionNodeBinaryOperator::computeInt( qlonglong x, qlonglong y )
641QDateTime QgsExpressionNodeBinaryOperator::computeDateTimeFromInterval(
const QDateTime &d,
QgsInterval *i )
646 return d.addSecs( i->
seconds() );
648 return d.addSecs( -i->
seconds() );
655double QgsExpressionNodeBinaryOperator::computeDouble(
double x,
double y )
668 return std::fmod( x, y );
682 bool resL = mOpLeft->prepare( parent, context );
683 bool resR = mOpRight->prepare( parent, context );
729 Q_ASSERT(
false &&
"unexpected binary operator" );
765 Q_ASSERT(
false &&
"unexpected binary operator" );
775 QString rdump( mOpRight->dump() );
780 rdump.prepend(
'(' ).append(
')' );
784 if ( leftAssociative() )
786 fmt += lOp && ( lOp->
precedence() < precedence() ) ? QStringLiteral(
"(%1)" ) : QStringLiteral(
"%1" );
787 fmt += QLatin1String(
" %2 " );
788 fmt += rOp && ( rOp->
precedence() <= precedence() ) ? QStringLiteral(
"(%3)" ) : QStringLiteral(
"%3" );
792 fmt += lOp && ( lOp->
precedence() <= precedence() ) ? QStringLiteral(
"(%1)" ) : QStringLiteral(
"%1" );
793 fmt += QLatin1String(
" %2 " );
794 fmt += rOp && ( rOp->
precedence() < precedence() ) ? QStringLiteral(
"(%3)" ) : QStringLiteral(
"%3" );
797 return fmt.arg( mOpLeft->dump(), BINARY_OPERATOR_TEXT[mOp], rdump );
803 return QSet< QString >();
805 return mOpLeft->referencedColumns() + mOpRight->referencedColumns();
810 return mOpLeft->referencedVariables() + mOpRight->referencedVariables();
815 return mOpLeft->referencedFunctions() + mOpRight->referencedFunctions();
820 QList<const QgsExpressionNode *> lst;
822 lst += mOpLeft->nodes() + mOpRight->nodes();
828 return mOpLeft->needsGeometry() || mOpRight->needsGeometry();
840 const bool leftStatic = mOpLeft->isStatic( parent, context );
841 const bool rightStatic = mOpRight->isStatic( parent, context );
843 if ( leftStatic && rightStatic )
855 mOpLeft->prepare( parent, context );
856 if ( mOpLeft->hasCachedStaticValue() )
858 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
859 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
867 else if ( rightStatic )
869 mOpRight->prepare( parent, context );
870 if ( mOpRight->hasCachedStaticValue() )
872 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
873 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
891 mOpLeft->prepare( parent, context );
892 if ( mOpLeft->hasCachedStaticValue() )
894 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
895 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
903 else if ( rightStatic )
905 mOpRight->prepare( parent, context );
906 if ( mOpRight->hasCachedStaticValue() )
908 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
909 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
952 if ( mList->count() == 0 )
953 return mNotIn ? TVL_True : TVL_False;
954 QVariant v1 = mNode->eval( parent, context );
956 if ( QgsExpressionUtils::isNull( v1 ) )
959 bool listHasNull =
false;
961 const QList< QgsExpressionNode * > nodeList = mList->list();
964 QVariant v2 = n->eval( parent, context );
966 if ( QgsExpressionUtils::isNull( v2 ) )
972 if ( ( v1.type() != QVariant::String || v2.type() != QVariant::String ) &&
973 QgsExpressionUtils::isDoubleSafe( v1 ) && QgsExpressionUtils::isDoubleSafe( v2 ) )
977 double f1 = QgsExpressionUtils::getDoubleValue( v1, parent );
979 double f2 = QgsExpressionUtils::getDoubleValue( v2, parent );
985 QString s1 = QgsExpressionUtils::getStringValue( v1, parent );
987 QString s2 = QgsExpressionUtils::getStringValue( v2, parent );
989 equal = QString::compare( s1, s2 ) == 0;
993 return mNotIn ? TVL_False : TVL_True;
1001 return mNotIn ? TVL_True : TVL_False;
1017 bool res = mNode->prepare( parent, context );
1018 const QList< QgsExpressionNode * > nodeList = mList->list();
1021 res = res && n->prepare( parent, context );
1028 return QStringLiteral(
"%1 %2 IN (%3)" ).arg( mNode->dump(), mNotIn ?
"NOT" :
"", mList->dump() );
1040 if ( !mNode->isStatic( parent, context ) )
1043 const QList< QgsExpressionNode * > nodeList = mList->list();
1046 if ( !n->isStatic( parent, context ) )
1057 QString name = QgsExpression::QgsExpression::Functions()[mFnIndex]->name();
1060 QVariant res = fd->
run( mArgs, context, parent,
this );
1068 : mFnIndex( fnIndex )
1071 if ( functionParams.isEmpty() )
1092 while ( idx < args->names().size() &&
args->
names().at( idx ).isEmpty() )
1099 for ( ; idx < functionParams.count(); ++idx )
1101 int nodeIdx =
args->
names().indexOf( functionParams.at( idx ).name().toLower() );
1131 bool res = fd->
prepare(
this, parent, context );
1134 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1137 res = res && n->prepare( parent, context );
1147 return QStringLiteral(
"%1%2" ).arg( fd->
name(), fd->
name().startsWith(
'$' ) ? QString() : QStringLiteral(
"()" ) );
1149 return QStringLiteral(
"%1(%2)" ).arg( fd->
name(), mArgs ? mArgs->
dump() : QString() );
1155 return QSet< QString >();
1163 return functionColumns;
1167 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1170 if ( fd->
parameters().count() <= paramIndex || !fd->
parameters().at( paramIndex ).isSubExpression() )
1171 functionColumns.unite( n->referencedColumns() );
1175 return functionColumns;
1181 if ( fd->
name() == QLatin1String(
"var" ) )
1183 if ( !mArgs->
list().isEmpty() )
1187 return QSet<QString>() << var->
value().toString();
1189 return QSet<QString>() << QString();
1193 QSet<QString> functionVariables = QSet<QString>();
1196 return functionVariables;
1198 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1201 functionVariables.unite( n->referencedVariables() );
1204 return functionVariables;
1211 QSet<QString> functions = QSet<QString>();
1212 functions.insert( fd->
name() );
1217 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1220 functions.unite( n->referencedFunctions() );
1227 QList<const QgsExpressionNode *> lst;
1232 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1242 bool needs = QgsExpression::QgsExpression::Functions()[mFnIndex]->usesGeometry(
this );
1245 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1247 needs |= n->needsGeometry();
1270 if ( functionParams.isEmpty() )
1277 QSet< int > providedArgs;
1278 QSet< int > handledArgs;
1281 while (
args->
names().at( idx ).isEmpty() )
1283 providedArgs << idx;
1289 for ( ; idx < functionParams.count(); ++idx )
1291 int nodeIdx =
args->
names().indexOf( functionParams.at( idx ).name().toLower() );
1294 if ( !functionParams.at( idx ).optional() )
1296 error = QStringLiteral(
"No value specified for QgsExpressionFunction::Parameter '%1' for %2" ).arg( functionParams.at( idx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1302 if ( providedArgs.contains( idx ) )
1304 error = QStringLiteral(
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2" ).arg( functionParams.at( idx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1308 providedArgs << idx;
1309 handledArgs << nodeIdx;
1314 const QStringList nameList =
args->
names();
1315 for (
const QString &name : nameList )
1317 if ( !name.isEmpty() && !functionParams.contains( name ) )
1322 if ( !name.isEmpty() && !handledArgs.contains( idx ) )
1324 int functionIdx = functionParams.indexOf( name );
1325 if ( providedArgs.contains( functionIdx ) )
1327 error = QStringLiteral(
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2" ).arg( functionParams.at( functionIdx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1363 return QStringLiteral(
"NULL" );
1365 switch ( mValue.type() )
1368 return QString::number( mValue.toInt() );
1369 case QVariant::Double:
1370 return QString::number( mValue.toDouble() );
1371 case QVariant::LongLong:
1372 return QString::number( mValue.toLongLong() );
1373 case QVariant::String:
1375 case QVariant::Bool:
1376 return mValue.toBool() ? QStringLiteral(
"TRUE" ) : QStringLiteral(
"FALSE" );
1378 return tr(
"[unsupported type: %1; value: %2]" ).arg( mValue.typeName(), mValue.toString() );
1389 return QSet<QString>();
1394 return QSet<QString>();
1399 return QSet<QString>();
1404 QList<const QgsExpressionNode *> lst;
1457 parent->
setEvalErrorString( tr(
"No feature available for field '%1' evaluation" ).arg( mName ) );
1494 const thread_local QRegularExpression re( QStringLiteral(
"^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" ) );
1495 const QRegularExpressionMatch match = re.match( mName );
1501 return QSet<QString>() << mName;
1506 return QSet<QString>();
1511 return QSet<QString>();
1516 QList<const QgsExpressionNode *> result;
1543 : mConditions( *conditions )
1544 , mElseExp( elseExp )
1552 qDeleteAll( mConditions );
1562 for (
WhenThen *cond : std::as_const( mConditions ) )
1564 QVariant vWhen = cond->mWhenExp->eval( parent, context );
1565 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( vWhen, parent );
1567 if ( tvl == QgsExpressionUtils::True )
1569 QVariant vRes = cond->mThenExp->eval( parent, context );
1577 QVariant vElse = mElseExp->
eval( parent, context );
1588 bool foundAnyNonStaticConditions =
false;
1589 for (
WhenThen *cond : std::as_const( mConditions ) )
1591 const bool res = cond->mWhenExp->prepare( parent, context )
1592 && cond->mThenExp->prepare( parent, context );
1596 foundAnyNonStaticConditions |= !cond->mWhenExp->hasCachedStaticValue();
1597 if ( !foundAnyNonStaticConditions && QgsExpressionUtils::getTVLValue( cond->mWhenExp->cachedStaticValue(), parent ) == QgsExpressionUtils::True )
1601 if ( cond->mThenExp->hasCachedStaticValue() )
1620 const bool res = mElseExp->
prepare( parent, context );
1624 if ( !foundAnyNonStaticConditions )
1648 QString msg( QStringLiteral(
"CASE" ) );
1649 for (
WhenThen *cond : mConditions )
1651 msg += QStringLiteral(
" WHEN %1 THEN %2" ).arg( cond->mWhenExp->dump(), cond->mThenExp->dump() );
1654 msg += QStringLiteral(
" ELSE %1" ).arg( mElseExp->
dump() );
1655 msg += QLatin1String(
" END" );
1662 return QSet< QString >();
1665 for (
WhenThen *cond : mConditions )
1667 lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
1679 for (
WhenThen *cond : mConditions )
1681 lst += cond->mWhenExp->referencedVariables() + cond->mThenExp->referencedVariables();
1693 for (
WhenThen *cond : mConditions )
1695 lst += cond->mWhenExp->referencedFunctions() + cond->mThenExp->referencedFunctions();
1706 QList<const QgsExpressionNode *> lst;
1708 for (
WhenThen *cond : mConditions )
1710 lst += cond->mWhenExp->nodes() + cond->mThenExp->nodes();
1714 lst += mElseExp->
nodes();
1721 for (
WhenThen *cond : mConditions )
1723 if ( cond->mWhenExp->needsGeometry() ||
1724 cond->mThenExp->needsGeometry() )
1747 if ( !wt->mWhenExp->isStatic( parent, context ) || !wt->mThenExp->isStatic( parent, context ) )
1752 return mElseExp->
isStatic( parent, context );
1760 return QSet< QString >();
1763 const QList< QgsExpressionNode * > nodeList = mList->
list();
1765 lst.unite( n->referencedColumns() );
1772 const QList< QgsExpressionNode * > nodeList = mList->
list();
1774 lst.unite( n->referencedVariables() );
1781 const QList< QgsExpressionNode * > nodeList = mList->
list();
1783 lst.unite( n->referencedFunctions() );
1789 QList<const QgsExpressionNode *> lst;
1791 const QList< QgsExpressionNode * > nodeList = mList->
list();
1802 delete mHigherBound;
1812 bool res = mNode->
prepare( parent, context );
1813 res = res && mLowerBound->
prepare( parent, context );
1814 res = res && mHigherBound->
prepare( parent, context );
1820 const QVariant nodeVal = mNode->
eval( parent, context );
1829 const QVariant lowBoundValue = lowBound.
eval( parent, context );
1830 const bool lowBoundBool { lowBoundValue.toBool() };
1834 return QVariant( mNegate );
1838 const QVariant highBoundValue = highBound.
eval( parent, context );
1845 const bool highBoundBool { highBoundValue.toBool() };
1855 return QVariant( mNegate );
1865 return QVariant( mNegate );
1868 const bool res { lowBoundBool &&highBoundBool };
1869 return mNegate ? QVariant( ! res ) : QVariant( res );
1875 return QStringLiteral(
"%1 %2 %3 AND %4" ).arg( mNode->
dump(), mNegate ? QStringLiteral(
"NOT BETWEEN" ) : QStringLiteral(
"BETWEEN" ), mLowerBound->
dump(), mHigherBound->
dump() );
1896 return {
this, mLowerBound, mHigherBound };
1930 if ( !mNode->
isStatic( parent, context ) )
1933 if ( !mLowerBound->
isStatic( parent, context ) )
1936 if ( !mHigherBound->
isStatic( parent, context ) )
1949 return mHigherBound;
1958 : mWhenExp( whenExp )
1959 , mThenExp( thenExp )
1971 return new WhenThen( mWhenExp->clone(), mThenExp->clone() );
1976 return BINARY_OPERATOR_TEXT[mOp];
1983 const QVariant container = mContainer->eval( parent, context );
1985 const QVariant index = mIndex->eval( parent, context );
1988 switch ( container.type() )
1991 return QgsExpressionUtils::getMapValue( container, parent ).value( index.toString() );
1993 case QVariant::List:
1994 case QVariant::StringList:
1996 const QVariantList list = QgsExpressionUtils::getListValue( container, parent );
1997 qlonglong pos = QgsExpressionUtils::getIntValue( index, parent );
1998 if ( pos >= list.length() || pos < -list.length() )
2005 pos += list.length();
2008 return list.at( pos );
2025 bool resC = mContainer->prepare( parent, context );
2026 bool resV = mIndex->prepare( parent, context );
2027 return resC && resV;
2032 return QStringLiteral(
"%1[%2]" ).arg( mContainer->dump(), mIndex->dump() );
2038 return QSet< QString >();
2040 return mContainer->referencedColumns() + mIndex->referencedColumns();
2045 return mContainer->referencedVariables() + mIndex->referencedVariables();
2050 return mContainer->referencedFunctions() + mIndex->referencedFunctions();
2055 QList<const QgsExpressionNode *> lst;
2057 lst += mContainer->nodes() + mIndex->nodes();
2063 return mContainer->needsGeometry() || mIndex->needsGeometry();
2075 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.