Skip to content

Commit

Permalink
[spatialite] Several fixes for provider (Fix #8636)
Browse files Browse the repository at this point in the history
And fixes the NoGeometry behavior
  • Loading branch information
m-kuhn committed Oct 12, 2013
1 parent 44b7767 commit adc850e
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 137 deletions.
2 changes: 1 addition & 1 deletion src/core/qgsfeature.h
Expand Up @@ -325,6 +325,6 @@ typedef QMap<int, QString> QgsFieldNameMap;

typedef QList<QgsFeature> QgsFeatureList;

Q_DECLARE_METATYPE( QgsFeatureList );
Q_DECLARE_METATYPE( QgsFeatureList )

#endif
5 changes: 3 additions & 2 deletions src/providers/spatialite/qgsspatialitefeatureiterator.cpp
Expand Up @@ -44,6 +44,8 @@ QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteProvide
{
P->mActiveIterators << this;

mFetchGeometry = !P->mGeometryColumn.isNull() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry );

QString whereClause;
if ( request.filterType() == QgsFeatureRequest::FilterRect && !P->mGeometryColumn.isNull() )
{
Expand Down Expand Up @@ -278,7 +280,6 @@ QString QgsSpatiaLiteFeatureIterator::fieldName( const QgsField& fld )

bool QgsSpatiaLiteFeatureIterator::getFeature( sqlite3_stmt *stmt, QgsFeature &feature )
{
mFetchGeometry = !( mRequest.flags() & QgsFeatureRequest::NoGeometry );
bool subsetAttributes = mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes;

int ret = sqlite3_step( stmt );
Expand Down Expand Up @@ -331,7 +332,7 @@ bool QgsSpatiaLiteFeatureIterator::getFeature( sqlite3_stmt *stmt, QgsFeature &f
}
else
{
int attrIndex = subsetAttributes ? mRequest.subsetOfAttributes()[ic-1] : ic - 1;
int attrIndex = ic - 1;
feature.setAttribute( attrIndex, getFeatureAttribute( stmt, ic, P->attributeFields[attrIndex].type() ) );
}
}
Expand Down
1 change: 0 additions & 1 deletion src/providers/spatialite/qgsspatialitefeatureiterator.h
Expand Up @@ -65,7 +65,6 @@ class QgsSpatiaLiteFeatureIterator : public QgsAbstractFeatureIterator

//! Set to true, if geometry is in the requested columns
bool mFetchGeometry;

};

#endif // QGSSPATIALITEFEATUREITERATOR_H
262 changes: 129 additions & 133 deletions src/providers/spatialite/qgsspatialiteprovider.cpp
Expand Up @@ -3552,168 +3552,164 @@ bool QgsSpatiaLiteProvider::addFeatures( QgsFeatureList & flist )
const QgsAttributes & attributevec = flist[0].attributes();

ret = sqlite3_exec( sqliteHandle, "BEGIN", NULL, NULL, &errMsg );
if ( ret != SQLITE_OK )
{
// some error occurred
goto abort;
}
toCommit = true;

sql = QString( "INSERT INTO %1(" ).arg( quotedIdentifier( mTableName ) );
values = QString( ") VALUES (" );
separator = "";

if ( !mGeometryColumn.isEmpty() )
{
sql += separator + quotedIdentifier( mGeometryColumn );
values += separator + geomParam();
separator = ",";
}

for ( int i = 0; i < attributevec.count(); ++i )
{
if ( !attributevec[i].isNull() )
continue;

if ( i >= attributeFields.count() )
continue;

QString fieldname = attributeFields[i].name();
if ( fieldname.isEmpty() || fieldname == mGeometryColumn )
continue;

sql += separator + quotedIdentifier( fieldname );
values += separator + "?";
separator = ",";
}

sql += values;
sql += ")";

// SQLite prepared statement
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;
}

for ( QgsFeatureList::iterator features = flist.begin(); features != flist.end(); features++ )
if ( ret == SQLITE_OK )
{
// looping on each feature to insert
const QgsAttributes& attributevec = features->attributes();

// resetting Prepared Statement and bindings
sqlite3_reset( stmt );
sqlite3_clear_bindings( stmt );
toCommit = true;

// initializing the column counter
ia = 0;
sql = QString( "INSERT INTO %1(" ).arg( quotedIdentifier( mTableName ) );
values = QString( ") VALUES (" );
separator = "";

if ( !mGeometryColumn.isEmpty() )
{
// binding GEOMETRY to Prepared Statement
if ( !features->geometry() )
{
sqlite3_bind_null( stmt, ++ia );
}
else
{
unsigned char *wkb = NULL;
size_t wkb_size;
convertFromGeosWKB( features->geometry()->asWkb(),
features->geometry()->wkbSize(),
&wkb, &wkb_size, nDims );
if ( !wkb )
sqlite3_bind_null( stmt, ++ia );
else
sqlite3_bind_blob( stmt, ++ia, wkb, wkb_size, free );
}
sql += separator + quotedIdentifier( mGeometryColumn );
values += separator + geomParam();
separator = ",";
}

for ( int i = 0; i < attributevec.count(); ++i )
{
QVariant v = attributevec[i];
if ( !v.isNull() )
if ( !attributevec[i].isValid() )
continue;

// binding values for each attribute
if ( i >= attributeFields.count() )
break;
continue;

QString fieldname = attributeFields[i].name();
if ( fieldname.isEmpty() || fieldname == mGeometryColumn )
continue;

QVariant::Type type = attributeFields[i].type();
sql += separator + quotedIdentifier( fieldname );
values += separator + "?";
separator = ",";
}

if ( type == QVariant::Int )
{
// binding an INTEGER value
sqlite3_bind_int( stmt, ++ia, v.toInt() );
}
else if ( type == QVariant::Double )
{
// binding a DOUBLE value
sqlite3_bind_double( stmt, ++ia, v.toDouble() );
}
else if ( type == QVariant::String )
sql += values;
sql += ")";

// SQLite prepared statement
ret = sqlite3_prepare_v2( sqliteHandle, sql.toUtf8().constData(), -1, &stmt, NULL );
if ( ret == SQLITE_OK )
{
for ( QgsFeatureList::iterator feature = flist.begin(); feature != flist.end(); feature++ )
{
// binding a TEXT value
QByteArray ba = v.toString().toUtf8();
sqlite3_bind_text( stmt, ++ia, ba.constData(), ba.size(), SQLITE_TRANSIENT );
// looping on each feature to insert
const QgsAttributes& attributevec = feature->attributes();

// resetting Prepared Statement and bindings
sqlite3_reset( stmt );
sqlite3_clear_bindings( stmt );

// initializing the column counter
ia = 0;

if ( !mGeometryColumn.isEmpty() )
{
// binding GEOMETRY to Prepared Statement
if ( !feature->geometry() )
{
sqlite3_bind_null( stmt, ++ia );
}
else
{
unsigned char *wkb = NULL;
size_t wkb_size;
convertFromGeosWKB( feature->geometry()->asWkb(),
feature->geometry()->wkbSize(),
&wkb, &wkb_size, nDims );
if ( !wkb )
sqlite3_bind_null( stmt, ++ia );
else
sqlite3_bind_blob( stmt, ++ia, wkb, wkb_size, free );
}
}

for ( int i = 0; i < attributevec.count(); ++i )
{
QVariant v = attributevec[i];
if ( !v.isValid() )
continue;

// binding values for each attribute
if ( i >= attributeFields.count() )
break;

QString fieldname = attributeFields[i].name();
if ( fieldname.isEmpty() || fieldname == mGeometryColumn )
continue;

QVariant::Type type = attributeFields[i].type();

if ( type == QVariant::Int )
{
// binding an INTEGER value
sqlite3_bind_int( stmt, ++ia, v.toInt() );
}
if ( type == QVariant::LongLong )
{
// binding a LONGLONG value
sqlite3_bind_int64( stmt, ++ia, v.toLongLong() );
}
else if ( type == QVariant::Double )
{
// binding a DOUBLE value
sqlite3_bind_double( stmt, ++ia, v.toDouble() );
}
else if ( type == QVariant::String )
{
// binding a TEXT value
QByteArray ba = v.toString().toUtf8();
sqlite3_bind_text( stmt, ++ia, ba.constData(), ba.size(), SQLITE_TRANSIENT );
}
else
{
// binding a NULL value
sqlite3_bind_null( stmt, ++ia );
}
}

// performing actual row insert
ret = sqlite3_step( stmt );

if ( ret == SQLITE_DONE || ret == SQLITE_ROW )
{
// update feature id
feature->setFeatureId( sqlite3_last_insert_rowid( sqliteHandle ) );
numberFeatures++;
}
else
{
// some unexpected error occurred
const char *err = sqlite3_errmsg( sqliteHandle );
int len = strlen( err );
errMsg = ( char * ) sqlite3_malloc( len + 1 );
strcpy( errMsg, err );
break;
}
}
else
if ( ret == SQLITE_DONE || ret == SQLITE_ROW )
{
// binding a NULL value
sqlite3_bind_null( stmt, ++ia );
ret = sqlite3_exec( sqliteHandle, "COMMIT", NULL, NULL, &errMsg );
}
}
} // prepared statement
} // BEGIN statement

// performing actual row insert
ret = sqlite3_step( stmt );

if ( ret == SQLITE_DONE || ret == SQLITE_ROW )
if ( ret != SQLITE_OK )
{
pushError( tr( "SQLite error: %2\nSQL: %1" ).arg( sql ).arg( errMsg ? errMsg : tr( "unknown cause" ) ) );
if ( errMsg )
{
// update feature id
features->setFeatureId( sqlite3_last_insert_rowid( sqliteHandle ) );
numberFeatures++;
sqlite3_free( errMsg );
}
else

if ( toCommit )
{
// some unexpected error occurred
const char *err = sqlite3_errmsg( sqliteHandle );
int len = strlen( err );
errMsg = ( char * ) sqlite3_malloc( len + 1 );
strcpy( errMsg, err );
goto abort;
// ROLLBACK after some previous error
sqlite3_exec( sqliteHandle, "ROLLBACK", NULL, NULL, NULL );
}

}
sqlite3_finalize( stmt );

ret = sqlite3_exec( sqliteHandle, "COMMIT", NULL, NULL, &errMsg );
if ( ret != SQLITE_OK )
{
// some error occurred
goto abort;
}
return true;

abort:
pushError( tr( "SQLite error: %2\nSQL: %1" ).arg( sql ).arg( errMsg ? errMsg : tr( "unknown cause" ) ) );
if ( errMsg )
{
sqlite3_free( errMsg );
}

if ( toCommit )
{
// ROLLBACK after some previous error
sqlite3_exec( sqliteHandle, "ROLLBACK", NULL, NULL, NULL );
}

return false;
return ret == SQLITE_OK;
}

bool QgsSpatiaLiteProvider::deleteFeatures( const QgsFeatureIds &id )
Expand Down

1 comment on commit adc850e

@gioman
Copy link
Contributor

@gioman gioman commented on adc850e Oct 12, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any of this fixes do also fix http://hub.qgis.org/issues/8340 and/or http://hub.qgis.org/issues/8638 ? cheers!

Please sign in to comment.