Skip to content

Commit

Permalink
Fix: HANA mixes up attribute fields by import
Browse files Browse the repository at this point in the history
  • Loading branch information
mrylov authored and nyalldawson committed May 17, 2021
1 parent d94b60a commit 85b1a87
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 9 deletions.
17 changes: 8 additions & 9 deletions src/providers/hana/qgshanaprovider.cpp
Expand Up @@ -1409,7 +1409,10 @@ void QgsHanaProvider::readAttributeFields( QgsHanaConnection &conn )
void QgsHanaProvider::readGeometryType( QgsHanaConnection &conn )
{
if ( mGeometryColumn.isNull() || mGeometryColumn.isEmpty() )
{
mDetectedGeometryType = QgsWkbTypes::NoGeometry;
return;
}

if ( mIsQuery )
{
Expand Down Expand Up @@ -1705,18 +1708,12 @@ QgsVectorLayerExporter::ExportError QgsHanaProvider::createEmptyLayer(

if ( fields.size() > 0 )
{
int offset = ( fields.indexFromName( primaryKey ) >= 0 ) ? 1 : 0;

// if we create a new primary key column, we start the old columns from 1
int offset = ( fields.indexFromName( primaryKey ) >= 0 ) ? 0 : 1;
QList<QgsField> flist;
for ( int i = 0, n = fields.size(); i < n; ++i )
{
QgsField fld = fields.at( i );
if ( oldToNewAttrIdxMap && fld.name() == primaryKey )
{
oldToNewAttrIdxMap->insert( fields.lookupField( fld.name() ), 0 );
continue;
}

if ( fld.name() == geometryColumn )
continue;

Expand All @@ -1728,7 +1725,9 @@ QgsVectorLayerExporter::ExportError QgsHanaProvider::createEmptyLayer(
return QgsVectorLayerExporter::ErrAttributeTypeUnsupported;
}

flist.append( fld );
if ( fld.name() != primaryKey )
flist.append( fld );

if ( oldToNewAttrIdxMap )
oldToNewAttrIdxMap->insert( fields.lookupField( fld.name() ), offset++ );
}
Expand Down
8 changes: 8 additions & 0 deletions tests/src/python/test_hana_utils.py
Expand Up @@ -63,6 +63,14 @@ def createAndFillTable(conn, create_statement, insert_statement, insert_args):
QgsHanaProviderUtils.executeSQL(conn, create_statement)
QgsHanaProviderUtils.executeSQLMany(conn, insert_statement, insert_args)

@staticmethod
def dropTableIfExists(conn, schema_name, table_name):
res = QgsHanaProviderUtils.executeSQLFetchOne(conn,
f"SELECT COUNT(*) FROM SYS.TABLES WHERE "
f"SCHEMA_NAME='{schema_name}' AND TABLE_NAME='{table_name}'")
if res != 0:
QgsHanaProviderUtils.executeSQL(conn, f'DROP TABLE "{schema_name}"."{table_name}" CASCADE')

@staticmethod
def dropSchemaIfExists(conn, schema_name):
res = QgsHanaProviderUtils.executeSQLFetchOne(conn,
Expand Down
64 changes: 64 additions & 0 deletions tests/src/python/test_provider_hana.py
Expand Up @@ -27,11 +27,16 @@
QgsDataSourceUri,
QgsFeatureRequest,
QgsFeature,
QgsField,
QgsFieldConstraints,
QgsGeometry,
QgsPointXY,
QgsProviderRegistry,
QgsRectangle,
QgsSettings,
QgsVectorDataProvider,
QgsVectorLayer,
QgsVectorLayerExporter,
QgsWkbTypes)
from qgis.testing import start_app, unittest
from test_hana_utils import QgsHanaProviderUtils
Expand Down Expand Up @@ -442,6 +447,65 @@ def testGeometryAttributes(self):
values = {feat['ID']: feat['GEOM2'] for feat in vl.getFeatures()}
self.assertEqual(values, {1: 'LINESTRING (0 0,2 2)'})

def testCreateLayerViaExport(self):
def runTest(self, primaryKey, attributeNames, attributeValues):
layer = QgsVectorLayer("Point?", "new_table", "memory")
pr = layer.dataProvider()

fields = [QgsField("fldid", QVariant.LongLong),
QgsField("fldtxt", QVariant.String),
QgsField("fldint", QVariant.Int)]

if primaryKey == "fldid":
constraints = QgsFieldConstraints()
constraints.setConstraint(QgsFieldConstraints.ConstraintNotNull,
QgsFieldConstraints.ConstraintOriginProvider)
constraints.setConstraint(QgsFieldConstraints.ConstraintUnique,
QgsFieldConstraints.ConstraintOriginProvider)
fields[0].setConstraints(constraints)

layer.startEditing()
for f in fields:
layer.addAttribute(f)
layer.commitChanges(True)

f1 = QgsFeature()
f1.setAttributes([1, "test", 11])
f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2)))
f2 = QgsFeature()
f2.setAttributes([2, "test2", 13])
f3 = QgsFeature()
f3.setAttributes([3, "test2", NULL])
f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(3, 2)))
f4 = QgsFeature()
f4.setAttributes([4, NULL, 13])
f4.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(4, 3)))
pr.addFeatures([f1, f2, f3, f4])
layer.commitChanges()

QgsHanaProviderUtils.dropTableIfExists(self.conn, self.schemaName, 'import_data')
uri = self.uri + f' key=\'{primaryKey}\' table="{self.schemaName}"."import_data" (geom) sql='
error, message = QgsVectorLayerExporter.exportLayer(layer, uri, 'hana',
QgsCoordinateReferenceSystem('EPSG:4326'))
self.assertEqual(error, QgsVectorLayerExporter.NoError)

import_layer = self.createVectorLayer(
f'key=\'{primaryKey}\' table="{self.schemaName}"."import_data" (geom) sql=', 'testimportedlayer')
self.assertEqual(import_layer.wkbType(), QgsWkbTypes.Point)
self.assertEqual([f.name() for f in import_layer.fields()], attributeNames)

features = [f.attributes() for f in import_layer.getFeatures()]
self.assertEqual(features, attributeValues)
geom = [f.geometry().asWkt() for f in import_layer.getFeatures()]
self.assertEqual(geom, ['Point (1 2)', '', 'Point (3 2)', 'Point (4 3)'])

# primary key already exists in the imported layer
runTest(self, 'fldid', ['fldid', 'fldtxt', 'fldint'], [[1, 'test', 11], [2, 'test2', 13],
[3, 'test2', NULL], [4, NULL, 13]])
# primary key doesn't exist in the imported layer
runTest(self, 'pk', ['pk', 'fldid', 'fldtxt', 'fldint'], [[1, 1, 'test', 11], [2, 2, 'test2', 13],
[3, 3, 'test2', NULL], [4, 4, NULL, 13]])

def testFilterRectOutsideSrsExtent(self):
"""Test filterRect which partially lies outside of the srs extent"""
self.source.setSubsetString(None)
Expand Down

0 comments on commit 85b1a87

Please sign in to comment.