From eb439d34ba656b401a89572d361f3780ec8c4385 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Mon, 8 Oct 2018 14:48:31 +1000 Subject: [PATCH] [mssql] Update test for skipping invalid geometry handling --- src/providers/mssql/qgsmssqlprovider.cpp | 4 +-- tests/src/python/test_provider_mssql.py | 39 ++++++++++++++++++++-- tests/testdata/provider/testdata_mssql.sql | 32 +++++++++++++++--- 3 files changed, 67 insertions(+), 8 deletions(-) diff --git a/src/providers/mssql/qgsmssqlprovider.cpp b/src/providers/mssql/qgsmssqlprovider.cpp index 589eb196983..df832949058 100644 --- a/src/providers/mssql/qgsmssqlprovider.cpp +++ b/src/providers/mssql/qgsmssqlprovider.cpp @@ -724,9 +724,9 @@ void QgsMssqlProvider::UpdateStatistics( bool estimate ) const if ( mGeometryColType == QLatin1String( "geometry" ) ) { if ( mDisableInvalidGeometryHandling ) - statement = QStringLiteral( "select min(case when ([%1].STIsValid() = 1) THEN [%1].STEnvelope().STPointN(1).STX else NULL end), min(case when ([%1].STIsValid() = 1) THEN [%1].STEnvelope().STPointN(1).STY else NULL end), max(case when ([%1].STIsValid() = 1) THEN [%1].STEnvelope().STPointN(3).STX else NULL end), max(case when ([%1].STIsValid() = 1) THEN [%1].STEnvelope().STPointN(3).STY else NULL end)" ).arg( mGeometryColName ); - else statement = QStringLiteral( "select min([%1].STEnvelope().STPointN(1).STX), min([%1].STEnvelope().STPointN(1).STY), max([%1].STEnvelope().STPointN(3).STX), max([%1].STEnvelope().STPointN(3).STY)" ).arg( mGeometryColName ); + else + statement = QStringLiteral( "select min(case when ([%1].STIsValid() = 1) THEN [%1].STEnvelope().STPointN(1).STX else NULL end), min(case when ([%1].STIsValid() = 1) THEN [%1].STEnvelope().STPointN(1).STY else NULL end), max(case when ([%1].STIsValid() = 1) THEN [%1].STEnvelope().STPointN(3).STX else NULL end), max(case when ([%1].STIsValid() = 1) THEN [%1].STEnvelope().STPointN(3).STY else NULL end)" ).arg( mGeometryColName ); } else { diff --git a/tests/src/python/test_provider_mssql.py b/tests/src/python/test_provider_mssql.py index e841bcf4bc3..0c633fdfefa 100644 --- a/tests/src/python/test_provider_mssql.py +++ b/tests/src/python/test_provider_mssql.py @@ -24,6 +24,7 @@ from qgis.core import (QgsSettings, QgsField, QgsGeometry, QgsPointXY, + QgsRectangle, NULL, QgsVectorLayerExporter, QgsCoordinateReferenceSystem) @@ -43,7 +44,8 @@ class TestPyQgsMssqlProvider(unittest.TestCase, ProviderTestCase): @classmethod def setUpClass(cls): """Run before all tests""" - cls.dbconn = "dbname='gis' host=localhost\sqlexpress" + cls.dbconn = "service='Driver={ODBC Driver 13 for SQL Server};server=127.0.0.1;uid=SA;pwd=' user='SA' password=''" + if 'QGIS_MSSQLTEST_DB' in os.environ: cls.dbconn = os.environ['QGIS_MSSQLTEST_DB'] # Create test layers @@ -271,7 +273,9 @@ class TestPyQgsMssqlProvider(unittest.TestCase, ProviderTestCase): """ Test what happens when SQL Server is a POS and throws an exception on encountering an invalid geometry """ vl = QgsVectorLayer('%s srid=4167 type=POLYGON table="qgis_test"."invalid_polys" (ogr_geometry) sql=' % (self.dbconn), "testinvalid", "mssql") - assert(vl.isValid()) + self.assertTrue(vl.isValid()) + + self.assertEqual(vl.dataProvider().extent().toString(1), QgsRectangle(173.953, -41.513, 173.967, -41.502).toString(1)) #burn through features - don't want SQL server to trip up on the invalid ones count = 0 @@ -287,6 +291,37 @@ class TestPyQgsMssqlProvider(unittest.TestCase, ProviderTestCase): self.assertEqual(count, 37) # sorry... you get NO chance to see these features exist and repair them... because SQL server. Use PostGIS instead and live a happier life! + # with estimated metadata + vl = QgsVectorLayer('%s srid=4167 type=POLYGON estimatedmetadata=true table="qgis_test"."invalid_polys" (ogr_geometry) sql=' % + (self.dbconn), "testinvalid", "mssql") + self.assertTrue(vl.isValid()) + self.assertEqual(vl.dataProvider().extent().toString(1), QgsRectangle(173.954, -41.513, 173.967, -41.502).toString(1)) + + # Now, play on the edge! Let's disable invalid geometry handling and watch things crash and burn + vl = QgsVectorLayer('%s srid=4167 type=POLYGON table="qgis_test"."invalid_polys" (ogr_geometry) disableInvalidGeometryHandling="1" sql=' % + (self.dbconn), "testinvalid", "mssql") + self.assertTrue(vl.isValid()) + + self.assertEqual(vl.dataProvider().extent().toString(1), 'Empty') # HAHA - you asked for it + #burn through features - don't expect anything wrong here yet + count = 0 + for f in vl.dataProvider().getFeatures(): + count += 1 + self.assertEqual(count, 39) + count = 0 + + for f in vl.dataProvider().getFeatures(QgsFeatureRequest(QgsRectangle(173, -42, 174, -41))): + count += 1 + # now you only get 1 feature *sad trumpet* + self.assertEqual(count, 1) + count = 0 + + # same, with estimated metadata + vl = QgsVectorLayer('%s srid=4167 type=POLYGON estimatedmetadata=true table="qgis_test"."invalid_polys" (ogr_geometry) disableInvalidGeometryHandling="1" sql=' % + (self.dbconn), "testinvalid", "mssql") + self.assertTrue(vl.isValid()) + self.assertEqual(vl.dataProvider().extent().toString(1), 'Empty') + if __name__ == '__main__': unittest.main() diff --git a/tests/testdata/provider/testdata_mssql.sql b/tests/testdata/provider/testdata_mssql.sql index 46f4fee7365..2b2cfd9d02d 100644 --- a/tests/testdata/provider/testdata_mssql.sql +++ b/tests/testdata/provider/testdata_mssql.sql @@ -1,3 +1,27 @@ +DROP TABLE IF EXISTS qgis_test.[someData]; +GO + +DROP TABLE IF EXISTS qgis_test.[some_poly_data]; +GO + +DROP TABLE IF EXISTS qgis_test.[date_times]; +GO + +DROP TABLE IF EXISTS qgis_test.[new_table]; +GO + +DROP TABLE IF EXISTS qgis_test.[new_table_multipoint]; +GO + +DROP TABLE IF EXISTS qgis_test.[invalid_polys]; +GO + +DROP TABLE IF EXISTS qgis_test.[new_table_multipolygon]; +GO + +DROP SCHEMA qgis_test; +GO + CREATE SCHEMA qgis_test; GO @@ -68,6 +92,10 @@ SET IDENTITY_INSERT [qgis_test].[invalid_polys] ON GO INSERT [qgis_test].[invalid_polys] ([id], [ogr_geometry]) VALUES (258348, 0x47100000010408000000DC293B02AABE654008C8480AADC144C05C395D11AABE6540D81F66D1A9C144C0CC35D9FAAABE654050DD9A16AAC144C0ECCDD77BADBE6540506342CCA5C144C0E04E1598ADBE65402071DEEBA3C144C0B4DF72A6ADBE6540C8D4A2ADA6C144C088403273AABE6540982A29C1ACC144C0DC293B02AABE654008C8480AADC144C001000000020000000002000000FFFFFFFF0000000006000000000000000003) GO +INSERT [qgis_test].[invalid_polys] ([id], [ogr_geometry]) VALUES (1528836, 0x4710000001001000000074C8AF1AB9BE6540581FB97CFEC044C0381C2E23B9BE6540C8788F91FEC044C0582BE746B9BE654030831B3DFFC044C0281F717EB9BE6540A0DFEBFCFFC044C058C8128CB9BE6540686A1E2F00C144C034FF507FB9BE6540D881240000C144C004DAC298B9BE6540484FCF5D00C144C0846AC076B9BE654010E836F502C144C05CB8077CB9BE654008FA501103C144C0D07A3596B9BE6540F8FDA78A05C144C00CB48933B9BE6540F8555E9706C144C08C6D52D1B8BE65407010F7A207C144C0B0DE03CFB8BE654048AD41A907C144C0A0C97789B7BE654090F0A0200BC144C06845E570B7BE654000DD860703C144C074C8AF1AB9BE6540581FB97CFEC044C001000000020000000002000000FFFFFFFF0000000006000000000000000003) +GO +INSERT [qgis_test].[invalid_polys] ([id], [ogr_geometry]) VALUES (1528864, 0x47100000010016000000DCFADC15B9BE6540D0386351FEC044C0F4C5FCE1B9BE65406083B93BFDC044C0DCBD37E1B9BE654010BBAA44FDC044C0B80970DAB9BE654098B5BE8FFDC044C048AD4ED3B9BE654030D28BDAFDC044C0F4A0F7CBB9BE6540F06C3425FEC044C0184CB2C4B9BE654088890170FEC044C0C44D57C1B9BE65405016AD92FEC044C048C950BAB9BE6540008F9CDDFEC044C0C8444AB3B9BE654098AB6928FFC044C03C985EACB9BE654020A67D73FFC044C00CBCB1A5B9BE6540A8A091BEFFC044C03C474C9FB9BE65402079EC0900C144C0B4E96399B9BE65405055905500C144C004DAC298B9BE6540484FCF5D00C144C034FF507FB9BE6540D881240000C144C058C8128CB9BE6540686A1E2F00C144C0281F717EB9BE6540A0DFEBFCFFC044C0582BE746B9BE654030831B3DFFC044C0381C2E23B9BE6540C8788F91FEC044C074C8AF1AB9BE6540581FB97CFEC044C0DCFADC15B9BE6540D0386351FEC044C001000000020000000002000000FFFFFFFF0000000006000000000000000003) +GO INSERT [qgis_test].[invalid_polys] ([id], [ogr_geometry]) VALUES (3705263, 0x47100000010405000000988FB5D0DFBE6540284A2C3D9BC044C01CA53ED5E0BE654088FFC34999C044C05CEBA9DAE0BE6540C0D2596399C044C06C4C20D6DFBE6540889B9D569BC044C0988FB5D0DFBE6540284A2C3D9BC044C001000000020000000002000000FFFFFFFF0000000006000000000000000003) GO INSERT [qgis_test].[invalid_polys] ([id], [ogr_geometry]) VALUES (3705291, 0x4710000001040F000000548E7F55E4BE6540A829FDE264C144C020EEEA55E4BE654028F86D8871C144C070CF4E61E0BE65409052B34E6FC144C00037E6D0DDBE654010EECEDA6DC144C058433DD8DDBE6540588467E461C144C0FCF0EFDDDDBE654030241BA058C144C0309882DFDDBE6540A878C83956C144C0F458F6CEDFBE6540C8D7603F56C144C0A8B79AD0DFBE654070DC1DAA4DC144C0F82C3767E0BE654090203F624EC144C0180D0C65E0BE654058CC74545AC144C058868263E0BE65401045E86A62C144C07461495EE2BE65402873F84662C144C0EC955B55E4BE6540D8475D2162C144C0548E7F55E4BE6540A829FDE264C144C001000000020000000002000000FFFFFFFF0000000006000000000000000003) @@ -140,10 +168,6 @@ INSERT [qgis_test].[invalid_polys] ([id], [ogr_geometry]) VALUES (3705915, 0x471 GO INSERT [qgis_test].[invalid_polys] ([id], [ogr_geometry]) VALUES (3705938, 0x47100000010405000000748C75BBA8BE654098EF25FCAEC044C010A90134AEBE6540D816E36BABC044C0E4B4B40EAFBE65405095162BB3C044C0709E8FD7A8BE654048E5924FB4C044C0748C75BBA8BE654098EF25FCAEC044C001000000020000000002000000FFFFFFFF0000000006000000000000000003) GO -INSERT [qgis_test].[invalid_polys] ([id], [ogr_geometry]) VALUES (6528836, 0x4710000001001000000074C8AF1AB9BE6540581FB97CFEC044C0381C2E23B9BE6540C8788F91FEC044C0582BE746B9BE654030831B3DFFC044C0281F717EB9BE6540A0DFEBFCFFC044C058C8128CB9BE6540686A1E2F00C144C034FF507FB9BE6540D881240000C144C004DAC298B9BE6540484FCF5D00C144C0846AC076B9BE654010E836F502C144C05CB8077CB9BE654008FA501103C144C0D07A3596B9BE6540F8FDA78A05C144C00CB48933B9BE6540F8555E9706C144C08C6D52D1B8BE65407010F7A207C144C0B0DE03CFB8BE654048AD41A907C144C0A0C97789B7BE654090F0A0200BC144C06845E570B7BE654000DD860703C144C074C8AF1AB9BE6540581FB97CFEC044C001000000020000000002000000FFFFFFFF0000000006000000000000000003) -GO -INSERT [qgis_test].[invalid_polys] ([id], [ogr_geometry]) VALUES (6528864, 0x47100000010016000000DCFADC15B9BE6540D0386351FEC044C0F4C5FCE1B9BE65406083B93BFDC044C0DCBD37E1B9BE654010BBAA44FDC044C0B80970DAB9BE654098B5BE8FFDC044C048AD4ED3B9BE654030D28BDAFDC044C0F4A0F7CBB9BE6540F06C3425FEC044C0184CB2C4B9BE654088890170FEC044C0C44D57C1B9BE65405016AD92FEC044C048C950BAB9BE6540008F9CDDFEC044C0C8444AB3B9BE654098AB6928FFC044C03C985EACB9BE654020A67D73FFC044C00CBCB1A5B9BE6540A8A091BEFFC044C03C474C9FB9BE65402079EC0900C144C0B4E96399B9BE65405055905500C144C004DAC298B9BE6540484FCF5D00C144C034FF507FB9BE6540D881240000C144C058C8128CB9BE6540686A1E2F00C144C0281F717EB9BE6540A0DFEBFCFFC044C0582BE746B9BE654030831B3DFFC044C0381C2E23B9BE6540C8788F91FEC044C074C8AF1AB9BE6540581FB97CFEC044C0DCFADC15B9BE6540D0386351FEC044C001000000020000000002000000FFFFFFFF0000000006000000000000000003) -GO SET IDENTITY_INSERT [qgis_test].[invalid_polys] OFF GO