qgsogrprovider.cpp (QGIS-final-3_10_11) | : | qgsogrprovider.cpp (QGIS-final-3_10_12) | ||
---|---|---|---|---|
skipping to change at line 1408 | skipping to change at line 1408 | |||
} | } | |||
QString QgsOgrProvider::defaultValueClause( int fieldIndex ) const | QString QgsOgrProvider::defaultValueClause( int fieldIndex ) const | |||
{ | { | |||
return mDefaultValues.value( fieldIndex, QString() ); | return mDefaultValues.value( fieldIndex, QString() ); | |||
} | } | |||
bool QgsOgrProvider::skipConstraintCheck( int fieldIndex, QgsFieldConstraints::C onstraint constraint, const QVariant &value ) const | bool QgsOgrProvider::skipConstraintCheck( int fieldIndex, QgsFieldConstraints::C onstraint constraint, const QVariant &value ) const | |||
{ | { | |||
Q_UNUSED( constraint ) | Q_UNUSED( constraint ) | |||
// If the field is a fid, skip in case it's the default value | if ( providerProperty( EvaluateDefaultValues, false ).toBool() ) | |||
if ( fieldIndex == 0 && mFirstFieldIsFid ) | ||||
{ | { | |||
return ! mDefaultValues.value( fieldIndex ).isEmpty(); | return ! mDefaultValues.value( fieldIndex ).isEmpty(); | |||
} | } | |||
else | else | |||
{ | { | |||
// stricter check | // stricter check | |||
return mDefaultValues.contains( fieldIndex ) && mDefaultValues.value( fieldI ndex ) == value.toString() && !value.isNull(); | return mDefaultValues.contains( fieldIndex ) && mDefaultValues.value( fieldI ndex ) == value.toString() && !value.isNull(); | |||
} | } | |||
} | } | |||
skipping to change at line 1522 | skipping to change at line 1521 | |||
{ | { | |||
//store as string, because it's no valid QJson value | //store as string, because it's no valid QJson value | |||
stringValue = value.toString(); | stringValue = value.toString(); | |||
} | } | |||
return stringValue; | return stringValue; | |||
} | } | |||
bool QgsOgrProvider::addFeaturePrivate( QgsFeature &f, Flags flags ) | bool QgsOgrProvider::addFeaturePrivate( QgsFeature &f, Flags flags ) | |||
{ | { | |||
bool returnValue = true; | bool returnValue = true; | |||
QgsOgrFeatureDefn &fdef = mOgrLayer->GetLayerDefn(); | QgsOgrFeatureDefn &featureDefinition = mOgrLayer->GetLayerDefn(); | |||
gdal::ogr_feature_unique_ptr feature( fdef.CreateFeature() ); | gdal::ogr_feature_unique_ptr feature( featureDefinition.CreateFeature() ); | |||
if ( f.hasGeometry() ) | if ( f.hasGeometry() ) | |||
{ | { | |||
QByteArray wkb( f.geometry().asWkb() ); | QByteArray wkb( f.geometry().asWkb() ); | |||
OGRGeometryH geom = nullptr; | OGRGeometryH geom = nullptr; | |||
if ( !wkb.isEmpty() ) | if ( !wkb.isEmpty() ) | |||
{ | { | |||
if ( OGR_G_CreateFromWkb( reinterpret_cast<unsigned char *>( const_cast<ch ar *>( wkb.constData() ) ), nullptr, &geom, wkb.length() ) != OGRERR_NONE ) | if ( OGR_G_CreateFromWkb( reinterpret_cast<unsigned char *>( const_cast<ch ar *>( wkb.constData() ) ), nullptr, &geom, wkb.length() ) != OGRERR_NONE ) | |||
{ | { | |||
pushError( tr( "OGR error creating wkb for feature %1: %2" ).arg( f.id() ).arg( CPLGetLastErrorMsg() ) ); | pushError( tr( "OGR error creating wkb for feature %1: %2" ).arg( f.id() ).arg( CPLGetLastErrorMsg() ) ); | |||
return false; | return false; | |||
} | } | |||
geom = ConvertGeometryIfNecessary( geom ); | geom = ConvertGeometryIfNecessary( geom ); | |||
OGR_F_SetGeometryDirectly( feature.get(), geom ); | OGR_F_SetGeometryDirectly( feature.get(), geom ); | |||
} | } | |||
} | } | |||
QgsAttributes attrs = f.attributes(); | QgsAttributes attributes = f.attributes(); | |||
const QgsFields qgisFields { f.fields() }; | ||||
QgsLocaleNumC l; | QgsLocaleNumC l; | |||
int qgisAttId = ( mFirstFieldIsFid ) ? 1 : 0; | int qgisAttributeId = ( mFirstFieldIsFid ) ? 1 : 0; | |||
// If the first attribute is the FID and the user has set it, then use it | // If the first attribute is the FID and the user has set it, then use it | |||
if ( mFirstFieldIsFid && attrs.count() > 0 ) | if ( mFirstFieldIsFid && attributes.count() > 0 ) | |||
{ | { | |||
QVariant attrFid = attrs.at( 0 ); | QVariant attrFid = attributes.at( 0 ); | |||
if ( !attrFid.isNull() ) | if ( !attrFid.isNull() ) | |||
{ | { | |||
bool ok = false; | bool ok = false; | |||
qlonglong id = attrFid.toLongLong( &ok ); | qlonglong id = attrFid.toLongLong( &ok ); | |||
if ( ok ) | if ( ok ) | |||
{ | { | |||
OGR_F_SetFID( feature.get(), static_cast<GIntBig>( id ) ); | OGR_F_SetFID( feature.get(), static_cast<GIntBig>( id ) ); | |||
} | } | |||
} | } | |||
} | } | |||
//add possible attribute information | //add possible attribute information | |||
for ( int ogrAttId = 0; qgisAttId < attrs.count(); ++qgisAttId, ++ogrAttId ) | for ( int ogrAttributeId = 0; qgisAttributeId < attributes.count(); ++qgisAttr ibuteId, ++ogrAttributeId ) | |||
{ | { | |||
// Skip fields that have no provider origin | ||||
if ( qgisFields.exists( qgisAttributeId ) && qgisFields.fieldOrigin( qgisAtt | ||||
ributeId ) != QgsFields::FieldOrigin::OriginProvider ) | ||||
{ | ||||
qgisAttributeId++; | ||||
continue; | ||||
} | ||||
// don't try to set field from attribute map if it's not present in layer | // don't try to set field from attribute map if it's not present in layer | |||
if ( ogrAttId >= fdef.GetFieldCount() ) | if ( ogrAttributeId >= featureDefinition.GetFieldCount() ) | |||
{ | { | |||
pushError( tr( "Feature has too many attributes (expecting %1, received %2 )" ).arg( fdef.GetFieldCount() ).arg( f.attributes().count() ) ); | pushError( tr( "Feature has too many attributes (expecting %1, received %2 )" ).arg( featureDefinition.GetFieldCount() ).arg( f.attributes().count() ) ); | |||
continue; | continue; | |||
} | } | |||
//if(!s.isEmpty()) | //if(!s.isEmpty()) | |||
// continue; | // continue; | |||
// | // | |||
OGRFieldDefnH fldDef = fdef.GetFieldDefn( ogrAttId ); | OGRFieldDefnH fldDef = featureDefinition.GetFieldDefn( ogrAttributeId ); | |||
OGRFieldType type = OGR_Fld_GetType( fldDef ); | OGRFieldType type = OGR_Fld_GetType( fldDef ); | |||
QVariant attrVal = attrs.at( qgisAttId ); | QVariant attrVal = attributes.at( qgisAttributeId ); | |||
// The field value is equal to the default (that might be a provider-side ex pression) | // The field value is equal to the default (that might be a provider-side ex pression) | |||
if ( mDefaultValues.contains( qgisAttId ) && attrVal.toString() == mDefaultV alues.value( qgisAttId ) ) | if ( mDefaultValues.contains( qgisAttributeId ) && attrVal.toString() == mDe faultValues.value( qgisAttributeId ) ) | |||
{ | { | |||
OGR_F_UnsetField( feature.get(), ogrAttId ); | OGR_F_UnsetField( feature.get(), ogrAttributeId ); | |||
} | } | |||
else if ( attrVal.isNull() || ( type != OFTString && attrVal.toString().isEm pty() ) ) | else if ( attrVal.isNull() || ( type != OFTString && attrVal.toString().isEm pty() ) ) | |||
{ | { | |||
// Starting with GDAL 2.2, there are 2 concepts: unset fields and null fields | // Starting with GDAL 2.2, there are 2 concepts: unset fields and null fields | |||
// whereas previously there was only unset fields. For a GeoJSON output, | // whereas previously there was only unset fields. For a GeoJSON output, | |||
// leaving a field unset will cause it to not appear at all in the output | // leaving a field unset will cause it to not appear at all in the output | |||
// feature. | // feature. | |||
// When all features of a layer have a field unset, this would cause the | // When all features of a layer have a field unset, this would cause the | |||
// field to not be present at all in the output, and thus on reading to | // field to not be present at all in the output, and thus on reading to | |||
// have disappeared. #16812 | // have disappeared. #16812 | |||
#ifdef OGRNullMarker | #ifdef OGRNullMarker | |||
OGR_F_SetFieldNull( feature.get(), ogrAttId ); | OGR_F_SetFieldNull( feature.get(), ogrAttributeId ); | |||
#else | #else | |||
OGR_F_UnsetField( feature.get(), ogrAttId ); | OGR_F_UnsetField( feature.get(), ogrAttId ); | |||
#endif | #endif | |||
} | } | |||
else | else | |||
{ | { | |||
switch ( type ) | switch ( type ) | |||
{ | { | |||
case OFTInteger: | case OFTInteger: | |||
OGR_F_SetFieldInteger( feature.get(), ogrAttId, attrVal.toInt() ); | OGR_F_SetFieldInteger( feature.get(), ogrAttributeId, attrVal.toInt() ); | |||
break; | break; | |||
case OFTInteger64: | case OFTInteger64: | |||
OGR_F_SetFieldInteger64( feature.get(), ogrAttId, attrVal.toLongLong() ); | OGR_F_SetFieldInteger64( feature.get(), ogrAttributeId, attrVal.toLong Long() ); | |||
break; | break; | |||
case OFTReal: | case OFTReal: | |||
OGR_F_SetFieldDouble( feature.get(), ogrAttId, attrVal.toDouble() ); | OGR_F_SetFieldDouble( feature.get(), ogrAttributeId, attrVal.toDouble( ) ); | |||
break; | break; | |||
case OFTDate: | case OFTDate: | |||
OGR_F_SetFieldDateTime( feature.get(), ogrAttId, | OGR_F_SetFieldDateTime( feature.get(), ogrAttributeId, | |||
attrVal.toDate().year(), | attrVal.toDate().year(), | |||
attrVal.toDate().month(), | attrVal.toDate().month(), | |||
attrVal.toDate().day(), | attrVal.toDate().day(), | |||
0, 0, 0, | 0, 0, 0, | |||
0 ); | 0 ); | |||
break; | break; | |||
case OFTTime: | case OFTTime: | |||
OGR_F_SetFieldDateTime( feature.get(), ogrAttId, | OGR_F_SetFieldDateTime( feature.get(), ogrAttributeId, | |||
0, 0, 0, | 0, 0, 0, | |||
attrVal.toTime().hour(), | attrVal.toTime().hour(), | |||
attrVal.toTime().minute(), | attrVal.toTime().minute(), | |||
attrVal.toTime().second(), | attrVal.toTime().second(), | |||
0 ); | 0 ); | |||
break; | break; | |||
case OFTDateTime: | case OFTDateTime: | |||
OGR_F_SetFieldDateTime( feature.get(), ogrAttId, | OGR_F_SetFieldDateTime( feature.get(), ogrAttributeId, | |||
attrVal.toDateTime().date().year(), | attrVal.toDateTime().date().year(), | |||
attrVal.toDateTime().date().month(), | attrVal.toDateTime().date().month(), | |||
attrVal.toDateTime().date().day(), | attrVal.toDateTime().date().day(), | |||
attrVal.toDateTime().time().hour(), | attrVal.toDateTime().time().hour(), | |||
attrVal.toDateTime().time().minute(), | attrVal.toDateTime().time().minute(), | |||
attrVal.toDateTime().time().second(), | attrVal.toDateTime().time().second(), | |||
0 ); | 0 ); | |||
break; | break; | |||
case OFTString: | case OFTString: | |||
skipping to change at line 1661 | skipping to change at line 1668 | |||
if ( OGR_Fld_GetSubType( fldDef ) == OFSTJSON ) | if ( OGR_Fld_GetSubType( fldDef ) == OFSTJSON ) | |||
stringValue = jsonStringValue( attrVal ); | stringValue = jsonStringValue( attrVal ); | |||
else | else | |||
{ | { | |||
stringValue = attrVal.toString(); | stringValue = attrVal.toString(); | |||
} | } | |||
#else | #else | |||
stringValue = attrVal.toString(); | stringValue = attrVal.toString(); | |||
#endif | #endif | |||
QgsDebugMsgLevel( QStringLiteral( "Writing string attribute %1 with %2 , encoding %3" ) | QgsDebugMsgLevel( QStringLiteral( "Writing string attribute %1 with %2 , encoding %3" ) | |||
.arg( qgisAttId ) | .arg( qgisAttributeId ) | |||
.arg( attrVal.toString(), | .arg( attrVal.toString(), | |||
textEncoding()->name().data() ), 3 ); | textEncoding()->name().data() ), 3 ); | |||
OGR_F_SetFieldString( feature.get(), ogrAttId, textEncoding()->fromUni code( stringValue ).constData() ); | OGR_F_SetFieldString( feature.get(), ogrAttributeId, textEncoding()->f romUnicode( stringValue ).constData() ); | |||
break; | break; | |||
} | } | |||
case OFTBinary: | case OFTBinary: | |||
{ | { | |||
const QByteArray ba = attrVal.toByteArray(); | const QByteArray ba = attrVal.toByteArray(); | |||
OGR_F_SetFieldBinary( feature.get(), ogrAttId, ba.size(), const_cast< GByte * >( reinterpret_cast< const GByte * >( ba.data() ) ) ); | OGR_F_SetFieldBinary( feature.get(), ogrAttributeId, ba.size(), const_ cast< GByte * >( reinterpret_cast< const GByte * >( ba.data() ) ) ); | |||
break; | break; | |||
} | } | |||
#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,4,0) | #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,4,0) | |||
case OFTStringList: | case OFTStringList: | |||
{ | { | |||
QStringList list = attrVal.toStringList(); | QStringList list = attrVal.toStringList(); | |||
int count = list.count(); | int count = list.count(); | |||
char **lst = new char *[count + 1]; | char **lst = new char *[count + 1]; | |||
if ( count > 0 ) | if ( count > 0 ) | |||
{ | { | |||
int pos = 0; | int pos = 0; | |||
for ( QString string : list ) | for ( QString string : list ) | |||
{ | { | |||
lst[pos] = textEncoding()->fromUnicode( string ).data(); | lst[pos] = textEncoding()->fromUnicode( string ).data(); | |||
pos++; | pos++; | |||
} | } | |||
} | } | |||
lst[count] = nullptr; | lst[count] = nullptr; | |||
OGR_F_SetFieldStringList( feature.get(), ogrAttId, lst ); | OGR_F_SetFieldStringList( feature.get(), ogrAttributeId, lst ); | |||
break; | break; | |||
} | } | |||
#endif | #endif | |||
default: | default: | |||
QgsMessageLog::logMessage( tr( "type %1 for attribute %2 not found" ). arg( type ).arg( qgisAttId ), tr( "OGR" ) ); | QgsMessageLog::logMessage( tr( "type %1 for attribute %2 not found" ). arg( type ).arg( qgisAttributeId ), tr( "OGR" ) ); | |||
break; | break; | |||
} | } | |||
} | } | |||
} | } | |||
if ( mOgrLayer->CreateFeature( feature.get() ) != OGRERR_NONE ) | if ( mOgrLayer->CreateFeature( feature.get() ) != OGRERR_NONE ) | |||
{ | { | |||
pushError( tr( "OGR error creating feature %1: %2" ).arg( f.id() ).arg( CPLG etLastErrorMsg() ) ); | pushError( tr( "OGR error creating feature %1: %2" ).arg( f.id() ).arg( CPLG etLastErrorMsg() ) ); | |||
returnValue = false; | returnValue = false; | |||
} | } | |||
else if ( !( flags & QgsFeatureSink::FastInsert ) ) | else if ( !( flags & QgsFeatureSink::FastInsert ) ) | |||
{ | { | |||
QgsFeatureId id = static_cast<QgsFeatureId>( OGR_F_GetFID( feature.get() ) ) ; | QgsFeatureId id = static_cast<QgsFeatureId>( OGR_F_GetFID( feature.get() ) ) ; | |||
if ( id >= 0 ) | if ( id >= 0 ) | |||
{ | { | |||
f.setId( id ); | f.setId( id ); | |||
if ( mFirstFieldIsFid && attrs.count() > 0 ) | if ( mFirstFieldIsFid && attributes.count() > 0 ) | |||
{ | { | |||
f.setAttribute( 0, id ); | f.setAttribute( 0, id ); | |||
} | } | |||
} | } | |||
} | } | |||
return returnValue; | return returnValue; | |||
} | } | |||
bool QgsOgrProvider::addFeatures( QgsFeatureList &flist, Flags flags ) | bool QgsOgrProvider::addFeatures( QgsFeatureList &flist, Flags flags ) | |||
skipping to change at line 4200 | skipping to change at line 4207 | |||
#endif | #endif | |||
GDALClose( hDS ); | GDALClose( hDS ); | |||
} | } | |||
} | } | |||
} | } | |||
else | else | |||
{ | { | |||
GDALClose( hDS ); | GDALClose( hDS ); | |||
} | } | |||
} | } | |||
#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,1,0) && GDAL_VERSION_NUM <= GDAL_ | ||||
COMPUTE_VERSION(3,1,3) | ||||
else if ( mGDALDriverName == QLatin1String( "XLSX" ) || | ||||
mGDALDriverName == QLatin1String( "ODS" ) ) | ||||
{ | ||||
// Workaround bug in GDAL 3.1.0 to 3.1.3 that creates XLSX and ODS files inc | ||||
ompatible with LibreOffice due to use of ZIP64 | ||||
CPLSetThreadLocalConfigOption( "CPL_CREATE_ZIP64", "NO" ); | ||||
GDALClose( hDS ); | ||||
CPLSetThreadLocalConfigOption( "CPL_CREATE_ZIP64", nullptr ); | ||||
} | ||||
#endif | ||||
else | else | |||
{ | { | |||
GDALClose( hDS ); | GDALClose( hDS ); | |||
} | } | |||
} | } | |||
QByteArray QgsOgrProviderUtils::quotedIdentifier( QByteArray field, const QStrin g &driverName ) | QByteArray QgsOgrProviderUtils::quotedIdentifier( QByteArray field, const QStrin g &driverName ) | |||
{ | { | |||
if ( driverName == QLatin1String( "MySQL" ) ) | if ( driverName == QLatin1String( "MySQL" ) ) | |||
{ | { | |||
skipping to change at line 6040 | skipping to change at line 6059 | |||
OGRErr QgsOgrLayer::RollbackTransaction() | OGRErr QgsOgrLayer::RollbackTransaction() | |||
{ | { | |||
QMutexLocker locker( &ds->mutex ); | QMutexLocker locker( &ds->mutex ); | |||
return OGR_L_RollbackTransaction( hLayer ); | return OGR_L_RollbackTransaction( hLayer ); | |||
} | } | |||
OGRErr QgsOgrLayer::SyncToDisk() | OGRErr QgsOgrLayer::SyncToDisk() | |||
{ | { | |||
QMutexLocker locker( &ds->mutex ); | QMutexLocker locker( &ds->mutex ); | |||
return OGR_L_SyncToDisk( hLayer ); | ||||
OGRErr eErr; | ||||
#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,1,0) && GDAL_VERSION_NUM <= GDAL_ | ||||
COMPUTE_VERSION(3,1,3) | ||||
// Workaround bug in GDAL 3.1.0 to 3.1.3 that creates XLSX and ODS files incom | ||||
patible with LibreOffice due to use of ZIP64 | ||||
QString drvName = GDALGetDriverShortName( GDALGetDatasetDriver( ds->hDS ) ); | ||||
if ( drvName == QLatin1String( "XLSX" ) || | ||||
drvName == QLatin1String( "ODS" ) ) | ||||
{ | ||||
CPLSetThreadLocalConfigOption( "CPL_CREATE_ZIP64", "NO" ); | ||||
eErr = OGR_L_SyncToDisk( hLayer ); | ||||
CPLSetThreadLocalConfigOption( "CPL_CREATE_ZIP64", nullptr ); | ||||
} | ||||
else | ||||
#endif | ||||
{ | ||||
eErr = OGR_L_SyncToDisk( hLayer ); | ||||
} | ||||
return eErr; | ||||
} | } | |||
void QgsOgrLayer::ExecuteSQLNoReturn( const QByteArray &sql ) | void QgsOgrLayer::ExecuteSQLNoReturn( const QByteArray &sql ) | |||
{ | { | |||
QMutexLocker locker( &ds->mutex ); | QMutexLocker locker( &ds->mutex ); | |||
OGRLayerH hSqlLayer = GDALDatasetExecuteSQL( ds->hDS, | OGRLayerH hSqlLayer = GDALDatasetExecuteSQL( ds->hDS, | |||
sql.constData(), | sql.constData(), | |||
nullptr, | nullptr, | |||
nullptr ); | nullptr ); | |||
GDALDatasetReleaseResultSet( ds->hDS, hSqlLayer ); | GDALDatasetReleaseResultSet( ds->hDS, hSqlLayer ); | |||
End of changes. 29 change blocks. | ||||
29 lines changed or deleted | 71 lines changed or added |