From 477f8e296532c65d10dc27f6cff96462504c47f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C5=A1a=20=C5=BDivkov?= Date: Wed, 26 Nov 2014 15:42:03 +0100 Subject: [PATCH] postgres: fix PK drop, don't assume PK name as TABLE_pkey When dropping a primary key, postgres requires the primary key name to be specified. In the UpdatePrimaryKeys init step it was assumed that the primary key name for a table X is always X_pkey. However, since the Schema_82 this pattern doesn't hold for those tables which were renamed in that migration, as the migration only renamed the tables. For example, before Schema_82 we had a table name: account_group_includes_by_uuid_audit and its primary key named: account_group_includes_by_uuid_audit_pkey This table was renamed to: account_group_by_id_aud but the primary key name didn't change. Therefore, the UpdatePrimaryKeys failed to drop the primary key using the TABLE_pkey pattern and couldn't then create the new primary key. Instead of assuming the TABLE_pkey pattern get the old primary key name from the DatabaseMetaData and use this name for dropping the existing primary key. Change-Id: I671b9912110fc22c842d2c15930a2c7b9906bd48 --- .../gerrit/pgm/init/UpdatePrimaryKeys.java | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/UpdatePrimaryKeys.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/UpdatePrimaryKeys.java index 0c99fcfd06..79bd73072a 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/UpdatePrimaryKeys.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/UpdatePrimaryKeys.java @@ -42,6 +42,11 @@ import java.util.TreeMap; public class UpdatePrimaryKeys implements InitStep { + private static class PrimaryKey { + String oldNameInDb; + List cols; + } + private final ConsoleUI ui; private SchemaFactory dbFactory; @@ -64,7 +69,7 @@ public class UpdatePrimaryKeys implements InitStep { try { conn = ((JdbcSchema) db).getConnection(); dialect = ((JdbcSchema) db).getDialect(); - Map> corrections = findPKUpdates(); + Map corrections = findPKUpdates(); if (corrections.isEmpty()) { return; } @@ -76,7 +81,7 @@ public class UpdatePrimaryKeys implements InitStep { ui.message("fixing primary keys...\n"); JdbcExecutor executor = new JdbcExecutor(conn); try { - for (Map.Entry> c : corrections.entrySet()) { + for (Map.Entry c : corrections.entrySet()) { ui.message(" table: %s ... ", c.getKey()); recreatePK(executor, c.getKey(), c.getValue()); ui.message("done\n"); @@ -96,19 +101,20 @@ public class UpdatePrimaryKeys implements InitStep { this.dbFactory = dbFactory; } - private Map> findPKUpdates() + private Map findPKUpdates() throws OrmException, SQLException { - Map> corrections = new TreeMap<>(); + Map corrections = new TreeMap<>(); ReviewDb db = dbFactory.open(); try { DatabaseMetaData meta = conn.getMetaData(); JavaSchemaModel jsm = new JavaSchemaModel(ReviewDb.class); for (RelationModel rm : jsm.getRelations()) { String tableName = rm.getRelationName(); - List expectedPK = relationPK(rm); - List actualPK = dbTablePK(meta, tableName); - if (!expectedPK.equals(actualPK)) { - corrections.put(tableName, expectedPK); + List expectedPKCols = relationPK(rm); + PrimaryKey actualPK = dbTablePK(meta, tableName); + if (!expectedPKCols.equals(actualPK.cols)) { + actualPK.cols = expectedPKCols; + corrections.put(tableName, actualPK); } } return corrections; @@ -126,7 +132,7 @@ public class UpdatePrimaryKeys implements InitStep { return pk; } - private List dbTablePK(DatabaseMetaData meta, String tableName) + private PrimaryKey dbTablePK(DatabaseMetaData meta, String tableName) throws SQLException { if (meta.storesUpperCaseIdentifiers()) { tableName = tableName.toUpperCase(); @@ -136,14 +142,18 @@ public class UpdatePrimaryKeys implements InitStep { ResultSet cols = meta.getPrimaryKeys(null, null, tableName); try { + PrimaryKey pk = new PrimaryKey(); Map seqToName = new TreeMap<>(); while (cols.next()) { seqToName.put(cols.getShort("KEY_SEQ"), cols.getString("COLUMN_NAME")); + if (pk.oldNameInDb == null) { + pk.oldNameInDb = cols.getString("PK_NAME"); + } } - List pk = new ArrayList<>(seqToName.size()); + pk.cols = new ArrayList<>(seqToName.size()); for (String name : seqToName.values()) { - pk.add(name.toLowerCase(Locale.US)); + pk.cols.add(name.toLowerCase(Locale.US)); } return pk; } finally { @@ -152,20 +162,19 @@ public class UpdatePrimaryKeys implements InitStep { } private void recreatePK(StatementExecutor executor, String tableName, - List cols) throws OrmException { - try { + PrimaryKey pk) throws OrmException { + if (pk.oldNameInDb == null) { + ui.message("WARN: primary key for table %s didn't exist ... ", tableName); + } else { if (dialect instanceof DialectPostgreSQL) { // postgresql doesn't support the ALTER TABLE foo DROP PRIMARY KEY form executor.execute("ALTER TABLE " + tableName + " DROP CONSTRAINT " - + tableName + "_pkey"); + + pk.oldNameInDb); } else { executor.execute("ALTER TABLE " + tableName + " DROP PRIMARY KEY"); } - } catch (OrmException ignore) { - // maybe the primary key was dropped in a previous run but the creation failed - ui.message("WARN: %s\n", ignore.getMessage()); } executor.execute("ALTER TABLE " + tableName - + " ADD PRIMARY KEY(" + Joiner.on(",").join(cols) + ")"); + + " ADD PRIMARY KEY(" + Joiner.on(",").join(pk.cols) + ")"); } }