From 0672abbaed506d96ffa5f3a6d3e51109e442ec5b Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Fri, 15 Apr 2016 05:47:47 +1000 Subject: [PATCH] [FEATURE] Compilation support for unary - operation --- src/core/qgssqlexpressioncompiler.cpp | 14 +++++++++++++- src/core/qgssqlexpressioncompiler.h | 1 + src/providers/ogr/qgsogrexpressioncompiler.cpp | 3 ++- tests/src/python/providertestbase.py | 5 +++++ tests/src/python/test_provider_shapefile.py | 7 ++++++- 5 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/core/qgssqlexpressioncompiler.cpp b/src/core/qgssqlexpressioncompiler.cpp index cdc4f1e2e3c..9cba8b2fe73 100644 --- a/src/core/qgssqlexpressioncompiler.cpp +++ b/src/core/qgssqlexpressioncompiler.cpp @@ -93,7 +93,19 @@ QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const Qg } case QgsExpression::uoMinus: - break; + { + if ( mFlags.testFlag( NoUnaryMinus ) ) + return Fail; + + QString right; + if ( compileNode( n->operand(), right ) == Complete ) + { + result = "( - (" + right + "))"; + return Complete; + } + + return Fail; + } } break; diff --git a/src/core/qgssqlexpressioncompiler.h b/src/core/qgssqlexpressioncompiler.h index 5e0da3b0902..1974217960b 100644 --- a/src/core/qgssqlexpressioncompiler.h +++ b/src/core/qgssqlexpressioncompiler.h @@ -50,6 +50,7 @@ class CORE_EXPORT QgsSqlExpressionCompiler CaseInsensitiveStringMatch = 0x01, //!< Provider performs case-insensitive string matching for all strings LikeIsCaseInsensitive = 0x02, //!< Provider treats LIKE as case-insensitive NoNullInBooleanLogic = 0x04, //!< Provider does not support using NULL with boolean logic, eg "(...) OR NULL" + NoUnaryMinus = 0x08, //!< Provider does not unary minus, eg " -( 100 * 2 ) = ..." }; Q_DECLARE_FLAGS( Flags, Flag ) diff --git a/src/providers/ogr/qgsogrexpressioncompiler.cpp b/src/providers/ogr/qgsogrexpressioncompiler.cpp index db88da24e9f..8baac96ce01 100644 --- a/src/providers/ogr/qgsogrexpressioncompiler.cpp +++ b/src/providers/ogr/qgsogrexpressioncompiler.cpp @@ -17,7 +17,8 @@ #include "qgsogrprovider.h" QgsOgrExpressionCompiler::QgsOgrExpressionCompiler( QgsOgrFeatureSource* source ) - : QgsSqlExpressionCompiler( source->mFields, QgsSqlExpressionCompiler::CaseInsensitiveStringMatch | QgsSqlExpressionCompiler::NoNullInBooleanLogic ) + : QgsSqlExpressionCompiler( source->mFields, QgsSqlExpressionCompiler::CaseInsensitiveStringMatch | QgsSqlExpressionCompiler::NoNullInBooleanLogic + | QgsSqlExpressionCompiler::NoUnaryMinus ) , mSource( source ) { } diff --git a/tests/src/python/providertestbase.py b/tests/src/python/providertestbase.py index a3eb06558fc..2f4e2c20885 100644 --- a/tests/src/python/providertestbase.py +++ b/tests/src/python/providertestbase.py @@ -119,7 +119,9 @@ class ProviderTestCase(object): self.assert_query(provider, 'name ILIKE \'aPple\'', [2]) self.assert_query(provider, 'name ILIKE \'%pp%\'', [2]) self.assert_query(provider, 'cnt > 0', [1, 2, 3, 4]) + self.assert_query(provider, '-cnt > 0', [5]) self.assert_query(provider, 'cnt < 0', [5]) + self.assert_query(provider, '-cnt < 0', [1, 2, 3, 4]) self.assert_query(provider, 'cnt >= 100', [1, 2, 3, 4]) self.assert_query(provider, 'cnt <= 100', [1, 5]) self.assert_query(provider, 'pk IN (1, 2, 4, 8)', [1, 2, 4]) @@ -127,6 +129,9 @@ class ProviderTestCase(object): self.assert_query(provider, 'cnt = 99 + 1', [1]) self.assert_query(provider, 'cnt = 101 - 1', [1]) self.assert_query(provider, 'cnt - 1 = 99', [1]) + self.assert_query(provider, '-cnt - 1 = -101', [1]) + self.assert_query(provider, '-(-cnt) = 100', [1]) + self.assert_query(provider, '-(cnt) = -(100)', [1]) self.assert_query(provider, 'cnt + 1 = 101', [1]) self.assert_query(provider, 'cnt = 1100 % 1000', [1]) self.assert_query(provider, '"name" || \' \' || "name" = \'Orange Orange\'', [1]) diff --git a/tests/src/python/test_provider_shapefile.py b/tests/src/python/test_provider_shapefile.py index a6e70a7c163..aafaaece04b 100644 --- a/tests/src/python/test_provider_shapefile.py +++ b/tests/src/python/test_provider_shapefile.py @@ -99,7 +99,12 @@ class TestPyQgsShapefileProvider(unittest.TestCase, ProviderTestCase): 'not name = \'Apple\' or not name = \'Apple\'', 'not name = \'Apple\' and pk = 4', 'not name = \'Apple\' and not pk = 4', - 'num_char IN (2, 4, 5)']) + 'num_char IN (2, 4, 5)', + '-cnt > 0', + '-cnt < 0', + '-cnt - 1 = -101', + '-(-cnt) = 100', + '-(cnt) = -(100)']) def partiallyCompiledFilters(self): return set(['name = \'Apple\'',