Unify sqlite string quoting functions to a single QgsSqliteUtils::quoteString

function, with tests
This commit is contained in:
Nyall Dawson 2018-10-05 09:22:27 +10:00
parent 7e81226b51
commit ed35ad9ca7
13 changed files with 144 additions and 143 deletions

View File

@ -141,7 +141,7 @@ bool QgsCustomProjectionDialog::deleteCrs( const QString &id )
{
sqlite3_database_unique_ptr database;
QString sql = "delete from tbl_srs where srs_id=" + quotedValue( id );
QString sql = "delete from tbl_srs where srs_id=" + QgsSqliteUtils::quotedString( id );
QgsDebugMsg( sql );
//check the db is available
int result = database.open( QgsApplication::qgisUserDatabaseFilePath() );
@ -191,7 +191,7 @@ void QgsCustomProjectionDialog::insertProjection( const QString &projectionAcro
else
{
// Set up the query to retrieve the projection information needed to populate the PROJECTION list
QString srsSql = "select acronym,name,notes,parameters from tbl_projection where acronym=" + quotedValue( projectionAcronym );
QString srsSql = "select acronym,name,notes,parameters from tbl_projection where acronym=" + QgsSqliteUtils::quotedString( projectionAcronym );
sqlite3_statement_unique_ptr srsPreparedStatement = srsDatabase.prepare( srsSql, srsResult );
if ( srsResult == SQLITE_OK )
@ -201,10 +201,10 @@ void QgsCustomProjectionDialog::insertProjection( const QString &projectionAcro
QgsDebugMsg( "Trying to insert projection" );
// We have the result from system srs.db. Now insert into user db.
sql = "insert into tbl_projection(acronym,name,notes,parameters) values ("
+ quotedValue( srsPreparedStatement.columnAsText( 0 ) )
+ ',' + quotedValue( srsPreparedStatement.columnAsText( 1 ) )
+ ',' + quotedValue( srsPreparedStatement.columnAsText( 2 ) )
+ ',' + quotedValue( srsPreparedStatement.columnAsText( 3 ) )
+ QgsSqliteUtils::quotedString( srsPreparedStatement.columnAsText( 0 ) )
+ ',' + QgsSqliteUtils::quotedString( srsPreparedStatement.columnAsText( 1 ) )
+ ',' + QgsSqliteUtils::quotedString( srsPreparedStatement.columnAsText( 2 ) )
+ ',' + QgsSqliteUtils::quotedString( srsPreparedStatement.columnAsText( 3 ) )
+ ')';
sqlite3_statement_unique_ptr preparedStatement = database.prepare( sql, result );
if ( result != SQLITE_OK || preparedStatement.step() != SQLITE_DONE )
@ -239,12 +239,12 @@ bool QgsCustomProjectionDialog::saveCrs( QgsCoordinateReferenceSystem parameters
else
{
sql = "update tbl_srs set description="
+ quotedValue( name )
+ ",projection_acronym=" + quotedValue( projectionAcronym )
+ ",ellipsoid_acronym=" + quotedValue( ellipsoidAcronym )
+ ",parameters=" + quotedValue( parameters.toProj4() )
+ QgsSqliteUtils::quotedString( name )
+ ",projection_acronym=" + QgsSqliteUtils::quotedString( projectionAcronym )
+ ",ellipsoid_acronym=" + QgsSqliteUtils::quotedString( ellipsoidAcronym )
+ ",parameters=" + QgsSqliteUtils::quotedString( parameters.toProj4() )
+ ",is_geo=0" // <--shamelessly hard coded for now
+ " where srs_id=" + quotedValue( id )
+ " where srs_id=" + QgsSqliteUtils::quotedString( id )
;
QgsDebugMsg( sql );
sqlite3_database_unique_ptr database;
@ -521,12 +521,6 @@ void QgsCustomProjectionDialog::pbnCalculate_clicked()
pj_ctx_free( pContext );
}
QString QgsCustomProjectionDialog::quotedValue( QString value )
{
value.replace( '\'', QLatin1String( "''" ) );
return value.prepend( '\'' ).append( '\'' );
}
void QgsCustomProjectionDialog::showHelp()
{
QgsHelp::openHelp( QStringLiteral( "working_with_projections/working_with_projections.html" ) );

View File

@ -50,7 +50,6 @@ class APP_EXPORT QgsCustomProjectionDialog : public QDialog, private Ui::QgsCust
//helper functions
void populateList();
QString quotedValue( QString value );
bool deleteCrs( const QString &id );
bool saveCrs( QgsCoordinateReferenceSystem parameters, const QString &name, const QString &id, bool newEntry );
void insertProjection( const QString &projectionAcronym );

View File

@ -421,11 +421,11 @@ bool QgsNewSpatialiteLayerDialog::apply()
if ( mGeometryTypeBox->currentIndex() != 0 )
{
QString sqlAddGeom = QStringLiteral( "select AddGeometryColumn(%1,%2,%3,%4,%5)" )
.arg( quotedValue( leLayerName->text() ),
quotedValue( leGeometryColumn->text() ) )
.arg( QgsSqliteUtils::quotedString( leLayerName->text() ),
QgsSqliteUtils::quotedString( leGeometryColumn->text() ) )
.arg( mCrsId.split( ':' ).value( 1, QStringLiteral( "0" ) ).toInt() )
.arg( quotedValue( selectedType() ) )
.arg( quotedValue( selectedZM() ) );
.arg( QgsSqliteUtils::quotedString( selectedType() ) )
.arg( QgsSqliteUtils::quotedString( selectedZM() ) );
QgsDebugMsg( sqlAddGeom );
rc = sqlite3_exec( database.get(), sqlAddGeom.toUtf8(), nullptr, nullptr, &errmsg );
@ -439,8 +439,8 @@ bool QgsNewSpatialiteLayerDialog::apply()
}
QString sqlCreateIndex = QStringLiteral( "select CreateSpatialIndex(%1,%2)" )
.arg( quotedValue( leLayerName->text() ),
quotedValue( leGeometryColumn->text() ) );
.arg( QgsSqliteUtils::quotedString( leLayerName->text() ),
QgsSqliteUtils::quotedString( leGeometryColumn->text() ) );
QgsDebugMsg( sqlCreateIndex );
rc = sqlite3_exec( database.get(), sqlCreateIndex.toUtf8(), nullptr, nullptr, &errmsg );
@ -488,12 +488,6 @@ QString QgsNewSpatialiteLayerDialog::quotedIdentifier( QString id )
return id.prepend( '\"' ).append( '\"' );
}
QString QgsNewSpatialiteLayerDialog::quotedValue( QString value )
{
value.replace( '\'', QLatin1String( "''" ) );
return value.prepend( '\'' ).append( '\'' );
}
void QgsNewSpatialiteLayerDialog::showHelp()
{
QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#creating-a-new-spatialite-layer" ) );

View File

@ -66,7 +66,6 @@ class APP_EXPORT QgsNewSpatialiteLayerDialog: public QDialog, private Ui::QgsNew
void showHelp();
static QString quotedIdentifier( QString id );
static QString quotedValue( QString value );
QPushButton *mOkButton = nullptr;
QString mCrsId;

View File

@ -498,7 +498,7 @@ bool QgsCoordinateReferenceSystem::loadFromDatabase( const QString &db, const QS
QString mySql = "select srs_id,description,projection_acronym,"
"ellipsoid_acronym,parameters,srid,auth_name||':'||auth_id,is_geo "
"from tbl_srs where " + expression + '=' + quotedValue( value ) + " order by deprecated";
"from tbl_srs where " + expression + '=' + QgsSqliteUtils::quotedString( value ) + " order by deprecated";
statement = database.prepare( mySql, myResult );
// XXX Need to free memory from the error msg if one is set
if ( myResult == SQLITE_OK && statement.step() == SQLITE_ROW )
@ -729,7 +729,7 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString &proj4String )
* We try to match the proj string to and srsid using the following logic:
* - perform a whole text search on proj4 string (if not null)
*/
myRecord = getRecord( "select * from tbl_srs where parameters=" + quotedValue( myProj4String ) + " order by deprecated" );
myRecord = getRecord( "select * from tbl_srs where parameters=" + QgsSqliteUtils::quotedString( myProj4String ) + " order by deprecated" );
if ( myRecord.empty() )
{
// Ticket #722 - aaronr
@ -764,7 +764,7 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString &proj4String )
myStart2 = myLat2RegExp.indexIn( proj4String, myStart2 );
proj4StringModified.replace( myStart2 + LAT_PREFIX_LEN, myLength2 - LAT_PREFIX_LEN, lat1Str );
QgsDebugMsgLevel( "trying proj4string match with swapped lat_1,lat_2", 4 );
myRecord = getRecord( "select * from tbl_srs where parameters=" + quotedValue( proj4StringModified.trimmed() ) + " order by deprecated" );
myRecord = getRecord( "select * from tbl_srs where parameters=" + QgsSqliteUtils::quotedString( proj4StringModified.trimmed() ) + " order by deprecated" );
}
}
@ -785,7 +785,7 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString &proj4String )
QStringList myParams;
Q_FOREACH ( const QString &param, myProj4String.split( QRegExp( "\\s+(?=\\+)" ), QString::SkipEmptyParts ) )
{
QString arg = QStringLiteral( "' '||parameters||' ' LIKE %1" ).arg( quotedValue( QStringLiteral( "% %1 %" ).arg( param.trimmed() ) ) );
QString arg = QStringLiteral( "' '||parameters||' ' LIKE %1" ).arg( QgsSqliteUtils::quotedString( QStringLiteral( "% %1 %" ).arg( param.trimmed() ) ) );
if ( param.startsWith( QLatin1String( "+datum=" ) ) )
{
datum = arg;
@ -1234,8 +1234,8 @@ long QgsCoordinateReferenceSystem::findMatchingProj()
// needed to populate the list
QString mySql = QString( "select srs_id,parameters from tbl_srs where "
"projection_acronym=%1 and ellipsoid_acronym=%2 order by deprecated" )
.arg( quotedValue( d->mProjectionAcronym ),
quotedValue( d->mEllipsoidAcronym ) );
.arg( QgsSqliteUtils::quotedString( d->mProjectionAcronym ),
QgsSqliteUtils::quotedString( d->mEllipsoidAcronym ) );
// Get the full path name to the sqlite3 spatial reference database.
QString myDatabaseFileName = QgsApplication::srsDatabaseFilePath();
@ -1620,19 +1620,19 @@ long QgsCoordinateReferenceSystem::saveAsUserCrs( const QString &name )
{
mySql = "insert into tbl_srs (srs_id,description,projection_acronym,ellipsoid_acronym,parameters,is_geo) values ("
+ QString::number( USER_CRS_START_ID )
+ ',' + quotedValue( name )
+ ',' + quotedValue( projectionAcronym() )
+ ',' + quotedValue( ellipsoidAcronym() )
+ ',' + quotedValue( toProj4() )
+ ',' + QgsSqliteUtils::quotedString( name )
+ ',' + QgsSqliteUtils::quotedString( projectionAcronym() )
+ ',' + QgsSqliteUtils::quotedString( ellipsoidAcronym() )
+ ',' + QgsSqliteUtils::quotedString( toProj4() )
+ ",0)"; // <-- is_geo shamelessly hard coded for now
}
else
{
mySql = "insert into tbl_srs (description,projection_acronym,ellipsoid_acronym,parameters,is_geo) values ("
+ quotedValue( name )
+ ',' + quotedValue( projectionAcronym() )
+ ',' + quotedValue( ellipsoidAcronym() )
+ ',' + quotedValue( toProj4() )
+ QgsSqliteUtils::quotedString( name )
+ ',' + QgsSqliteUtils::quotedString( projectionAcronym() )
+ ',' + QgsSqliteUtils::quotedString( ellipsoidAcronym() )
+ ',' + QgsSqliteUtils::quotedString( toProj4() )
+ ",0)"; // <-- is_geo shamelessly hard coded for now
}
sqlite3_database_unique_ptr database;
@ -1707,12 +1707,6 @@ long QgsCoordinateReferenceSystem::getRecordCount()
return myRecordCount;
}
QString QgsCoordinateReferenceSystem::quotedValue( QString value )
{
value.replace( '\'', QLatin1String( "''" ) );
return value.prepend( '\'' ).append( '\'' );
}
// adapted from gdal/ogr/ogr_srs_dict.cpp
bool QgsCoordinateReferenceSystem::loadWkts( QHash<int, QString> &wkts, const char *filename )
{
@ -1951,8 +1945,8 @@ int QgsCoordinateReferenceSystem::syncDatabase()
{
errMsg = nullptr;
sql = QStringLiteral( "UPDATE tbl_srs SET parameters=%1,description=%2,deprecated=%3 WHERE auth_name='EPSG' AND auth_id=%4" )
.arg( quotedValue( proj4 ) )
.arg( quotedValue( name ) )
.arg( QgsSqliteUtils::quotedString( proj4 ) )
.arg( QgsSqliteUtils::quotedString( name ) )
.arg( deprecated ? 1 : 0 )
.arg( it.key() );
@ -1989,10 +1983,10 @@ int QgsCoordinateReferenceSystem::syncDatabase()
}
sql = QStringLiteral( "INSERT INTO tbl_srs(description,projection_acronym,ellipsoid_acronym,parameters,srid,auth_name,auth_id,is_geo,deprecated) VALUES (%1,%2,%3,%4,%5,'EPSG',%5,%6,%7)" )
.arg( quotedValue( name ),
quotedValue( projRegExp.cap( 1 ) ),
quotedValue( ellps ),
quotedValue( proj4 ) )
.arg( QgsSqliteUtils::quotedString( name ),
QgsSqliteUtils::quotedString( projRegExp.cap( 1 ) ),
QgsSqliteUtils::quotedString( ellps ),
QgsSqliteUtils::quotedString( proj4 ) )
.arg( it.key() )
.arg( OSRIsGeographic( crs ) )
.arg( deprecated ? 1 : 0 );
@ -2081,9 +2075,9 @@ int QgsCoordinateReferenceSystem::syncDatabase()
if ( proj4 != params )
{
sql = QStringLiteral( "UPDATE tbl_srs SET parameters=%1 WHERE auth_name=%2 AND auth_id=%3" )
.arg( quotedValue( proj4 ),
quotedValue( auth_name ),
quotedValue( auth_id ) );
.arg( QgsSqliteUtils::quotedString( proj4 ),
QgsSqliteUtils::quotedString( auth_name ),
QgsSqliteUtils::quotedString( auth_id ) );
if ( sqlite3_exec( database.get(), sql.toUtf8(), nullptr, nullptr, &errMsg ) == SQLITE_OK )
{
@ -2291,7 +2285,7 @@ bool QgsCoordinateReferenceSystem::syncDatumTransform( const QString &dbPath )
int idx = map[i].idx;
Q_ASSERT( idx != -1 );
Q_ASSERT( idx < n );
v.insert( i, *values[ idx ] ? quotedValue( values[idx] ) : QStringLiteral( "NULL" ) );
v.insert( i, *values[ idx ] ? QgsSqliteUtils::quotedString( values[idx] ) : QStringLiteral( "NULL" ) );
}
CSLDestroy( values );

View File

@ -741,9 +741,6 @@ class CORE_EXPORT QgsCoordinateReferenceSystem
//! Helper for getting number of user CRS already in db
long getRecordCount();
//! Helper for sql-safe value quoting
static QString quotedValue( QString value );
/**
* Initialize the CRS object by looking up CRS database in path given in db argument,
* using first CRS entry where expression = 'value'

View File

@ -91,6 +91,16 @@ sqlite3_statement_unique_ptr sqlite3_database_unique_ptr::prepare( const QString
return s;
}
QString QgsSqliteUtils::quotedString( const QString &value )
{
if ( value.isNull() )
return QStringLiteral( "NULL" );
QString v = value;
v.replace( '\'', QLatin1String( "''" ) );
return v.prepend( '\'' ).append( '\'' );
}
QString QgsSqlite3Mprintf( const char *format, ... )
{
va_list ap;

View File

@ -135,8 +135,24 @@ class CORE_EXPORT sqlite3_database_unique_ptr : public std::unique_ptr< sqlite3,
* argument will be filled with the sqlite3 result code.
*/
sqlite3_statement_unique_ptr prepare( const QString &sql, int &resultCode ) const;
};
/**
* Contains utilities for working with Sqlite data sources.
* \note not available in Python bindings
* \since QGIS 3.4
*/
class CORE_EXPORT QgsSqliteUtils
{
public:
/**
* Returns a quoted string \a value, surround by ' characters and with special
* characters correctly escaped.
*/
static QString quotedString( const QString &value );
};
/**
* Wraps sqlite3_mprintf() by automatically freeing the memory.

View File

@ -454,15 +454,6 @@ error:
return false;
}
QString QgsSpatiaLiteConnection::quotedValue( QString value ) const
{
if ( value.isNull() )
return QStringLiteral( "NULL" );
value.replace( '\'', QLatin1String( "''" ) );
return value.prepend( '\'' ).append( '\'' );
}
bool QgsSpatiaLiteConnection::checkGeometryColumnsAuth( sqlite3 *handle )
{
int ret;
@ -624,8 +615,8 @@ bool QgsSpatiaLiteConnection::isDeclaredHidden( sqlite3 *handle, const QString &
return false;
// checking if some Layer has been declared as HIDDEN
QString sql = QString( "SELECT hidden FROM geometry_columns_auth"
" WHERE f_table_name=%1 and f_geometry_column=%2" ).arg( quotedValue( table ),
quotedValue( geom ) );
" WHERE f_table_name=%1 and f_geometry_column=%2" ).arg( QgsSqliteUtils::quotedString( table ),
QgsSqliteUtils::quotedString( geom ) );
ret = sqlite3_get_table( handle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )

View File

@ -104,9 +104,6 @@ class QgsSpatiaLiteConnection : public QObject
*/
bool getTableInfoAbstractInterface( sqlite3 *handle, bool loadGeometrylessTables );
//! Cleaning well-formatted SQL strings
QString quotedValue( QString value ) const;
//! Checks if geometry_columns_auth table exists
bool checkGeometryColumnsAuth( sqlite3 *handle );

View File

@ -229,7 +229,7 @@ QgsSpatiaLiteProvider::createEmptyLayer( const QString &uri,
throw SLException( errMsg );
sql = QStringLiteral( "DELETE FROM geometry_columns WHERE upper(f_table_name) = upper(%1)" )
.arg( quotedValue( tableName ) );
.arg( QgsSqliteUtils::quotedString( tableName ) );
ret = sqlite3_exec( sqliteHandle, sql.toUtf8().constData(), nullptr, nullptr, &errMsg );
if ( ret != SQLITE_OK )
@ -308,10 +308,10 @@ QgsSpatiaLiteProvider::createEmptyLayer( const QString &uri,
if ( !geometryType.isEmpty() )
{
sql = QStringLiteral( "SELECT AddGeometryColumn(%1, %2, %3, %4, %5)" )
.arg( QgsSpatiaLiteProvider::quotedValue( tableName ),
QgsSpatiaLiteProvider::quotedValue( geometryColumn ) )
.arg( QgsSqliteUtils::quotedString( tableName ),
QgsSqliteUtils::quotedString( geometryColumn ) )
.arg( srid )
.arg( QgsSpatiaLiteProvider::quotedValue( geometryType ) )
.arg( QgsSqliteUtils::quotedString( geometryType ) )
.arg( dim );
ret = sqlite3_exec( sqliteHandle, sql.toUtf8().constData(), nullptr, nullptr, &errMsg );
@ -820,7 +820,7 @@ QString QgsSpatiaLiteProvider::tableSchemaCondition( const QgsDataSourceUri &dsU
{
return dsUri.schema().isEmpty() ?
QStringLiteral( "IS NULL" ) :
QStringLiteral( "= %1" ).arg( quotedValue( dsUri.schema( ) ) );
QStringLiteral( "= %1" ).arg( QgsSqliteUtils::quotedString( dsUri.schema( ) ) );
}
void QgsSpatiaLiteProvider::fetchConstraints()
@ -1102,8 +1102,8 @@ void QgsSpatiaLiteProvider::determineViewPrimaryKey()
{
QString sql = QString( "SELECT view_rowid"
" FROM views_geometry_columns"
" WHERE upper(view_name) = upper(%1) and upper(view_geometry) = upper(%2)" ).arg( quotedValue( mTableName ),
quotedValue( mGeometryColumn ) );
" WHERE upper(view_name) = upper(%1) and upper(view_geometry) = upper(%2)" ).arg( QgsSqliteUtils::quotedString( mTableName ),
QgsSqliteUtils::quotedString( mGeometryColumn ) );
char **results = nullptr;
int rows;
@ -4322,12 +4322,12 @@ bool QgsSpatiaLiteProvider::changeAttributeValues( const QgsChangedAttributesMap
else if ( type == QVariant::StringList || type == QVariant::List )
{
// binding an array value
sql += QStringLiteral( "%1=%2" ).arg( quotedIdentifier( fld.name() ), quotedValue( QgsJsonUtils::encodeValue( val ) ) );
sql += QStringLiteral( "%1=%2" ).arg( quotedIdentifier( fld.name() ), QgsSqliteUtils::quotedString( QgsJsonUtils::encodeValue( val ) ) );
}
else
{
// binding a TEXT value
sql += QStringLiteral( "%1=%2" ).arg( quotedIdentifier( fld.name() ), quotedValue( val.toString() ) );
sql += QStringLiteral( "%1=%2" ).arg( quotedIdentifier( fld.name() ), QgsSqliteUtils::quotedString( val.toString() ) );
}
}
catch ( SLFieldNotFound )
@ -4465,15 +4465,6 @@ QString QgsSpatiaLiteProvider::quotedIdentifier( QString id )
return id.prepend( '\"' ).append( '\"' );
}
QString QgsSpatiaLiteProvider::quotedValue( QString value )
{
if ( value.isNull() )
return QStringLiteral( "NULL" );
value.replace( '\'', QLatin1String( "''" ) );
return value.prepend( '\'' ).append( '\'' );
}
bool QgsSpatiaLiteProvider::checkLayerTypeAbstractInterface( gaiaVectorLayerPtr lyr )
{
if ( !lyr )
@ -4538,7 +4529,7 @@ bool QgsSpatiaLiteProvider::checkLayerType()
// checking if is a non-spatial table
sql = QString( "SELECT type FROM sqlite_master "
"WHERE lower(name) = lower(%1) "
"AND type in ('table', 'view') " ).arg( quotedValue( mTableName ) );
"AND type in ('table', 'view') " ).arg( QgsSqliteUtils::quotedString( mTableName ) );
ret = sqlite3_get_table( mSqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret == SQLITE_OK && rows == 1 )
@ -4652,8 +4643,8 @@ bool QgsSpatiaLiteProvider::checkLayerType()
"LEFT JOIN geometry_columns_auth "
"USING (f_table_name, f_geometry_column) "
"WHERE upper(f_table_name) = upper(%1) and upper(f_geometry_column) = upper(%2)" )
.arg( quotedValue( mTableName ),
quotedValue( mGeometryColumn ) );
.arg( QgsSqliteUtils::quotedString( mTableName ),
QgsSqliteUtils::quotedString( mGeometryColumn ) );
ret = sqlite3_get_table( mSqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )
@ -4662,8 +4653,8 @@ bool QgsSpatiaLiteProvider::checkLayerType()
{
sqlite3_free( errMsg );
sql = QStringLiteral( "SELECT 0 FROM geometry_columns WHERE upper(f_table_name) = upper(%1) and upper(f_geometry_column) = upper(%2)" )
.arg( quotedValue( mTableName ),
quotedValue( mGeometryColumn ) );
.arg( QgsSqliteUtils::quotedString( mTableName ),
QgsSqliteUtils::quotedString( mGeometryColumn ) );
ret = sqlite3_get_table( mSqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
}
}
@ -4691,8 +4682,8 @@ bool QgsSpatiaLiteProvider::checkLayerType()
// checking if this one is a View-based layer
sql = QString( "SELECT view_name, view_geometry FROM views_geometry_columns"
" WHERE view_name=%1 and view_geometry=%2" ).arg( quotedValue( mTableName ),
quotedValue( mGeometryColumn ) );
" WHERE view_name=%1 and view_geometry=%2" ).arg( QgsSqliteUtils::quotedString( mTableName ),
QgsSqliteUtils::quotedString( mGeometryColumn ) );
ret = sqlite3_get_table( mSqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret == SQLITE_OK && rows == 1 )
@ -4711,8 +4702,8 @@ bool QgsSpatiaLiteProvider::checkLayerType()
// checking if this one is a VirtualShapefile-based layer
sql = QString( "SELECT virt_name, virt_geometry FROM virts_geometry_columns"
" WHERE virt_name=%1 and virt_geometry=%2" ).arg( quotedValue( mTableName ),
quotedValue( mGeometryColumn ) );
" WHERE virt_name=%1 and virt_geometry=%2" ).arg( QgsSqliteUtils::quotedString( mTableName ),
QgsSqliteUtils::quotedString( mGeometryColumn ) );
ret = sqlite3_get_table( mSqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret == SQLITE_OK && rows == 1 )
@ -4822,8 +4813,8 @@ void QgsSpatiaLiteProvider::getViewSpatialIndexName()
QString sql = QString( "SELECT f_table_name, f_geometry_column "
"FROM views_geometry_columns "
"WHERE upper(view_name) = upper(%1) and upper(view_geometry) = upper(%2)" ).arg( quotedValue( mTableName ),
quotedValue( mGeometryColumn ) );
"WHERE upper(view_name) = upper(%1) and upper(view_geometry) = upper(%2)" ).arg( QgsSqliteUtils::quotedString( mTableName ),
QgsSqliteUtils::quotedString( mGeometryColumn ) );
ret = sqlite3_get_table( mSqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )
{
@ -4876,8 +4867,8 @@ bool QgsSpatiaLiteProvider::getTableGeometryDetails()
mIndexGeometry = mGeometryColumn;
QString sql = QString( "SELECT type, srid, spatial_index_enabled, coord_dimension FROM geometry_columns"
" WHERE upper(f_table_name) = upper(%1) and upper(f_geometry_column) = upper(%2)" ).arg( quotedValue( mTableName ),
quotedValue( mGeometryColumn ) );
" WHERE upper(f_table_name) = upper(%1) and upper(f_geometry_column) = upper(%2)" ).arg( QgsSqliteUtils::quotedString( mTableName ),
QgsSqliteUtils::quotedString( mGeometryColumn ) );
ret = sqlite3_get_table( mSqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )
@ -4974,8 +4965,8 @@ bool QgsSpatiaLiteProvider::getViewGeometryDetails()
QString sql = QString( "SELECT type, srid, spatial_index_enabled, f_table_name, f_geometry_column "
" FROM views_geometry_columns"
" JOIN geometry_columns USING (f_table_name, f_geometry_column)"
" WHERE upper(view_name) = upper(%1) and upper(view_geometry) = upper(%2)" ).arg( quotedValue( mTableName ),
quotedValue( mGeometryColumn ) );
" WHERE upper(view_name) = upper(%1) and upper(view_geometry) = upper(%2)" ).arg( QgsSqliteUtils::quotedString( mTableName ),
QgsSqliteUtils::quotedString( mGeometryColumn ) );
ret = sqlite3_get_table( mSqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )
@ -5052,8 +5043,8 @@ bool QgsSpatiaLiteProvider::getVShapeGeometryDetails()
char *errMsg = nullptr;
QString sql = QString( "SELECT type, srid FROM virts_geometry_columns"
" WHERE virt_name=%1 and virt_geometry=%2" ).arg( quotedValue( mTableName ),
quotedValue( mGeometryColumn ) );
" WHERE virt_name=%1 and virt_geometry=%2" ).arg( QgsSqliteUtils::quotedString( mTableName ),
QgsSqliteUtils::quotedString( mGeometryColumn ) );
ret = sqlite3_get_table( mSqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )
@ -5692,7 +5683,7 @@ QGISEXTERN bool saveStyle( const QString &uri, const QString &qmlStyle, const QS
if ( !uiFileContent.isEmpty() )
{
uiFileColumn = QStringLiteral( ",ui" );
uiFileValue = QStringLiteral( ",%1" ).arg( QgsSpatiaLiteProvider::quotedValue( uiFileContent ) );
uiFileValue = QStringLiteral( ",%1" ).arg( QgsSqliteUtils::quotedString( uiFileContent ) );
}
QString sql = QString( "INSERT INTO layer_styles("
@ -5700,16 +5691,16 @@ QGISEXTERN bool saveStyle( const QString &uri, const QString &qmlStyle, const QS
") VALUES ("
"%1,%2,%3,%4,%5,%6,%7,%8,%9,%10%12"
")" )
.arg( QgsSpatiaLiteProvider::quotedValue( QString() ) )
.arg( QgsSpatiaLiteProvider::quotedValue( dsUri.schema() ) )
.arg( QgsSpatiaLiteProvider::quotedValue( dsUri.table() ) )
.arg( QgsSpatiaLiteProvider::quotedValue( dsUri.geometryColumn() ) )
.arg( QgsSpatiaLiteProvider::quotedValue( styleName.isEmpty() ? dsUri.table() : styleName ) )
.arg( QgsSpatiaLiteProvider::quotedValue( qmlStyle ) )
.arg( QgsSpatiaLiteProvider::quotedValue( sldStyle ) )
.arg( QgsSqliteUtils::quotedString( QString() ) )
.arg( QgsSqliteUtils::quotedString( dsUri.schema() ) )
.arg( QgsSqliteUtils::quotedString( dsUri.table() ) )
.arg( QgsSqliteUtils::quotedString( dsUri.geometryColumn() ) )
.arg( QgsSqliteUtils::quotedString( styleName.isEmpty() ? dsUri.table() : styleName ) )
.arg( QgsSqliteUtils::quotedString( qmlStyle ) )
.arg( QgsSqliteUtils::quotedString( sldStyle ) )
.arg( useAsDefault ? "1" : "0" )
.arg( QgsSpatiaLiteProvider::quotedValue( styleDescription.isEmpty() ? QDateTime::currentDateTime().toString() : styleDescription ) )
.arg( QgsSpatiaLiteProvider::quotedValue( dsUri.username() ) )
.arg( QgsSqliteUtils::quotedString( styleDescription.isEmpty() ? QDateTime::currentDateTime().toString() : styleDescription ) )
.arg( QgsSqliteUtils::quotedString( dsUri.username() ) )
.arg( uiFileColumn )
.arg( uiFileValue );
@ -5720,9 +5711,9 @@ QGISEXTERN bool saveStyle( const QString &uri, const QString &qmlStyle, const QS
" AND f_geometry_column=%3"
" AND styleName=%4" )
.arg( QgsSpatiaLiteProvider::tableSchemaCondition( dsUri ) )
.arg( QgsSpatiaLiteProvider::quotedValue( dsUri.table() ) )
.arg( QgsSpatiaLiteProvider::quotedValue( dsUri.geometryColumn() ) )
.arg( QgsSpatiaLiteProvider::quotedValue( styleName.isEmpty() ? dsUri.table() : styleName ) );
.arg( QgsSqliteUtils::quotedString( dsUri.table() ) )
.arg( QgsSqliteUtils::quotedString( dsUri.geometryColumn() ) )
.arg( QgsSqliteUtils::quotedString( styleName.isEmpty() ? dsUri.table() : styleName ) );
ret = sqlite3_get_table( sqliteHandle, checkQuery.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( SQLITE_OK != ret )
@ -5757,14 +5748,14 @@ QGISEXTERN bool saveStyle( const QString &uri, const QString &qmlStyle, const QS
" AND f_geometry_column=%8"
" AND styleName=%9" )
.arg( useAsDefault ? "1" : "0" )
.arg( QgsSpatiaLiteProvider::quotedValue( qmlStyle ) )
.arg( QgsSpatiaLiteProvider::quotedValue( sldStyle ) )
.arg( QgsSpatiaLiteProvider::quotedValue( styleDescription.isEmpty() ? QDateTime::currentDateTime().toString() : styleDescription ) )
.arg( QgsSpatiaLiteProvider::quotedValue( dsUri.username() ) )
.arg( QgsSqliteUtils::quotedString( qmlStyle ) )
.arg( QgsSqliteUtils::quotedString( sldStyle ) )
.arg( QgsSqliteUtils::quotedString( styleDescription.isEmpty() ? QDateTime::currentDateTime().toString() : styleDescription ) )
.arg( QgsSqliteUtils::quotedString( dsUri.username() ) )
.arg( QgsSpatiaLiteProvider::tableSchemaCondition( dsUri ) )
.arg( QgsSpatiaLiteProvider::quotedValue( dsUri.table() ) )
.arg( QgsSpatiaLiteProvider::quotedValue( dsUri.geometryColumn() ) )
.arg( QgsSpatiaLiteProvider::quotedValue( styleName.isEmpty() ? dsUri.table() : styleName ) );
.arg( QgsSqliteUtils::quotedString( dsUri.table() ) )
.arg( QgsSqliteUtils::quotedString( dsUri.geometryColumn() ) )
.arg( QgsSqliteUtils::quotedString( styleName.isEmpty() ? dsUri.table() : styleName ) );
}
if ( useAsDefault )
@ -5775,8 +5766,8 @@ QGISEXTERN bool saveStyle( const QString &uri, const QString &qmlStyle, const QS
" AND f_table_name=%2"
" AND f_geometry_column=%3" )
.arg( QgsSpatiaLiteProvider::tableSchemaCondition( dsUri ) )
.arg( QgsSpatiaLiteProvider::quotedValue( dsUri.table() ) )
.arg( QgsSpatiaLiteProvider::quotedValue( dsUri.geometryColumn() ) );
.arg( QgsSqliteUtils::quotedString( dsUri.table() ) )
.arg( QgsSqliteUtils::quotedString( dsUri.geometryColumn() ) );
sql = QStringLiteral( "BEGIN; %1; %2; COMMIT;" ).arg( removeDefaultSql, sql );
}
@ -5821,7 +5812,7 @@ QGISEXTERN QString loadStyle( const QString &uri, QString &errCause )
}
else
{
geomColumnExpr = QStringLiteral( "=" ) + QgsSpatiaLiteProvider::quotedValue( dsUri.geometryColumn() );
geomColumnExpr = QStringLiteral( "=" ) + QgsSqliteUtils::quotedString( dsUri.geometryColumn() );
}
QString selectQmlQuery = QString( "SELECT styleQML"
@ -5832,7 +5823,7 @@ QGISEXTERN QString loadStyle( const QString &uri, QString &errCause )
" ORDER BY CASE WHEN useAsDefault THEN 1 ELSE 2 END"
",update_time DESC LIMIT 1" )
.arg( QgsSpatiaLiteProvider::tableSchemaCondition( dsUri ) )
.arg( QgsSpatiaLiteProvider::quotedValue( dsUri.table() ) )
.arg( QgsSqliteUtils::quotedString( dsUri.table() ) )
.arg( geomColumnExpr );
char **results = nullptr;
@ -5912,8 +5903,8 @@ QGISEXTERN int listStyles( const QString &uri, QStringList &ids, QStringList &na
" AND f_geometry_column=%3"
" ORDER BY useasdefault DESC, update_time DESC" )
.arg( QgsSpatiaLiteProvider::tableSchemaCondition( dsUri ) )
.arg( QgsSpatiaLiteProvider::quotedValue( dsUri.table() ) )
.arg( QgsSpatiaLiteProvider::quotedValue( dsUri.geometryColumn() ) );
.arg( QgsSqliteUtils::quotedString( dsUri.table() ) )
.arg( QgsSqliteUtils::quotedString( dsUri.geometryColumn() ) );
ret = sqlite3_get_table( sqliteHandle, selectRelatedQuery.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( SQLITE_OK != ret )
@ -5938,8 +5929,8 @@ QGISEXTERN int listStyles( const QString &uri, QStringList &ids, QStringList &na
" WHERE NOT (f_table_schema %1 AND f_table_name=%2 AND f_geometry_column=%3)"
" ORDER BY update_time DESC" )
.arg( QgsSpatiaLiteProvider::tableSchemaCondition( dsUri ) )
.arg( QgsSpatiaLiteProvider::quotedValue( dsUri.table() ) )
.arg( QgsSpatiaLiteProvider::quotedValue( dsUri.geometryColumn() ) );
.arg( QgsSqliteUtils::quotedString( dsUri.table() ) )
.arg( QgsSqliteUtils::quotedString( dsUri.geometryColumn() ) );
ret = sqlite3_get_table( sqliteHandle, selectOthersQuery.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( SQLITE_OK != ret )
@ -5980,7 +5971,7 @@ QGISEXTERN QString getStyleById( const QString &uri, QString styleId, QString &e
sqlite3 *sqliteHandle = handle->handle();
QString style;
QString selectQmlQuery = QStringLiteral( "SELECT styleQml FROM layer_styles WHERE id=%1" ).arg( QgsSpatiaLiteProvider::quotedValue( styleId ) );
QString selectQmlQuery = QStringLiteral( "SELECT styleQml FROM layer_styles WHERE id=%1" ).arg( QgsSqliteUtils::quotedString( styleId ) );
char **results = nullptr;
int rows;
int columns;

View File

@ -144,7 +144,6 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
static int computeMultiWKB3Dsize( const unsigned char *p_in, int little_endian,
int endian_arch );
static QString quotedIdentifier( QString id );
static QString quotedValue( QString value );
struct SLFieldNotFound {}; //! Exception to throw

View File

@ -46,6 +46,8 @@ class TestQgsSqliteUtils : public QObject
void testPrintfAscii();
void testPrintfUtf8();
void testQuotedString_data();
void testQuotedString();
};
@ -90,6 +92,24 @@ void TestQgsSqliteUtils::testPrintfUtf8()
QCOMPARE( query, QString( "SELECT id FROM tag WHERE LOWER(name)='%1'" ).arg( lowerTag ) );
}
void TestQgsSqliteUtils::testQuotedString_data()
{
QTest::addColumn<QString>( "input" );
QTest::addColumn<QString>( "expected" );
QTest::newRow( "test 1" ) << "university of qgis" << "'university of qgis'";
QTest::newRow( "test 2" ) << "university of 'qgis'" << "'university of ''qgis'''";
QTest::newRow( "test NULL" ) << QString() << "NULL";
}
void TestQgsSqliteUtils::testQuotedString()
{
QFETCH( QString, input );
QFETCH( QString, expected );
QCOMPARE( QgsSqliteUtils::quotedString( input ), expected );
}
QGSTEST_MAIN( TestQgsSqliteUtils )
#include "testqgssqliteutils.moc"