Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't offer non-vector layer providers as options for virtual layer source layers #48988

Merged
merged 7 commits into from
Jun 15, 2022
Prev Previous commit
Next Next commit
Cleanup virtual layer error handling, and avoid copying an unterminated
string
nyalldawson committed Jun 14, 2022
commit fe4d499d8dd765df5436d0c1fb0fd1a70fa7f848
3 changes: 2 additions & 1 deletion src/providers/virtual/qgsvirtuallayersqlitehelper.cpp
Original file line number Diff line number Diff line change
@@ -165,7 +165,8 @@ namespace Sqlite
const int r = sqlite3_exec( db, sql.toUtf8().constData(), nullptr, nullptr, &errMsg );
if ( r )
{
const QString err = QStringLiteral( "Query execution error on %1: %2 - %3" ).arg( sql ).arg( r ).arg( errMsg );
const QString err = QStringLiteral( "Query execution error on %1: %2 - %3" ).arg( sql ).arg( r ).arg( QString::fromUtf8( errMsg ) );
sqlite3_free( errMsg );
throw std::runtime_error( err.toUtf8().constData() );
}
}
28 changes: 17 additions & 11 deletions src/providers/virtual/qgsvirtuallayersqlitemodule.cpp
Original file line number Diff line number Diff line change
@@ -118,10 +118,10 @@ struct VTable
, mValid( true )
{
QgsDataProvider::ProviderOptions providerOptions;
mProvider = static_cast<QgsVectorDataProvider *>( QgsProviderRegistry::instance()->createProvider( provider, source, providerOptions ) );
mProvider = qobject_cast<QgsVectorDataProvider *>( QgsProviderRegistry::instance()->createProvider( provider, source, providerOptions ) );
if ( !mProvider )
{
throw std::runtime_error( "Invalid provider" );
throw std::runtime_error( QStringLiteral( "Invalid provider: Cannot use %1 source layers in virtual layers" ).arg( provider ).toUtf8().constData() );
}
else if ( mProvider && !mProvider->isValid() )
{
@@ -333,13 +333,20 @@ int vtableCreateConnect( sqlite3 *sql, void *aux, int argc, const char *const *a
Q_UNUSED( aux )
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.toUtf8().size() )+1)); strncpy(*outErr, err.toUtf8().constData(), err.toUtf8().size());}
auto returnStrError = [&outErr]( const QString & err )
{
if ( outErr )
{
const int size = err.toUtf8().size();
*outErr = reinterpret_cast<char *>( sqlite3_malloc( size + 1 ) );
strncpy( *outErr, err.toUtf8().constData(), size + 1 );
}
};

if ( argc < 4 )
{
QString err( QStringLiteral( "Missing arguments: layer_id | provider, source" ) );
RETURN_CPPSTR_ERROR( err );
const QString err( QStringLiteral( "Missing arguments: layer_id | provider, source" ) );
returnStrError( err );
return SQLITE_ERROR;
}

@@ -363,11 +370,11 @@ int vtableCreateConnect( sqlite3 *sql, void *aux, int argc, const char *const *a
{
QString err( QStringLiteral( "Cannot find layer " ) );
err += QString::fromUtf8( argv[3] );
RETURN_CPPSTR_ERROR( err );
returnStrError( err );
}
return SQLITE_ERROR;
}
newVtab.reset( new VTable( sql, static_cast<QgsVectorLayer *>( l ) ) );
newVtab.reset( new VTable( sql, qobject_cast<QgsVectorLayer *>( l ) ) );

}
else if ( argc == 5 || argc == 6 )
@@ -400,21 +407,20 @@ int vtableCreateConnect( sqlite3 *sql, void *aux, int argc, const char *const *a
}
catch ( std::runtime_error &e )
{
RETURN_CSTR_ERROR( e.what() );
returnStrError( e.what() );
return SQLITE_ERROR;
}
}

r = sqlite3_declare_vtab( sql, newVtab->creationString().toUtf8().constData() );
if ( r )
{
RETURN_CSTR_ERROR( sqlite3_errmsg( sql ) );
returnStrError( sqlite3_errmsg( sql ) );
return r;
}

*outVtab = reinterpret_cast< sqlite3_vtab * >( newVtab.release() );
return SQLITE_OK;
#undef RETURN_CSTR_ERROR
#undef RETURN_CPPSTR_ERROR
}