Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/providers/postgres/qgspostgresdataitemguiprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,17 @@ void QgsPostgresDataItemGuiProvider::renameLayer( QgsPGLayerItem *layerItem, Qgs

notify( tr( "Rename %1" ).arg( typeName ), tr( "%1 '%2' renamed correctly to '%3'." ).arg( typeName, oldName, newName ), context, Qgis::MessageLevel::Success );

if ( QgsPostgresUtils::tableExists( conn, u"public"_s, u"layer_styles"_s ) )
{
const QString updateStylesSql = u"UPDATE public.layer_styles SET f_table_name=%1 WHERE f_table_schema=%2 AND f_table_name=%3"_s
.arg( QgsPostgresConn::quotedValue( dlg.name() ), QgsPostgresConn::quotedValue( schemaName ), QgsPostgresConn::quotedValue( tableName ) );

QgsPostgresResult stylesResult( conn->LoggedPQexec( "QgsPostgresDataItemGuiProvider", updateStylesSql ) );
Comment thread
JanCaha marked this conversation as resolved.
Outdated
if ( stylesResult.PQresultStatus() != PGRES_COMMAND_OK )
{
notify( tr( "Rename %1" ).arg( typeName ), tr( "Unable to update layer styles for '%1'.\n%2" ).arg( dlg.name(), stylesResult.PQresultErrorMessage() ), context, Qgis::MessageLevel::Warning );
}
}
conn->unref();

if ( layerItem->parent() )
Expand Down
21 changes: 21 additions & 0 deletions src/providers/postgres/qgspostgresproviderconnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "qgspostgresconnpool.h"
#include "qgspostgresprovider.h"
#include "qgspostgresprovidermetadatautils.h"
#include "qgspostgresutils.h"
#include "qgssettings.h"
#include "qgsvectorlayer.h"

Expand Down Expand Up @@ -215,6 +216,19 @@ void QgsPostgresProviderConnection::dropRasterTable( const QString &schema, cons
void QgsPostgresProviderConnection::renameTablePrivate( const QString &schema, const QString &name, const QString &newName ) const
{
executeSqlPrivate( u"ALTER TABLE %1.%2 RENAME TO %3"_s.arg( QgsPostgresConn::quotedIdentifier( schema ), QgsPostgresConn::quotedIdentifier( name ), QgsPostgresConn::quotedIdentifier( newName ) ) );

const QgsDataSourceUri dsUri { uri() };
QgsPostgresConn *conn = QgsPostgresConnPool::instance()->acquireConnection( QgsPostgresConn::connectionInfo( dsUri, false ), -1, false );
Comment thread
JanCaha marked this conversation as resolved.
Outdated

if ( conn )
{
if ( QgsPostgresUtils::tableExists( conn, u"public"_s, u"layer_styles"_s ) )
{
executeSqlPrivate( u"UPDATE public.layer_styles SET f_table_name=%1 WHERE f_table_schema=%2 AND f_table_name=%3"_s
.arg( QgsPostgresConn::quotedValue( newName ), QgsPostgresConn::quotedValue( schema ), QgsPostgresConn::quotedValue( name ) ) );
}
QgsPostgresConnPool::instance()->releaseConnection( conn );
}
}

QList<QgsAbstractDatabaseProviderConnection::TableProperty> QgsPostgresProviderConnection::tablesPrivate( const QString &schema, const QString &table, const TableFlags &flags, QgsFeedback *feedback ) const
Expand Down Expand Up @@ -1955,6 +1969,13 @@ void QgsPostgresProviderConnection::moveTableToSchema( const QString &sourceSche
}
}

if ( QgsPostgresUtils::tableExists( conn->get(), u"public"_s, u"layer_styles"_s ) )
{
const QString sqlMoveStyles = u"UPDATE public.layer_styles SET f_table_schema=%1 WHERE f_table_schema=%2 AND f_table_name=%3;"_s
.arg( QgsPostgresConn::quotedValue( targetSchema ), QgsPostgresConn::quotedValue( sourceSchema ), QgsPostgresConn::quotedValue( tableName ) );
sqlAdditionalCommands.append( sqlMoveStyles );
}

conn->get()->begin();

QgsPostgresResult resMove( conn->get()->LoggedPQexec( "QgsPostgresProviderConnection", u"%1 %2"_s.arg( sqlMoveTable ).arg( sqlAdditionalCommands ) ) );
Expand Down
107 changes: 107 additions & 0 deletions tests/src/python/test_qgsproviderconnection_postgres.py
Original file line number Diff line number Diff line change
Expand Up @@ -1103,6 +1103,113 @@ def test_move_raster_with_overviews_to_schema(self):
tables,
)

def test_rename_table_updates_layer_styles(self):
"""Test that renaming a table also updates f_table_name in layer_styles."""
md = QgsProviderRegistry.instance().providerMetadata("postgres")
conn = md.createConnection(self.uri, {})

conn.executeSql(
"""
DROP TABLE IF EXISTS qgis_test.rename_style_test CASCADE;
CREATE TABLE qgis_test.rename_style_test (id SERIAL PRIMARY KEY, geom geometry(POINT,4326));
INSERT INTO qgis_test.rename_style_test (geom) VALUES (ST_GeomFromText('POINT(0 0)', 4326));
"""
)

vl = QgsVectorLayer(
conn.tableUri("qgis_test", "rename_style_test"),
"test_rename_with_style",
"postgres",
)
self.assertTrue(vl.isValid())
err = vl.saveStyleToDatabase("test_style", "", False, "")
self.assertFalse(err)

# Verify style was saved under the original name
rows = conn.executeSql(
"SELECT f_table_name FROM public.layer_styles "
"WHERE f_table_schema = 'qgis_test' AND f_table_name = 'rename_style_test'"
)
self.assertEqual(len(rows), 1)

conn.renameVectorTable(
"qgis_test", "rename_style_test", "rename_style_test_renamed"
)

# Style must now reference the new table name
rows = conn.executeSql(
"SELECT f_table_name FROM public.layer_styles "
"WHERE f_table_schema = 'qgis_test' AND f_table_name = 'rename_style_test_renamed'"
)
self.assertEqual(len(rows), 1)

# No stale row for the old name
rows = conn.executeSql(
"SELECT f_table_name FROM public.layer_styles "
"WHERE f_table_schema = 'qgis_test' AND f_table_name = 'rename_style_test'"
)
self.assertEqual(len(rows), 0)

conn.executeSql(
"DROP TABLE IF EXISTS qgis_test.rename_style_test_renamed CASCADE"
)

def test_move_table_to_schema_updates_layer_styles(self):
"""Test that moving a table also updates f_table_schema in layer_styles."""
md = QgsProviderRegistry.instance().providerMetadata("postgres")
conn = md.createConnection(self.uri, {})

conn.executeSql(
"""
DROP TABLE IF EXISTS qgis_test.move_style_test CASCADE;
DROP SCHEMA IF EXISTS qgis_schema_test CASCADE;
CREATE TABLE qgis_test.move_style_test (id SERIAL PRIMARY KEY, geom geometry(POINT,4326));
INSERT INTO qgis_test.move_style_test (geom) VALUES (ST_GeomFromText('POINT(0 0)', 4326));
CREATE SCHEMA IF NOT EXISTS qgis_schema_test;
"""
)

vl = QgsVectorLayer(
conn.tableUri("qgis_test", "move_style_test"),
"test_move_with_style",
"postgres",
)
self.assertTrue(vl.isValid())
err = vl.saveStyleToDatabaseV2("test_style_move", "", False, "")
self.assertFalse(err)

# Verify style initially points to the source schema
rows = conn.executeSql(
"SELECT f_table_schema FROM public.layer_styles "
"WHERE f_table_schema = 'qgis_test' AND f_table_name = 'move_style_test'"
)
self.assertEqual(len(rows), 1)

conn.moveTableToSchema(
"qgis_test",
"move_style_test",
"qgis_schema_test",
)

# Style must now reference the target schema
rows = conn.executeSql(
"SELECT f_table_schema FROM public.layer_styles "
"WHERE f_table_schema = 'qgis_schema_test' AND f_table_name = 'move_style_test'"
)
self.assertEqual(len(rows), 1)

# No stale row for the old schema
rows = conn.executeSql(
"SELECT f_table_schema FROM public.layer_styles "
"WHERE f_table_schema = 'qgis_test' AND f_table_name = 'move_style_test'"
)
self.assertEqual(len(rows), 0)

conn.executeSql(
"DROP TABLE IF EXISTS qgis_schema_test.move_style_test CASCADE;"
"DROP SCHEMA IF EXISTS qgis_schema_test CASCADE;"
)


if __name__ == "__main__":
unittest.main()
Loading