Skip to content

Commit

Permalink
Fix virtual layer queries with accents in layer name
Browse files Browse the repository at this point in the history
(cherry-picked from af0d6b9)
  • Loading branch information
Hugo Mercier committed Sep 1, 2016
1 parent e95ddd9 commit 9fdd461
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 13 deletions.
6 changes: 3 additions & 3 deletions src/providers/virtual/qgsvirtuallayerqueryparser.cpp
Expand Up @@ -39,16 +39,16 @@ namespace QgsVirtualLayerQueryParser
while ( true )
{
char *errMsg = nullptr;
int r = sqlite3_exec( db.get(), query.toLocal8Bit().constData(), nullptr, nullptr, &errMsg );
QString err = errMsg;
int r = sqlite3_exec( db.get(), query.toUtf8().constData(), nullptr, nullptr, &errMsg );
QString err = QString::fromUtf8( errMsg );
if ( r && err.startsWith( noSuchError ) )
{
QString tableName = err.mid( noSuchError.size() );
tables << tableName;

// create a dummy table to skip this error
QString createStr = QString( "CREATE TABLE \"%1\" (id int)" ).arg( tableName.replace( "\"", "\"\"" ) );
( void )sqlite3_exec( db.get(), createStr.toLocal8Bit().constData(), nullptr, NULL, NULL );
( void )sqlite3_exec( db.get(), createStr.toUtf8().constData(), nullptr, NULL, NULL );
}
else
{
Expand Down
19 changes: 9 additions & 10 deletions src/providers/virtual/qgsvirtuallayersqlitemodule.cpp
Expand Up @@ -327,11 +327,11 @@ int vtableCreateConnect( sqlite3* sql, void* aux, int argc, const char* const* a
Q_UNUSED( isCreated );

#define RETURN_CSTR_ERROR(err) if (outErr) {size_t s = strlen(err); *outErr=reinterpret_cast<char*>(sqlite3_malloc( static_cast<int>( s ) +1)); strncpy(*outErr, err, s);}
#define RETURN_CPPSTR_ERROR(err) if (outErr) {*outErr=reinterpret_cast<char*>(sqlite3_malloc( static_cast<int>( err.size() )+1)); strncpy(*outErr, err.c_str(), err.size());}
#define RETURN_CPPSTR_ERROR(err) if (outErr) {*outErr=reinterpret_cast<char*>(sqlite3_malloc( static_cast<int>( err.toUtf8().size() )+1)); strncpy(*outErr, err.toUtf8().constData(), err.toUtf8().size());}

if ( argc < 4 )
{
std::string err( "Missing arguments: layer_id | provider, source" );
QString err( "Missing arguments: layer_id | provider, source" );
RETURN_CPPSTR_ERROR( err );
return SQLITE_ERROR;
}
Expand All @@ -344,7 +344,7 @@ int vtableCreateConnect( sqlite3* sql, void* aux, int argc, const char* const* a
// CREATE VIRTUAL TABLE vtab USING QgsVLayer(layer_id)
// vtab = argv[2]
// layer_id = argv[3]
QString layerid( argv[3] );
QString layerid = QString::fromUtf8( argv[3] );
if ( layerid.size() >= 1 && layerid[0] == '\'' )
{
layerid = layerid.mid( 1, layerid.size() - 2 );
Expand All @@ -354,8 +354,8 @@ int vtableCreateConnect( sqlite3* sql, void* aux, int argc, const char* const* a
{
if ( outErr )
{
std::string err( "Cannot find layer " );
err += argv[3];
QString err( "Cannot find layer " );
err += QString::fromUtf8( argv[3] );
RETURN_CPPSTR_ERROR( err );
}
return SQLITE_ERROR;
Expand All @@ -371,7 +371,7 @@ int vtableCreateConnect( sqlite3* sql, void* aux, int argc, const char* const* a
// source = argv[4]
// encoding = argv[5]
QString provider = argv[3];
QString source = argv[4];
QString source = QString::fromUtf8( argv[4] );
QString encoding = "UTF-8";
if ( argc == 6 )
{
Expand All @@ -389,17 +389,16 @@ int vtableCreateConnect( sqlite3* sql, void* aux, int argc, const char* const* a
}
try
{
newVtab.reset( new VTable( sql, provider, source, argv[2], encoding ) );
newVtab.reset( new VTable( sql, provider, source, QString::fromUtf8( argv[2] ), encoding ) );
}
catch ( std::runtime_error& e )
{
std::string err( e.what() );
RETURN_CPPSTR_ERROR( err );
RETURN_CSTR_ERROR( e.what() );
return SQLITE_ERROR;
}
}

r = sqlite3_declare_vtab( sql, newVtab->creationString().toLocal8Bit().constData() );
r = sqlite3_declare_vtab( sql, newVtab->creationString().toUtf8().constData() );
if ( r )
{
RETURN_CSTR_ERROR( sqlite3_errmsg( sql ) );
Expand Down
15 changes: 15 additions & 0 deletions tests/src/python/test_provider_virtual.py
Expand Up @@ -733,6 +733,21 @@ def test_query_with_accents(self):
ids = [f.id() for f in vl2.getFeatures()]
self.assertEqual(ids, [])

def test_layer_with_accents(self):
l1 = QgsVectorLayer(os.path.join(self.testDataDir, "france_parts.shp"), u"françéà", "ogr", False)
self.assertEqual(l1.isValid(), True)
QgsMapLayerRegistry.instance().addMapLayer(l1)

df = QgsVirtualLayerDefinition()
df.setQuery(u'select * from "françéà"')

vl = QgsVectorLayer(df.toString(), "testq", "virtual")
self.assertEqual(vl.isValid(), True)
ids = [f.id() for f in vl.getFeatures()]
self.assertEqual(len(ids), 4)

QgsMapLayerRegistry.instance().removeMapLayer(l1.id())

def test_joined_layers_conversion(self):
v1 = QgsVectorLayer("Point?field=id:integer&field=b_id:integer&field=c_id:integer&field=name:string", "A", "memory")
self.assertEqual(v1.isValid(), True)
Expand Down

0 comments on commit 9fdd461

Please sign in to comment.