Skip to content

Commit cf0442d

Browse files
authored
Merge pull request #8630 from elpaso/bugfix-20674-db-manager-sqlite-aliased-queries
sqlite accept aliased queries from db manager
2 parents 87d2da1 + a44b13b commit cf0442d

File tree

4 files changed

+32
-8
lines changed

4 files changed

+32
-8
lines changed

python/plugins/db_manager/dlg_sql_layer_window.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,13 @@ def __init__(self, iface, layer, parent=None):
147147

148148
# Update from layer
149149
# First the SQL from QgsDataSourceUri table
150-
sql = uri.table()
150+
sql = uri.table().replace('\n', ' ').strip()
151151
if uri.keyColumn() == '_uid_':
152-
match = re.search(r'^\(SELECT .+ AS _uid_,\* FROM \((.*)\) AS _subq_.+_\s*\)$', sql, re.S | re.X)
152+
match = re.search(r'^\(SELECT .+ AS _uid_,\* FROM \((.*)\) AS _subq_.+_\s*\)$', sql, re.S | re.X | re.IGNORECASE)
153153
if match:
154154
sql = match.group(1)
155155
else:
156-
match = re.search(r'^\((SELECT .+ FROM .+)\)$', sql, re.S | re.X)
156+
match = re.search(r'^\((SELECT .+ FROM .+)\)$', sql, re.S | re.X | re.IGNORECASE)
157157
if match:
158158
sql = match.group(1)
159159
# Need to check on table() since the parentheses were removed by the regexp

python/plugins/db_manager/dlg_sql_window.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@ def createView(self):
602602
def _getSqlQuery(self):
603603
sql = self.editSql.selectedText()
604604
if len(sql) == 0:
605-
sql = self.editSql.text()
605+
sql = self.editSql.text().replace('\n', ' ').strip()
606606
return sql
607607

608608
def uniqueChanged(self):

src/providers/spatialite/qgsspatialiteprovider.cpp

+13-1
Original file line numberDiff line numberDiff line change
@@ -4603,9 +4603,21 @@ bool QgsSpatiaLiteProvider::checkLayerType()
46034603
// 3. check if ROWID injection works
46044604
if ( ! queryGeomTableName.isEmpty() )
46054605
{
4606+
// Check if the whole sql is aliased (I couldn't find a sqlite API call to get this information)
4607+
QRegularExpression re { R"re(\s+AS\s+(\w+)\n?\)?$)re" };
4608+
re.setPatternOptions( QRegularExpression::PatternOption::MultilineOption |
4609+
QRegularExpression::PatternOption::CaseInsensitiveOption );
4610+
QRegularExpressionMatch match { re.match( mTableName ) };
4611+
regex.setPattern( QStringLiteral( R"re(\s+AS\s+(\w+)\n?\)?$)re" ) );
4612+
QString tableAlias;
4613+
if ( match.hasMatch() )
4614+
{
4615+
tableAlias = match.captured( 1 );
4616+
}
46064617
QString newSql( mQuery.replace( QStringLiteral( "SELECT " ),
46074618
QStringLiteral( "SELECT %1.%2, " )
4608-
.arg( quotedIdentifier( queryGeomTableName ), QStringLiteral( "ROWID" ) ),
4619+
.arg( quotedIdentifier( tableAlias.isEmpty() ? queryGeomTableName : tableAlias ),
4620+
QStringLiteral( "ROWID" ) ),
46094621
Qt::CaseInsensitive ) );
46104622
sql = QStringLiteral( "SELECT ROWID FROM %1 WHERE ROWID IS NOT NULL LIMIT 1" ).arg( newSql );
46114623
ret = sqlite3_get_table( mSqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );

tests/src/python/test_provider_spatialite.py

+15-3
Original file line numberDiff line numberDiff line change
@@ -654,14 +654,14 @@ def testVectorLayerUtilsCreateFeatureWithProviderDefaultLiteral(self):
654654
f = QgsVectorLayerUtils.createFeature(vl)
655655
self.assertEqual(f.attributes(), [None, "qgis 'is good", 5, 5.7, None])
656656

657-
# check that provider default literals take precedence over passed attribute values
657+
# check that provider default literals do not take precedence over passed attribute values
658658
f = QgsVectorLayerUtils.createFeature(vl, attributes={1: 'qgis is great', 0: 3})
659-
self.assertEqual(f.attributes(), [3, "qgis 'is good", 5, 5.7, None])
659+
self.assertEqual(f.attributes(), [3, "qgis is great", 5, 5.7, None])
660660

661661
# test that vector layer default value expression overrides provider default literal
662662
vl.setDefaultValueDefinition(3, QgsDefaultValue("4*3"))
663663
f = QgsVectorLayerUtils.createFeature(vl, attributes={1: 'qgis is great', 0: 3})
664-
self.assertEqual(f.attributes(), [3, "qgis 'is good", 5, 12, None])
664+
self.assertEqual(f.attributes(), [3, "qgis is great", 5, 12, None])
665665

666666
def testCreateAttributeIndex(self):
667667
vl = QgsVectorLayer("dbname=%s table='test_defaults' key='id'" % self.dbname, "test_defaults", "spatialite")
@@ -848,6 +848,18 @@ def _check_features(vl, offset):
848848
self.assertTrue(vl_no_pk.isValid())
849849
_check_features(vl_no_pk, 10)
850850

851+
def testAliasedQueries(self):
852+
"""Test regression when sending queries with aliased tables from DB manager"""
853+
854+
def _test(sql):
855+
vl = QgsVectorLayer('dbname=\'{}/provider/spatialite.db\' table="{}" (geom) sql='.format(TEST_DATA_DIR, sql), 'test', 'spatialite')
856+
self.assertTrue(vl.isValid())
857+
858+
_test("(SELECT * FROM somedata as my_alias\n)")
859+
_test("(SELECT * FROM somedata as my_alias)")
860+
_test("(SELECT * FROM somedata AS my_alias)")
861+
_test('(SELECT * FROM \\"somedata\\" as my_alias\n)')
862+
851863

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

0 commit comments

Comments
 (0)