Skip to content

Commit af8f9c9

Browse files
author
Sandro Santilli
committed
Retain old TopoGeometry id on editing
Avoids leaving orphaned TopoGeometry objects and breaking upper hirearchical layers
1 parent 1357767 commit af8f9c9

File tree

1 file changed

+110
-9
lines changed

1 file changed

+110
-9
lines changed

src/providers/postgres/qgspostgresprovider.cpp

Lines changed: 110 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2396,21 +2396,47 @@ bool QgsPostgresProvider::changeGeometryValues( QgsGeometryMap & geometry_map )
23962396
mConnectionRW->PQexecNR( "BEGIN" );
23972397

23982398
QString update;
2399+
QgsPostgresResult result;
23992400

24002401
if ( mSpatialColType == sctTopoGeometry )
24012402
{
2402-
// NOTE: We are creating a new TopoGeometry objects with the new shape.
2403-
// TODO: _replace_ the initial TopoGeometry instead, so that it keeps
2404-
// the same identifier and thus still partecipates in any
2405-
// hierarchical definition. Also creating a new object results
2406-
// in orphaned topogeometries!
2403+
// We will create a new TopoGeometry object with the new shape.
2404+
// Later, we'll replace the old TopoGeometry with the new one,
2405+
// to avoid orphans and retain higher level in an eventual
2406+
// hierarchical definition
24072407
update = QString( "UPDATE %1 SET %2=toTopoGeom(%3,t.name,layer_id(%2))"
24082408
" FROM topology.topology t WHERE t.id = topology_id(%2)"
2409-
" AND %4" )
2409+
" AND %4 RETURNING layer_id(%2), id(%2), t.name" )
24102410
.arg( mQuery )
24112411
.arg( quotedIdentifier( mGeometryColumn ) )
24122412
.arg( geomParam( 1 ) )
24132413
.arg( pkParamWhereClause( 2 ) );
2414+
2415+
QString getid = QString( "SELECT id(%1) FROM %2 WHERE %3" )
2416+
.arg( quotedIdentifier( mGeometryColumn ) )
2417+
.arg( mQuery )
2418+
.arg( pkParamWhereClause( 1 ) );
2419+
2420+
QgsDebugMsg( "getting old topogeometry id: " + getid );
2421+
2422+
result = mConnectionRO->PQprepare( "getid", getid, 1, NULL );
2423+
if ( result.PQresultStatus() != PGRES_COMMAND_OK ) {
2424+
QgsDebugMsg( QString("Exception thrown due to PQprepare of this query returning != PGRES_COMMAND_OK (%1 != expected %2): %3").arg(result.PQresultStatus()).arg(PGRES_COMMAND_OK).arg(getid) );
2425+
throw PGException( result );
2426+
}
2427+
2428+
QString replace = QString( "UPDATE %1 SET %2="
2429+
"( topology_id(%2),layer_id(%2),$1,type(%2) )"
2430+
"WHERE %3" )
2431+
.arg( mQuery )
2432+
.arg( quotedIdentifier( mGeometryColumn ) )
2433+
.arg( pkParamWhereClause( 2 ) );
2434+
result = mConnectionRW->PQprepare( "replacetopogeom", replace, 2, NULL );
2435+
if ( result.PQresultStatus() != PGRES_COMMAND_OK ) {
2436+
QgsDebugMsg( QString("Exception thrown due to PQprepare of this query returning != PGRES_COMMAND_OK (%1 != expected %2): %3").arg(result.PQresultStatus()).arg(PGRES_COMMAND_OK).arg(replace) );
2437+
throw PGException( result );
2438+
}
2439+
24142440
}
24152441
else
24162442
{
@@ -2423,9 +2449,11 @@ bool QgsPostgresProvider::changeGeometryValues( QgsGeometryMap & geometry_map )
24232449

24242450
QgsDebugMsg( "updating: " + update );
24252451

2426-
QgsPostgresResult result = mConnectionRW->PQprepare( "updatefeatures", update, 2, NULL );
2427-
if ( result.PQresultStatus() != PGRES_COMMAND_OK )
2452+
result = mConnectionRW->PQprepare( "updatefeatures", update, 2, NULL );
2453+
if ( result.PQresultStatus() != PGRES_COMMAND_OK ) {
2454+
QgsDebugMsg( QString("Exception thrown due to PQprepare of this query returning != PGRES_COMMAND_OK (%1 != expected %2): %3").arg(result.PQresultStatus()).arg(PGRES_COMMAND_OK).arg(update) );
24282455
throw PGException( result );
2456+
}
24292457

24302458
for ( QgsGeometryMap::iterator iter = geometry_map.begin();
24312459
iter != geometry_map.end();
@@ -2441,23 +2469,96 @@ bool QgsPostgresProvider::changeGeometryValues( QgsGeometryMap & geometry_map )
24412469

24422470
QgsDebugMsg( "iterating over feature id " + FID_TO_STRING( iter.key() ) );
24432471

2472+
// Save the id of the current topogeometry
2473+
long old_tg_id;
2474+
if ( mSpatialColType == sctTopoGeometry )
2475+
{
2476+
QStringList params;
2477+
appendPkParams( iter.key(), params );
2478+
result = mConnectionRO->PQexecPrepared( "getid", params );
2479+
if ( result.PQresultStatus() != PGRES_TUPLES_OK ) {
2480+
QgsDebugMsg( QString("Exception thrown due to PQexecPrepared of 'getid' returning != PGRES_COMMAND_OK (%1 != expected %2)").arg(result.PQresultStatus()).arg(PGRES_COMMAND_OK) );
2481+
throw PGException( result );
2482+
}
2483+
// TODO: watch out for NULL , handle somehow
2484+
old_tg_id = result.PQgetvalue( 0, 0 ).toLong();
2485+
QgsDebugMsg( QString("Old TG id is %1").arg(old_tg_id) );
2486+
}
2487+
24442488
QStringList params;
24452489
appendGeomParam( &*iter, params );
24462490
appendPkParams( iter.key(), params );
24472491

24482492
result = mConnectionRW->PQexecPrepared( "updatefeatures", params );
2449-
if ( result.PQresultStatus() != PGRES_COMMAND_OK )
2493+
int expected_status = ( mSpatialColType == sctTopoGeometry ) ? PGRES_TUPLES_OK : PGRES_COMMAND_OK;
2494+
if ( result.PQresultStatus() != expected_status )
2495+
{
2496+
QgsDebugMsg( QString("Exception thrown due to PQexecPrepared of 'getid' returning != PGRES_COMMAND_OK (%1 != expected %2)").arg(result.PQresultStatus()).arg(expected_status) );
24502497
throw PGException( result );
2498+
}
2499+
2500+
if ( mSpatialColType == sctTopoGeometry )
2501+
{
2502+
long layer_id = result.PQgetvalue( 0, 0 ).toLong(); // new layer_id == old layer_id
2503+
long new_tg_id = result.PQgetvalue( 0, 1 ).toLong(); // new topogeo_id
2504+
QString toponame = result.PQgetvalue( 0, 2 ); // new topology name == old topology name
2505+
2506+
// Replace old TopoGeom with new TopoGeom, so that
2507+
// any hierarchically defined TopoGeom will still have its
2508+
// definition and we'll leave no orphans
2509+
QString replace = QString( "DELETE FROM %1.relation WHERE "
2510+
"layer_id = %2 AND topogeo_id = %3" )
2511+
.arg( quotedIdentifier(toponame) )
2512+
.arg( layer_id )
2513+
.arg( old_tg_id );
2514+
result = mConnectionRW->PQexec( replace );
2515+
if ( result.PQresultStatus() != PGRES_COMMAND_OK ) {
2516+
QgsDebugMsg( QString("Exception thrown due to PQexec of this query returning != PGRES_COMMAND_OK (%1 != expected %2): %3").arg(result.PQresultStatus()).arg(PGRES_COMMAND_OK).arg(replace) );
2517+
throw PGException( result );
2518+
}
2519+
replace = QString( "UPDATE %1.relation SET topogeo_id = %2 "
2520+
"WHERE layer_id = %3 AND topogeo_id = %4" )
2521+
.arg( quotedIdentifier(toponame) )
2522+
.arg( old_tg_id )
2523+
.arg( layer_id )
2524+
.arg( new_tg_id );
2525+
QgsDebugMsg( "relation swap: " + replace );
2526+
result = mConnectionRW->PQexec( replace );
2527+
if ( result.PQresultStatus() != PGRES_COMMAND_OK ) {
2528+
QgsDebugMsg( QString("Exception thrown due to PQexec of this query returning != PGRES_COMMAND_OK (%1 != expected %2): %3").arg(result.PQresultStatus()).arg(PGRES_COMMAND_OK).arg(replace) );
2529+
throw PGException( result );
2530+
}
2531+
// Change the ID of the TopoGeometry object put in the table again
2532+
params = QStringList();
2533+
params << QString::number( old_tg_id );
2534+
appendPkParams( iter.key(), params );
2535+
QgsDebugMsg( "Replacing topogeom reference to use id " + QString::number(old_tg_id) );
2536+
result = mConnectionRW->PQexecPrepared( "replacetopogeom", params );
2537+
if ( result.PQresultStatus() != PGRES_COMMAND_OK )
2538+
{
2539+
QgsDebugMsg( QString("Exception thrown due to PQexecPrepared of 'replacetopogeom' returning != PGRES_COMMAND_OK (%1 != expected %2)").arg(result.PQresultStatus()).arg(PGRES_COMMAND_OK) );
2540+
throw PGException( result );
2541+
}
2542+
} // if TopoGeometry
2543+
24512544
} // for each feature
24522545

24532546
mConnectionRW->PQexecNR( "DEALLOCATE updatefeatures" );
2547+
if ( mSpatialColType == sctTopoGeometry ) {
2548+
mConnectionRO->PQexecNR( "DEALLOCATE getid" );
2549+
mConnectionRW->PQexecNR( "DEALLOCATE replacetopogeom" );
2550+
}
24542551
mConnectionRW->PQexecNR( "COMMIT" );
24552552
}
24562553
catch ( PGException &e )
24572554
{
24582555
pushError( tr( "PostGIS error while changing geometry values: %1" ).arg( e.errorMessage() ) );
24592556
mConnectionRW->PQexecNR( "ROLLBACK" );
24602557
mConnectionRW->PQexecNR( "DEALLOCATE updatefeatures" );
2558+
if ( mSpatialColType == sctTopoGeometry ) {
2559+
mConnectionRO->PQexecNR( "DEALLOCATE getid" );
2560+
mConnectionRW->PQexecNR( "DEALLOCATE replacetopogeom" );
2561+
}
24612562
returnvalue = false;
24622563
}
24632564

0 commit comments

Comments
 (0)