Skip to content

Commit 381c8b6

Browse files
authored
Merge pull request #5225 from manisandro/ogr_gdb_subset218
[OGR] Add workaround for OGRSQL not recognizing the column name returned by OGR_L_GetFIDColumn
2 parents da22be6 + a51ef7d commit 381c8b6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+76
-27
lines changed

src/providers/ogr/qgsogrfeatureiterator.cpp

+14-9
Original file line numberDiff line numberDiff line change
@@ -172,23 +172,28 @@ bool QgsOgrFeatureIterator::nextFeatureFilterExpression( QgsFeature& f )
172172
bool QgsOgrFeatureIterator::fetchFeatureWithId( QgsFeatureId id, QgsFeature& feature ) const
173173
{
174174
feature.setValid( false );
175-
OGRFeatureH fet;
175+
OGRFeatureH fet = 0;
176176
if ( mOrigFidAdded )
177177
{
178178
OGR_L_ResetReading( ogrLayer );
179-
while (( fet = OGR_L_GetNextFeature( ogrLayer ) ) )
179+
OGRFeatureDefnH fdef = OGR_L_GetLayerDefn( ogrLayer );
180+
int lastField = OGR_FD_GetFieldCount( fdef ) - 1;
181+
if ( lastField >= 0 )
180182
{
181-
if (
183+
while (( fet = OGR_L_GetNextFeature( ogrLayer ) ) )
184+
{
185+
if (
182186
#if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 2000000
183-
OGR_F_GetFieldAsInteger64
187+
OGR_F_GetFieldAsInteger64
184188
#else
185-
OGR_F_GetFieldAsInteger
189+
OGR_F_GetFieldAsInteger
186190
#endif
187-
( fet, 0 ) == FID_TO_NUMBER( id ) )
188-
{
189-
break;
191+
( fet, lastField ) == FID_TO_NUMBER( id ) )
192+
{
193+
break;
194+
}
195+
OGR_F_Destroy( fet );
190196
}
191-
OGR_F_Destroy( fet );
192197
}
193198
}
194199
else

src/providers/ogr/qgsogrprovider.cpp

+41-15
Original file line numberDiff line numberDiff line change
@@ -3443,33 +3443,59 @@ OGRLayerH QgsOgrProviderUtils::setSubsetString( OGRLayerH layer, OGRDataSourceH
34433443
layerName = encoding->fromUnicode( modifiedLayerName );
34443444
}
34453445
}
3446-
QByteArray sql;
3447-
if ( subsetString.startsWith( "SELECT ", Qt::CaseInsensitive ) )
3448-
sql = encoding->fromUnicode( subsetString );
3446+
OGRLayerH subsetLayer = 0;
3447+
if ( subsetString.startsWith( QLatin1String( "SELECT " ), Qt::CaseInsensitive ) )
3448+
{
3449+
QByteArray sql = encoding->fromUnicode( subsetString );
3450+
3451+
QgsDebugMsg( QString( "SQL: %1" ).arg( encoding->toUnicode( sql ) ) );
3452+
subsetLayer = GDALDatasetExecuteSQL( ds, sql.constData(), nullptr, nullptr );
3453+
}
34493454
else
34503455
{
3456+
QByteArray sqlPart1 = "SELECT *";
3457+
QByteArray sqlPart3 = " FROM " + quotedIdentifier( layerName, ogrDriverName )
3458+
+ " WHERE " + encoding->fromUnicode( subsetString );
3459+
3460+
origFidAddAttempted = true;
3461+
34513462
QByteArray fidColumn = OGR_L_GetFIDColumn( layer );
3463+
// Fallback to FID if OGR_L_GetFIDColumn returns nothing
3464+
if ( fidColumn.isEmpty() )
3465+
{
3466+
fidColumn = "FID";
3467+
}
3468+
3469+
QByteArray sql = sqlPart1 + ", " + fidColumn + " as orig_ogc_fid" + sqlPart3;
3470+
QgsDebugMsg( QString( "SQL: %1" ).arg( encoding->toUnicode( sql ) ) );
3471+
subsetLayer = GDALDatasetExecuteSQL( ds, sql.constData(), nullptr, nullptr );
34523472

3453-
sql = QByteArray( "SELECT " );
3454-
if ( !fidColumn.isEmpty() )
3473+
// See https://lists.osgeo.org/pipermail/qgis-developer/2017-September/049802.html
3474+
// If execute SQL fails because it did not find the fidColumn, retry with hardcoded FID
3475+
if ( !subsetLayer )
34553476
{
3456-
sql += fidColumn + " as orig_ogc_fid, ";
3457-
origFidAddAttempted = true;
3477+
QByteArray sql = sqlPart1 + ", " + "FID as orig_ogc_fid" + sqlPart3;
3478+
QgsDebugMsg( QString( "SQL: %1" ).arg( encoding->toUnicode( sql ) ) );
3479+
subsetLayer = GDALDatasetExecuteSQL( ds, sql.constData(), nullptr, nullptr );
3480+
}
3481+
// If that also fails, just continue without the orig_ogc_fid
3482+
if ( !subsetLayer )
3483+
{
3484+
QByteArray sql = sqlPart1 + sqlPart3;
3485+
QgsDebugMsg( QString( "SQL: %1" ).arg( encoding->toUnicode( sql ) ) );
3486+
subsetLayer = GDALDatasetExecuteSQL( ds, sql.constData(), nullptr, nullptr );
3487+
origFidAddAttempted = false;
34583488
}
3459-
sql += "* FROM " + quotedIdentifier( layerName, ogrDriverName );
3460-
sql += " WHERE " + encoding->fromUnicode( subsetString );
34613489
}
34623490

3463-
QgsDebugMsg( QString( "SQL: %1" ).arg( encoding->toUnicode( sql ) ) );
3464-
OGRLayerH subsetLayer = OGR_DS_ExecuteSQL( ds, sql.constData(), nullptr, nullptr );
3465-
3466-
// Check if first column is orig_ogc_fid
3491+
// Check if last column is orig_ogc_fid
34673492
if ( origFidAddAttempted && subsetLayer )
34683493
{
34693494
OGRFeatureDefnH fdef = OGR_L_GetLayerDefn( subsetLayer );
3470-
if ( OGR_FD_GetFieldCount( fdef ) > 0 )
3495+
int fieldCount = OGR_FD_GetFieldCount( fdef );
3496+
if ( fieldCount > 0 )
34713497
{
3472-
OGRFieldDefnH fldDef = OGR_FD_GetFieldDefn( fdef, 0 );
3498+
OGRFieldDefnH fldDef = OGR_FD_GetFieldDefn( fdef, fieldCount - 1 );
34733499
origFidAdded = qstrcmp( OGR_Fld_GetNameRef( fldDef ), "orig_ogc_fid" ) == 0;
34743500
}
34753501
}

tests/src/python/test_provider_ogr.py

+19-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import sys
1818
import tempfile
1919

20-
from qgis.core import QgsVectorLayer, QgsVectorDataProvider, QgsWKBTypes
20+
from qgis.core import QgsVectorLayer, QgsVectorDataProvider, QgsWKBTypes, QgsFeature
2121
from qgis.testing import (
2222
start_app,
2323
unittest
@@ -240,5 +240,23 @@ def testGeometryCollection(self):
240240
os.unlink(datasource)
241241
self.assertFalse(os.path.exists(datasource))
242242

243+
def testGdb(self):
244+
""" Test opening a GDB database layer"""
245+
gdb_path = os.path.join(unitTestDataPath(), 'test_gdb.gdb')
246+
for i in range(3):
247+
l = QgsVectorLayer(gdb_path + '|layerid=' + str(i), 'test', 'ogr')
248+
self.assertTrue(l.isValid())
249+
250+
def testGdbFilter(self):
251+
""" Test opening a GDB database layer with filter"""
252+
gdb_path = os.path.join(unitTestDataPath(), 'test_gdb.gdb')
253+
l = QgsVectorLayer(gdb_path + '|layerid=1|subset="text" = \'shape 2\'', 'test', 'ogr')
254+
self.assertTrue(l.isValid())
255+
it = l.getFeatures()
256+
f = QgsFeature()
257+
while it.nextFeature(f):
258+
self.assertTrue(f.attribute("text") == "shape 2")
259+
260+
243261
if __name__ == '__main__':
244262
unittest.main()

tests/src/python/test_provider_ogr_sqlite.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ def testSubsetStringFids(self):
175175

176176
vl = QgsVectorLayer(tmpfile + "|subset=type=2", 'test', 'ogr')
177177
self.assertTrue(vl.isValid())
178-
self.assertTrue(vl.fields().at(0).name() == "orig_ogc_fid")
178+
self.assertTrue(vl.fields().at(vl.fields().count() - 1).name() == "orig_ogc_fid")
179179

180180
req = QgsFeatureRequest()
181181
req.setFilterExpression("value=16")
@@ -186,7 +186,7 @@ def testSubsetStringFids(self):
186186

187187
# Check that subset string is correctly set on reload
188188
vl.reload()
189-
self.assertTrue(vl.fields().at(0).name() == "orig_ogc_fid")
189+
self.assertTrue(vl.fields().at(vl.fields().count() - 1).name() == "orig_ogc_fid")
190190

191191

192192
if __name__ == '__main__':
Binary file not shown.
110 Bytes
Binary file not shown.
345 Bytes
Binary file not shown.
5.03 KB
Binary file not shown.
2.01 KB
Binary file not shown.
5.03 KB
Binary file not shown.
42 Bytes
Binary file not shown.
758 Bytes
Binary file not shown.
5.03 KB
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
310 Bytes
Binary file not shown.
12.6 KB
Binary file not shown.
5.03 KB
Binary file not shown.
4.02 KB
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
296 Bytes
Binary file not shown.
1.76 KB
Binary file not shown.
5.03 KB
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
318 Bytes
Binary file not shown.
409 Bytes
Binary file not shown.
5.03 KB
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
602 Bytes
Binary file not shown.
2.45 KB
Binary file not shown.
5.03 KB
Binary file not shown.
116 Bytes
Binary file not shown.
833 Bytes
Binary file not shown.
5.03 KB
Binary file not shown.
4.02 KB
Binary file not shown.
116 Bytes
Binary file not shown.
793 Bytes
Binary file not shown.
5.03 KB
Binary file not shown.
4.02 KB
Binary file not shown.
116 Bytes
Binary file not shown.
662 Bytes
Binary file not shown.
5.03 KB
Binary file not shown.
4.02 KB
Binary file not shown.

tests/testdata/test_gdb.gdb/gdb

4 Bytes
Binary file not shown.
400 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)