Skip to content
Permalink
Browse files

[Oracle] Fix create layer with lowercase and large field names

  • Loading branch information
troopa81 authored and nyalldawson committed Feb 19, 2021
1 parent b1067af commit 1ffbb78a5c58620bbe8c991528006ce2a36531a9
@@ -139,6 +139,13 @@ QgsVectorLayerExporter::QgsVectorLayerExporter( const QString &uri,
}
}

// Oracle specific HACK: we cannot guess the geometry type when there is no rows, so we need
// to force it in the uri
if ( providerKey == QLatin1String( "oracle" ) )
{
uriUpdated += QStringLiteral( " type=%1" ).arg( QgsWkbTypes::displayString( geometryType ) );
}

QgsDataProvider::ProviderOptions providerOptions;
QgsVectorDataProvider *vectorProvider = qobject_cast< QgsVectorDataProvider * >( pReg->createProvider( providerKey, uriUpdated, providerOptions ) );
if ( !vectorProvider || !vectorProvider->isValid() || ( vectorProvider->capabilities() & QgsVectorDataProvider::AddFeatures ) == 0 )
@@ -3091,6 +3091,9 @@ QgsVectorLayerExporter::ExportError QgsOracleProvider::createEmptyLayer(
// use the provider to edit the table1
dsUri.setDataSource( ownerName, tableName, geometryColumn, QString(), primaryKey );

// provider cannot guess the type when there is no feature, so force the wkbtype in the uri
dsUri.setWkbType( wkbType );

QgsDataProvider::ProviderOptions providerOptions;
std::unique_ptr<QgsOracleProvider> provider( new QgsOracleProvider( dsUri.uri( false ), providerOptions ) );
if ( !provider->isValid() )
@@ -3114,7 +3117,7 @@ QgsVectorLayerExporter::ExportError QgsOracleProvider::createEmptyLayer(
{
QgsField fld = fields.at( i );

QString name = fld.name().left( 30 ).toUpper();
QString name = fld.name();

if ( names.contains( name ) )
{
@@ -3268,6 +3271,10 @@ void QgsOracleProvider::insertGeomMetadata( QgsOracleConn *conn, const QString &
}
}

if ( tableName.toUpper() != tableName || geometryColumn.toUpper() != geometryColumn )
throw OracleException( tr( "Cannot insert geometry metadata for table '%1' and geometry column '%2'. Both needs to be uppercase" ).arg(
tableName, geometryColumn ), qry );

if ( !exec( qry, QStringLiteral( "INSERT INTO mdsys.user_sdo_geom_metadata(table_name,column_name,srid,diminfo) VALUES (?,?,?,%1)" ).arg( diminfo ),
QVariantList() << tableName.toUpper() << geometryColumn.toUpper() << srid ) )
{
@@ -951,6 +951,69 @@ def countFeature(table_name):
self.assertTrue(vl.dataProvider().addFeatures([feature])[0])
self.assertEqual(countFeature('EMPTYFEATURE_NOGEOM_LAYER'), 1)

def testCreateLayerLongFieldNames(self):
"""
Test to create an empty layer with long field names
"""

# cleanup (it seems overwrite option doesn't clean the sdo_geom_metadata table)
self.execSQLCommand('DROP TABLE "QGIS"."LONGFIELD_LAYER"', ignore_errors=True)

long_name = "this_is_a_very_long_field_name_more_than_30_characters"

fields = QgsFields()
fields.append(QgsField(long_name, QVariant.Int))

uri = self.dbconn + "table=\"LONGFIELD_LAYER\""
exporter = QgsVectorLayerExporter(uri=uri, provider='oracle', fields=fields, geometryType=QgsWkbTypes.Point, crs=QgsCoordinateReferenceSystem("EPSG:4326"), overwrite=True)
self.assertEqual(exporter.errorCount(), 0)
self.assertEqual(exporter.errorCode(), 0)

self.execSQLCommand('SELECT count(*) FROM "QGIS"."LONGFIELD_LAYER"')
vl = QgsVectorLayer(self.dbconn + ' sslmode=disable table="QGIS"."LONGFIELD_LAYER" sql=', 'test', 'oracle')
self.assertTrue(vl.isValid())

self.assertEqual(vl.fields().names(), [long_name])

def testCreateGeomLowercase(self):
"""
Test to create an empty layer with either table or geometry column in lower case. It has to fail
"""

# table is lower case -> fails
self.execSQLCommand('DROP TABLE "QGIS"."lowercase_layer"', ignore_errors=True)

fields = QgsFields()
fields.append(QgsField("test", QVariant.Int))

uri = self.dbconn + "table=\"lowercase_layer\" (GEOM)"
exporter = QgsVectorLayerExporter(uri=uri, provider='oracle', fields=fields, geometryType=QgsWkbTypes.Point, crs=QgsCoordinateReferenceSystem("EPSG:4326"), overwrite=True)
self.assertEqual(exporter.errorCode(), 2)

# geom column is lower case -> fails
self.execSQLCommand('DROP TABLE "QGIS"."LOWERCASEGEOM_LAYER"', ignore_errors=True)

fields = QgsFields()
fields.append(QgsField("test", QVariant.Int))

uri = self.dbconn + "table=\"LOWERCASEGEOM\" (geom)"
exporter = QgsVectorLayerExporter(uri=uri, provider='oracle', fields=fields, geometryType=QgsWkbTypes.Point, crs=QgsCoordinateReferenceSystem("EPSG:4326"), overwrite=True)
self.assertEqual(exporter.errorCode(), 2)

# table and geom column are uppercase -> success
self.execSQLCommand('DROP TABLE "QGIS"."UPPERCASEGEOM_LAYER"', ignore_errors=True)
self.execSQLCommand("""DELETE FROM user_sdo_geom_metadata where TABLE_NAME = 'UPPERCASEGEOM_LAYER'""")

fields = QgsFields()
fields.append(QgsField("test", QVariant.Int))

uri = self.dbconn + "table=\"UPPERCASEGEOM_LAYER\" (GEOM)"

exporter = QgsVectorLayerExporter(uri=uri, provider='oracle', fields=fields, geometryType=QgsWkbTypes.Point, crs=QgsCoordinateReferenceSystem("EPSG:4326"), overwrite=True)
print(exporter.errorMessage())
self.assertEqual(exporter.errorCount(), 0)
self.assertEqual(exporter.errorCode(), 0)


if __name__ == '__main__':
unittest.main()

0 comments on commit 1ffbb78

Please sign in to comment.