23 #include <QRegularExpression>
25 const char *QgsExpressionNodeBinaryOperator::BINARY_OPERATOR_TEXT[] =
29 "=",
"<>",
"<=",
">=",
"<",
">",
"~",
"LIKE",
"NOT LIKE",
"ILIKE",
"NOT ILIKE",
"IS",
"IS NOT",
30 "+",
"-",
"*",
"/",
"//",
"%",
"^",
34 const char *QgsExpressionNodeUnaryOperator::UNARY_OPERATOR_TEXT[] =
43 const QList< QgsExpressionNode * > nodeList = mList->
list();
45 needs |= n->needsGeometry();
56 mList.append( node->
node );
57 mNameList.append( cleanNamedNodeName( node->
name ) );
58 mHasNamedNodes =
true;
67 nl->mList.append( node->clone() );
69 nl->mNameList = mNameList;
80 if ( !first ) msg += QLatin1String(
", " );
87 QString QgsExpressionNode::NodeList::cleanNamedNodeName(
const QString &name )
89 QString cleaned = name.toLower();
92 if ( cleaned == QLatin1String(
"geom" ) )
93 cleaned = QStringLiteral(
"geometry" );
94 else if ( cleaned == QLatin1String(
"val" ) )
95 cleaned = QStringLiteral(
"value" );
96 else if ( cleaned == QLatin1String(
"geometry a" ) )
97 cleaned = QStringLiteral(
"geometry1" );
98 else if ( cleaned == QLatin1String(
"geometry b" ) )
99 cleaned = QStringLiteral(
"geometry2" );
109 QVariant val = mOperand->eval( parent, context );
116 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( val, parent );
118 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::NOT[tvl] );
122 if ( QgsExpressionUtils::isIntSafe( val ) )
123 return QVariant( - QgsExpressionUtils::getIntValue( val, parent ) );
124 else if ( QgsExpressionUtils::isDoubleSafe( val ) )
125 return QVariant( - QgsExpressionUtils::getDoubleValue( val, parent ) );
139 return mOperand->prepare( parent, context );
145 return QStringLiteral(
"%1 ( %2 )" ).arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
147 return QStringLiteral(
"%1 %2" ).arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
153 return QSet< QString >();
155 return mOperand->referencedColumns();
160 return mOperand->referencedVariables();
165 return mOperand->referencedFunctions();
170 QList<const QgsExpressionNode *> lst;
172 lst += mOperand->nodes();
178 return mOperand->needsGeometry();
190 return mOperand->isStatic( parent, context );
195 return UNARY_OPERATOR_TEXT[mOp];
202 QVariant vL = mOpLeft->eval( parent, context );
205 if ( mOp == boAnd || mOp == boOr )
207 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent );
209 if ( mOp == boAnd && tvlL == QgsExpressionUtils::False )
211 if ( mOp == boOr && tvlL == QgsExpressionUtils::True )
215 QVariant vR = mOpRight->eval( parent, context );
221 if ( vL.type() == QVariant::String && vR.type() == QVariant::String )
223 QString sL = QgsExpressionUtils::isNull( vL ) ? QString() : QgsExpressionUtils::getStringValue( vL, parent );
225 QString sR = QgsExpressionUtils::isNull( vR ) ? QString() : QgsExpressionUtils::getStringValue( vR, parent );
227 return QVariant( sL + sR );
236 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
238 else if ( mOp != boDiv && QgsExpressionUtils::isIntSafe( vL ) && QgsExpressionUtils::isIntSafe( vR ) )
241 qlonglong iL = QgsExpressionUtils::getIntValue( vL, parent );
243 qlonglong iR = QgsExpressionUtils::getIntValue( vR, parent );
246 if ( mOp == boMod && iR == 0 )
249 return QVariant( computeInt( iL, iR ) );
251 else if ( QgsExpressionUtils::isDateTimeSafe( vL ) && QgsExpressionUtils::isIntervalSafe( vR ) )
253 QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
255 QgsInterval iL = QgsExpressionUtils::getInterval( vR, parent );
257 if ( mOp == boDiv || mOp == boMul || mOp == boMod )
259 parent->
setEvalErrorString( tr(
"Can't perform /, *, or % on DateTime and Interval" ) );
262 return QVariant( computeDateTimeFromInterval( dL, &iL ) );
264 else if ( mOp == boPlus && ( ( vL.type() == QVariant::Date && vR.type() == QVariant::Time ) ||
265 ( vR.type() == QVariant::Date && vL.type() == QVariant::Time ) ) )
267 QDate date = QgsExpressionUtils::getDateValue( vL.type() == QVariant::Date ? vL : vR, parent );
269 QTime time = QgsExpressionUtils::getTimeValue( vR.type() == QVariant::Time ? vR : vL, parent );
271 QDateTime dt = QDateTime( date, time );
272 return QVariant( dt );
274 else if ( mOp == boMinus && vL.type() == QVariant::Date && vR.type() == QVariant::Date )
276 QDate date1 = QgsExpressionUtils::getDateValue( vL, parent );
278 QDate date2 = QgsExpressionUtils::getDateValue( vR, parent );
280 return date1 - date2;
282 else if ( mOp == boMinus && vL.type() == QVariant::Time && vR.type() == QVariant::Time )
284 QTime time1 = QgsExpressionUtils::getTimeValue( vL, parent );
286 QTime time2 = QgsExpressionUtils::getTimeValue( vR, parent );
288 return time1 - time2;
290 else if ( mOp == boMinus && vL.type() == QVariant::DateTime && vR.type() == QVariant::DateTime )
292 QDateTime datetime1 = QgsExpressionUtils::getDateTimeValue( vL, parent );
294 QDateTime datetime2 = QgsExpressionUtils::getDateTimeValue( vR, parent );
296 return datetime1 - datetime2;
301 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
303 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
305 if ( ( mOp == boDiv || mOp == boMod ) && fR == 0. )
307 return QVariant( computeDouble( fL, fR ) );
313 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
315 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
319 return QVariant( qlonglong( std::floor( fL / fR ) ) );
322 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
326 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
328 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
330 return QVariant( std::pow( fL, fR ) );
335 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
337 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::AND[tvlL][tvlR] );
342 QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
344 return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::OR[tvlL][tvlR] );
353 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
357 else if ( QgsExpressionUtils::isList( vL ) || QgsExpressionUtils::isList( vR ) )
360 if ( !QgsExpressionUtils::isList( vL ) || !QgsExpressionUtils::isList( vR ) )
364 QVariantList lL = vL.toList();
365 QVariantList lR = vR.toList();
366 for (
int i = 0; i < lL.length() && i < lR.length(); i++ )
368 if ( QgsExpressionUtils::isNull( lL.at( i ) ) && QgsExpressionUtils::isNull( lR.at( i ) ) )
371 if ( QgsExpressionUtils::isNull( lL.at( i ) ) || QgsExpressionUtils::isNull( lR.at( i ) ) )
381 return QgsExpressionUtils::isNull( lR.at( i ) );
384 return QgsExpressionUtils::isNull( lL.at( i ) );
394 QVariant eq = eqNode.
eval( parent, context );
396 if ( eq == TVL_False )
400 QVariant v = node.
eval( parent, context );
410 return lL.length() == lR.length();
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();
426 else if ( ( vL.type() == QVariant::DateTime && vR.type() == QVariant::DateTime ) )
428 QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
430 QDateTime dR = QgsExpressionUtils::getDateTimeValue( vR, parent );
437 dL.setTimeSpec( Qt::UTC );
438 dR.setTimeSpec( Qt::UTC );
440 return compare( dR.msecsTo( dL ) ) ? TVL_True : TVL_False;
442 else if ( ( vL.type() == QVariant::Date && vR.type() == QVariant::Date ) )
444 const QDate dL = QgsExpressionUtils::getDateValue( vL, parent );
446 const QDate dR = QgsExpressionUtils::getDateValue( vR, parent );
448 return compare( dR.daysTo( dL ) ) ? TVL_True : TVL_False;
450 else if ( ( vL.type() == QVariant::Time && vR.type() == QVariant::Time ) )
452 const QTime dL = QgsExpressionUtils::getTimeValue( vL, parent );
454 const QTime dR = QgsExpressionUtils::getTimeValue( vR, parent );
456 return compare( dR.msecsTo( dL ) ) ? TVL_True : TVL_False;
458 else if ( ( vL.type() != QVariant::String || vR.type() != QVariant::String ) &&
459 QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) )
463 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
465 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
467 return compare( fL - fR ) ? TVL_True : TVL_False;
472 double fL = QgsExpressionUtils::getInterval( vL, parent ).seconds();
474 double fR = QgsExpressionUtils::getInterval( vR, parent ).seconds();
476 return compare( fL - fR ) ? TVL_True : TVL_False;
481 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
483 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
485 int diff = QString::compare( sL, sR );
486 return compare( diff ) ? TVL_True : TVL_False;
491 if ( QgsExpressionUtils::isNull( vL ) && QgsExpressionUtils::isNull( vR ) )
492 return ( mOp == boIs ? TVL_True : TVL_False );
493 else if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
494 return ( mOp == boIs ? TVL_False : TVL_True );
498 if ( QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) &&
499 ( vL.type() != QVariant::String || vR.type() != QVariant::String ) )
501 double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
503 double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
509 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
511 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
513 equal = QString::compare( sL, sR ) == 0;
516 return mOp == boIs ? TVL_True : TVL_False;
518 return mOp == boIs ? TVL_False : TVL_True;
526 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
530 QString
str = QgsExpressionUtils::getStringValue( vL, parent );
532 QString regexp = QgsExpressionUtils::getStringValue( vR, parent );
536 if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike )
538 QString esc_regexp = QRegExp::escape( regexp );
540 if ( esc_regexp.startsWith(
'%' ) )
542 esc_regexp.replace( 0, 1, QStringLiteral(
".*" ) );
544 thread_local QRegExp rx1( QStringLiteral(
"[^\\\\](%)" ) );
546 while ( ( pos = rx1.indexIn( esc_regexp, pos ) ) != -1 )
548 esc_regexp.replace( pos + 1, 1, QStringLiteral(
".*" ) );
551 thread_local QRegExp rx2( QStringLiteral(
"\\\\%" ) );
552 esc_regexp.replace( rx2, QStringLiteral(
"%" ) );
553 if ( esc_regexp.startsWith(
'_' ) )
555 esc_regexp.replace( 0, 1, QStringLiteral(
"." ) );
557 thread_local QRegExp rx3( QStringLiteral(
"[^\\\\](_)" ) );
559 while ( ( pos = rx3.indexIn( esc_regexp, pos ) ) != -1 )
561 esc_regexp.replace( pos + 1, 1,
'.' );
564 esc_regexp.replace( QLatin1String(
"\\\\_" ), QLatin1String(
"_" ) );
566 matches = QRegExp( esc_regexp, mOp == boLike || mOp == boNotLike ? Qt::CaseSensitive : Qt::CaseInsensitive ).exactMatch(
str );
570 matches = QRegularExpression( regexp ).match(
str ).hasMatch();
573 if ( mOp == boNotLike || mOp == boNotILike )
578 return matches ? TVL_True : TVL_False;
582 if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
586 QString sL = QgsExpressionUtils::getStringValue( vL, parent );
588 QString sR = QgsExpressionUtils::getStringValue( vR, parent );
590 return QVariant( sL + sR );
597 bool QgsExpressionNodeBinaryOperator::compare(
double diff )
619 qlonglong QgsExpressionNodeBinaryOperator::computeInt( qlonglong x, qlonglong y )
639 QDateTime QgsExpressionNodeBinaryOperator::computeDateTimeFromInterval(
const QDateTime &d,
QgsInterval *i )
644 return d.addSecs( i->
seconds() );
646 return d.addSecs( -i->
seconds() );
653 double QgsExpressionNodeBinaryOperator::computeDouble(
double x,
double y )
666 return std::fmod( x, y );
680 bool resL = mOpLeft->prepare( parent, context );
681 bool resR = mOpRight->prepare( parent, context );
727 Q_ASSERT(
false &&
"unexpected binary operator" );
763 Q_ASSERT(
false &&
"unexpected binary operator" );
773 QString rdump( mOpRight->dump() );
778 rdump.prepend(
'(' ).append(
')' );
782 if ( leftAssociative() )
784 fmt += lOp && ( lOp->
precedence() < precedence() ) ? QStringLiteral(
"(%1)" ) : QStringLiteral(
"%1" );
785 fmt += QLatin1String(
" %2 " );
786 fmt += rOp && ( rOp->
precedence() <= precedence() ) ? QStringLiteral(
"(%3)" ) : QStringLiteral(
"%3" );
790 fmt += lOp && ( lOp->
precedence() <= precedence() ) ? QStringLiteral(
"(%1)" ) : QStringLiteral(
"%1" );
791 fmt += QLatin1String(
" %2 " );
792 fmt += rOp && ( rOp->
precedence() < precedence() ) ? QStringLiteral(
"(%3)" ) : QStringLiteral(
"%3" );
795 return fmt.arg( mOpLeft->dump(), BINARY_OPERATOR_TEXT[mOp], rdump );
801 return QSet< QString >();
803 return mOpLeft->referencedColumns() + mOpRight->referencedColumns();
808 return mOpLeft->referencedVariables() + mOpRight->referencedVariables();
813 return mOpLeft->referencedFunctions() + mOpRight->referencedFunctions();
818 QList<const QgsExpressionNode *> lst;
820 lst += mOpLeft->nodes() + mOpRight->nodes();
826 return mOpLeft->needsGeometry() || mOpRight->needsGeometry();
838 const bool leftStatic = mOpLeft->isStatic( parent, context );
839 const bool rightStatic = mOpRight->isStatic( parent, context );
841 if ( leftStatic && rightStatic )
853 mOpLeft->prepare( parent, context );
854 if ( mOpLeft->hasCachedStaticValue() )
856 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
857 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
865 else if ( rightStatic )
867 mOpRight->prepare( parent, context );
868 if ( mOpRight->hasCachedStaticValue() )
870 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
871 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::True )
889 mOpLeft->prepare( parent, context );
890 if ( mOpLeft->hasCachedStaticValue() )
892 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
893 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
901 else if ( rightStatic )
903 mOpRight->prepare( parent, context );
904 if ( mOpRight->hasCachedStaticValue() )
906 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
907 if ( !parent->
hasEvalError() && tvl == QgsExpressionUtils::False )
950 if ( mList->count() == 0 )
951 return mNotIn ? TVL_True : TVL_False;
952 QVariant v1 = mNode->eval( parent, context );
954 if ( QgsExpressionUtils::isNull( v1 ) )
957 bool listHasNull =
false;
959 const QList< QgsExpressionNode * > nodeList = mList->list();
962 QVariant v2 = n->eval( parent, context );
964 if ( QgsExpressionUtils::isNull( v2 ) )
970 if ( ( v1.type() != QVariant::String || v2.type() != QVariant::String ) &&
971 QgsExpressionUtils::isDoubleSafe( v1 ) && QgsExpressionUtils::isDoubleSafe( v2 ) )
975 double f1 = QgsExpressionUtils::getDoubleValue( v1, parent );
977 double f2 = QgsExpressionUtils::getDoubleValue( v2, parent );
983 QString s1 = QgsExpressionUtils::getStringValue( v1, parent );
985 QString s2 = QgsExpressionUtils::getStringValue( v2, parent );
987 equal = QString::compare( s1, s2 ) == 0;
991 return mNotIn ? TVL_False : TVL_True;
999 return mNotIn ? TVL_True : TVL_False;
1015 bool res = mNode->prepare( parent, context );
1016 const QList< QgsExpressionNode * > nodeList = mList->list();
1019 res = res && n->prepare( parent, context );
1026 return QStringLiteral(
"%1 %2 IN (%3)" ).arg( mNode->dump(), mNotIn ?
"NOT" :
"", mList->dump() );
1038 if ( !mNode->isStatic( parent, context ) )
1041 const QList< QgsExpressionNode * > nodeList = mList->list();
1044 if ( !n->isStatic( parent, context ) )
1055 QString name = QgsExpression::QgsExpression::Functions()[mFnIndex]->name();
1058 QVariant res = fd->
run( mArgs, context, parent,
this );
1066 : mFnIndex( fnIndex )
1069 if ( !
args || functionParams.isEmpty() )
1080 while ( idx < args->names().size() &&
args->
names().at( idx ).isEmpty() )
1087 for ( ; idx < functionParams.count(); ++idx )
1089 int nodeIdx =
args->
names().indexOf( functionParams.at( idx ).name().toLower() );
1119 bool res = fd->
prepare(
this, parent, context );
1122 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1125 res = res && n->prepare( parent, context );
1135 return QStringLiteral(
"%1%2" ).arg( fd->
name(), fd->
name().startsWith(
'$' ) ? QString() : QStringLiteral(
"()" ) );
1137 return QStringLiteral(
"%1(%2)" ).arg( fd->
name(), mArgs ? mArgs->
dump() : QString() );
1143 return QSet< QString >();
1151 return functionColumns;
1155 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1158 if ( fd->
parameters().count() <= paramIndex || !fd->
parameters().at( paramIndex ).isSubExpression() )
1159 functionColumns.unite( n->referencedColumns() );
1163 return functionColumns;
1169 if ( fd->
name() == QLatin1String(
"var" ) )
1171 if ( !mArgs->
list().isEmpty() )
1175 return QSet<QString>() << var->
value().toString();
1177 return QSet<QString>() << QString();
1181 QSet<QString> functionVariables = QSet<QString>();
1184 return functionVariables;
1186 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1189 functionVariables.unite( n->referencedVariables() );
1192 return functionVariables;
1199 QSet<QString> functions = QSet<QString>();
1200 functions.insert( fd->
name() );
1205 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1208 functions.unite( n->referencedFunctions() );
1215 QList<const QgsExpressionNode *> lst;
1220 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1230 bool needs = QgsExpression::QgsExpression::Functions()[mFnIndex]->usesGeometry(
this );
1233 const QList< QgsExpressionNode * > nodeList = mArgs->
list();
1235 needs |= n->needsGeometry();
1258 if ( functionParams.isEmpty() )
1265 QSet< int > providedArgs;
1266 QSet< int > handledArgs;
1269 while (
args->
names().at( idx ).isEmpty() )
1271 providedArgs << idx;
1277 for ( ; idx < functionParams.count(); ++idx )
1279 int nodeIdx =
args->
names().indexOf( functionParams.at( idx ).name().toLower() );
1282 if ( !functionParams.at( idx ).optional() )
1284 error = QStringLiteral(
"No value specified for QgsExpressionFunction::Parameter '%1' for %2" ).arg( functionParams.at( idx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1290 if ( providedArgs.contains( idx ) )
1292 error = QStringLiteral(
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2" ).arg( functionParams.at( idx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1296 providedArgs << idx;
1297 handledArgs << nodeIdx;
1302 const QStringList nameList =
args->
names();
1303 for (
const QString &name : nameList )
1305 if ( !name.isEmpty() && !functionParams.contains( name ) )
1310 if ( !name.isEmpty() && !handledArgs.contains( idx ) )
1312 int functionIdx = functionParams.indexOf( name );
1313 if ( providedArgs.contains( functionIdx ) )
1315 error = QStringLiteral(
"Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2" ).arg( functionParams.at( functionIdx ).name(),
QgsExpression::Functions()[
fnIndex]->name() );
1350 if ( mValue.isNull() )
1351 return QStringLiteral(
"NULL" );
1353 switch ( mValue.type() )
1356 return QString::number( mValue.toInt() );
1357 case QVariant::Double:
1358 return QString::number( mValue.toDouble() );
1359 case QVariant::LongLong:
1360 return QString::number( mValue.toLongLong() );
1361 case QVariant::String:
1363 case QVariant::Bool:
1364 return mValue.toBool() ? QStringLiteral(
"TRUE" ) : QStringLiteral(
"FALSE" );
1366 return tr(
"[unsupported type: %1; value: %2]" ).arg( mValue.typeName(), mValue.toString() );
1377 return QSet<QString>();
1382 return QSet<QString>();
1387 return QSet<QString>();
1392 QList<const QgsExpressionNode *> lst;
1445 parent->
setEvalErrorString( tr(
"No feature available for field '%1' evaluation" ).arg( mName ) );
1482 const thread_local QRegExp re( QStringLiteral(
"^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" ) );
1488 return QSet<QString>() << mName;
1493 return QSet<QString>();
1498 return QSet<QString>();
1503 QList<const QgsExpressionNode *> result;
1530 : mConditions( *conditions )
1531 , mElseExp( elseExp )
1539 qDeleteAll( mConditions );
1549 for (
WhenThen *cond : std::as_const( mConditions ) )
1551 QVariant vWhen = cond->mWhenExp->eval( parent, context );
1552 QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( vWhen, parent );
1554 if ( tvl == QgsExpressionUtils::True )
1556 QVariant vRes = cond->mThenExp->eval( parent, context );
1564 QVariant vElse = mElseExp->
eval( parent, context );
1575 bool foundAnyNonStaticConditions =
false;
1576 for (
WhenThen *cond : std::as_const( mConditions ) )
1578 const bool res = cond->mWhenExp->prepare( parent, context )
1579 && cond->mThenExp->prepare( parent, context );
1583 foundAnyNonStaticConditions |= !cond->mWhenExp->hasCachedStaticValue();
1584 if ( !foundAnyNonStaticConditions && QgsExpressionUtils::getTVLValue( cond->mWhenExp->cachedStaticValue(), parent ) == QgsExpressionUtils::True )
1588 if ( cond->mThenExp->hasCachedStaticValue() )
1607 const bool res = mElseExp->
prepare( parent, context );
1611 if ( !foundAnyNonStaticConditions )
1635 QString msg( QStringLiteral(
"CASE" ) );
1636 for (
WhenThen *cond : mConditions )
1638 msg += QStringLiteral(
" WHEN %1 THEN %2" ).arg( cond->mWhenExp->dump(), cond->mThenExp->dump() );
1641 msg += QStringLiteral(
" ELSE %1" ).arg( mElseExp->
dump() );
1642 msg += QLatin1String(
" END" );
1649 return QSet< QString >();
1652 for (
WhenThen *cond : mConditions )
1654 lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
1666 for (
WhenThen *cond : mConditions )
1668 lst += cond->mWhenExp->referencedVariables() + cond->mThenExp->referencedVariables();
1680 for (
WhenThen *cond : mConditions )
1682 lst += cond->mWhenExp->referencedFunctions() + cond->mThenExp->referencedFunctions();
1693 QList<const QgsExpressionNode *> lst;
1695 for (
WhenThen *cond : mConditions )
1697 lst += cond->mWhenExp->nodes() + cond->mThenExp->nodes();
1701 lst += mElseExp->
nodes();
1708 for (
WhenThen *cond : mConditions )
1710 if ( cond->mWhenExp->needsGeometry() ||
1711 cond->mThenExp->needsGeometry() )
1734 if ( !wt->mWhenExp->isStatic( parent, context ) || !wt->mThenExp->isStatic( parent, context ) )
1739 return mElseExp->
isStatic( parent, context );
1747 return QSet< QString >();
1750 const QList< QgsExpressionNode * > nodeList = mList->
list();
1752 lst.unite( n->referencedColumns() );
1759 const QList< QgsExpressionNode * > nodeList = mList->
list();
1761 lst.unite( n->referencedVariables() );
1768 const QList< QgsExpressionNode * > nodeList = mList->
list();
1770 lst.unite( n->referencedFunctions() );
1776 QList<const QgsExpressionNode *> lst;
1778 const QList< QgsExpressionNode * > nodeList = mList->
list();
1785 : mWhenExp( whenExp )
1786 , mThenExp( thenExp )
1798 return new WhenThen( mWhenExp->clone(), mThenExp->clone() );
1803 return BINARY_OPERATOR_TEXT[mOp];
1810 const QVariant container = mContainer->eval( parent, context );
1812 const QVariant index = mIndex->eval( parent, context );
1815 switch ( container.type() )
1818 return QgsExpressionUtils::getMapValue( container, parent ).value( index.toString() );
1820 case QVariant::List:
1821 case QVariant::StringList:
1823 const QVariantList list = QgsExpressionUtils::getListValue( container, parent );
1824 qlonglong pos = QgsExpressionUtils::getIntValue( index, parent );
1825 if ( pos >= list.length() || pos < -list.length() )
1832 pos += list.length();
1835 return list.at( pos );
1839 if ( !container.isNull() )
1852 bool resC = mContainer->prepare( parent, context );
1853 bool resV = mIndex->prepare( parent, context );
1854 return resC && resV;
1859 return QStringLiteral(
"%1[%2]" ).arg( mContainer->dump(), mIndex->dump() );
1865 return QSet< QString >();
1867 return mContainer->referencedColumns() + mIndex->referencedColumns();
1872 return mContainer->referencedVariables() + mIndex->referencedVariables();
1877 return mContainer->referencedFunctions() + mIndex->referencedFunctions();
1882 QList<const QgsExpressionNode *> lst;
1884 lst += mContainer->nodes() + mIndex->nodes();
1890 return mContainer->needsGeometry() || mIndex->needsGeometry();
1902 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.
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.
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.