Skip to content

Commit

Permalink
Add pg version guard and test on estimated count for view
Browse files Browse the repository at this point in the history
  • Loading branch information
troopa81 committed Nov 7, 2019
1 parent be4c4d3 commit 5f43b3f
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 16 deletions.
35 changes: 19 additions & 16 deletions src/providers/postgres/qgspostgresprovider.cpp
Expand Up @@ -3332,24 +3332,27 @@ long QgsPostgresProvider::featureCount() const
// use estimated metadata even when there is a where clause,
// although we get an incorrect feature count for the subset
// - but make huge dataset usable.
long num = 0;
long num = -1;
if ( !mIsQuery && mUseEstimatedMetadata )
{
// parse explain output to estimate feature count
// we don't use pg_class reltuples because it returns 0 for view
sql = QStringLiteral( "EXPLAIN (FORMAT JSON) SELECT count(*) FROM %1%2" ).arg( mQuery, filterWhereClause() );
QgsPostgresResult result( connectionRO()->PQexec( sql ) );

const QString json = result.PQgetvalue( 0, 0 );
const QVariantList explain = QgsJsonUtils::parseJson( json ).toList();
const QVariantMap countPlan = explain.count() ? explain[0].toMap().value( "Plan" ).toMap() : QVariantMap();
const QVariantList queryPlan = countPlan.value( "Plans" ).toList();
const QVariant nbRows = queryPlan.count() ? queryPlan[0].toMap().value( "Plan Rows" ) : QVariant();

if ( nbRows.isValid() )
num = nbRows.toInt();
else
QgsLogger::warning( QStringLiteral( "Cannot parse JSON explain result to estimate feature count (%1) : %2" ).arg( sql, json ) );
if ( connectionRO()->pgVersion() >= 90000 )
{
// parse explain output to estimate feature count
// we don't use pg_class reltuples because it returns 0 for view
sql = QStringLiteral( "EXPLAIN (FORMAT JSON) SELECT count(*) FROM %1%2" ).arg( mQuery, filterWhereClause() );
QgsPostgresResult result( connectionRO()->PQexec( sql ) );

const QString json = result.PQgetvalue( 0, 0 );
const QVariantList explain = QgsJsonUtils::parseJson( json ).toList();
const QVariantMap countPlan = explain.count() ? explain[0].toMap().value( "Plan" ).toMap() : QVariantMap();
const QVariantList queryPlan = countPlan.value( "Plans" ).toList();
const QVariant nbRows = queryPlan.count() ? queryPlan[0].toMap().value( "Plan Rows" ) : QVariant();

if ( nbRows.isValid() )
num = nbRows.toInt();
else
QgsLogger::warning( QStringLiteral( "Cannot parse JSON explain result to estimate feature count (%1) : %2" ).arg( sql, json ) );
}
}
else
{
Expand Down
10 changes: 10 additions & 0 deletions tests/src/python/test_provider_postgres.py
Expand Up @@ -1415,6 +1415,16 @@ def testCheckTidPkOnViews(self):
for f in vl0.getFeatures():
self.assertNotEqual(f.attribute(0), NULL)

def testFeatureCountEstimatedOnView(self):
"""
Test feature count on view when estimated data is enabled
"""
self.execSQLCommand('DROP VIEW IF EXISTS qgis_test.somedataview')
self.execSQLCommand('CREATE VIEW qgis_test.somedataview AS SELECT * FROM qgis_test."someData"')
vl = QgsVectorLayer(self.dbconn + ' sslmode=disable key=\'pk\' estimatedmetadata=true srid=4326 type=POINT table="qgis_test"."somedataview" (geom) sql=', 'test', 'postgres')
self.assertTrue(vl.isValid())
self.assertTrue(self.source.featureCount() > 0)


class TestPyQgsPostgresProviderCompoundKey(unittest.TestCase, ProviderTestCase):

Expand Down

0 comments on commit 5f43b3f

Please sign in to comment.