Skip to content

Commit

Permalink
spatialite provider: fix segfault looking for nonexistent field
Browse files Browse the repository at this point in the history
  • Loading branch information
brushtyler committed Jul 27, 2012
1 parent 1f6246e commit 237baea
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 95 deletions.
222 changes: 127 additions & 95 deletions src/providers/spatialite/qgsspatialiteprovider.cpp
Expand Up @@ -3262,35 +3262,43 @@ bool QgsSpatiaLiteProvider::prepareStatement(

QString primaryKey = !isQuery ? "ROWID" : quotedIdentifier( mPrimaryKey );

QString sql = QString( "SELECT %1" ).arg( primaryKey );
int colIdx = 1; // column 0 is primary key
for ( QgsAttributeList::const_iterator it = fetchAttributes.constBegin(); it != fetchAttributes.constEnd(); ++it )
try
{
const QgsField & fld = field( *it );
QString fieldname = quotedIdentifier( fld.name() );
const QString type = fld.typeName().toLower();
if ( type.contains( "geometry" ) || type.contains( "point" ) ||
type.contains( "line" ) || type.contains( "polygon" ) )
QString sql = QString( "SELECT %1" ).arg( primaryKey );
int colIdx = 1; // column 0 is primary key
for ( QgsAttributeList::const_iterator it = fetchAttributes.constBegin(); it != fetchAttributes.constEnd(); ++it )
{
fieldname = QString( "AsText(%1)" ).arg( fieldname );
const QgsField & fld = field( *it );
QString fieldname = quotedIdentifier( fld.name() );
const QString type = fld.typeName().toLower();
if ( type.contains( "geometry" ) || type.contains( "point" ) ||
type.contains( "line" ) || type.contains( "polygon" ) )
{
fieldname = QString( "AsText(%1)" ).arg( fieldname );
}
sql += "," + fieldname;
colIdx++;
}
sql += "," + fieldname;
colIdx++;
}
if ( fetchGeometry )
{
sql += QString( ", AsBinary(%1)" ).arg( quotedIdentifier( mGeometryColumn ) );
mGeomColIdx = colIdx;
}
sql += QString( " FROM %1" ).arg( mQuery );
if ( fetchGeometry )
{
sql += QString( ", AsBinary(%1)" ).arg( quotedIdentifier( mGeometryColumn ) );
mGeomColIdx = colIdx;
}
sql += QString( " FROM %1" ).arg( mQuery );

if ( !whereClause.isEmpty() )
sql += QString( " WHERE %1" ).arg( whereClause );
if ( !whereClause.isEmpty() )
sql += QString( " WHERE %1" ).arg( whereClause );

if ( sqlite3_prepare_v2( sqliteHandle, sql.toUtf8().constData(), -1, &stmt, NULL ) != SQLITE_OK )
if ( sqlite3_prepare_v2( sqliteHandle, sql.toUtf8().constData(), -1, &stmt, NULL ) != SQLITE_OK )
{
// some error occurred
QgsMessageLog::logMessage( tr( "SQLite error: %2\nSQL: %1" ).arg( sql ).arg( sqlite3_errmsg( sqliteHandle ) ), tr( "SpatiaLite" ) );
return false;
}
}
catch ( SLFieldNotFound )
{
// some error occurred
QgsMessageLog::logMessage( tr( "SQLite error: %2\nSQL: %1" ).arg( sql ).arg( sqlite3_errmsg( sqliteHandle ) ), tr( "SpatiaLite" ) );
rewind();
return false;
}

Expand Down Expand Up @@ -3393,40 +3401,48 @@ QVariant QgsSpatiaLiteProvider::minimumValue( int index )
int columns;
char *errMsg = NULL;
QString minValue;
QString sql;

// get the field name
const QgsField & fld = field( index );
try
{
// get the field name
const QgsField & fld = field( index );

QString sql = QString( "SELECT Min(%1) FROM %2" ).arg( quotedIdentifier( fld.name() ) ).arg( mQuery );
sql = QString( "SELECT Min(%1) FROM %2" ).arg( quotedIdentifier( fld.name() ) ).arg( mQuery );

if ( !mSubsetString.isEmpty() )
{
sql += " WHERE ( " + mSubsetString + ")";
}
if ( !mSubsetString.isEmpty() )
{
sql += " WHERE ( " + mSubsetString + ")";
}

ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )
goto error;
if ( rows < 1 )
;
else
{
for ( i = 1; i <= rows; i++ )
ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )
goto error;
if ( rows < 1 )
;
else
{
for ( i = 1; i <= rows; i++ )
{
minValue = results[( i * columns ) + 0];
}
}
sqlite3_free_table( results );

if ( minValue.isEmpty() )
{
// NULL or not found
return QVariant( QString::null );
}
else
{
minValue = results[( i * columns ) + 0];
return convertValue( fld.type(), minValue );
}
}
sqlite3_free_table( results );

if ( minValue.isEmpty() )
catch ( SLFieldNotFound )
{
// NULL or not found
return QVariant( QString::null );
}
else
{
return convertValue( fld.type(), minValue );
}

error:
QgsMessageLog::logMessage( tr( "SQLite error: %2\nSQL: %1" ).arg( sql ).arg( errMsg ? errMsg : tr( "unknown cause" ) ), tr( "SpatiaLite" ) );
Expand All @@ -3448,39 +3464,47 @@ QVariant QgsSpatiaLiteProvider::maximumValue( int index )
int columns;
char *errMsg = NULL;
QString maxValue;
QString sql;

// get the field name
const QgsField & fld = field( index );
try
{
// get the field name
const QgsField & fld = field( index );

QString sql = QString( "SELECT Max(%1) FROM %2" ).arg( quotedIdentifier( fld.name() ) ).arg( mQuery );
sql = QString( "SELECT Max(%1) FROM %2" ).arg( quotedIdentifier( fld.name() ) ).arg( mQuery );

if ( !mSubsetString.isEmpty() )
{
sql += " WHERE ( " + mSubsetString + ")";
}
if ( !mSubsetString.isEmpty() )
{
sql += " WHERE ( " + mSubsetString + ")";
}

ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )
goto error;
if ( rows < 1 )
;
else
{
for ( i = 1; i <= rows; i++ )
ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
if ( ret != SQLITE_OK )
goto error;
if ( rows < 1 )
;
else
{
maxValue = results[( i * columns ) + 0];
for ( i = 1; i <= rows; i++ )
{
maxValue = results[( i * columns ) + 0];
}
}
}
sqlite3_free_table( results );
sqlite3_free_table( results );

if ( maxValue.isEmpty() )
{
// NULL or not found
return QVariant( QString::null );
if ( maxValue.isEmpty() )
{
// NULL or not found
return QVariant( QString::null );
}
else
{
return convertValue( fld.type(), maxValue );
}
}
else
catch ( SLFieldNotFound )
{
return convertValue( fld.type(), maxValue );
return QVariant( QString::null );
}

error:
Expand Down Expand Up @@ -3910,34 +3934,41 @@ bool QgsSpatiaLiteProvider::changeAttributeValues( const QgsChangedAttributesMap
// cycle through the changed attributes of the feature
for ( QgsAttributeMap::const_iterator siter = attrs.begin(); siter != attrs.end(); ++siter )
{
QString fieldName = field( siter.key() ).name();
try
{
QString fieldName = field( siter.key() ).name();

if ( !first )
sql += ",";
else
first = false;
if ( !first )
sql += ",";
else
first = false;

QVariant::Type type = siter->type();
if ( siter->toString().isEmpty() )
{
// assuming to be a NULL value
type = QVariant::Invalid;
}
QVariant::Type type = siter->type();
if ( siter->toString().isEmpty() )
{
// assuming to be a NULL value
type = QVariant::Invalid;
}

if ( type == QVariant::Invalid )
{
// binding a NULL value
sql += QString( "%1=NULL" ).arg( quotedIdentifier( fieldName ) );
}
else if ( type == QVariant::Int || type == QVariant::Double )
{
// binding a NUMERIC value
sql += QString( "%1=%2" ).arg( quotedIdentifier( fieldName ) ).arg( siter->toString() );
if ( type == QVariant::Invalid )
{
// binding a NULL value
sql += QString( "%1=NULL" ).arg( quotedIdentifier( fieldName ) );
}
else if ( type == QVariant::Int || type == QVariant::Double )
{
// binding a NUMERIC value
sql += QString( "%1=%2" ).arg( quotedIdentifier( fieldName ) ).arg( siter->toString() );
}
else
{
// binding a TEXT value
sql += QString( "%1=%2" ).arg( quotedIdentifier( fieldName ) ).arg( quotedValue( siter->toString() ) );
}
}
else
catch ( SLFieldNotFound )
{
// binding a TEXT value
sql += QString( "%1=%2" ).arg( quotedIdentifier( fieldName ) ).arg( quotedValue( siter->toString() ) );
// Field was missing - shouldn't happen
}
}
sql += QString( " WHERE ROWID=%1" ).arg( fid );
Expand Down Expand Up @@ -4865,7 +4896,8 @@ const QgsField & QgsSpatiaLiteProvider::field( int index ) const

if ( it == attributeFields.constEnd() )
{
QgsDebugMsg( QString( "Field %1 not found." ).arg( index ) );
QgsLogger::warning( QString( "FAILURE: Field %1 not found." ).arg( index ) );
throw SLFieldNotFound();
}

return it.value();
Expand Down
2 changes: 2 additions & 0 deletions src/providers/spatialite/qgsspatialiteprovider.h
Expand Up @@ -453,6 +453,8 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
GEOS_3D_GEOMETRYCOLLECTION = -2147483641,
};

struct SLFieldNotFound {}; //! Exception to throw

public:
static QString quotedIdentifier( QString id );
static QString quotedValue( QString value );
Expand Down

0 comments on commit 237baea

Please sign in to comment.