Skip to content

Commit bd87b35

Browse files
authored
Merge pull request #8713 from m-kuhn/sqlite_quoted_value_to_qgssqliteutils
Move sqlite quoted value methods to QgsSqliteUtils
2 parents dab069e + c03f1a6 commit bd87b35

7 files changed

+150
-87
lines changed

src/core/qgssqliteexpressioncompiler.cpp

+3-27
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "qgssqliteexpressioncompiler.h"
1919
#include "qgssqlexpressioncompiler.h"
2020
#include "qgsexpressionnodeimpl.h"
21+
#include "qgssqliteutils.h"
2122

2223
QgsSQLiteExpressionCompiler::QgsSQLiteExpressionCompiler( const QgsFields &fields )
2324
: QgsSqlExpressionCompiler( fields, QgsSqlExpressionCompiler::LikeIsCaseInsensitive | QgsSqlExpressionCompiler::IntegerDivisionResultsInInteger )
@@ -51,38 +52,13 @@ QgsSqlExpressionCompiler::Result QgsSQLiteExpressionCompiler::compileNode( const
5152

5253
QString QgsSQLiteExpressionCompiler::quotedIdentifier( const QString &identifier )
5354
{
54-
QString id( identifier );
55-
id.replace( '\"', QLatin1String( "\"\"" ) );
56-
return id.prepend( '\"' ).append( '\"' );
55+
return QgsSqliteUtils::quotedIdentifier( identifier );
5756
}
5857

5958
QString QgsSQLiteExpressionCompiler::quotedValue( const QVariant &value, bool &ok )
6059
{
6160
ok = true;
62-
63-
if ( value.isNull() )
64-
return QStringLiteral( "NULL" );
65-
66-
switch ( value.type() )
67-
{
68-
case QVariant::Int:
69-
case QVariant::LongLong:
70-
case QVariant::Double:
71-
return value.toString();
72-
73-
case QVariant::Bool:
74-
//SQLite has no boolean literals
75-
return value.toBool() ? "1" : "0";
76-
77-
default:
78-
case QVariant::String:
79-
QString v = value.toString();
80-
// https://www.sqlite.org/lang_expr.html :
81-
// """A string constant is formed by enclosing the string in single quotes (').
82-
// A single quote within the string can be encoded by putting two single quotes
83-
// in a row - as in Pascal. C-style escapes using the backslash character are not supported because they are not standard SQL. """
84-
return v.replace( '\'', QLatin1String( "''" ) ).prepend( '\'' ).append( '\'' );
85-
}
61+
return QgsSqliteUtils::quotedValue( value );
8662
}
8763

8864
QString QgsSQLiteExpressionCompiler::sqlFunctionFromFunctionName( const QString &fnName ) const

src/core/qgssqliteutils.cpp

+35
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include <sqlite3.h>
2121
#include <cstdarg>
22+
#include <QVariant>
2223

2324
void QgsSqlite3Closer::operator()( sqlite3 *database )
2425
{
@@ -101,6 +102,40 @@ QString QgsSqliteUtils::quotedString( const QString &value )
101102
return v.prepend( '\'' ).append( '\'' );
102103
}
103104

105+
QString QgsSqliteUtils::quotedIdentifier( const QString &identifier )
106+
{
107+
QString id( identifier );
108+
id.replace( '\"', QLatin1String( "\"\"" ) );
109+
return id.prepend( '\"' ).append( '\"' );
110+
}
111+
112+
QString QgsSqliteUtils::quotedValue( const QVariant &value )
113+
{
114+
if ( value.isNull() )
115+
return QStringLiteral( "NULL" );
116+
117+
switch ( value.type() )
118+
{
119+
case QVariant::Int:
120+
case QVariant::LongLong:
121+
case QVariant::Double:
122+
return value.toString();
123+
124+
case QVariant::Bool:
125+
//SQLite has no boolean literals
126+
return value.toBool() ? QStringLiteral( "1" ) : QStringLiteral( "0" );
127+
128+
default:
129+
case QVariant::String:
130+
QString v = value.toString();
131+
// https://www.sqlite.org/lang_expr.html :
132+
// """A string constant is formed by enclosing the string in single quotes (').
133+
// A single quote within the string can be encoded by putting two single quotes
134+
// in a row - as in Pascal. C-style escapes using the backslash character are not supported because they are not standard SQL. """
135+
return v.replace( '\'', QLatin1String( "''" ) ).prepend( '\'' ).append( '\'' );
136+
}
137+
}
138+
104139
QString QgsSqlite3Mprintf( const char *format, ... )
105140
{
106141
va_list ap;

src/core/qgssqliteutils.h

+16
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
struct sqlite3;
2828
struct sqlite3_stmt;
29+
class QVariant;
2930

3031
/**
3132
* \ingroup core
@@ -153,6 +154,21 @@ class CORE_EXPORT QgsSqliteUtils
153154
* characters correctly escaped.
154155
*/
155156
static QString quotedString( const QString &value );
157+
158+
/**
159+
* Returns a properly quoted version of \a identifier.
160+
*
161+
* \since QGIS 3.6
162+
*/
163+
static QString quotedIdentifier( const QString &identifier );
164+
165+
/**
166+
* Returns a properly quoted and escaped version of \a value
167+
* for use in SQL strings.
168+
*
169+
* \since QGIS 3.6
170+
*/
171+
static QString quotedValue( const QVariant &value );
156172
};
157173

158174
/**

src/providers/spatialite/qgsspatialitefeatureiterator.cpp

+8-8
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ bool QgsSpatiaLiteFeatureIterator::prepareStatement( const QString &whereClause,
341341

342342
if ( mFetchGeometry )
343343
{
344-
sql += QStringLiteral( ", AsBinary(%1)" ).arg( QgsSpatiaLiteProvider::quotedIdentifier( mSource->mGeometryColumn ) );
344+
sql += QStringLiteral( ", AsBinary(%1)" ).arg( QgsSqliteUtils::quotedIdentifier( mSource->mGeometryColumn ) );
345345
mGeomColIdx = colIdx;
346346
}
347347
sql += QStringLiteral( " FROM %1" ).arg( mSource->mQuery );
@@ -375,7 +375,7 @@ bool QgsSpatiaLiteFeatureIterator::prepareStatement( const QString &whereClause,
375375

376376
QString QgsSpatiaLiteFeatureIterator::quotedPrimaryKey()
377377
{
378-
return mSource->mPrimaryKey.isEmpty() ? QStringLiteral( "ROWID" ) : QgsSpatiaLiteProvider::quotedIdentifier( mSource->mPrimaryKey );
378+
return mSource->mPrimaryKey.isEmpty() ? QStringLiteral( "ROWID" ) : QgsSqliteUtils::quotedIdentifier( mSource->mPrimaryKey );
379379
}
380380

381381
QString QgsSpatiaLiteFeatureIterator::whereClauseFid()
@@ -405,12 +405,12 @@ QString QgsSpatiaLiteFeatureIterator::whereClauseRect()
405405
if ( mRequest.flags() & QgsFeatureRequest::ExactIntersect )
406406
{
407407
// we are requested to evaluate a true INTERSECT relationship
408-
whereClause += QStringLiteral( "Intersects(%1, BuildMbr(%2)) AND " ).arg( QgsSpatiaLiteProvider::quotedIdentifier( mSource->mGeometryColumn ), mbr( mFilterRect ) );
408+
whereClause += QStringLiteral( "Intersects(%1, BuildMbr(%2)) AND " ).arg( QgsSqliteUtils::quotedIdentifier( mSource->mGeometryColumn ), mbr( mFilterRect ) );
409409
}
410410
if ( mSource->mVShapeBased )
411411
{
412412
// handling a VirtualShape layer
413-
whereClause += QStringLiteral( "MbrIntersects(%1, BuildMbr(%2))" ).arg( QgsSpatiaLiteProvider::quotedIdentifier( mSource->mGeometryColumn ), mbr( mFilterRect ) );
413+
whereClause += QStringLiteral( "MbrIntersects(%1, BuildMbr(%2))" ).arg( QgsSqliteUtils::quotedIdentifier( mSource->mGeometryColumn ), mbr( mFilterRect ) );
414414
}
415415
else if ( mFilterRect.isFinite() )
416416
{
@@ -424,7 +424,7 @@ QString QgsSpatiaLiteFeatureIterator::whereClauseRect()
424424
QString idxName = QStringLiteral( "idx_%1_%2" ).arg( mSource->mIndexTable, mSource->mIndexGeometry );
425425
whereClause += QStringLiteral( "%1 IN (SELECT pkid FROM %2 WHERE %3)" )
426426
.arg( quotedPrimaryKey(),
427-
QgsSpatiaLiteProvider::quotedIdentifier( idxName ),
427+
QgsSqliteUtils::quotedIdentifier( idxName ),
428428
mbrFilter );
429429
}
430430
else if ( mSource->mSpatialIndexMbrCache )
@@ -433,13 +433,13 @@ QString QgsSpatiaLiteFeatureIterator::whereClauseRect()
433433
QString idxName = QStringLiteral( "cache_%1_%2" ).arg( mSource->mIndexTable, mSource->mIndexGeometry );
434434
whereClause += QStringLiteral( "%1 IN (SELECT rowid FROM %2 WHERE mbr = FilterMbrIntersects(%3))" )
435435
.arg( quotedPrimaryKey(),
436-
QgsSpatiaLiteProvider::quotedIdentifier( idxName ),
436+
QgsSqliteUtils::quotedIdentifier( idxName ),
437437
mbr( mFilterRect ) );
438438
}
439439
else
440440
{
441441
// using simple MBR filtering
442-
whereClause += QStringLiteral( "MbrIntersects(%1, BuildMbr(%2))" ).arg( QgsSpatiaLiteProvider::quotedIdentifier( mSource->mGeometryColumn ), mbr( mFilterRect ) );
442+
whereClause += QStringLiteral( "MbrIntersects(%1, BuildMbr(%2))" ).arg( QgsSqliteUtils::quotedIdentifier( mSource->mGeometryColumn ), mbr( mFilterRect ) );
443443
}
444444
}
445445
else
@@ -462,7 +462,7 @@ QString QgsSpatiaLiteFeatureIterator::mbr( const QgsRectangle &rect )
462462

463463
QString QgsSpatiaLiteFeatureIterator::fieldName( const QgsField &fld )
464464
{
465-
QString fieldname = QgsSpatiaLiteProvider::quotedIdentifier( fld.name() );
465+
QString fieldname = QgsSqliteUtils::quotedIdentifier( fld.name() );
466466
const QString type = fld.typeName().toLower();
467467
if ( type.contains( QLatin1String( "geometry" ) ) || type.contains( QLatin1String( "point" ) ) ||
468468
type.contains( QLatin1String( "line" ) ) || type.contains( QLatin1String( "polygon" ) ) )

0 commit comments

Comments
 (0)