From 07d9d1dbb83d1fd73a922c2c9c47b2dcfa3c175d Mon Sep 17 00:00:00 2001 From: Alessandro Pasotti Date: Tue, 18 Dec 2018 18:32:14 +0100 Subject: [PATCH] Fix views query tables in spatialite There is still an old issue: views are only available through DB manager. Fixes #20674 - again - Life is really simple, but we insist on making it complicated. Confucius --- .../spatialite/qgsspatialiteprovider.cpp | 24 +++++++++++++----- tests/src/python/test_provider_spatialite.py | 7 +++++ tests/testdata/provider/spatialite.db | Bin 5009408 -> 5012480 bytes 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/providers/spatialite/qgsspatialiteprovider.cpp b/src/providers/spatialite/qgsspatialiteprovider.cpp index a452402211e6..27a14f9b1910 100644 --- a/src/providers/spatialite/qgsspatialiteprovider.cpp +++ b/src/providers/spatialite/qgsspatialiteprovider.cpp @@ -4666,18 +4666,28 @@ bool QgsSpatiaLiteProvider::checkLayerType() .arg( sql ), tr( "SpatiaLite" ), Qgis::MessageLevel::Warning ); } - QString pk { QStringLiteral( "%1.%2" ).arg( quotedIdentifier( alias ) ).arg( pks.first() ) }; - QString newSql( mQuery.replace( injectionRe, - QStringLiteral( R"re(SELECT %1.%2, \1)re" ) - .arg( quotedIdentifier( tableIdentifier ) ) - .arg( pks.first() ) ) ); - sql = QStringLiteral( "SELECT %1 FROM %2 LIMIT 1" ).arg( pk ).arg( newSql ); + // Try first without any injection or manipulation + sql = QStringLiteral( "SELECT %1, %2 FROM %3 LIMIT 1" ).arg( quotedIdentifier( pks.first( ) ), quotedIdentifier( mGeometryColumn ), mQuery ); ret = sqlite3_get_table( mSqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg ); if ( ret == SQLITE_OK && rows == 1 ) { - mQuery = newSql; mPrimaryKey = pks.first( ); } + else // if that does not work, try injection with table name/alias + { + QString pk { QStringLiteral( "%1.%2" ).arg( quotedIdentifier( alias ) ).arg( pks.first() ) }; + QString newSql( mQuery.replace( injectionRe, + QStringLiteral( R"re(SELECT %1.%2, \1)re" ) + .arg( quotedIdentifier( tableIdentifier ) ) + .arg( pks.first() ) ) ); + sql = QStringLiteral( "SELECT %1 FROM %2 LIMIT 1" ).arg( pk ).arg( newSql ); + ret = sqlite3_get_table( mSqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg ); + if ( ret == SQLITE_OK && rows == 1 ) + { + mQuery = newSql; + mPrimaryKey = pks.first( ); + } + } } // If there is still no primary key, check if we can get use the ROWID from the table that provides the geometry diff --git a/tests/src/python/test_provider_spatialite.py b/tests/src/python/test_provider_spatialite.py index 9162c9113e46..da23f3c90285 100644 --- a/tests/src/python/test_provider_spatialite.py +++ b/tests/src/python/test_provider_spatialite.py @@ -791,6 +791,8 @@ def testLoadStyle(self): def _aliased_sql_helper(self, dbname): queries = ( + '(SELECT * FROM (SELECT * from \\"some view\\"))', + '(SELECT * FROM \\"some view\\")', '(select sd.* from somedata as sd left join somedata as sd2 on ( sd2.name = sd.name ))', '(select sd.* from \\"somedata\\" as sd left join \\"somedata\\" as sd2 on ( sd2.name = sd.name ))', "(SELECT * FROM somedata as my_alias1\n)", @@ -814,6 +816,8 @@ def _aliased_sql_helper(self, dbname): for sql in queries: vl = QgsVectorLayer('dbname=\'{}\' table="{}" (geom) sql='.format(dbname, sql), 'test', 'spatialite') self.assertTrue(vl.isValid(), 'dbname: {} - sql: {}'.format(dbname, sql)) + self.assertTrue(vl.featureCount() > 1) + self.assertTrue(vl.isSpatial()) def testPkLessQuery(self): """Test if features in queries with/without pk can be retrieved by id""" @@ -855,6 +859,9 @@ def _make_table(table_name): _make_table("somedata") _make_table("some data") + sql = "CREATE VIEW \"some view\" AS SELECT * FROM \"somedata\"" + cur.execute(sql) + cur.execute("COMMIT") con.close() diff --git a/tests/testdata/provider/spatialite.db b/tests/testdata/provider/spatialite.db index c75891247498f1f1ec3a63cafb71076d643da287..e37acc2da191f034f8c592183776ee9d8099528c 100644 GIT binary patch delta 1280 zcmZwG%TE(g6bA4)cRJH46tI@I^hJl^VL{%{ic|$G7O6sjsF4`bKvl#-qk!yyuyEr7 zLWHGprwd~WCS%+gm#!qN2pazd<3bV^`d!Ma)JcAmX1+7$-nQq?|4g#^-6UIbTfPf| z)h8TZf0ip7@UZIFM+pyySPkx0?{eY;V>P~rLTGTB&mOffj{p8H6S&$88$bnqQgEL@(vtWgM;63f&fC6xW3*6uVFBF0gR44)silGEb zp$yJ}AIhNu&O;?sK{eDsE!06hG(aOXK{K>K04_i)T!c0V!X>y2SD+m_pcAe_2)f`J zgrOU*LyvBjBfBv(qg8=@#Vsn_IiAmEeKj6=#8v|lgTmM>D%kAd(D}(j1APl&+2->p z(=%hSXZ!P$_Mx*s)IJzeZ*_-mtJ+blsqF*mKqwOG98@dRuKwN|2O*z5O^-f~G!b7? zbO}8#jZ{8IO!y&u64r!-(1W=?c@?|z_z0R5g%sjJ+7R#0qCqZo@**or6h&a{R1qIb z>2H9RiVAp{B~@lZw}W1DsS|-Al_bq^qSc9-R0*F~)YwsD;(Jmkb5DG94Q-kYHHs}` ztyCXA#gbH(pI6HJ=+#7<%$$R7$Ha9(+!ogl|Af@Z_u~xSEc5W4dHJG>DdU$oI?hsw Qo7Xw^>oRwjI@pr@4{RtW`v3p{ delta 518 zcmYMwJ4k|I6vpxIeP6ZIuZwARQPXaw-OKE5_lwoH)g&}H1QA3L1&wV%M05ciTN+v# z#NcahYzV5UrRKI4aqREZf!`S(IL~lSiaB}mos*Y7*Sn^<{o4N&uDWA{J-<&@!jz1& z-TtfnN7EG%Zjm36uMeI(O+BkU)gtfZn>>~g@geR^*Rk(RIC}&3U~QtjRCsfd^JafG zgsuk1Qu&YExm5)6Y4bLDy=_q*5zdw!8qqAZ1v7kPd`ho_BahTIwW*RSrUJ?)Q*zD> zTST46h9ctYRJRF8C|F>H4P_{Y9S%65qXLzvLN#2dfg2vw!izf8qXCWZ!H)o%5JU*g zXhAF5(2g)V5J423=t4Jo(2G9wV*rDQVF+;yV+5lZ!#E}|i3FxFjTy{h4)a*RB9^d> kBv!DBHB+}4#Vv=@(wck`87*D<^t$