Skip to content
Permalink
Browse files

We can trust compiled expressions, remove option to disable

  • Loading branch information
nirvn committed Dec 24, 2020
1 parent eb1c7b1 commit 129ebbb18d060a270336c689a5011a438d70f0b6
@@ -704,7 +704,6 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl, const QList<QgsOpti
cbxCheckVersion->setChecked( mSettings->value( QStringLiteral( "/qgis/checkVersion" ), true ).toBool() );
cbxCheckVersion->setVisible( mSettings->value( QStringLiteral( "/qgis/allowVersionCheck" ), true ).toBool() );
cbxAttributeTableDocked->setChecked( mSettings->value( QStringLiteral( "/qgis/dockAttributeTable" ), false ).toBool() );
cbxCompileExpressions->setChecked( mSettings->value( QStringLiteral( "/qgis/compileExpressions" ), true ).toBool() );

mComboCopyFeatureFormat->addItem( tr( "Plain Text, No Geometry" ), QgsClipboard::AttributesOnly );
mComboCopyFeatureFormat->addItem( tr( "Plain Text, WKT Geometry" ), QgsClipboard::AttributesWithWKT );
@@ -1567,8 +1566,6 @@ void QgsOptions::saveOptions()
cmbScanZipInBrowser->currentData().toString() );
mSettings->setValue( QStringLiteral( "/qgis/mainSnappingWidgetMode" ), mSnappingMainDialogComboBox->currentData() );

mSettings->setValue( QStringLiteral( "/qgis/compileExpressions" ), cbxCompileExpressions->isChecked() );

mSettings->setValue( QStringLiteral( "/qgis/legendsymbolMinimumSize" ), mLegendSymbolMinimumSizeSpinBox->value() );
mSettings->setValue( QStringLiteral( "/qgis/legendsymbolMaximumSize" ), mLegendSymbolMaximumSizeSpinBox->value() );
QgsSymbolLegendNode::MINIMUM_SIZE = mLegendSymbolMinimumSizeSpinBox->value();
@@ -196,8 +196,7 @@ QgsOgrFeatureIterator::QgsOgrFeatureIterator( QgsOgrFeatureSource *source, bool
}
}

if ( request.filterType() == QgsFeatureRequest::FilterExpression
&& QgsSettings().value( QStringLiteral( "qgis/compileExpressions" ), true ).toBool() )
if ( request.filterType() == QgsFeatureRequest::FilterExpression )
{
QgsSqlExpressionCompiler *compiler = nullptr;
if ( source->mDriverName == QLatin1String( "SQLite" ) || source->mDriverName == QLatin1String( "GPKG" ) )
@@ -191,30 +191,22 @@ void QgsDb2FeatureIterator::BuildStatement( const QgsFeatureRequest &request )
mCompileStatus = NoCompilation;
if ( request.filterType() == QgsFeatureRequest::FilterExpression )
{
QgsDebugMsg( QStringLiteral( "compileExpressions: %1" ).arg( QgsSettings().value( "qgis/compileExpressions", true ).toString() ) );
if ( QgsSettings().value( QStringLiteral( "qgis/compileExpressions" ), true ).toBool() )
QgsDb2ExpressionCompiler compiler = QgsDb2ExpressionCompiler( mSource );
QgsDebugMsg( "expression dump: " + request.filterExpression()->dump() );
QgsDebugMsg( "expression expression: " + request.filterExpression()->expression() );
QgsSqlExpressionCompiler::Result result = compiler.compile( request.filterExpression() );
QgsDebugMsg( QStringLiteral( "compiler result: %1" ).arg( result ) + "; query: " + compiler.result() );
if ( result == QgsSqlExpressionCompiler::Complete || result == QgsSqlExpressionCompiler::Partial )
{
QgsDb2ExpressionCompiler compiler = QgsDb2ExpressionCompiler( mSource );
QgsDebugMsg( "expression dump: " + request.filterExpression()->dump() );
QgsDebugMsg( "expression expression: " + request.filterExpression()->expression() );
QgsSqlExpressionCompiler::Result result = compiler.compile( request.filterExpression() );
QgsDebugMsg( QStringLiteral( "compiler result: %1" ).arg( result ) + "; query: " + compiler.result() );
if ( result == QgsSqlExpressionCompiler::Complete || result == QgsSqlExpressionCompiler::Partial )
{
if ( !filterAdded )
mStatement += " WHERE (" + compiler.result() + ')';
else
mStatement += " AND (" + compiler.result() + ')';

//if only partial success when compiling expression, we need to double-check results using QGIS' expressions
mExpressionCompiled = ( result == QgsSqlExpressionCompiler::Complete );
mCompileStatus = ( mExpressionCompiled ? Compiled : PartiallyCompiled );
limitAtProvider = mExpressionCompiled;
}
if ( !filterAdded )
mStatement += " WHERE (" + compiler.result() + ')';
else
{
limitAtProvider = false;
}
mStatement += " AND (" + compiler.result() + ')';

//if only partial success when compiling expression, we need to double-check results using QGIS' expressions
mExpressionCompiled = ( result == QgsSqlExpressionCompiler::Complete );
mCompileStatus = ( mExpressionCompiled ? Compiled : PartiallyCompiled );
limitAtProvider = mExpressionCompiled;
}
else
{
@@ -224,8 +216,7 @@ void QgsDb2FeatureIterator::BuildStatement( const QgsFeatureRequest &request )

QStringList orderByParts;
mOrderByCompiled = true;
QgsDebugMsg( QStringLiteral( "compileExpressions: %1" ).arg( QgsSettings().value( "qgis/compileExpressions", true ).toString() ) );
if ( QgsSettings().value( QStringLiteral( "qgis/compileExpressions" ), true ).toBool() && limitAtProvider )
if ( limitAtProvider )
{
const auto constOrderBy = request.orderBy();
for ( const QgsFeatureRequest::OrderByClause &clause : constOrderBy )
@@ -330,27 +330,20 @@ void QgsMssqlFeatureIterator::BuildStatement( const QgsFeatureRequest &request )
mCompileStatus = NoCompilation;
if ( request.filterType() == QgsFeatureRequest::FilterExpression )
{
if ( QgsSettings().value( QStringLiteral( "qgis/compileExpressions" ), true ).toBool() )
QgsMssqlExpressionCompiler compiler = QgsMssqlExpressionCompiler( mSource );
QgsSqlExpressionCompiler::Result result = compiler.compile( request.filterExpression() );
if ( result == QgsSqlExpressionCompiler::Complete || result == QgsSqlExpressionCompiler::Partial )
{
QgsMssqlExpressionCompiler compiler = QgsMssqlExpressionCompiler( mSource );
QgsSqlExpressionCompiler::Result result = compiler.compile( request.filterExpression() );
if ( result == QgsSqlExpressionCompiler::Complete || result == QgsSqlExpressionCompiler::Partial )
{
mFallbackStatement = mStatement;
if ( !filterAdded )
mStatement += " WHERE (" + compiler.result() + ')';
else
mStatement += " AND (" + compiler.result() + ')';

//if only partial success when compiling expression, we need to double-check results using QGIS' expressions
mExpressionCompiled = ( result == QgsSqlExpressionCompiler::Complete );
mCompileStatus = ( mExpressionCompiled ? Compiled : PartiallyCompiled );
limitAtProvider = mExpressionCompiled;
}
mFallbackStatement = mStatement;
if ( !filterAdded )
mStatement += " WHERE (" + compiler.result() + ')';
else
{
limitAtProvider = false;
}
mStatement += " AND (" + compiler.result() + ')';

//if only partial success when compiling expression, we need to double-check results using QGIS' expressions
mExpressionCompiled = ( result == QgsSqlExpressionCompiler::Complete );
mCompileStatus = ( mExpressionCompiled ? Compiled : PartiallyCompiled );
limitAtProvider = mExpressionCompiled;
}
else
{
@@ -361,41 +354,34 @@ void QgsMssqlFeatureIterator::BuildStatement( const QgsFeatureRequest &request )
QStringList orderByParts;
mOrderByCompiled = true;

if ( QgsSettings().value( QStringLiteral( "qgis/compileExpressions" ), true ).toBool() )
const auto constOrderBy = request.orderBy();
for ( const QgsFeatureRequest::OrderByClause &clause : constOrderBy )
{
const auto constOrderBy = request.orderBy();
for ( const QgsFeatureRequest::OrderByClause &clause : constOrderBy )
if ( ( clause.ascending() && !clause.nullsFirst() ) || ( !clause.ascending() && clause.nullsFirst() ) )
{
if ( ( clause.ascending() && !clause.nullsFirst() ) || ( !clause.ascending() && clause.nullsFirst() ) )
{
//not supported by SQL Server
mOrderByCompiled = false;
break;
}
//not supported by SQL Server
mOrderByCompiled = false;
break;
}

QgsMssqlExpressionCompiler compiler = QgsMssqlExpressionCompiler( mSource );
QgsExpression expression = clause.expression();
if ( compiler.compile( &expression ) == QgsSqlExpressionCompiler::Complete )
{
QString part;
part = compiler.result();
part += clause.ascending() ? QStringLiteral( " ASC" ) : QStringLiteral( " DESC" );
orderByParts << part;
}
else
{
// Bail out on first non-complete compilation.
// Most important clauses at the beginning of the list
// will still be sent and used to pre-sort so the local
// CPU can use its cycles for fine-tuning.
mOrderByCompiled = false;
break;
}
QgsMssqlExpressionCompiler compiler = QgsMssqlExpressionCompiler( mSource );
QgsExpression expression = clause.expression();
if ( compiler.compile( &expression ) == QgsSqlExpressionCompiler::Complete )
{
QString part;
part = compiler.result();
part += clause.ascending() ? QStringLiteral( " ASC" ) : QStringLiteral( " DESC" );
orderByParts << part;
}
else
{
// Bail out on first non-complete compilation.
// Most important clauses at the beginning of the list
// will still be sent and used to pre-sort so the local
// CPU can use its cycles for fine-tuning.
mOrderByCompiled = false;
break;
}
}
else
{
mOrderByCompiled = false;
}

if ( !mOrderByCompiled && !request.orderBy().isEmpty() )
@@ -199,25 +199,18 @@ QgsOracleFeatureIterator::QgsOracleFeatureIterator( QgsOracleFeatureSource *sour
bool useFallback = false;
if ( request.filterType() == QgsFeatureRequest::FilterExpression )
{
if ( QgsSettings().value( QStringLiteral( "qgis/compileExpressions" ), true ).toBool() )
QgsOracleExpressionCompiler compiler( mSource );
QgsSqlExpressionCompiler::Result result = compiler.compile( mRequest.filterExpression() );
if ( result == QgsSqlExpressionCompiler::Complete || result == QgsSqlExpressionCompiler::Partial )
{
QgsOracleExpressionCompiler compiler( mSource );
QgsSqlExpressionCompiler::Result result = compiler.compile( mRequest.filterExpression() );
if ( result == QgsSqlExpressionCompiler::Complete || result == QgsSqlExpressionCompiler::Partial )
{
fallbackStatement = whereClause;
useFallback = true;
whereClause = QgsOracleUtils::andWhereClauses( whereClause, compiler.result() );

//if only partial success when compiling expression, we need to double-check results using QGIS' expressions
mExpressionCompiled = ( result == QgsSqlExpressionCompiler::Complete );
mCompileStatus = ( mExpressionCompiled ? Compiled : PartiallyCompiled );
limitAtProvider = mExpressionCompiled;
}
else
{
limitAtProvider = false;
}
fallbackStatement = whereClause;
useFallback = true;
whereClause = QgsOracleUtils::andWhereClauses( whereClause, compiler.result() );

//if only partial success when compiling expression, we need to double-check results using QGIS' expressions
mExpressionCompiled = ( result == QgsSqlExpressionCompiler::Complete );
mCompileStatus = ( mExpressionCompiled ? Compiled : PartiallyCompiled );
limitAtProvider = mExpressionCompiled;
}
else
{
@@ -113,23 +113,16 @@ QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresFeatureSource
}
mFilterRequiresGeometry = request.filterExpression()->needsGeometry();

if ( QgsSettings().value( QStringLiteral( "qgis/compileExpressions" ), true ).toBool() )
{
//IMPORTANT - this MUST be the last clause added!
QgsPostgresExpressionCompiler compiler = QgsPostgresExpressionCompiler( source );
//IMPORTANT - this MUST be the last clause added!
QgsPostgresExpressionCompiler compiler = QgsPostgresExpressionCompiler( source );

if ( compiler.compile( request.filterExpression() ) == QgsSqlExpressionCompiler::Complete )
{
useFallbackWhereClause = true;
fallbackWhereClause = whereClause;
whereClause = QgsPostgresUtils::andWhereClauses( whereClause, compiler.result() );
mExpressionCompiled = true;
mCompileStatus = Compiled;
}
else
{
limitAtProvider = false;
}
if ( compiler.compile( request.filterExpression() ) == QgsSqlExpressionCompiler::Complete )
{
useFallbackWhereClause = true;
fallbackWhereClause = whereClause;
whereClause = QgsPostgresUtils::andWhereClauses( whereClause, compiler.result() );
mExpressionCompiled = true;
mCompileStatus = Compiled;
}
else
{
@@ -123,33 +123,24 @@ QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteFeature
mFetchGeometry = true;
}

if ( QgsSettings().value( QStringLiteral( "qgis/compileExpressions" ), true ).toBool() )
QgsSQLiteExpressionCompiler compiler = QgsSQLiteExpressionCompiler( source->mFields );
QgsSqlExpressionCompiler::Result result = compiler.compile( request.filterExpression() );
if ( result == QgsSqlExpressionCompiler::Complete || result == QgsSqlExpressionCompiler::Partial )
{
QgsSQLiteExpressionCompiler compiler = QgsSQLiteExpressionCompiler( source->mFields );

QgsSqlExpressionCompiler::Result result = compiler.compile( request.filterExpression() );

if ( result == QgsSqlExpressionCompiler::Complete || result == QgsSqlExpressionCompiler::Partial )
whereClause = compiler.result();
if ( !whereClause.isEmpty() )
{
whereClause = compiler.result();
if ( !whereClause.isEmpty() )
{
useFallbackWhereClause = true;
fallbackWhereClause = whereClauses.join( QLatin1String( " AND " ) );
whereClauses.append( whereClause );
//if only partial success when compiling expression, we need to double-check results using QGIS' expressions
mExpressionCompiled = ( result == QgsSqlExpressionCompiler::Complete );
mCompileStatus = ( mExpressionCompiled ? Compiled : PartiallyCompiled );
}
}
if ( result != QgsSqlExpressionCompiler::Complete )
{
//can't apply limit at provider side as we need to check all results using QGIS expressions
limitAtProvider = false;
useFallbackWhereClause = true;
fallbackWhereClause = whereClauses.join( QLatin1String( " AND " ) );
whereClauses.append( whereClause );
//if only partial success when compiling expression, we need to double-check results using QGIS' expressions
mExpressionCompiled = ( result == QgsSqlExpressionCompiler::Complete );
mCompileStatus = ( mExpressionCompiled ? Compiled : PartiallyCompiled );
}
}
else
if ( result != QgsSqlExpressionCompiler::Complete )
{
//can't apply limit at provider side as we need to check all results using QGIS expressions
limitAtProvider = false;
}
}
@@ -163,40 +154,33 @@ QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteFeature

mOrderByCompiled = true;

if ( QgsSettings().value( QStringLiteral( "qgis/compileExpressions" ), true ).toBool() )
const auto constOrderBy = request.orderBy();
for ( const QgsFeatureRequest::OrderByClause &clause : constOrderBy )
{
const auto constOrderBy = request.orderBy();
for ( const QgsFeatureRequest::OrderByClause &clause : constOrderBy )
QgsSQLiteExpressionCompiler compiler = QgsSQLiteExpressionCompiler( source->mFields );
QgsExpression expression = clause.expression();
if ( compiler.compile( &expression ) == QgsSqlExpressionCompiler::Complete )
{
QgsSQLiteExpressionCompiler compiler = QgsSQLiteExpressionCompiler( source->mFields );
QgsExpression expression = clause.expression();
if ( compiler.compile( &expression ) == QgsSqlExpressionCompiler::Complete )
{
QString part;
part = compiler.result();

if ( clause.nullsFirst() )
orderByParts << QStringLiteral( "%1 IS NOT NULL" ).arg( part );
else
orderByParts << QStringLiteral( "%1 IS NULL" ).arg( part );
QString part;
part = compiler.result();

part += clause.ascending() ? " COLLATE NOCASE ASC" : " COLLATE NOCASE DESC";
orderByParts << part;
}
if ( clause.nullsFirst() )
orderByParts << QStringLiteral( "%1 IS NOT NULL" ).arg( part );
else
{
// Bail out on first non-complete compilation.
// Most important clauses at the beginning of the list
// will still be sent and used to pre-sort so the local
// CPU can use its cycles for fine-tuning.
mOrderByCompiled = false;
break;
}
orderByParts << QStringLiteral( "%1 IS NULL" ).arg( part );

part += clause.ascending() ? " COLLATE NOCASE ASC" : " COLLATE NOCASE DESC";
orderByParts << part;
}
else
{
// Bail out on first non-complete compilation.
// Most important clauses at the beginning of the list
// will still be sent and used to pre-sort so the local
// CPU can use its cycles for fine-tuning.
mOrderByCompiled = false;
break;
}
}
else
{
mOrderByCompiled = false;
}

if ( !mOrderByCompiled )
@@ -2087,7 +2087,7 @@
<item row="0" column="2">
<widget class="QComboBox" name="cmbScanItemsInBrowser"/>
</item>
<item row="6" column="0" colspan="4">
<item row="5" column="0" colspan="4">
<widget class="QCheckBox" name="cbxEvaluateDefaultValues">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When digitizing a new feature, default values are retrieved from the database. With this option turned on, the default values will be evaluated at the time of digitizing. With this option turned off, the default values will be evaluated at the time of saving.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -2142,13 +2142,6 @@
</property>
</widget>
</item>
<item row="5" column="0" colspan="4">
<widget class="QCheckBox" name="cbxCompileExpressions">
<property name="text">
<string>Execute expressions on server-side if possible</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_29">
<property name="text">

0 comments on commit 129ebbb

Please sign in to comment.
You can’t perform that action at this time.