Skip to content
Permalink
Browse files

Fix virtual layer queries with accents in layer name

(cherry-picked from af0d6b9)
  • Loading branch information
Hugo Mercier
Hugo Mercier committed Sep 1, 2016
1 parent d130b32 commit 682023f6be0cfea43219206ed5b002a23f9229a6
@@ -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
{
@@ -324,11 +324,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;
}
@@ -341,7 +341,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 );
@@ -351,8 +351,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;
@@ -368,7 +368,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 )
{
@@ -386,17 +386,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 ) );
@@ -738,6 +738,20 @@ 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())

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

0 comments on commit 682023f

Please sign in to comment.
You can’t perform that action at this time.