Skip to content

Commit

Permalink
[mssql] Fix handling of geometry column when multiple geometry/geography
Browse files Browse the repository at this point in the history
columns are present

Fixes #13932
  • Loading branch information
nyalldawson committed Oct 8, 2018
1 parent 71c5051 commit da21193
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 9 deletions.
21 changes: 13 additions & 8 deletions src/providers/mssql/qgsmssqlprovider.cpp
Expand Up @@ -338,10 +338,15 @@ void QgsMssqlProvider::loadFields()
QStringList pkCandidates;
while ( query.next() )
{
QString sqlTypeName = query.value( 5 ).toString();
if ( sqlTypeName == QLatin1String( "geometry" ) || sqlTypeName == QLatin1String( "geography" ) )
const QString colName = query.value( 3 ).toString();
const QString sqlTypeName = query.value( 5 ).toString();

// if we don't have an explicitly set geometry column name, and this is a geometry column, then use it
// but if we DO have an explicitly set geometry column name, then load the other information if this is that column
if ( ( mGeometryColName.isEmpty() && ( sqlTypeName == QLatin1String( "geometry" ) || sqlTypeName == QLatin1String( "geography" ) ) )
|| colName == mGeometryColName )
{
mGeometryColName = query.value( 3 ).toString();
mGeometryColName = colName;
mGeometryColType = sqlTypeName;
mParser.IsGeography = sqlTypeName == QLatin1String( "geography" );
}
Expand All @@ -350,7 +355,7 @@ void QgsMssqlProvider::loadFields()
QVariant::Type sqlType = DecodeSqlType( sqlTypeName );
if ( sqlTypeName == QLatin1String( "int identity" ) || sqlTypeName == QLatin1String( "bigint identity" ) )
{
mFidColName = query.value( 3 ).toString();
mFidColName = colName;
isIdentity = true;
}
else if ( sqlTypeName == QLatin1String( "int" ) || sqlTypeName == QLatin1String( "bigint" ) )
Expand All @@ -368,15 +373,15 @@ void QgsMssqlProvider::loadFields()
}
mAttributeFields.append(
QgsField(
query.value( 3 ).toString(), sqlType,
colName, sqlType,
sqlTypeName,
length ) );
}
else if ( sqlType == QVariant::Double )
{
mAttributeFields.append(
QgsField(
query.value( 3 ).toString(), sqlType,
colName, sqlType,
sqlTypeName,
query.value( 6 ).toInt(),
sqlTypeName == QLatin1String( "decimal" ) ? query.value( 8 ).toInt() : -1 ) );
Expand All @@ -385,7 +390,7 @@ void QgsMssqlProvider::loadFields()
{
mAttributeFields.append(
QgsField(
query.value( 3 ).toString(), sqlType,
colName, sqlType,
sqlTypeName,
-1,
-1 ) );
Expand All @@ -394,7 +399,7 @@ void QgsMssqlProvider::loadFields()
{
mAttributeFields.append(
QgsField(
query.value( 3 ).toString(), sqlType,
colName, sqlType,
sqlTypeName ) );
}

Expand Down
15 changes: 15 additions & 0 deletions tests/src/python/test_provider_mssql.py
Expand Up @@ -298,6 +298,21 @@ def testInsertPolygonInMultiPolygon(self):
geom = [f.geometry().asWkt() for f in new_layer.getFeatures()]
self.assertEqual(geom, ['MultiPolygon (((0 0, 1 0, 1 1, 0 1, 0 0)),((10 0, 11 0, 11 1, 10 1, 10 0)))', 'MultiPolygon (((30 0, 31 0, 31 1, 30 1, 30 0)))'])

def testMultiGeomColumns(self):
uri = '{} table="qgis_test"."multiGeomColumns" (geom1) sql='.format(self.dbconn)
new_layer = QgsVectorLayer(uri, 'new', 'mssql')
self.assertTrue(new_layer.isValid())

geom = {f[0]: f.geometry().asWkt() for f in new_layer.getFeatures()}
self.assertEqual(geom, {1: 'Point (2 3)', 2: 'Point (3 4)', 3: '', 4: 'Point (5 6)', 5: 'Point (1 2)'})

uri = '{} table="qgis_test"."multiGeomColumns" (geom2) sql='.format(self.dbconn)
new_layer2 = QgsVectorLayer(uri, 'new', 'mssql')
self.assertTrue(new_layer2.isValid())

geom = {f[0]: f.geometry().asWkt() for f in new_layer2.getFeatures()}
self.assertEqual(geom, {1: 'LineString (2 3, 4 5)', 2: 'LineString (3 4, 5 6)', 3: 'LineString (1 2, 3 4)', 4: 'LineString (5 6, 7 8)', 5: ''})

def testInvalidGeometries(self):
""" 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=' %
Expand Down
19 changes: 18 additions & 1 deletion tests/testdata/provider/testdata_mssql.sql
Expand Up @@ -22,6 +22,9 @@ GO
DROP TABLE IF EXISTS qgis_test.[float_dec];
GO

DROP TABLE IF EXISTS qgis_test.[multiGeomColumns];
GO

DROP SCHEMA qgis_test;
GO

Expand Down Expand Up @@ -59,6 +62,13 @@ CREATE TABLE qgis_test.[float_dec] (
);
GO

CREATE TABLE qgis_test.[multiGeomColumns] (
pk integer PRIMARY KEY,
geom1 geometry,
geom2 geometry
);
GO

INSERT INTO qgis_test.[someData] (pk, cnt, name, name2, num_char, geom) VALUES
(5, -200, NULL, 'NuLl', '5', geometry::STGeomFromText( 'Point(-71.123 78.23)', 4326 )),
(3, 300, 'Pear', 'PEaR', '3', NULL),
Expand All @@ -83,7 +93,14 @@ INSERT INTO qgis_test.[float_dec] (id, float_field, dec_field ) VALUES
(1, 1.1111111111, 1.123 );
GO


INSERT INTO qgis_test.[multiGeomColumns] (pk, geom1, geom2) VALUES
(5, geometry::STGeomFromText( 'Point( 1 2 )', 4326 ), NULL),
(3, NULL, geometry::STGeomFromText( 'LineString( 1 2, 3 4 )', 4326 )),
(1, geometry::STGeomFromText( 'Point( 2 3 )', 4326 ), geometry::STGeomFromText( 'LineString( 2 3, 4 5 )', 4326 )),
(2, geometry::STGeomFromText( 'Point( 3 4 )', 4326 ), geometry::STGeomFromText( 'LineString( 3 4, 5 6 )', 4326 )),
(4, geometry::STGeomFromText( 'Point( 5 6 )', 4326 ), geometry::STGeomFromText( 'LineString( 5 6, 7 8 )', 4326 ))
;
GO

/** Contains invalid polygons **/
SET ANSI_NULLS ON
Expand Down

0 comments on commit da21193

Please sign in to comment.