PG raster: support mosaics with no metadata

Fixes #39017
This commit is contained in:
Alessandro Pasotti 2020-09-25 15:16:34 +02:00 committed by Nyall Dawson
parent 9953570e30
commit 84e204954f
3 changed files with 72 additions and 9 deletions

View File

@ -1221,10 +1221,7 @@ bool QgsPostgresRasterProvider::init()
where = QStringLiteral( "WHERE %1" ).arg( subsetString() );
}
// If we dropped here from the fast track because there was something wrong reading metadata
// we can safely assume that the raster is NOT tiled and add LIMIT 1 in the query below to
// speed things up.
// Unfortunately we cannot safely assume that the raster is untiled and just LIMIT 1
// Fastest SQL: fetch all metadata in one pass
// 0 1 3 3 4 5 6 7 8 9 10 11 12 13 14
// encode | upperleftx | upperlefty | width | height | scalex | scaley | skewx | skewy | srid | numbands | pixeltype | nodatavalue | isoutdb | path
@ -1237,9 +1234,7 @@ bool QgsPostgresRasterProvider::init()
(ST_Metadata( band )).*,
(ST_BandMetadata( band )).*
FROM cte_band
)" ).arg( quotedIdentifier( mRasterColumn ),
tableToQuery,
where.isEmpty() &&mUseEstimatedMetadata ? QStringLiteral( "LIMIT 1" ) : where ) };
)" ).arg( quotedIdentifier( mRasterColumn ), tableToQuery, where ) };
QgsDebugMsgLevel( QStringLiteral( "Raster information sql: %1" ).arg( sql ), 4 );

View File

@ -80,6 +80,7 @@ class TestPyQgsPostgresRasterProvider(unittest.TestCase):
cls._load_test_table(
'public', 'int16_regression_36689', 'bug_36689_pg_raster')
cls._load_test_table('public', 'bug_37968_dem_linear_cdn_extract')
cls._load_test_table('public', 'bug_39017_untiled_no_metadata')
# Fix timing issues in backend
# time.sleep(1)
@ -493,8 +494,8 @@ class TestPyQgsPostgresRasterProvider(unittest.TestCase):
table='bug_37968_dem_linear_cdn_extract', schema='public'), 'pg_layer', 'postgresraster')
self.assertTrue(rl.isValid())
compareWkt(rl.extent().asWktPolygon(
), 'POLYGON((-40953.223387096 170588, -40873.21532258 170588, -40873.21532258 170668, -40953.223387096 170668, -40953.23387096))')
self.assertTrue(compareWkt(rl.extent().asWktPolygon(
), 'POLYGON((-40953 170588, -40873 170588, -40873 170668, -40953 170668, -40953 170588))', 1))
block = rl.dataProvider().block(1, rl.extent(), 6, 6)
data = []
for i in range(6):
@ -503,6 +504,57 @@ class TestPyQgsPostgresRasterProvider(unittest.TestCase):
self.assertEqual(data, [52, 52, 52, 52, 44, 43, 52, 52, 52, 48, 44, 44, 49, 52, 49, 44, 44, 44, 43, 47, 46, 44, 44, 44, 42, 42, 43, 44, 44, 48, 42, 43, 43, 44, 44, 47])
def testUntiledMosaicNoMetadata(self):
"""Test regression https://github.com/qgis/QGIS/issues/39017
+-----------+------------------------------+
| | |
| rid = 1 | rid = 2 |
| | |
+-----------+------------------------------+
"""
rl = QgsRasterLayer(
self.dbconn + " sslmode=disable table={table} schema={schema}".format(
table='bug_39017_untiled_no_metadata', schema='public'), 'pg_layer', 'postgresraster')
self.assertTrue(rl.isValid())
self.assertTrue(compareWkt(rl.extent().asWktPolygon(
), 'POLYGON((47.061 40.976, 47.123 40.976, 47.123 41.000, 47.061 41.000, 47.061 40.976))', 0.01))
rl1 = QgsRasterLayer(
self.dbconn + " sslmode=disable table={table} schema={schema} sql=\"rid\"=1".format(
table='bug_39017_untiled_no_metadata', schema='public'), 'pg_layer', 'postgresraster')
self.assertTrue(rl1.isValid())
self.assertTrue(compareWkt(rl1.extent().asWktPolygon(
), 'POLYGON((47.061 40.976, 47.070 40.976, 47.070 41.000, 47.061 41.000, 47.061 40.976))', 0.01))
rl2 = QgsRasterLayer(
self.dbconn + " sslmode=disable table={table} schema={schema} sql=\"rid\"=2".format(
table='bug_39017_untiled_no_metadata', schema='public'), 'pg_layer', 'postgresraster')
self.assertTrue(rl2.isValid())
self.assertTrue(compareWkt(rl2.extent().asWktPolygon(
), 'POLYGON((47.061 40.976, 47.123 40.976, 47.123 41.000, 47.070 41.000, 47.070 40.976))', 0.01))
extent_1 = rl1.extent()
extent_2 = rl2.extent()
def _6x6_block_data(layer, extent):
block = layer.dataProvider().block(1, extent, 6, 6)
data = []
for i in range(6):
for j in range(6):
data.append(int(block.value(i, j)))
return data
rl_r1 = _6x6_block_data(rl, extent_1)
r1_r1 = _6x6_block_data(rl1, extent_1)
self.assertEqual(rl_r1, r1_r1)
rl_r2 = _6x6_block_data(rl, extent_2)
r2_r2 = _6x6_block_data(rl2, extent_2)
self.assertEqual(rl_r2, r2_r2)
if __name__ == '__main__':
unittest.main()

File diff suppressed because one or more lines are too long