Skip to content

Commit 2419cbe

Browse files
PDavidclaude
andcommitted
PHOENIX-7955 CREATE TABLE IF NOT EXISTS should not mutate existing HBase table properties
Problem: When CREATE TABLE IF NOT EXISTS was executed against an already-existing table, Phoenix would overwrite the HBase-level table and column family properties (e.g. REGION_REPLICATION, VERSIONS, TTL) with the values from the new DDL statement. This is unexpected - IF NOT EXISTS should be a no-op if the table already exists. Fix: In ConnectionQueryServicesImpl changed ensureTableCreated call for TABLE types - passes modifyExistingMetaData = false when the table type is TABLE, so existing properties are not overwritten. Testing: Added new test in CreateTableIT which reproduces the problem and verifies the fix. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 80c9125 commit 2419cbe

2 files changed

Lines changed: 60 additions & 1 deletion

File tree

phoenix-core-client/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2550,8 +2550,9 @@ public MetaDataMutationResult createTable(final List<Mutation> tableMetaData,
25502550
) {
25512551
// For views this will ensure that metadata already exists
25522552
// For tables and indexes, this will create the metadata if it doesn't already exist
2553+
boolean modifyExistingMetaData = tableType != PTableType.TABLE;
25532554
ensureTableCreated(physicalTableNameBytes, null, tableType, tableProps, families, splits,
2554-
true, isNamespaceMapped, isDoNotUpgradePropSet);
2555+
modifyExistingMetaData, isNamespaceMapped, isDoNotUpgradePropSet);
25552556
}
25562557
ImmutableBytesWritable ptr = new ImmutableBytesWritable();
25572558
if (tableType == PTableType.INDEX) { // Index on view

phoenix-core/src/it/java/org/apache/phoenix/end2end/CreateTableIT.java

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import static org.junit.Assert.assertNotEquals;
2626
import static org.junit.Assert.assertNotNull;
2727
import static org.junit.Assert.assertNull;
28+
import static org.junit.Assert.assertThrows;
2829
import static org.junit.Assert.assertTrue;
2930
import static org.junit.Assert.fail;
3031

@@ -1769,4 +1770,61 @@ private int checkGuidePostWidth(String tableName) throws Exception {
17691770
}
17701771
}
17711772

1773+
@Test
1774+
public void testCreateTableDoesNotMutateExistingHBaseTableProperties() throws Exception {
1775+
String tableName = generateUniqueName();
1776+
Properties props = new Properties();
1777+
1778+
// Step 1: Create table with VERSIONS=1 and TTL=86400
1779+
String createDdl = "CREATE TABLE " + tableName + " (" + " PK VARCHAR NOT NULL PRIMARY KEY,"
1780+
+ " COL1 VARCHAR," + " COL2 INTEGER" + " ) VERSIONS=1, TTL=86400";
1781+
try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
1782+
conn.createStatement().execute(createDdl);
1783+
}
1784+
1785+
// Verify initial HBase table properties
1786+
Admin admin = driver.getConnectionQueryServices(getUrl(), props).getAdmin();
1787+
TableDescriptor descBefore = admin.getDescriptor(TableName.valueOf(tableName));
1788+
ColumnFamilyDescriptor[] cfsBefore = descBefore.getColumnFamilies();
1789+
assertEquals(1, cfsBefore.length);
1790+
assertEquals(1, cfsBefore[0].getMaxVersions());
1791+
assertEquals(86400, cfsBefore[0].getTimeToLive());
1792+
1793+
// Step 2: Execute CREATE TABLE IF NOT EXISTS with different properties
1794+
String createIfNotExistsDdl =
1795+
"CREATE TABLE IF NOT EXISTS " + tableName + " (" + " PK VARCHAR NOT NULL PRIMARY KEY,"
1796+
+ " COL1 VARCHAR," + " COL2 INTEGER" + " ) VERSIONS=5, TTL=120000";
1797+
try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
1798+
conn.createStatement().execute(createIfNotExistsDdl);
1799+
}
1800+
1801+
// Step 3: Verify that HBase table properties are NOT changed
1802+
TableDescriptor descAfter = admin.getDescriptor(TableName.valueOf(tableName));
1803+
ColumnFamilyDescriptor[] cfsAfter = descAfter.getColumnFamilies();
1804+
assertEquals(1, cfsAfter.length);
1805+
assertEquals("VERSIONS should not be modified by IF NOT EXISTS", 1,
1806+
cfsAfter[0].getMaxVersions());
1807+
assertEquals("TTL should not be modified by IF NOT EXISTS", 86400, cfsAfter[0].getTimeToLive());
1808+
1809+
// Step 4: Execute CREATE TABLE without IF NOT EXISTS with different properties
1810+
String createWithoutIfNotExistsDdl =
1811+
"CREATE TABLE " + tableName + " (" + " PK VARCHAR NOT NULL PRIMARY KEY," + " COL1 VARCHAR,"
1812+
+ " COL2 INTEGER" + " ) VERSIONS=6, TTL=120000";
1813+
try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
1814+
// Should fail as table exists already.
1815+
TableAlreadyExistsException exception = assertThrows(TableAlreadyExistsException.class,
1816+
() -> conn.createStatement().execute(createWithoutIfNotExistsDdl));
1817+
assertEquals("ERROR 1013 (42M04): Table already exists. tableName=N000063",
1818+
exception.getMessage());
1819+
}
1820+
1821+
// Step 5: Verify that HBase table properties are still NOT changed
1822+
TableDescriptor descAfter2 = admin.getDescriptor(TableName.valueOf(tableName));
1823+
ColumnFamilyDescriptor[] cfsAfter2 = descAfter2.getColumnFamilies();
1824+
assertEquals(1, cfsAfter2.length);
1825+
assertEquals("VERSIONS should not be modified for existing table", 1,
1826+
cfsAfter2[0].getMaxVersions());
1827+
assertEquals("TTL should not be modified for existing table", 86400,
1828+
cfsAfter2[0].getTimeToLive());
1829+
}
17721830
}

0 commit comments

Comments
 (0)