24 #include <QRegularExpression>
26 const char *QgsExpressionNodeBinaryOperator::BINARY_OPERATOR_TEXT[] =
30 "=",
"<>",
"<=",
">=",
"<",
">",
"~",
"LIKE",
"NOT LIKE",
"ILIKE",
"NOT ILIKE",
"IS",
"IS NOT",
31 "+",
"-",
"*",
"/",
"//",
"%",
"^",
35 const char *QgsExpressionNodeUnaryOperator::UNARY_OPERATOR_TEXT[] =
44 const QList< QgsExpressionNode * > nodeList = mList->
list();
46 needs |= n->needsGeometry();
57 mList.append( node->
node );
58 mNameList.append( cleanNamedNodeName( node->
name ) );
59 mHasNamedNodes =
true;
68 nl->mList.append( node->clone() );
70 nl->mNameList = mNameList;
81 if ( !first ) msg += QLatin1String(
", " );
88 QString QgsExpressionNode::NodeList::cleanNamedNodeName(
const QString &name )
90 QString cleaned = name.toLower();
93 if ( cleaned == QLatin1String(
"geom" ) )
94 cleaned = QStringLiteral(
"geometry" );
95 else if ( cleaned == QLatin1String(
"val" ) )
96 cleaned = QStringLiteral(
"value" );
97 else if ( cleaned == QLatin1String(
"geometry a" ) )
98 cleaned = QStringLiteral(
"geometry1" );
99 else if ( cleaned == QLatin1String(
"geometry b" ) )
100 cleaned = QStringLiteral(
"geometry2" );
110 QVariant val = mOperand->eval( parent, context );
117 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( val, parent );
119 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::NOT[tvl] );
123 if ( QgsExpressionUtils::isIntSafe( val ) )
124 return QVariant( - QgsExpressionUtils::getIntValue( val, parent ) );
125 else if ( QgsExpressionUtils::isDoubleSafe( val ) )
126 return QVariant( - QgsExpressionUtils::getDoubleValue( val, parent ) );
140 return mOperand->prepare( parent, context );
146 return QStringLiteral(
"%1 ( %2 )" ).arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
148 return QStringLiteral(
"%1 %2" ).arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
154 return QSet< QString >();
156 return mOperand->referencedColumns();
161 return mOperand->referencedVariables();
166 return mOperand->referencedFunctions();
171 QList<const QgsExpressionNode *> lst;
173 lst += mOperand->nodes();
179 return mOperand->needsGeometry();
191 return mOperand->isStatic( parent, context );
196 return UNARY_OPERATOR_TEXT[mOp];
203 QVariant vL = mOpLeft->eval( parent, context );
206 if ( mOp == boAnd || mOp == boOr )
208 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent );
210 if ( mOp == boAnd && tvlL == QgsExpressionUtils::False )
212 if ( mOp == boOr && tvlL == QgsExpressionUtils::True )
216 QVariant vR = mOpRight->eval( parent, context );
222 if ( vL.type() == QVariant::String && vR.type() == QVariant::String )
224 QString sL = QgsExpressionUtils::isNull( vL ) ? QString() : QgsExpressionUtils::getStringValue( vL, parent );
226 QString sR = QgsExpressionUtils::isNull( vR ) ? QString() : QgsExpressionUtils::getStringValue( vR, parent );
228 return QVariant( sL + sR );
237 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
239 else if ( mOp != boDiv && QgsExpressionUtils::isIntSafe( vL ) && QgsExpressionUtils::isIntSafe( vR ) )
242 qlonglong iL = QgsExpressionUtils::getIntValue( vL, parent );
244 qlonglong iR = QgsExpressionUtils::getIntValue( vR, parent );
247 if ( mOp == boMod && iR == 0 )
250 return QVariant( computeInt( iL, iR ) );
252 else if ( QgsExpressionUtils::isDateTimeSafe( vL ) && QgsExpressionUtils::isIntervalSafe( vR ) )
254 QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
256 QgsInterval iL = QgsExpressionUtils::getInterval( vR, parent );
258 if ( mOp == boDiv || mOp == boMul || mOp == boMod )
260 parent->
setEvalErrorString( tr(
"Can't perform /, *, or % on DateTime and Interval" ) );
263 return QVariant( computeDateTimeFromInterval( dL, &iL ) );
265 else if ( mOp == boPlus && ( ( vL.type() == QVariant::Date && vR.type() == QVariant::Time ) ||
266 ( vR.type() == QVariant::Date && vL.type() == QVariant::Time ) ) )
268 QDate date = QgsExpressionUtils::getDateValue( vL.type() == QVariant::Date ? vL : vR, parent );
270 QTime time = QgsExpressionUtils::getTimeValue( vR.type() == QVariant::Time ? vR : vL, parent );
272 QDateTime dt = QDateTime( date, time );
273 return QVariant( dt );
275 else if ( mOp == boMinus && vL.type() == QVariant::Date && vR.type() == QVariant::Date )
277 QDate date1 = QgsExpressionUtils::getDateValue( vL, parent );
279 QDate date2 = QgsExpressionUtils::getDateValue( vR, parent );
281 return date1 - date2;
283 else if ( mOp == boMinus && vL.type() == QVariant::Time && vR.type() == QVariant::Time )
285 QTime time1 = QgsExpressionUtils::getTimeValue( vL, parent );
287 QTime time2 = QgsExpressionUtils::getTimeValue( vR, parent );
289 return time1 - time2;
291 else if ( mOp == boMinus && vL.type() == QVariant::DateTime && vR.type() == QVariant::DateTime )
293 QDateTime datetime1 = QgsExpressionUtils::getDateTimeValue( vL, parent );
295 QDateTime datetime2 = QgsExpressionUtils::getDateTimeValue( vR, parent );
297 return datetime1 - datetime2;
302 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
304 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
306 if ( ( mOp == boDiv || mOp == boMod ) && fR == 0. )
308 return QVariant( computeDouble( fL, fR ) );
314 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
316 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
320 return QVariant( qlonglong( std::floor( fL / fR ) ) );
323 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
327 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
329 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
331 return QVariant( std::pow( fL, fR ) );
336 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
338 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::AND[tvlL][tvlR] );
343 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
345 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::OR[tvlL][tvlR] );
354 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
358 else if ( QgsExpressionUtils::isList( vL ) || QgsExpressionUtils::isList( vR ) )
361 if ( !QgsExpressionUtils::isList( vL ) || !QgsExpressionUtils::isList( vR ) )
365 QVariantList lL = vL.toList();
366 QVariantList lR = vR.toList();
367 for (
int i = 0; i < lL.length() && i < lR.length(); i++ )
369 if ( QgsExpressionUtils::isNull( lL.at( i ) ) && QgsExpressionUtils::isNull( lR.at( i ) ) )
372 if ( QgsExpressionUtils::isNull( lL.at( i ) ) || QgsExpressionUtils::isNull( lR.at( i ) ) )
382 return QgsExpressionUtils::isNull( lR.at( i ) );
385 return QgsExpressionUtils::isNull( lL.at( i ) );
395 QVariant eq = eqNode.
eval( parent, context );
397 if ( eq == TVL_False )
401 QVariant v = node.
eval( parent, context );
411 return lL.length() == lR.length();
413 return lL.length() != lR.length();
415 return lL.length() < lR.length();
417 return lL.length() > lR.length();
419 return lL.length() <= lR.length();
421 return lL.length() >= lR.length();
427 else if ( ( vL.type() == QVariant::DateTime && vR.type() == QVariant::DateTime ) )
429 QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
431 QDateTime dR = QgsExpressionUtils::getDateTimeValue( vR, parent );
438 dL.setTimeSpec( Qt::UTC );
439 dR.setTimeSpec( Qt::UTC );
441 return compare( dR.msecsTo( dL ) ) ? TVL_True : TVL_False;
443 else if ( ( vL.type() == QVariant::Date && vR.type() == QVariant::Date ) )
445 const QDate dL = QgsExpressionUtils::getDateValue( vL, parent );
447 const QDate dR = QgsExpressionUtils::getDateValue( vR, parent );
449 return compare( dR.daysTo( dL ) ) ? TVL_True : TVL_False;
451 else if ( ( vL.type() == QVariant::Time && vR.type() == QVariant::Time ) )
453 const QTime dL = QgsExpressionUtils::getTimeValue( vL, parent );
455 const QTime dR = QgsExpressionUtils::getTimeValue( vR, parent );
457 return compare( dR.msecsTo( dL ) ) ? TVL_True : TVL_False;
459 else if ( ( vL.type() != QVariant::String || vR.type() != QVariant::String ) &&
460 QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) )
464 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
466 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
468 return compare( fL - fR ) ? TVL_True : TVL_False;
473 double fL = QgsExpressionUtils::getInterval( vL, parent ).seconds();
475 double fR = QgsExpressionUtils::getInterval( vR, parent ).seconds();
477 return compare( fL - fR ) ? TVL_True : TVL_False;
482 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
484 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
486 int diff = QString::compare( sL, sR );
487 return compare( diff ) ? TVL_True : TVL_False;
492 if ( QgsExpressionUtils::isNull( vL ) && QgsExpressionUtils::isNull( vR ) )
493 return ( mOp == boIs ? TVL_True : TVL_False );
494 else if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
495 return ( mOp == boIs ? TVL_False : TVL_True );
499 if ( QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) &&
500 ( vL.type() != QVariant::String || vR.type() != QVariant::String ) )
502 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
504 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
510 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
512 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
514 equal = QString::compare( sL, sR ) == 0;
517 return mOp == boIs ? TVL_True : TVL_False;
519 return mOp == boIs ? TVL_False : TVL_True;
527 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
531 QString
str = QgsExpressionUtils::getStringValue( vL, parent );
533 QString regexp = QgsExpressionUtils::getStringValue( vR, parent );
537 if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike )
541 if ( esc_regexp.startsWith(
'%' ) )
543 esc_regexp.replace( 0, 1, QStringLiteral(
".*" ) );
545 const thread_local QRegularExpression rx1( QStringLiteral(
"[^\\\\](%)" ) );
547 while ( ( pos = esc_regexp.indexOf( rx1, pos ) ) != -1 )
549 esc_regexp.replace( pos + 1, 1, QStringLiteral(
".*" ) );
552 const thread_local QRegularExpression rx2( QStringLiteral(
"\\\\%" ) );
553 esc_regexp.replace( rx2, QStringLiteral(
"%" ) );
554 if ( esc_regexp.startsWith(
'_' ) )
556 esc_regexp.replace( 0, 1, QStringLiteral(
"." ) );
558 const thread_local QRegularExpression rx3( QStringLiteral(
"[^\\\\](_)" ) );
560 while ( ( pos = esc_regexp.indexOf( rx3, pos ) ) != -1 )
562 esc_regexp.replace( pos + 1, 1,
'.' );
565 esc_regexp.replace( QLatin1String(
"\\\\_" ), QLatin1String(
"_" ) );
567 matches = QRegularExpression( QRegularExpression::anchoredPattern( esc_regexp ), mOp == boLike || mOp == boNotLike ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption ).match(
str ).hasMatch();
571 matches = QRegularExpression( regexp ).match(
str ).hasMatch();
574 if ( mOp == boNotLike || mOp == boNotILike )
579 return matches ? TVL_True : TVL_False;
583 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
587 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
589 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
591 return QVariant( sL + sR );
598 bool QgsExpressionNodeBinaryOperator::compare(
double diff )
620 qlonglong QgsExpressionNodeBinaryOperator::computeInt( qlonglong x, qlonglong y )
640 QDateTime QgsExpressionNodeBinaryOperator::computeDateTimeFromInterval(
const QDateTime &d,
QgsInterval *i )
645 return d.addSecs( i->
seconds() );
647 return d.addSecs( -i->
seconds() );
654 double QgsExpressionNodeBinaryOperator::computeDouble(
double x,
double y )
667 return std::fmod( x, y );
681 bool resL = mOpLeft->prepare( parent, context );
682 bool resR = mOpRight->prepare( parent, context );
728 Q_ASSERT(
false &&
"unexpected binary operator" );
764 Q_ASSERT(
false &&
"unexpected binary operator" );
774 QString rdump( mOpRight->dump() );
779 rdump.prepend(
'(' ).append(
')' );
783 if ( leftAssociative() )
785 fmt += lOp && ( lOp->
precedence() < precedence() ) ? QStringLiteral(
"(%1)" ) : QStringLiteral(
"%1" );
786 fmt += QLatin1String(
" %2 " );
787 fmt += rOp && ( rOp->
precedence() <= precedence() ) ? QStringLiteral(
"(%3)" ) : QStringLiteral(
"%3" );
791 fmt += lOp && ( lOp->
precedence() <= precedence() ) ? QStringLiteral(
"(%1)" ) : QStringLiteral(
"%1" );
792 fmt += QLatin1String(
" %2 " );
793 fmt += rOp && ( rOp->
precedence() < precedence() ) ? QStringLiteral(
"(%3)" ) : QStringLiteral(
"%3" );
796 return fmt.arg( mOpLeft->dump(), BINARY_OPERATOR_TEXT[mOp], rdump );
802 return QSet< QString >();
804 return mOpLeft->referencedColumns() + mOpRight->referencedColumns();
809 return mOpLeft->referencedVariables() + mOpRight->referencedVariables();
814 return mOpLeft->referencedFunctions() + mOpRight->referencedFunctions();
819 QList<const QgsExpressionNode *> lst;
821 lst += mOpLeft->nodes() + mOpRight->nodes();
827 return mOpLeft->needsGeometry() || mOpRight->needsGeometry();
839 const bool leftStatic = mOpLeft->isStatic( parent, context );
840 const bool rightStatic = mOpRight->isStatic( parent, context );
842 if ( leftStatic && rightStatic )
854 mOpLeft->prepare( parent, context );
855 if ( mOpLeft->hasCachedStaticValue() )
857 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
858 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
866 else if ( rightStatic )
868 mOpRight->prepare( parent, context );
869 if ( mOpRight->hasCachedStaticValue() )
871 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
872 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
890 mOpLeft->prepare( parent, context );
891 if ( mOpLeft->hasCachedStaticValue() )
893 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
894 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
902 else if ( rightStatic )
904 mOpRight->prepare( parent, context );
905 if ( mOpRight->hasCachedStaticValue() )
907 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
908 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
951 if ( mList->count() == 0 )
952 return mNotIn ? TVL_True : TVL_False;
953 QVariant v1 = mNode->eval( parent, context );
955 if ( QgsExpressionUtils::isNull( v1 ) )
958 bool listHasNull =
false;
960 const QList< QgsExpressionNode * > nodeList = mList->list();
963 QVariant v2 = n->eval( parent, context );
965 if ( QgsExpressionUtils::isNull( v2 ) )
971 if ( ( v1.type() != QVariant::String || v2.type() != QVariant::String ) &&
972 QgsExpressionUtils::isDoubleSafe( v1 ) && QgsExpressionUtils::isDoubleSafe( v2 ) )
976 double f1 = QgsExpressionUtils::getDoubleValue( v1, parent );
978 double f2 = QgsExpressionUtils::getDoubleValue( v2, parent );
984 QString s1 = QgsExpressionUtils::getStringValue( v1, parent );
986 QString s2 = QgsExpressionUtils::getStringValue( v2, parent );
988 equal = QString::compare( s1, s2 ) == 0;
992 return mNotIn ? TVL_False : TVL_True;
1000 return mNotIn ? TVL_True : TVL_False;
1016 bool res = mNode->prepare( parent, context );
1017 const QList< QgsExpressionNode * > nodeList = mList->list();
1020 res = res && n->prepare( parent, context );
1027 return QStringLiteral(
"%1 %2 IN (%3)" ).arg( mNode->dump(), mNotIn ?
"NOT" :
"", mList->dump() );
1039 if ( !mNode->isStatic( parent, context ) )
1042 const QList< QgsExpressionNode * > nodeList = mList->list();
1045 if ( !n->isStatic( parent, context ) )
1056 QString name = QgsExpression::QgsExpression::Functions()[mFnIndex]->name();
1059 QVariant res = fd->
run( mArgs, context, parent,
this );
1067 : mFnIndex( fnIndex )
1070 if ( functionParams.isEmpty() )
1091 while ( idx < args->names().size() &&
args->
names().at( idx ).isEmpty() )
1098 for ( ; idx < functionParams.count(); ++idx )
1100 int nodeIdx =
args->
names().indexOf( functionParams.at( idx ).name().toLower() );
1130 bool res = fd->
prepare(
this, parent, context );
1133 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1136 res = res && n->prepare( parent, context );
1146 return QStringLiteral(
"%1%2" ).arg( fd->
name(), fd->
name().startsWith(
'$' ) ? QString() : QStringLiteral(
"()" ) );
1148 return QStringLiteral(
"%1(%2)" ).arg( fd->
name(), mArgs ? mArgs->
dump() : QString() );
1154 return QSet< QString >();
1162 return functionColumns;
1166 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1169 if ( fd->
parameters().count() <= paramIndex || !fd->
parameters().at( paramIndex ).isSubExpression() )
1170 functionColumns.unite( n->referencedColumns() );
1174 return functionColumns;
1180 if ( fd->
name() == QLatin1String(
"var" ) )
1182 if ( !mArgs->
list().isEmpty() )
1186 return QSet<QString>() << var->
value().toString();
1188 return QSet<QString>() << QString();
1192 QSet<QString> functionVariables = QSet<QString>();
1195 return functionVariables;
1197 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1200 functionVariables.unite( n->referencedVariables() );
1203 return functionVariables;
1210 QSet<QString> functions = QSet<QString>();
1211 functions.insert( fd->
name() );
1216 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1219 functions.unite( n->referencedFunctions() );
1226 QList<const QgsExpressionNode *> lst;
1231 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1241 bool needs = QgsExpression::QgsExpression::Functions()[mFnIndex]->usesGeometry(
this );
1244 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1246 needs |= n->needsGeometry();
1269 if ( functionParams.isEmpty() )
1276 QSet< int > providedArgs;
1277 QSet< int > handledArgs;
1280 while (
args->
names().at( idx ).isEmpty() )
1282 providedArgs << idx;
1288 for ( ; idx < functionParams.count(); ++idx )
1290 int nodeIdx =
args->
names().indexOf( functionParams.at( idx ).name().toLower() );
1293 if ( !functionParams.at( idx ).optional() )
1295 error = QStringLiteral(
"No value specified for QgsExpressionFunction::Parameter '%1' for %2" ).arg( functionParams.at( idx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1301 if ( providedArgs.contains( idx ) )
1303 error = QStringLiteral(
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2" ).arg( functionParams.at( idx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1307 providedArgs << idx;
1308 handledArgs << nodeIdx;
1313 const QStringList nameList =
args->
names();
1314 for (
const QString &name : nameList )
1316 if ( !name.isEmpty() && !functionParams.contains( name ) )
1321 if ( !name.isEmpty() && !handledArgs.contains( idx ) )
1323 int functionIdx = functionParams.indexOf( name );
1324 if ( providedArgs.contains( functionIdx ) )
1326 error = QStringLiteral(
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2" ).arg( functionParams.at( functionIdx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1361 if ( mValue.isNull() )
1362 return QStringLiteral(
"NULL" );
1364 switch ( mValue.type() )
1367 return QString::number( mValue.toInt() );
1368 case QVariant::Double:
1369 return QString::number( mValue.toDouble() );
1370 case QVariant::LongLong:
1371 return QString::number( mValue.toLongLong() );
1372 case QVariant::String:
1374 case QVariant::Bool:
1375 return mValue.toBool() ? QStringLiteral(
"TRUE" ) : QStringLiteral(
"FALSE" );
1377 return tr(
"[unsupported type: %1; value: %2]" ).arg( mValue.typeName(), mValue.toString() );
1388 return QSet<QString>();
1393 return QSet<QString>();
1398 return QSet<QString>();
1403 QList<const QgsExpressionNode *> lst;
1456 parent->
setEvalErrorString( tr(
"No feature available for field '%1' evaluation" ).arg( mName ) );
1493 const thread_local QRegularExpression re( QStringLiteral(
"^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" ) );
1494 const QRegularExpressionMatch match = re.match( mName );
1500 return QSet<QString>() << mName;
1505 return QSet<QString>();
1510 return QSet<QString>();
1515 QList<const QgsExpressionNode *> result;
1542 : mConditions( *conditions )
1543 , mElseExp( elseExp )
1551 qDeleteAll( mConditions );
1561 for (
WhenThen *cond : std::as_const( mConditions ) )
1563 QVariant vWhen = cond->mWhenExp->eval( parent, context );
1564 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( vWhen, parent );
1566 if ( tvl == QgsExpressionUtils::True )
1568 QVariant vRes = cond->mThenExp->eval( parent, context );
1576 QVariant vElse = mElseExp->
eval( parent, context );
1587 bool foundAnyNonStaticConditions =
false;
1588 for (
WhenThen *cond : std::as_const( mConditions ) )
1590 const bool res = cond->mWhenExp->prepare( parent, context )
1591 && cond->mThenExp->prepare( parent, context );
1595 foundAnyNonStaticConditions |= !cond->mWhenExp->hasCachedStaticValue();
1596 if ( !foundAnyNonStaticConditions && QgsExpressionUtils::getTVLValue( cond->mWhenExp->cachedStaticValue(), parent ) == QgsExpressionUtils::True )
1600 if ( cond->mThenExp->hasCachedStaticValue() )
1619 const bool res = mElseExp->
prepare( parent, context );
1623 if ( !foundAnyNonStaticConditions )
1647 QString msg( QStringLiteral(
"CASE" ) );
1648 for (
WhenThen *cond : mConditions )
1650 msg += QStringLiteral(
" WHEN %1 THEN %2" ).arg( cond->mWhenExp->dump(), cond->mThenExp->dump() );
1653 msg += QStringLiteral(
" ELSE %1" ).arg( mElseExp->
dump() );
1654 msg += QLatin1String(
" END" );
1661 return QSet< QString >();
1664 for (
WhenThen *cond : mConditions )
1666 lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
1678 for (
WhenThen *cond : mConditions )
1680 lst += cond->mWhenExp->referencedVariables() + cond->mThenExp->referencedVariables();
1692 for (
WhenThen *cond : mConditions )
1694 lst += cond->mWhenExp->referencedFunctions() + cond->mThenExp->referencedFunctions();
1705 QList<const QgsExpressionNode *> lst;
1707 for (
WhenThen *cond : mConditions )
1709 lst += cond->mWhenExp->nodes() + cond->mThenExp->nodes();
1713 lst += mElseExp->
nodes();
1720 for (
WhenThen *cond : mConditions )
1722 if ( cond->mWhenExp->needsGeometry() ||
1723 cond->mThenExp->needsGeometry() )
1746 if ( !wt->mWhenExp->isStatic( parent, context ) || !wt->mThenExp->isStatic( parent, context ) )
1751 return mElseExp->
isStatic( parent, context );
1759 return QSet< QString >();
1762 const QList< QgsExpressionNode * > nodeList = mList->
list();
1764 lst.unite( n->referencedColumns() );
1771 const QList< QgsExpressionNode * > nodeList = mList->
list();
1773 lst.unite( n->referencedVariables() );
1780 const QList< QgsExpressionNode * > nodeList = mList->
list();
1782 lst.unite( n->referencedFunctions() );
1788 QList<const QgsExpressionNode *> lst;
1790 const QList< QgsExpressionNode * > nodeList = mList->
list();
1797 : mWhenExp( whenExp )
1798 , mThenExp( thenExp )
1810 return new WhenThen( mWhenExp->clone(), mThenExp->clone() );
1815 return BINARY_OPERATOR_TEXT[mOp];
1822 const QVariant container = mContainer->eval( parent, context );
1824 const QVariant index = mIndex->eval( parent, context );
1827 switch ( container.type() )
1830 return QgsExpressionUtils::getMapValue( container, parent ).value( index.toString() );
1832 case QVariant::List:
1833 case QVariant::StringList:
1835 const QVariantList list = QgsExpressionUtils::getListValue( container, parent );
1836 qlonglong pos = QgsExpressionUtils::getIntValue( index, parent );
1837 if ( pos >= list.length() || pos < -list.length() )
1844 pos += list.length();
1847 return list.at( pos );
1851 if ( !container.isNull() )
1864 bool resC = mContainer->prepare( parent, context );
1865 bool resV = mIndex->prepare( parent, context );
1866 return resC && resV;
1871 return QStringLiteral(
"%1[%2]" ).arg( mContainer->dump(), mIndex->dump() );
1877 return QSet< QString >();
1879 return mContainer->referencedColumns() + mIndex->referencedColumns();
1884 return mContainer->referencedVariables() + mIndex->referencedVariables();
1889 return mContainer->referencedFunctions() + mIndex->referencedFunctions();
1894 QList<const QgsExpressionNode *> lst;
1896 lst += mContainer->nodes() + mIndex->nodes();
1902 return mContainer->needsGeometry() || mIndex->needsGeometry();
1914 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.
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.
virtual QList< const QgsExpressionNode * > nodes() const =0
Returns a list of all nodes which are used in this 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 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.
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.
QVariant mCachedStaticValue
Contains the static, precalculated value for the node if mHasCachedValue is true.
virtual QSet< QString > referencedColumns() const =0
Abstract virtual method which returns a list of columns required to evaluate this node.
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.
@ ntIndexOperator
Index operator.
virtual bool needsGeometry() const =0
Abstract virtual method which returns if the geometry is required to evaluate 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.
virtual QSet< QString > referencedVariables() const =0
Returns a set of all variables which are used in this expression.
virtual QgsExpressionNode * clone() const =0
Generate a clone of this node.
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.
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.