diff --git a/src/app/qgscustomprojectiondialog.cpp b/src/app/qgscustomprojectiondialog.cpp index cc2470a3a6e5..75e4f863ae47 100644 --- a/src/app/qgscustomprojectiondialog.cpp +++ b/src/app/qgscustomprojectiondialog.cpp @@ -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" ) ); diff --git a/src/app/qgscustomprojectiondialog.h b/src/app/qgscustomprojectiondialog.h index f1b74773827c..045716607e61 100644 --- a/src/app/qgscustomprojectiondialog.h +++ b/src/app/qgscustomprojectiondialog.h @@ -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 ); diff --git a/src/app/qgsnewspatialitelayerdialog.cpp b/src/app/qgsnewspatialitelayerdialog.cpp index 81fb6e8ca412..60075c5b4026 100644 --- a/src/app/qgsnewspatialitelayerdialog.cpp +++ b/src/app/qgsnewspatialitelayerdialog.cpp @@ -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" ) ); diff --git a/src/app/qgsnewspatialitelayerdialog.h b/src/app/qgsnewspatialitelayerdialog.h index 689e5838d2bd..4b63cbfbf72f 100644 --- a/src/app/qgsnewspatialitelayerdialog.h +++ b/src/app/qgsnewspatialitelayerdialog.h @@ -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; diff --git a/src/core/qgscoordinatereferencesystem.cpp b/src/core/qgscoordinatereferencesystem.cpp index 68abac9b39d4..c3585ab6ac22 100644 --- a/src/core/qgscoordinatereferencesystem.cpp +++ b/src/core/qgscoordinatereferencesystem.cpp @@ -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 ¶m, 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 &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 ); diff --git a/src/core/qgscoordinatereferencesystem.h b/src/core/qgscoordinatereferencesystem.h index 72c8cc29bc71..cbc905258c87 100644 --- a/src/core/qgscoordinatereferencesystem.h +++ b/src/core/qgscoordinatereferencesystem.h @@ -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' diff --git a/src/core/qgssqliteutils.cpp b/src/core/qgssqliteutils.cpp index d5c6459609ea..5dd6db00af1d 100644 --- a/src/core/qgssqliteutils.cpp +++ b/src/core/qgssqliteutils.cpp @@ -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; diff --git a/src/core/qgssqliteutils.h b/src/core/qgssqliteutils.h index fc89678e1f12..4d8055f1c2b5 100644 --- a/src/core/qgssqliteutils.h +++ b/src/core/qgssqliteutils.h @@ -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. diff --git a/src/providers/spatialite/qgsspatialiteconnection.cpp b/src/providers/spatialite/qgsspatialiteconnection.cpp index fe8483f59001..7298b95d943d 100644 --- a/src/providers/spatialite/qgsspatialiteconnection.cpp +++ b/src/providers/spatialite/qgsspatialiteconnection.cpp @@ -454,15 +454,6 @@ bool QgsSpatiaLiteConnection::getTableInfo( sqlite3 *handle, bool loadGeometryle 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 ) diff --git a/src/providers/spatialite/qgsspatialiteconnection.h b/src/providers/spatialite/qgsspatialiteconnection.h index 1be6ff0b37f2..08b34cb0792b 100644 --- a/src/providers/spatialite/qgsspatialiteconnection.h +++ b/src/providers/spatialite/qgsspatialiteconnection.h @@ -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 ); diff --git a/src/providers/spatialite/qgsspatialiteprovider.cpp b/src/providers/spatialite/qgsspatialiteprovider.cpp index cc3c3680eb42..982841113a8c 100644 --- a/src/providers/spatialite/qgsspatialiteprovider.cpp +++ b/src/providers/spatialite/qgsspatialiteprovider.cpp @@ -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; diff --git a/src/providers/spatialite/qgsspatialiteprovider.h b/src/providers/spatialite/qgsspatialiteprovider.h index 3f6a6bba6616..b94329d40a41 100644 --- a/src/providers/spatialite/qgsspatialiteprovider.h +++ b/src/providers/spatialite/qgsspatialiteprovider.h @@ -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 diff --git a/tests/src/core/testqgssqliteutils.cpp b/tests/src/core/testqgssqliteutils.cpp index 7b78e5abeeb5..34353299e80e 100644 --- a/tests/src/core/testqgssqliteutils.cpp +++ b/tests/src/core/testqgssqliteutils.cpp @@ -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( "input" ); + QTest::addColumn( "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"