Skip to content
Permalink
Browse files

Correctly handle NULL start or end time values when filtering tempora…

…l ranges

We treat these as -infinity or +infinity (i.e. no time limit for the
feature start or end respectively)
  • Loading branch information
nyalldawson committed May 8, 2020
1 parent 61f1566 commit 9dfa7157661e110a726d8d9d07cd5077959ecadc
@@ -186,7 +186,7 @@ QString QgsVectorLayerTemporalProperties::createFilterString( QgsVectorLayer *,
return QString();

case ModeFeatureDateTimeInstantFromField:
return QStringLiteral( "%1 %2 %3 AND %1 %4 %5" ).arg( QgsExpression::quotedColumnRef( mStartFieldName ),
return QStringLiteral( "(%1 %2 %3 AND %1 %4 %5) OR %1 IS NULL" ).arg( QgsExpression::quotedColumnRef( mStartFieldName ),
range.includeBeginning() ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
dateTimeExpressionLiteral( range.begin() ),
range.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
@@ -196,7 +196,7 @@ QString QgsVectorLayerTemporalProperties::createFilterString( QgsVectorLayer *,
{
if ( !mStartFieldName.isEmpty() && !mEndFieldName.isEmpty() )
{
return QStringLiteral( "%1 %2 %3 AND %4 %5 %6" ).arg( QgsExpression::quotedColumnRef( mStartFieldName ),
return QStringLiteral( "(%1 %2 %3 OR %1 IS NULL) AND (%4 %5 %6 OR %4 IS NULL)" ).arg( QgsExpression::quotedColumnRef( mStartFieldName ),
range.includeEnd() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
dateTimeExpressionLiteral( range.end() ),
QgsExpression::quotedColumnRef( mEndFieldName ),
@@ -205,13 +205,13 @@ QString QgsVectorLayerTemporalProperties::createFilterString( QgsVectorLayer *,
}
else if ( !mStartFieldName.isEmpty() )
{
return QStringLiteral( "%1 %2 %3" ).arg( QgsExpression::quotedColumnRef( mStartFieldName ),
return QStringLiteral( "%1 %2 %3 OR %1 IS NULL" ).arg( QgsExpression::quotedColumnRef( mStartFieldName ),
range.includeBeginning() ? QStringLiteral( "<=" ) : QStringLiteral( "<" ),
dateTimeExpressionLiteral( range.end() ) );
}
else if ( !mEndFieldName.isEmpty() )
{
return QStringLiteral( "%1 %2 %3" ).arg( QgsExpression::quotedColumnRef( mEndFieldName ),
return QStringLiteral( "%1 %2 %3 OR %1 IS NULL" ).arg( QgsExpression::quotedColumnRef( mEndFieldName ),
range.includeBeginning() ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
dateTimeExpressionLiteral( range.begin() ) );
}
@@ -111,13 +111,13 @@ def testSingleFieldMode(self):
self.assertFalse(props.createFilterString(layer, range))

props.setIsActive(True)
self.assertEqual(props.createFilterString(layer, range), '"start_field" >= make_datetime(2019,3,4,11,12,13) AND "start_field" <= make_datetime(2020,5,6,8,9,10)')
self.assertEqual(props.createFilterString(layer, range), '("start_field" >= make_datetime(2019,3,4,11,12,13) AND "start_field" <= make_datetime(2020,5,6,8,9,10)) OR "start_field" IS NULL')

range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4), QTime(11, 12, 13)), QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)), includeBeginning=False)
self.assertEqual(props.createFilterString(layer, range), '"start_field" > make_datetime(2019,3,4,11,12,13) AND "start_field" <= make_datetime(2020,5,6,8,9,10)')
self.assertEqual(props.createFilterString(layer, range), '("start_field" > make_datetime(2019,3,4,11,12,13) AND "start_field" <= make_datetime(2020,5,6,8,9,10)) OR "start_field" IS NULL')

range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4), QTime(11, 12, 13)), QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)), includeEnd=False)
self.assertEqual(props.createFilterString(layer, range), '"start_field" >= make_datetime(2019,3,4,11,12,13) AND "start_field" < make_datetime(2020,5,6,8,9,10)')
self.assertEqual(props.createFilterString(layer, range), '("start_field" >= make_datetime(2019,3,4,11,12,13) AND "start_field" < make_datetime(2020,5,6,8,9,10)) OR "start_field" IS NULL')

def testDualFieldMode(self):
layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer&field=start_field:datetime&field=end_field:datetime", "test", "memory")
@@ -134,32 +134,32 @@ def testDualFieldMode(self):
self.assertFalse(props.createFilterString(layer, range))

props.setIsActive(True)
self.assertEqual(props.createFilterString(layer, range), '"start_field" <= make_datetime(2020,5,6,8,9,10) AND "end_field" >= make_datetime(2019,3,4,11,12,13)')
self.assertEqual(props.createFilterString(layer, range), '("start_field" <= make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL) AND ("end_field" >= make_datetime(2019,3,4,11,12,13) OR "end_field" IS NULL)')

range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4), QTime(11, 12, 13)), QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)), includeBeginning=False)
self.assertEqual(props.createFilterString(layer, range), '"start_field" <= make_datetime(2020,5,6,8,9,10) AND "end_field" > make_datetime(2019,3,4,11,12,13)')
self.assertEqual(props.createFilterString(layer, range), '("start_field" <= make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL) AND ("end_field" > make_datetime(2019,3,4,11,12,13) OR "end_field" IS NULL)')

range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4), QTime(11, 12, 13)), QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)), includeEnd=False)
self.assertEqual(props.createFilterString(layer, range), '"start_field" < make_datetime(2020,5,6,8,9,10) AND "end_field" >= make_datetime(2019,3,4,11,12,13)')
self.assertEqual(props.createFilterString(layer, range), '("start_field" < make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL) AND ("end_field" >= make_datetime(2019,3,4,11,12,13) OR "end_field" IS NULL)')

props.setEndField('')
self.assertEqual(props.createFilterString(layer, range), '"start_field" <= make_datetime(2020,5,6,8,9,10)')
self.assertEqual(props.createFilterString(layer, range), '"start_field" <= make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL')

range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4), QTime(11, 12, 13)), QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)), includeBeginning=False)
self.assertEqual(props.createFilterString(layer, range), '"start_field" < make_datetime(2020,5,6,8,9,10)')
self.assertEqual(props.createFilterString(layer, range), '"start_field" < make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL')

range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4), QTime(11, 12, 13)), QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)), includeEnd=False)
self.assertEqual(props.createFilterString(layer, range), '"start_field" <= make_datetime(2020,5,6,8,9,10)')
self.assertEqual(props.createFilterString(layer, range), '"start_field" <= make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL')

props.setStartField('')
props.setEndField('end_field')
self.assertEqual(props.createFilterString(layer, range), '"end_field" >= make_datetime(2019,3,4,11,12,13)')
self.assertEqual(props.createFilterString(layer, range), '"end_field" >= make_datetime(2019,3,4,11,12,13) OR "end_field" IS NULL')

range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4), QTime(11, 12, 13)), QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)), includeBeginning=False)
self.assertEqual(props.createFilterString(layer, range), '"end_field" > make_datetime(2019,3,4,11,12,13)')
self.assertEqual(props.createFilterString(layer, range), '"end_field" > make_datetime(2019,3,4,11,12,13) OR "end_field" IS NULL')

range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4), QTime(11, 12, 13)), QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)), includeEnd=False)
self.assertEqual(props.createFilterString(layer, range), '"end_field" >= make_datetime(2019,3,4,11,12,13)')
self.assertEqual(props.createFilterString(layer, range), '"end_field" >= make_datetime(2019,3,4,11,12,13) OR "end_field" IS NULL')


if __name__ == '__main__':

0 comments on commit 9dfa715

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