Allow ALTER TABLE <table> SET command to update HTableDescriptor and HColumnDescriptor properties (Samarth Jain/Alicia Ying Shu)
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/7578ee92 Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/7578ee92 Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/7578ee92 Branch: refs/heads/4.0 Commit: 7578ee92b70f81a531c1b56b71584c6bd5aaaf93 Parents: cae025a Author: Samarth <[email protected]> Authored: Fri Jan 9 16:35:03 2015 -0800 Committer: Samarth <[email protected]> Committed: Fri Jan 9 16:35:03 2015 -0800 ---------------------------------------------------------------------- .../apache/phoenix/end2end/AlterTableIT.java | 923 ++++++++++++++++++- .../apache/phoenix/end2end/CreateTableIT.java | 47 +- phoenix-core/src/main/antlr3/PhoenixSQL.g | 2 +- .../phoenix/exception/SQLExceptionCode.java | 15 +- .../apache/phoenix/jdbc/PhoenixStatement.java | 5 +- .../phoenix/parse/AddColumnStatement.java | 14 +- .../apache/phoenix/parse/ParseNodeFactory.java | 4 +- .../phoenix/query/ConnectionQueryServices.java | 3 + .../query/ConnectionQueryServicesImpl.java | 40 +- .../query/ConnectionlessQueryServicesImpl.java | 7 + .../query/DelegateConnectionQueryServices.java | 8 + .../apache/phoenix/schema/MetaDataClient.java | 305 +++++- .../apache/phoenix/schema/TableProperty.java | 111 +++ .../phoenix/compile/QueryCompilerTest.java | 12 +- 14 files changed, 1365 insertions(+), 131 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/7578ee92/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java index 2943fe6..9a262cb 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java @@ -17,12 +17,12 @@ */ package org.apache.phoenix.end2end; +import static org.apache.hadoop.hbase.HColumnDescriptor.DEFAULT_REPLICATION_SCOPE; import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES; import static org.apache.phoenix.util.TestUtil.closeConnection; import static org.apache.phoenix.util.TestUtil.closeStatement; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -33,11 +33,13 @@ import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.Collections; +import java.util.Map; import java.util.Properties; import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HTableDescriptor; -import org.apache.hadoop.hbase.client.HTableInterface; +import org.apache.hadoop.hbase.client.HBaseAdmin; import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.coprocessor.MetaDataProtocol; import org.apache.phoenix.exception.SQLExceptionCode; @@ -49,11 +51,23 @@ import org.apache.phoenix.schema.TableNotFoundException; import org.apache.phoenix.util.IndexUtil; import org.apache.phoenix.util.PhoenixRuntime; import org.apache.phoenix.util.PropertiesUtil; +import org.apache.phoenix.util.ReadOnlyProps; import org.apache.phoenix.util.SchemaUtil; +import org.junit.BeforeClass; import org.junit.Test; - -public class AlterTableIT extends BaseHBaseManagedTimeIT { +/** + * + * A lot of tests in this class test HBase level properties. As a result, + * tests need to have non-overlapping table names. The option of + * disabling and dropping underlying HBase tables at the end of each test + * to avoid the overlap makes the test class really slow. By having the + * test class run in its own cluster and having non overlapping table names + * we don't need to worry about dropping the tables between each test + * or at the end of test class. + * + */ +public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT { public static final String SCHEMA_NAME = ""; public static final String DATA_TABLE_NAME = "T"; public static final String INDEX_TABLE_NAME = "I"; @@ -61,7 +75,13 @@ public class AlterTableIT extends BaseHBaseManagedTimeIT { public static final String DATA_TABLE_FULL_NAME = SchemaUtil.getTableName(SCHEMA_NAME, "T"); public static final String INDEX_TABLE_FULL_NAME = SchemaUtil.getTableName(SCHEMA_NAME, "I"); public static final String LOCAL_INDEX_TABLE_FULL_NAME = SchemaUtil.getTableName(SCHEMA_NAME, "LI"); - + + @BeforeClass + public static void doSetup() throws Exception { + Map<String, String> props = Collections.emptyMap(); + setUpTestDriver(new ReadOnlyProps(props.entrySet().iterator())); + } + @Test public void testAlterTableWithVarBinaryKey() throws Exception { Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); @@ -195,36 +215,27 @@ public class AlterTableIT extends BaseHBaseManagedTimeIT { @Test - public void testAlterColumnFamilyProperty() throws Exception { - + public void testSetPropertyAndAddColumnForNewColumnFamily() throws Exception { Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); Connection conn = DriverManager.getConnection(getUrl(), props); - - String ddl = "CREATE TABLE test_table " + + String ddl = "CREATE TABLE SETPROPNEWCF " + " (a_string varchar not null, col1 integer" + " CONSTRAINT pk PRIMARY KEY (a_string))\n"; try { - conn.createStatement().execute(ddl); - - conn.createStatement().execute("ALTER TABLE TEST_TABLE ADD col2 integer IN_MEMORY=true"); - - HTableInterface htable1 = conn.unwrap(PhoenixConnection.class).getQueryServices().getTable(Bytes.toBytes("TEST_TABLE")); - HTableDescriptor htableDesciptor1 = htable1.getTableDescriptor(); - HColumnDescriptor hcolumnDescriptor1 = htableDesciptor1.getFamily(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES); - assertNotNull(hcolumnDescriptor1); - - try { - - conn.createStatement().execute("ALTER TABLE TEST_TABLE SET IN_MEMORY=false"); - fail("Should have caught exception."); - - } catch (SQLException e) { - assertTrue(e.getMessage(), e.getMessage().contains("ERROR 1025 (42Y84): Unsupported property set in ALTER TABLE command.")); - } - }finally { + conn.createStatement().execute(ddl); + conn.createStatement().execute("ALTER TABLE SETPROPNEWCF ADD CF.col2 integer CF.IN_MEMORY=true"); + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes("SETPROPNEWCF")).getColumnFamilies(); + assertEquals(2, columnFamilies.length); + assertEquals("0", columnFamilies[0].getNameAsString()); + assertFalse(columnFamilies[0].isInMemory()); + assertEquals("CF", columnFamilies[1].getNameAsString()); + assertTrue(columnFamilies[1].isInMemory()); + } + } finally { conn.close(); } - } + } private static void assertIndexExists(Connection conn, boolean exists) throws SQLException { ResultSet rs = conn.getMetaData().getIndexInfo(null, SCHEMA_NAME, DATA_TABLE_NAME, false, false); @@ -928,4 +939,860 @@ public class AlterTableIT extends BaseHBaseManagedTimeIT { ddl = "ALTER TABLE T ADD CF.STRING VARCHAR"; conn1.createStatement().execute(ddl); } + + @Test + public void testSetHColumnProperties() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + String ddl = "CREATE TABLE T1 (\n" + +"ID1 VARCHAR(15) NOT NULL,\n" + +"ID2 VARCHAR(15) NOT NULL,\n" + +"CREATED_DATE DATE,\n" + +"CREATION_TIME BIGINT,\n" + +"LAST_USED DATE,\n" + +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) SALT_BUCKETS = 8"; + Connection conn1 = DriverManager.getConnection(getUrl(), props); + conn1.createStatement().execute(ddl); + ddl = "ALTER TABLE T1 SET REPLICATION_SCOPE=1"; + conn1.createStatement().execute(ddl); + try (HBaseAdmin admin = conn1.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes("T1")).getColumnFamilies(); + assertEquals(1, columnFamilies.length); + assertEquals("0", columnFamilies[0].getNameAsString()); + assertEquals(1, columnFamilies[0].getScope()); + } + } + + @Test + public void testSetHTableProperties() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + String ddl = "CREATE TABLE T2 (\n" + +"ID1 VARCHAR(15) NOT NULL,\n" + +"ID2 VARCHAR(15) NOT NULL,\n" + +"CREATED_DATE DATE,\n" + +"CREATION_TIME BIGINT,\n" + +"LAST_USED DATE,\n" + +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) SALT_BUCKETS = 8"; + Connection conn1 = DriverManager.getConnection(getUrl(), props); + conn1.createStatement().execute(ddl); + ddl = "ALTER TABLE T2 SET COMPACTION_ENABLED=FALSE"; + conn1.createStatement().execute(ddl); + try (HBaseAdmin admin = conn1.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes("T2")); + assertEquals(1, tableDesc.getColumnFamilies().length); + assertEquals("0", tableDesc.getColumnFamilies()[0].getNameAsString()); + assertEquals(Boolean.toString(false), tableDesc.getValue(HTableDescriptor.COMPACTION_ENABLED)); + } + } + + @Test + public void testSetHTableAndHColumnProperties() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + String ddl = "CREATE TABLE T3 (\n" + +"ID1 VARCHAR(15) NOT NULL,\n" + +"ID2 VARCHAR(15) NOT NULL,\n" + +"CREATED_DATE DATE,\n" + +"CREATION_TIME BIGINT,\n" + +"LAST_USED DATE,\n" + +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) SALT_BUCKETS = 8"; + Connection conn1 = DriverManager.getConnection(getUrl(), props); + conn1.createStatement().execute(ddl); + ddl = "ALTER TABLE T3 SET COMPACTION_ENABLED = FALSE, REPLICATION_SCOPE = 1"; + conn1.createStatement().execute(ddl); + try (HBaseAdmin admin = conn1.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes("T3")); + HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies(); + assertEquals(1, columnFamilies.length); + assertEquals("0", columnFamilies[0].getNameAsString()); + assertEquals(1, columnFamilies[0].getScope()); + assertEquals(false, tableDesc.isCompactionEnabled()); + } + } + + @Test + public void testSetHTableHColumnAndPhoenixTableProperties() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + String ddl = "CREATE TABLE T3 (\n" + +"ID1 VARCHAR(15) NOT NULL,\n" + +"ID2 VARCHAR(15) NOT NULL,\n" + +"CREATED_DATE DATE,\n" + +"CF1.CREATION_TIME BIGINT,\n" + +"CF2.LAST_USED DATE,\n" + +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) IMMUTABLE_ROWS=true"; + Connection conn = DriverManager.getConnection(getUrl(), props); + conn.createStatement().execute(ddl); + assertImmutableRows(conn, "T3", true); + ddl = "ALTER TABLE T3 SET COMPACTION_ENABLED = FALSE, VERSIONS = 10"; + conn.createStatement().execute(ddl); + ddl = "ALTER TABLE T3 SET COMPACTION_ENABLED = FALSE, CF1.MIN_VERSIONS = 1, CF2.MIN_VERSIONS = 3, MIN_VERSIONS = 8, IMMUTABLE_ROWS=false"; + conn.createStatement().execute(ddl); + assertImmutableRows(conn, "T3", false); + + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes("T3")); + HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies(); + assertEquals(3, columnFamilies.length); + + assertEquals("0", columnFamilies[0].getNameAsString()); + assertEquals(8, columnFamilies[0].getMinVersions()); + assertEquals(10, columnFamilies[0].getMaxVersions()); + + assertEquals("CF1", columnFamilies[1].getNameAsString()); + assertEquals(1, columnFamilies[1].getMinVersions()); + assertEquals(10, columnFamilies[1].getMaxVersions()); + + assertEquals("CF2", columnFamilies[2].getNameAsString()); + assertEquals(3, columnFamilies[2].getMinVersions()); + assertEquals(10, columnFamilies[2].getMaxVersions()); + + assertEquals(Boolean.toString(false), tableDesc.getValue(HTableDescriptor.COMPACTION_ENABLED)); + } + } + + @Test + public void testSpecifyingColumnFamilyForHTablePropertyFails() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + String ddl = "CREATE TABLE T4 (\n" + +"ID1 VARCHAR(15) NOT NULL,\n" + +"ID2 VARCHAR(15) NOT NULL,\n" + +"CREATED_DATE DATE,\n" + +"CREATION_TIME BIGINT,\n" + +"LAST_USED DATE,\n" + +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) SALT_BUCKETS = 8"; + Connection conn1 = DriverManager.getConnection(getUrl(), props); + conn1.createStatement().execute(ddl); + ddl = "ALTER TABLE T4 SET CF.COMPACTION_ENABLED = FALSE"; + try { + conn1.createStatement().execute(ddl); + } catch (SQLException e) { + assertEquals(SQLExceptionCode.COLUMN_FAMILY_NOT_ALLOWED_TABLE_PROPERTY.getErrorCode(), e.getErrorCode()); + } + } + + @Test + public void testSpecifyingColumnFamilyForPhoenixTablePropertyFails() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + String ddl = "CREATE TABLE T5 (\n" + +"ID1 VARCHAR(15) NOT NULL,\n" + +"ID2 VARCHAR(15) NOT NULL,\n" + +"CREATED_DATE DATE,\n" + +"CREATION_TIME BIGINT,\n" + +"LAST_USED DATE,\n" + +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) SALT_BUCKETS = 8"; + Connection conn1 = DriverManager.getConnection(getUrl(), props); + conn1.createStatement().execute(ddl); + ddl = "ALTER TABLE T5 SET CF.DISABLE_WAL = TRUE"; + try { + conn1.createStatement().execute(ddl); + } catch (SQLException e) { + assertEquals(SQLExceptionCode.COLUMN_FAMILY_NOT_ALLOWED_TABLE_PROPERTY.getErrorCode(), e.getErrorCode()); + } + } + + @Test + public void testSpecifyingColumnFamilyForTTLFails() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + String ddl = "CREATE TABLE T6 (\n" + +"ID1 VARCHAR(15) NOT NULL,\n" + +"ID2 VARCHAR(15) NOT NULL,\n" + +"CREATED_DATE DATE,\n" + +"CREATION_TIME BIGINT,\n" + +"CF.LAST_USED DATE,\n" + +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) SALT_BUCKETS = 8"; + Connection conn1 = DriverManager.getConnection(getUrl(), props); + conn1.createStatement().execute(ddl); + ddl = "ALTER TABLE T6 SET CF.TTL = 86400"; + try { + conn1.createStatement().execute(ddl); + fail(); + } catch (SQLException e) { + assertEquals(SQLExceptionCode.COLUMN_FAMILY_NOT_ALLOWED_FOR_TTL.getErrorCode(), e.getErrorCode()); + } + } + + @Test + public void testSetPropertyNeedsColumnFamilyToExist() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + String ddl = "CREATE TABLE T7 (\n" + +"ID1 VARCHAR(15) NOT NULL,\n" + +"ID2 VARCHAR(15) NOT NULL,\n" + +"CREATED_DATE DATE,\n" + +"CREATION_TIME BIGINT,\n" + +"LAST_USED DATE,\n" + +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) SALT_BUCKETS = 8"; + Connection conn1 = DriverManager.getConnection(getUrl(), props); + conn1.createStatement().execute(ddl); + ddl = "ALTER TABLE T7 SET CF.REPLICATION_SCOPE = 1"; + try { + conn1.createStatement().execute(ddl); + } catch (SQLException e) { + assertEquals(SQLExceptionCode.COLUMN_FAMILY_NOT_FOUND.getErrorCode(), e.getErrorCode()); + } + } + + @Test + public void testSetDefaultColumnFamilyNotAllowed() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + String ddl = "CREATE TABLE T8 (\n" + +"ID1 VARCHAR(15) NOT NULL,\n" + +"ID2 VARCHAR(15) NOT NULL,\n" + +"CREATED_DATE DATE,\n" + +"CREATION_TIME BIGINT,\n" + +"LAST_USED DATE,\n" + +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) SALT_BUCKETS = 8"; + Connection conn1 = DriverManager.getConnection(getUrl(), props); + conn1.createStatement().execute(ddl); + ddl = "ALTER TABLE T8 SET DEFAULT_COLUMN_FAMILY = 'A'"; + try { + conn1.createStatement().execute(ddl); + } catch (SQLException e) { + assertEquals(SQLExceptionCode.DEFAULT_COLUMN_FAMILY_ONLY_ON_CREATE_TABLE.getErrorCode(), e.getErrorCode()); + } + } + + @Test + public void testSetHColumnOrHTablePropertiesOnViewsNotAllowed() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + String ddl = "CREATE TABLE T9 (\n" + +"ID1 VARCHAR(15) NOT NULL,\n" + +"ID2 VARCHAR(15) NOT NULL,\n" + +"CREATED_DATE DATE,\n" + +"CREATION_TIME BIGINT,\n" + +"LAST_USED DATE,\n" + +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) SALT_BUCKETS = 8"; + Connection conn1 = DriverManager.getConnection(getUrl(), props); + conn1.createStatement().execute(ddl); + ddl = "CREATE VIEW v AS SELECT * FROM T9 WHERE CREATION_TIME = 1"; + conn1.createStatement().execute(ddl); + ddl = "ALTER VIEW v SET REPLICATION_SCOPE = 1"; + try { + conn1.createStatement().execute(ddl); + } catch (SQLException e) { + assertEquals(SQLExceptionCode.VIEW_WITH_PROPERTIES.getErrorCode(), e.getErrorCode()); + } + ddl = "ALTER VIEW v SET COMPACTION_ENABLED = FALSE"; + try { + conn1.createStatement().execute(ddl); + } catch (SQLException e) { + assertEquals(SQLExceptionCode.VIEW_WITH_PROPERTIES.getErrorCode(), e.getErrorCode()); + } + } + + @Test + public void testSetForSomePhoenixTablePropertiesOnViewsAllowed() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + String ddl = "CREATE TABLE T10 (\n" + +"ID1 VARCHAR(15) NOT NULL,\n" + +"ID2 VARCHAR(15) NOT NULL,\n" + +"CREATED_DATE DATE,\n" + +"CREATION_TIME BIGINT,\n" + +"LAST_USED DATE,\n" + +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) SALT_BUCKETS = 8"; + Connection conn1 = DriverManager.getConnection(getUrl(), props); + conn1.createStatement().execute(ddl); + ddl = "CREATE VIEW v AS SELECT * FROM T10 WHERE CREATION_TIME = 1"; + conn1.createStatement().execute(ddl); + ddl = "ALTER VIEW v SET IMMUTABLE_ROWS = TRUE"; + conn1.createStatement().execute(ddl); + assertImmutableRows(conn1, "V", true); + ddl = "ALTER VIEW v SET IMMUTABLE_ROWS = FALSE"; + conn1.createStatement().execute(ddl); + assertImmutableRows(conn1, "V", false); + ddl = "ALTER VIEW v SET DISABLE_WAL = TRUE"; + try { + conn1.createStatement().execute(ddl); + } catch (SQLException e) { + assertEquals(SQLExceptionCode.VIEW_WITH_PROPERTIES.getErrorCode(), e.getErrorCode()); + } + } + + @Test + public void testSettingPropertiesWhenTableHasDefaultColFamilySpecified() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + String ddl = "CREATE TABLE T11 (\n" + +"ID1 VARCHAR(15) NOT NULL,\n" + +"ID2 VARCHAR(15) NOT NULL,\n" + +"CREATED_DATE DATE,\n" + +"CREATION_TIME BIGINT,\n" + +"CF.LAST_USED DATE,\n" + +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) IMMUTABLE_ROWS=true, DEFAULT_COLUMN_FAMILY = 'XYZ'"; + Connection conn = DriverManager.getConnection(getUrl(), props); + conn.createStatement().execute(ddl); + assertImmutableRows(conn, "T11", true); + ddl = "ALTER TABLE T11 SET COMPACTION_ENABLED = FALSE, CF.REPLICATION_SCOPE=1, IMMUTABLE_ROWS = TRUE, TTL=1000"; + conn.createStatement().execute(ddl); + assertImmutableRows(conn, "T11", true); + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes("T11")); + HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies(); + assertEquals(2, columnFamilies.length); + assertEquals("CF", columnFamilies[0].getNameAsString()); + assertEquals(1, columnFamilies[0].getScope()); + assertEquals(1000, columnFamilies[0].getTimeToLive()); + assertEquals("XYZ", columnFamilies[1].getNameAsString()); + assertEquals(DEFAULT_REPLICATION_SCOPE, columnFamilies[1].getScope()); + assertEquals(1000, columnFamilies[1].getTimeToLive()); + assertEquals(Boolean.toString(false), tableDesc.getValue(HTableDescriptor.COMPACTION_ENABLED)); + } + } + + @Test + public void testNewColumnFamilyInheritsTTLOfEmptyCF() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + String ddl = "CREATE TABLE NEWCFTTLTEST (\n" + +"ID1 VARCHAR(15) NOT NULL,\n" + +"ID2 VARCHAR(15) NOT NULL,\n" + +"CREATED_DATE DATE,\n" + +"CREATION_TIME BIGINT,\n" + +"LAST_USED DATE,\n" + +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) SALT_BUCKETS = 8, TTL = 1000"; + Connection conn1 = DriverManager.getConnection(getUrl(), props); + conn1.createStatement().execute(ddl); + ddl = "ALTER TABLE NEWCFTTLTEST ADD CF.STRING VARCHAR"; + conn1.createStatement().execute(ddl); + try (HBaseAdmin admin = conn1.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes("NEWCFTTLTEST")); + HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies(); + assertEquals(2, columnFamilies.length); + assertEquals("0", columnFamilies[0].getNameAsString()); + assertEquals(1000, columnFamilies[0].getTimeToLive()); + assertEquals("CF", columnFamilies[1].getNameAsString()); + assertEquals(1000, columnFamilies[1].getTimeToLive()); + } + } + + private static void assertImmutableRows(Connection conn, String fullTableName, boolean expectedValue) throws SQLException { + PhoenixConnection pconn = conn.unwrap(PhoenixConnection.class); + assertEquals(expectedValue, pconn.getMetaDataCache().getTable(new PTableKey(pconn.getTenantId(), fullTableName)).isImmutableRows()); + } + + @Test + public void testSetPropertyAndAddColumnForExistingColumnFamily() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + String ddl = "CREATE TABLE SETPROPEXISTINGCF " + + " (a_string varchar not null, col1 integer, CF.col2 integer" + + " CONSTRAINT pk PRIMARY KEY (a_string))\n"; + try { + conn.createStatement().execute(ddl); + conn.createStatement().execute("ALTER TABLE SETPROPEXISTINGCF ADD CF.col3 integer CF.IN_MEMORY=true"); + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes("SETPROPEXISTINGCF")).getColumnFamilies(); + assertEquals(2, columnFamilies.length); + assertEquals("0", columnFamilies[0].getNameAsString()); + assertFalse(columnFamilies[0].isInMemory()); + assertEquals("CF", columnFamilies[1].getNameAsString()); + assertTrue(columnFamilies[1].isInMemory()); + } + } finally { + conn.close(); + } + } + + @Test + public void testSetPropertyAndAddColumnForNewAndExistingColumnFamily() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + String ddl = "CREATE TABLE SETPROPNEWEXISTCF " + + " (a_string varchar not null, col1 integer, CF1.col2 integer" + + " CONSTRAINT pk PRIMARY KEY (a_string))\n"; + try { + conn.createStatement().execute(ddl); + conn.createStatement().execute("ALTER TABLE SETPROPNEWEXISTCF ADD col4 integer, CF1.col5 integer, CF2.col6 integer IN_MEMORY=true, CF1.REPLICATION_SCOPE=1, CF2.IN_MEMORY=false "); + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes("SETPROPNEWEXISTCF")).getColumnFamilies(); + assertEquals(3, columnFamilies.length); + assertEquals("0", columnFamilies[0].getNameAsString()); + assertTrue(columnFamilies[0].isInMemory()); + assertEquals(0, columnFamilies[0].getScope()); + assertEquals("CF1", columnFamilies[1].getNameAsString()); + assertTrue(columnFamilies[1].isInMemory()); + assertEquals(1, columnFamilies[1].getScope()); + assertEquals("CF2", columnFamilies[2].getNameAsString()); + assertFalse(columnFamilies[2].isInMemory()); + assertEquals(0, columnFamilies[2].getScope()); + } + } finally { + conn.close(); + } + } + + @Test + public void testSetPropertyAndAddColumnWhenTableHasExplicitDefaultColumnFamily() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + String ddl = "CREATE TABLE SETPROPNEWEXISTDEFCOLFAM " + + " (a_string varchar not null, col1 integer, CF1.col2 integer" + + " CONSTRAINT pk PRIMARY KEY (a_string)) DEFAULT_COLUMN_FAMILY = 'XYZ'\n"; + try { + conn.createStatement().execute(ddl); + conn.createStatement().execute("ALTER TABLE SETPROPNEWEXISTDEFCOLFAM ADD col4 integer, CF1.col5 integer, CF2.col6 integer IN_MEMORY=true, CF1.REPLICATION_SCOPE=1, CF2.IN_MEMORY=false, XYZ.REPLICATION_SCOPE=1 "); + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes("SETPROPNEWEXISTDEFCOLFAM")).getColumnFamilies(); + assertEquals(3, columnFamilies.length); + assertEquals("CF1", columnFamilies[0].getNameAsString()); + assertTrue(columnFamilies[0].isInMemory()); + assertEquals(1, columnFamilies[0].getScope()); + assertEquals("CF2", columnFamilies[1].getNameAsString()); + assertFalse(columnFamilies[1].isInMemory()); + assertEquals(0, columnFamilies[1].getScope()); + assertEquals("XYZ", columnFamilies[2].getNameAsString()); + assertTrue(columnFamilies[2].isInMemory()); + assertEquals(1, columnFamilies[2].getScope()); + } + } finally { + conn.close(); + } + } + + @Test + public void testSetPropertyAndAddColumnFailsForColumnFamilyNotPresentInAddCol() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + String ddl = "CREATE TABLE ADDCOLNOTPRESENT " + + " (a_string varchar not null, col1 integer, CF1.col2 integer" + + " CONSTRAINT pk PRIMARY KEY (a_string)) DEFAULT_COLUMN_FAMILY = 'XYZ'\n"; + try { + conn.createStatement().execute(ddl); + try { + conn.createStatement().execute("ALTER TABLE ADDCOLNOTPRESENT ADD col4 integer CF1.REPLICATION_SCOPE=1, XYZ.IN_MEMORY=true "); + fail(); + } catch(SQLException e) { + assertEquals(SQLExceptionCode.CANNOT_SET_PROPERTY_FOR_COLUMN_NOT_ADDED.getErrorCode(), e.getErrorCode()); + } + } finally { + conn.close(); + } + } + + @Test + public void testSetPropertyAndAddColumnForDifferentColumnFamilies() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + String ddl = "CREATE TABLE SETPROPDIFFCFSTABLE " + + " (a_string varchar not null, col1 integer, CF1.col2 integer, CF2.col3 integer" + + " CONSTRAINT pk PRIMARY KEY (a_string)) DEFAULT_COLUMN_FAMILY = 'XYZ'\n"; + try { + conn.createStatement().execute(ddl); + conn.createStatement().execute("ALTER TABLE SETPROPDIFFCFSTABLE ADD col4 integer, CF1.col5 integer, CF2.col6 integer, CF3.col7 integer CF1.REPLICATION_SCOPE=1, CF1.IN_MEMORY=false, IN_MEMORY=true "); + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes("SETPROPDIFFCFSTABLE")).getColumnFamilies(); + assertEquals(4, columnFamilies.length); + assertEquals("CF1", columnFamilies[0].getNameAsString()); + assertFalse(columnFamilies[0].isInMemory()); + assertEquals(1, columnFamilies[0].getScope()); + assertEquals("CF2", columnFamilies[1].getNameAsString()); + assertTrue(columnFamilies[1].isInMemory()); + assertEquals(0, columnFamilies[1].getScope()); + assertEquals("CF3", columnFamilies[2].getNameAsString()); + assertTrue(columnFamilies[2].isInMemory()); + assertEquals(0, columnFamilies[2].getScope()); + assertEquals("XYZ", columnFamilies[3].getNameAsString()); + assertTrue(columnFamilies[3].isInMemory()); + assertEquals(0, columnFamilies[3].getScope()); + } + } finally { + conn.close(); + } + } + + @Test + public void testSetPropertyAndAddColumnUsingDefaultColumnFamilySpecifier() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + String ddl = "CREATE TABLE SETPROPDEFCF " + + " (a_string varchar not null, col1 integer, CF1.col2 integer" + + " CONSTRAINT pk PRIMARY KEY (a_string)) DEFAULT_COLUMN_FAMILY = 'XYZ'\n"; + try { + conn.createStatement().execute(ddl); + conn.createStatement().execute("ALTER TABLE SETPROPDEFCF ADD col4 integer XYZ.REPLICATION_SCOPE=1 "); + conn.createStatement().execute("ALTER TABLE SETPROPDEFCF ADD XYZ.col5 integer IN_MEMORY=true "); + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes("SETPROPDEFCF")).getColumnFamilies(); + assertEquals(2, columnFamilies.length); + assertEquals("CF1", columnFamilies[0].getNameAsString()); + assertFalse(columnFamilies[0].isInMemory()); + assertEquals(0, columnFamilies[0].getScope()); + assertEquals("XYZ", columnFamilies[1].getNameAsString()); + assertTrue(columnFamilies[1].isInMemory()); + assertEquals(1, columnFamilies[1].getScope()); + } + } finally { + conn.close(); + } + } + + @Test + public void testSetPropertyAndAddColumnForDefaultColumnFamily() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + conn.setAutoCommit(false); + String ddl = "CREATE TABLE TT " + + " (a_string varchar not null, col1 integer" + + " CONSTRAINT pk PRIMARY KEY (a_string))\n"; + try { + conn.createStatement().execute(ddl); + conn.createStatement().execute("ALTER TABLE TT ADD col2 integer IN_MEMORY=true"); + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes("TT")).getColumnFamilies(); + assertEquals(1, columnFamilies.length); + assertEquals("0", columnFamilies[0].getNameAsString()); + assertTrue(columnFamilies[0].isInMemory()); + } + } finally { + conn.close(); + } + } + + @Test + public void testAddNewColumnFamilyProperties() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + conn.setAutoCommit(false); + + try { + conn.createStatement() + .execute( + "CREATE TABLE mixed_add_table " + + " (a_string varchar not null, col1 integer, cf1.col2 integer, col3 integer , cf2.col4 integer " + + " CONSTRAINT pk PRIMARY KEY (a_string)) immutable_rows=true , SALT_BUCKETS=3 "); + + String ddl = "Alter table mixed_add_table add cf3.col5 integer, cf4.col6 integer in_memory=true"; + conn.createStatement().execute(ddl); + + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes("MIXED_ADD_TABLE")); + assertTrue(tableDesc.isCompactionEnabled()); + HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies(); + assertEquals(5, columnFamilies.length); + assertEquals("0", columnFamilies[0].getNameAsString()); + assertFalse(columnFamilies[0].isInMemory()); + assertEquals("CF1", columnFamilies[1].getNameAsString()); + assertFalse(columnFamilies[1].isInMemory()); + assertEquals("CF2", columnFamilies[2].getNameAsString()); + assertFalse(columnFamilies[2].isInMemory()); + assertEquals("CF3", columnFamilies[3].getNameAsString()); + assertTrue(columnFamilies[3].isInMemory()); + assertEquals("CF4", columnFamilies[4].getNameAsString()); + assertTrue(columnFamilies[4].isInMemory()); + } + } finally { + conn.close(); + } + } + + @Test + public void testAddProperyToExistingColumnFamily() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + conn.setAutoCommit(false); + + try { + conn.createStatement() + .execute( + "CREATE TABLE exist_table " + + " (a_string varchar not null, col1 integer, cf1.col2 integer, col3 integer , cf2.col4 integer " + + " CONSTRAINT pk PRIMARY KEY (a_string)) immutable_rows=true , SALT_BUCKETS=3 "); + + String ddl = "Alter table exist_table add cf1.col5 integer in_memory=true"; + conn.createStatement().execute(ddl); + + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes("EXIST_TABLE")); + assertTrue(tableDesc.isCompactionEnabled()); + HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies(); + assertEquals(3, columnFamilies.length); + assertEquals("0", columnFamilies[0].getNameAsString()); + assertFalse(columnFamilies[0].isInMemory()); + assertEquals("CF1", columnFamilies[1].getNameAsString()); + assertTrue(columnFamilies[1].isInMemory()); + assertEquals("CF2", columnFamilies[2].getNameAsString()); + assertFalse(columnFamilies[2].isInMemory()); + } + } finally { + conn.close(); + } + } + + @Test + public void testAddTTLToExistingColumnFamily() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + conn.setAutoCommit(false); + + try { + String ddl = "CREATE TABLE exist_test (pk char(2) not null primary key, col1 integer, b.col1 integer) SPLIT ON ('EA','EZ')"; + conn.createStatement().execute(ddl); + ddl = "ALTER TABLE exist_test add b.col2 varchar ttl=30"; + conn.createStatement().execute(ddl); + fail(); + } catch (SQLException e) { + assertEquals(SQLExceptionCode.CANNOT_SET_TABLE_PROPERTY_ADD_COLUMN.getErrorCode(), e.getErrorCode()); + } finally { + conn.close(); + } + } + + @Test + public void testSettingTTLWhenAddingColumnNotAllowed() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + conn.setAutoCommit(false); + + try { + String ddl = "CREATE TABLE ttl_test (pk char(2) not null primary key) TTL=100 SPLIT ON ('EA','EZ')"; + conn.createStatement().execute(ddl); + ddl = "ALTER TABLE ttl_test add col1 varchar ttl=30"; + conn.createStatement().execute(ddl); + fail(); + } catch (SQLException e) { + assertEquals(SQLExceptionCode.CANNOT_SET_TABLE_PROPERTY_ADD_COLUMN.getErrorCode(), e.getErrorCode()); + } + try { + String ddl = "ALTER TABLE ttl_test add col1 varchar a.ttl=30"; + conn.createStatement().execute(ddl); + fail(); + } catch (SQLException e) { + assertEquals(SQLExceptionCode.CANNOT_SET_TABLE_PROPERTY_ADD_COLUMN.getErrorCode(), e.getErrorCode()); + } finally { + conn.close(); + } + } + + @Test + public void testSetTTLForTableWithOnlyPKCols() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + conn.setAutoCommit(false); + try { + String ddl = "create table IF NOT EXISTS ttl_test2 (" + + " id char(1) NOT NULL," + + " col1 integer NOT NULL," + + " col2 bigint NOT NULL," + + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)" + + " ) TTL=86400, SALT_BUCKETS = 4, DEFAULT_COLUMN_FAMILY='XYZ'"; + conn.createStatement().execute(ddl); + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes("TTL_TEST2")); + HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies(); + assertEquals(1, columnFamilies.length); + assertEquals("XYZ", columnFamilies[0].getNameAsString()); + assertEquals(86400, columnFamilies[0].getTimeToLive()); + } + ddl = "ALTER TABLE ttl_test2 SET TTL=30"; + conn.createStatement().execute(ddl); + conn.commit(); + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes("TTL_TEST2")); + HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies(); + assertEquals(1, columnFamilies.length); + assertEquals(30, columnFamilies[0].getTimeToLive()); + assertEquals("XYZ", columnFamilies[0].getNameAsString()); + } + } finally { + conn.close(); + } + } + + @Test + public void testSetHColumnPropertyForTableWithOnlyPKCols() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + conn.setAutoCommit(false); + try { + String ddl = "create table IF NOT EXISTS SETHCPROPPKONLY (" + + " id char(1) NOT NULL," + + " col1 integer NOT NULL," + + " col2 bigint NOT NULL," + + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)" + + " ) TTL=86400, SALT_BUCKETS = 4, DEFAULT_COLUMN_FAMILY='XYZ'"; + conn.createStatement().execute(ddl); + ddl = "ALTER TABLE SETHCPROPPKONLY SET IN_MEMORY=true"; + conn.createStatement().execute(ddl); + conn.commit(); + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes("SETHCPROPPKONLY")); + HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies(); + assertEquals(1, columnFamilies.length); + assertEquals(true, columnFamilies[0].isInMemory()); + assertEquals("XYZ", columnFamilies[0].getNameAsString()); + } + } finally { + conn.close(); + } + + try { + String ddl = "create table IF NOT EXISTS SETHCPROPPKONLY2 (" + + " id char(1) NOT NULL," + + " col1 integer NOT NULL," + + " col2 bigint NOT NULL," + + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)" + + " ) TTL=86400, SALT_BUCKETS = 4"; + conn.createStatement().execute(ddl); + ddl = "ALTER TABLE SETHCPROPPKONLY2 SET IN_MEMORY=true"; + conn.createStatement().execute(ddl); + conn.commit(); + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes("SETHCPROPPKONLY2")); + HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies(); + assertEquals(1, columnFamilies.length); + assertEquals(true, columnFamilies[0].isInMemory()); + assertEquals("0", columnFamilies[0].getNameAsString()); + } + } finally { + conn.close(); + } + } + + @Test + public void testSetHColumnPropertyAndAddColumnForDefaultCFForTableWithOnlyPKCols() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + conn.setAutoCommit(false); + try { + String ddl = "create table IF NOT EXISTS SETHCPROPADDCOLPKONLY (" + + " id char(1) NOT NULL," + + " col1 integer NOT NULL," + + " col2 bigint NOT NULL," + + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)" + + " ) TTL=86400, SALT_BUCKETS = 4, DEFAULT_COLUMN_FAMILY='XYZ'"; + conn.createStatement().execute(ddl); + ddl = "ALTER TABLE SETHCPROPADDCOLPKONLY ADD COL3 INTEGER IN_MEMORY=true"; + conn.createStatement().execute(ddl); + conn.commit(); + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes("SETHCPROPADDCOLPKONLY")); + HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies(); + assertEquals(1, columnFamilies.length); + assertEquals(true, columnFamilies[0].isInMemory()); + assertEquals("XYZ", columnFamilies[0].getNameAsString()); + } + } finally { + conn.close(); + } + } + + @Test + public void testSetHColumnPropertyAndAddColumnForNewCFForTableWithOnlyPKCols() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + conn.setAutoCommit(false); + try { + String ddl = "create table IF NOT EXISTS SETHCPROPADDNEWCFCOLPKONLY (" + + " id char(1) NOT NULL," + + " col1 integer NOT NULL," + + " col2 bigint NOT NULL," + + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)" + + " ) TTL=86400, SALT_BUCKETS = 4, DEFAULT_COLUMN_FAMILY='XYZ'"; + conn.createStatement().execute(ddl); + ddl = "ALTER TABLE SETHCPROPADDNEWCFCOLPKONLY ADD NEWCF.COL3 INTEGER IN_MEMORY=true"; + conn.createStatement().execute(ddl); + conn.commit(); + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes("SETHCPROPADDNEWCFCOLPKONLY")); + HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies(); + assertEquals(2, columnFamilies.length); + assertEquals("NEWCF", columnFamilies[0].getNameAsString()); + assertEquals(true, columnFamilies[0].isInMemory()); + assertEquals("XYZ", columnFamilies[1].getNameAsString()); + assertEquals(false, columnFamilies[1].isInMemory()); + } + } finally { + conn.close(); + } + } + + @Test + public void testTTLAssignmentForNewEmptyCF() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + conn.setAutoCommit(false); + try { + String ddl = "create table IF NOT EXISTS NEWEMPTYCFTABLE (" + + " id char(1) NOT NULL," + + " col1 integer NOT NULL," + + " col2 bigint NOT NULL," + + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)" + + " ) TTL=86400, SALT_BUCKETS = 4, DEFAULT_COLUMN_FAMILY='XYZ'"; + conn.createStatement().execute(ddl); + ddl = "ALTER TABLE NEWEMPTYCFTABLE ADD NEWCF.COL3 INTEGER IN_MEMORY=true"; + conn.createStatement().execute(ddl); + conn.commit(); + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes("NEWEMPTYCFTABLE")); + HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies(); + assertEquals(2, columnFamilies.length); + assertEquals("NEWCF", columnFamilies[0].getNameAsString()); + assertEquals(true, columnFamilies[0].isInMemory()); + assertEquals(86400, columnFamilies[0].getTimeToLive()); + assertEquals("XYZ", columnFamilies[1].getNameAsString()); + assertEquals(false, columnFamilies[1].isInMemory()); + assertEquals(86400, columnFamilies[1].getTimeToLive()); + } + + ddl = "ALTER TABLE NEWEMPTYCFTABLE SET TTL=1000"; + conn.createStatement().execute(ddl); + conn.commit(); + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes("NEWEMPTYCFTABLE")); + HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies(); + assertEquals(2, columnFamilies.length); + assertEquals("NEWCF", columnFamilies[0].getNameAsString()); + assertEquals(true, columnFamilies[0].isInMemory()); + assertEquals(1000, columnFamilies[0].getTimeToLive()); + assertEquals("XYZ", columnFamilies[1].getNameAsString()); + assertEquals(false, columnFamilies[1].isInMemory()); + assertEquals(86400, columnFamilies[1].getTimeToLive()); + } + + // the new column will be assigned to the column family XYZ. With the a KV column getting added for XYZ, + // the column family will start showing up in PTable.getColumnFamilies() after the column is added. Thus + // being a new column family for the PTable, it will end up inheriting the TTL of the emptyCF (NEWCF). + ddl = "ALTER TABLE NEWEMPTYCFTABLE ADD COL3 INTEGER"; + conn.createStatement().execute(ddl); + conn.commit(); + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes("NEWEMPTYCFTABLE")); + HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies(); + assertEquals(2, columnFamilies.length); + assertEquals("NEWCF", columnFamilies[0].getNameAsString()); + assertEquals(true, columnFamilies[0].isInMemory()); + assertEquals(1000, columnFamilies[0].getTimeToLive()); + assertEquals("XYZ", columnFamilies[1].getNameAsString()); + assertEquals(false, columnFamilies[1].isInMemory()); + assertEquals(1000, columnFamilies[1].getTimeToLive()); + } + } finally { + conn.close(); + } + } + + @Test + public void testSettingNotHColumnNorPhoenixPropertyEndsUpAsHTableProperty() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + try { + String ddl = "create table IF NOT EXISTS RANDMONPROPTABLE (" + + " id char(1) NOT NULL," + + " col1 integer NOT NULL," + + " col2 bigint NOT NULL," + + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)" + + " )"; + conn.createStatement().execute(ddl); + ddl = "ALTER TABLE RANDMONPROPTABLE ADD NEWCF.COL3 INTEGER NEWCF.UNKNOWN_PROP='ABC'"; + try { + conn.createStatement().execute(ddl); + } catch (SQLException e) { + assertEquals(SQLExceptionCode.CANNOT_SET_TABLE_PROPERTY_ADD_COLUMN.getErrorCode(), e.getErrorCode()); + } + ddl = "ALTER TABLE RANDMONPROPTABLE SET UNKNOWN_PROP='ABC'"; + conn.createStatement().execute(ddl); + try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) { + HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes("RANDMONPROPTABLE")); + assertEquals("ABC", tableDesc.getValue("UNKNOWN_PROP")); + } + } finally { + conn.close(); + } + } + } http://git-wip-us.apache.org/repos/asf/phoenix/blob/7578ee92/phoenix-core/src/it/java/org/apache/phoenix/end2end/CreateTableIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CreateTableIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CreateTableIT.java index e3bec28..31abd9b 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CreateTableIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CreateTableIT.java @@ -17,7 +17,7 @@ */ package org.apache.phoenix.end2end; -import static org.apache.hadoop.hbase.HColumnDescriptor.DEFAULT_TTL; +import static org.apache.hadoop.hbase.HColumnDescriptor.DEFAULT_REPLICATION_SCOPE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -198,12 +198,12 @@ public class CreateTableIT extends BaseClientManagedTimeIT { * Tests that when: * 1) DDL has both pk as well as key value columns * 2) Key value columns have both default and explicit column family names - * 3) TTL specifier has the explicit column family name. + * 3) Replication scope specifier has the explicit column family name. * * Then: - * 1)TTL is set. - * 2)The default column family has DEFAULT_TTL. - * 3)The explicit column family has the TTL specified in DDL. + * 1)REPLICATION_SCOPE is set. + * 2)The default column family has DEFAULT_REPLICATION_SCOPE. + * 3)The explicit column family has the REPLICATION_SCOPE specified in DDL. */ @Test public void testCreateTableColumnFamilyHBaseAttribs4() throws Exception { @@ -213,7 +213,7 @@ public class CreateTableIT extends BaseClientManagedTimeIT { + " b.col2 bigint," + " col3 bigint, " + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1)" - + " ) b.TTL=86400, SALT_BUCKETS = 4"; + + " ) b.REPLICATION_SCOPE=1, SALT_BUCKETS = 4"; long ts = nextTimestamp(); Properties props = new Properties(); props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts)); @@ -223,20 +223,20 @@ public class CreateTableIT extends BaseClientManagedTimeIT { HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes("TEST4")).getColumnFamilies(); assertEquals(2, columnFamilies.length); assertEquals("0", columnFamilies[0].getNameAsString()); - assertEquals(DEFAULT_TTL, columnFamilies[0].getTimeToLive()); + assertEquals(DEFAULT_REPLICATION_SCOPE, columnFamilies[0].getScope()); assertEquals("B", columnFamilies[1].getNameAsString()); - assertEquals(86400, columnFamilies[1].getTimeToLive()); + assertEquals(1, columnFamilies[1].getScope()); } /** * Tests that when: * 1) DDL has both pk as well as key value columns * 2) Key value columns have explicit column family names - * 3) Different TTL specifiers for different column family names. + * 3) Different REPLICATION_SCOPE specifiers for different column family names. * * Then: - * 1)TTL is set. - * 2)Each explicit column family has the TTL as specified in DDL. + * 1)REPLICATION_SCOPE is set. + * 2)Each explicit column family has the REPLICATION_SCOPE as specified in DDL. */ @Test public void testCreateTableColumnFamilyHBaseAttribs5() throws Exception { @@ -246,7 +246,7 @@ public class CreateTableIT extends BaseClientManagedTimeIT { + " b.col2 bigint," + " c.col3 bigint, " + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1)" - + " ) b.TTL=86400, c.TTL=10000, SALT_BUCKETS = 4"; + + " ) b.REPLICATION_SCOPE=0, c.REPLICATION_SCOPE=1, SALT_BUCKETS = 4"; long ts = nextTimestamp(); Properties props = new Properties(); props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts)); @@ -256,9 +256,9 @@ public class CreateTableIT extends BaseClientManagedTimeIT { HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes("TEST5")).getColumnFamilies(); assertEquals(2, columnFamilies.length); assertEquals("B", columnFamilies[0].getNameAsString()); - assertEquals(86400, columnFamilies[0].getTimeToLive()); + assertEquals(0, columnFamilies[0].getScope()); assertEquals("C", columnFamilies[1].getNameAsString()); - assertEquals(10000, columnFamilies[1].getTimeToLive()); + assertEquals(1, columnFamilies[1].getScope()); } /** @@ -363,4 +363,23 @@ public class CreateTableIT extends BaseClientManagedTimeIT { assertEquals(SQLExceptionCode.INVALID_NOT_NULL_CONSTRAINT.getErrorCode(),sqle.getErrorCode()); } } + + @Test + public void testSpecifyingColumnFamilyForTTLFails() throws Exception { + String ddl = "create table IF NOT EXISTS TESTXYZ (" + + " id char(1) NOT NULL," + + " col1 integer NOT NULL," + + " CF.col2 integer," + + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1)" + + " ) DEFAULT_COLUMN_FAMILY='a', CF.TTL=10000, SALT_BUCKETS = 4"; + long ts = nextTimestamp(); + Properties props = new Properties(); + props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts)); + Connection conn = DriverManager.getConnection(getUrl(), props); + try { + conn.createStatement().execute(ddl); + } catch (SQLException sqle) { + assertEquals(SQLExceptionCode.COLUMN_FAMILY_NOT_ALLOWED_FOR_TTL.getErrorCode(),sqle.getErrorCode()); + } + } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/7578ee92/phoenix-core/src/main/antlr3/PhoenixSQL.g ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/antlr3/PhoenixSQL.g b/phoenix-core/src/main/antlr3/PhoenixSQL.g index 2223380..c7a84cf 100644 --- a/phoenix-core/src/main/antlr3/PhoenixSQL.g +++ b/phoenix-core/src/main/antlr3/PhoenixSQL.g @@ -494,7 +494,7 @@ alter_index_node returns [AlterIndexStatement ret] // Parse an alter table statement. alter_table_node returns [AlterTableStatement ret] : ALTER (TABLE | v=VIEW) t=from_table_name - ( (DROP COLUMN (IF ex=EXISTS)? c=column_names) | (ADD (IF NOT ex=EXISTS)? (d=column_defs) (p=properties)?) | (SET (p=properties)) ) + ( (DROP COLUMN (IF ex=EXISTS)? c=column_names) | (ADD (IF NOT ex=EXISTS)? (d=column_defs) (p=fam_properties)?) | (SET (p=fam_properties)) ) { PTableType tt = v==null ? (QueryConstants.SYSTEM_SCHEMA_NAME.equals(t.getSchemaName()) ? PTableType.SYSTEM : PTableType.TABLE) : PTableType.VIEW; ret = ( c == null ? factory.addColumn(factory.namedTable(null,t), tt, d, ex!=null, p) : factory.dropColumn(factory.namedTable(null,t), tt, c, ex!=null) ); } ; http://git-wip-us.apache.org/repos/asf/phoenix/blob/7578ee92/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java b/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java index d23acc0..5035d0c 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java @@ -28,7 +28,6 @@ import org.apache.phoenix.schema.ColumnAlreadyExistsException; import org.apache.phoenix.schema.ColumnFamilyNotFoundException; import org.apache.phoenix.schema.ColumnNotFoundException; import org.apache.phoenix.schema.ConcurrentTableMutationException; -import org.apache.phoenix.schema.types.PDataType; import org.apache.phoenix.schema.ReadOnlyTableException; import org.apache.phoenix.schema.SequenceAlreadyExistsException; import org.apache.phoenix.schema.SequenceNotFoundException; @@ -36,6 +35,7 @@ import org.apache.phoenix.schema.StaleRegionBoundaryCacheException; import org.apache.phoenix.schema.TableAlreadyExistsException; import org.apache.phoenix.schema.TableNotFoundException; import org.apache.phoenix.schema.TypeMismatchException; +import org.apache.phoenix.schema.types.PDataType; import org.apache.phoenix.util.MetaDataUtil; import com.google.common.collect.Maps; @@ -204,8 +204,8 @@ public enum SQLExceptionCode { // Table properties exception. INVALID_BUCKET_NUM(1021, "42Y80", "Salt bucket numbers should be with 1 and 256."), NO_SPLITS_ON_SALTED_TABLE(1022, "42Y81", "Should not specify split points on salted table with default row key order."), - SALT_ONLY_ON_CREATE_TABLE(1024, "42Y83", "Salt bucket number may only be specified when creating a table."), - SET_UNSUPPORTED_PROP_ON_ALTER_TABLE(1025, "42Y84", "Unsupported property set in ALTER TABLE command."), + SALT_ONLY_ON_CREATE_TABLE(1024, "42Y82", "Salt bucket number may only be specified when creating a table."), + SET_UNSUPPORTED_PROP_ON_ALTER_TABLE(1025, "42Y83", "Unsupported property set in ALTER TABLE command."), CANNOT_ADD_NOT_NULLABLE_COLUMN(1038, "42Y84", "Only nullable columns may be added for a pre-existing table."), NO_MUTABLE_INDEXES(1026, "42Y85", "Mutable secondary indexes are only supported for HBase version " + MetaDataUtil.decodeHBaseVersionAsString(PhoenixDatabaseMetaData.MUTABLE_SI_VERSION_THRESHOLD) + " and above."), INVALID_FILTER_ON_IMMUTABLE_ROWS(1027, "42Y86", "All columns referenced in a WHERE clause must be available in every index for a table with immutable rows."), @@ -222,8 +222,13 @@ public enum SQLExceptionCode { VIEW_WHERE_IS_CONSTANT(1045, "43A02", "WHERE clause in VIEW should not evaluate to a constant."), CANNOT_UPDATE_VIEW_COLUMN(1046, "43A03", "Column updated in VIEW may not differ from value specified in WHERE clause."), TOO_MANY_INDEXES(1047, "43A04", "Too many indexes have already been created on the physical table."), - NO_LOCAL_INDEX_ON_TABLE_WITH_IMMUTABLE_ROWS(1048,"43A04","Local indexes aren't allowed on tables with immutable rows."), - + NO_LOCAL_INDEX_ON_TABLE_WITH_IMMUTABLE_ROWS(1048,"43A05","Local indexes aren't allowed on tables with immutable rows."), + COLUMN_FAMILY_NOT_ALLOWED_TABLE_PROPERTY(1049, "43A06", "Column family not allowed for table properties."), + COLUMN_FAMILY_NOT_ALLOWED_FOR_TTL(1050, "43A07", "Setting TTL for a column family not supported. You can only have TTL for the entire table."), + CANNOT_ALTER_PROPERTY(1051, "43A08", "Property can be specified or changed only when creating a table"), + CANNOT_SET_PROPERTY_FOR_COLUMN_NOT_ADDED(1052, "43A09", "Property cannot be specified for a column family that is not being added or modified"), + CANNOT_SET_TABLE_PROPERTY_ADD_COLUMN(1053, "43A10", "Table level property cannot be set when adding a column"), + /** Sequence related */ SEQUENCE_ALREADY_EXIST(1200, "42Z00", "Sequence already exists.", new Factory() { @Override http://git-wip-us.apache.org/repos/asf/phoenix/blob/7578ee92/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java index 01fefdd..0bb0b14 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java @@ -30,7 +30,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Map; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.util.Pair; @@ -726,7 +725,7 @@ public class PhoenixStatement implements Statement, SQLCloseable, org.apache.pho private static class ExecutableAddColumnStatement extends AddColumnStatement implements CompilableStatement { - ExecutableAddColumnStatement(NamedTableNode table, PTableType tableType, List<ColumnDef> columnDefs, boolean ifNotExists, Map<String, Object> props) { + ExecutableAddColumnStatement(NamedTableNode table, PTableType tableType, List<ColumnDef> columnDefs, boolean ifNotExists, ListMultimap<String,Pair<String,Object>> props) { super(table, tableType, columnDefs, ifNotExists, props); } @@ -851,7 +850,7 @@ public class PhoenixStatement implements Statement, SQLCloseable, org.apache.pho } @Override - public AddColumnStatement addColumn(NamedTableNode table, PTableType tableType, List<ColumnDef> columnDefs, boolean ifNotExists, Map<String,Object> props) { + public AddColumnStatement addColumn(NamedTableNode table, PTableType tableType, List<ColumnDef> columnDefs, boolean ifNotExists, ListMultimap<String,Pair<String,Object>> props) { return new ExecutableAddColumnStatement(table, tableType, columnDefs, ifNotExists, props); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/7578ee92/phoenix-core/src/main/java/org/apache/phoenix/parse/AddColumnStatement.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/AddColumnStatement.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/AddColumnStatement.java index d1b2424..1890d31 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/parse/AddColumnStatement.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/AddColumnStatement.java @@ -17,21 +17,23 @@ */ package org.apache.phoenix.parse; -import java.util.Collections; import java.util.List; -import java.util.Map; +import org.apache.hadoop.hbase.util.Pair; import org.apache.phoenix.schema.PTableType; +import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.ListMultimap; + public class AddColumnStatement extends AlterTableStatement { private final List<ColumnDef> columnDefs; private final boolean ifNotExists; - private final Map<String,Object> props; + private final ListMultimap<String,Pair<String,Object>> props; - protected AddColumnStatement(NamedTableNode table, PTableType tableType, List<ColumnDef> columnDefs, boolean ifNotExists, Map<String, Object> props) { + protected AddColumnStatement(NamedTableNode table, PTableType tableType, List<ColumnDef> columnDefs, boolean ifNotExists, ListMultimap<String,Pair<String,Object>> props) { super(table, tableType); this.columnDefs = columnDefs; - this.props = props == null ? Collections.<String,Object>emptyMap() : props; + this.props = props == null ? ImmutableListMultimap.<String,Pair<String,Object>>of() : props; this.ifNotExists = ifNotExists; } @@ -43,7 +45,7 @@ public class AddColumnStatement extends AlterTableStatement { return ifNotExists; } - public Map<String,Object> getProps() { + public ListMultimap<String,Pair<String,Object>> getProps() { return props; } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/7578ee92/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java index 0329ef4..cac36f9 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java @@ -41,13 +41,13 @@ import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction; import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunctionInfo; import org.apache.phoenix.parse.JoinTableNode.JoinType; import org.apache.phoenix.parse.LikeParseNode.LikeType; -import org.apache.phoenix.schema.types.PDataType; import org.apache.phoenix.schema.PIndexState; import org.apache.phoenix.schema.PTable.IndexType; import org.apache.phoenix.schema.PTableType; import org.apache.phoenix.schema.SortOrder; import org.apache.phoenix.schema.TypeMismatchException; import org.apache.phoenix.schema.stats.StatisticsCollectionScope; +import org.apache.phoenix.schema.types.PDataType; import org.apache.phoenix.util.SchemaUtil; import com.google.common.collect.ListMultimap; @@ -301,7 +301,7 @@ public class ParseNodeFactory { return new SequenceValueParseNode(tableName, SequenceValueParseNode.Op.NEXT_VALUE); } - public AddColumnStatement addColumn(NamedTableNode table, PTableType tableType, List<ColumnDef> columnDefs, boolean ifNotExists, Map<String,Object> props) { + public AddColumnStatement addColumn(NamedTableNode table, PTableType tableType, List<ColumnDef> columnDefs, boolean ifNotExists, ListMultimap<String,Pair<String,Object>> props) { return new AddColumnStatement(table, tableType, columnDefs, ifNotExists, props); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/7578ee92/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServices.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServices.java b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServices.java index 8826b48..f0fbf1d 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServices.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServices.java @@ -17,10 +17,12 @@ */ package org.apache.phoenix.query; +import java.io.IOException; import java.sql.SQLException; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.concurrent.TimeoutException; import org.apache.hadoop.hbase.HRegionLocation; import org.apache.hadoop.hbase.HTableDescriptor; @@ -110,4 +112,5 @@ public interface ConnectionQueryServices extends QueryServices, MetaDataMutated public void clearCache() throws SQLException; public int getSequenceSaltBuckets(); + public void modifyTable(byte[] tableName, HTableDescriptor newDesc) throws IOException, InterruptedException, TimeoutException; } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/phoenix/blob/7578ee92/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java index 2a5ff4a..483bedc 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java @@ -573,25 +573,25 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement private HTableDescriptor generateTableDescriptor(byte[] tableName, HTableDescriptor existingDesc, PTableType tableType, Map<String,Object> tableProps, List<Pair<byte[],Map<String,Object>>> families, byte[][] splits) throws SQLException { String defaultFamilyName = (String)tableProps.remove(PhoenixDatabaseMetaData.DEFAULT_COLUMN_FAMILY_NAME); - HTableDescriptor descriptor = (existingDesc != null) ? new HTableDescriptor(existingDesc) : + HTableDescriptor tableDescriptor = (existingDesc != null) ? new HTableDescriptor(existingDesc) : new HTableDescriptor(TableName.valueOf(tableName)); for (Entry<String,Object> entry : tableProps.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); - descriptor.setValue(key, value == null ? null : value.toString()); + tableDescriptor.setValue(key, value == null ? null : value.toString()); } if (families.isEmpty()) { if (tableType != PTableType.VIEW) { byte[] defaultFamilyByes = defaultFamilyName == null ? QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES : Bytes.toBytes(defaultFamilyName); // Add dummy column family so we have key values for tables that HColumnDescriptor columnDescriptor = generateColumnFamilyDescriptor(new Pair<byte[],Map<String,Object>>(defaultFamilyByes,Collections.<String,Object>emptyMap()), tableType); - descriptor.addFamily(columnDescriptor); + tableDescriptor.addFamily(columnDescriptor); } } else { for (Pair<byte[],Map<String,Object>> family : families) { // If family is only in phoenix description, add it. otherwise, modify its property accordingly. byte[] familyByte = family.getFirst(); - if (descriptor.getFamily(familyByte) == null) { + if (tableDescriptor.getFamily(familyByte) == null) { if (tableType == PTableType.VIEW) { String fullTableName = Bytes.toString(tableName); throw new ReadOnlyTableException( @@ -601,16 +601,16 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement Bytes.toString(familyByte)); } HColumnDescriptor columnDescriptor = generateColumnFamilyDescriptor(family, tableType); - descriptor.addFamily(columnDescriptor); + tableDescriptor.addFamily(columnDescriptor); } else { if (tableType != PTableType.VIEW) { - modifyColumnFamilyDescriptor(descriptor.getFamily(familyByte), family); + modifyColumnFamilyDescriptor(tableDescriptor.getFamily(familyByte), family); } } } } - addCoprocessors(tableName, descriptor, tableType); - return descriptor; + addCoprocessors(tableName, tableDescriptor, tableType); + return tableDescriptor; } private void addCoprocessors(byte[] tableName, HTableDescriptor descriptor, PTableType tableType) throws SQLException { @@ -756,6 +756,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement } else { admin.modifyColumn(tableName, newColumnDesc); } + admin.enableTable(tableName); } else { if (oldColumnDesc == null) { admin.addColumn(tableName, newColumnDesc); @@ -937,7 +938,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement return existingDesc; } - modifyTable(tableName, admin, newDesc); + modifyTable(tableName, newDesc); return newDesc; } @@ -969,15 +970,18 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement return null; // will never make it here } - private void modifyTable(byte[] tableName, HBaseAdmin admin, HTableDescriptor newDesc) throws IOException, - InterruptedException, TimeoutException { - if (!allowOnlineTableSchemaUpdate()) { - admin.disableTable(tableName); - admin.modifyTable(tableName, newDesc); - admin.enableTable(tableName); - } else { - admin.modifyTable(tableName, newDesc); - pollForUpdatedTableDescriptor(admin, newDesc, tableName); + @Override + public void modifyTable(byte[] tableName, HTableDescriptor newDesc) throws IOException, InterruptedException, + TimeoutException { + try (HBaseAdmin admin = new HBaseAdmin(config)) { + if (!allowOnlineTableSchemaUpdate()) { + admin.disableTable(tableName); + admin.modifyTable(tableName, newDesc); + admin.enableTable(tableName); + } else { + admin.modifyTable(tableName, newDesc); + pollForUpdatedTableDescriptor(admin, newDesc, tableName); + } } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/7578ee92/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java index ec10d5f..38c6139 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java @@ -19,11 +19,13 @@ package org.apache.phoenix.query; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.INDEX_STATE_BYTES; +import java.io.IOException; import java.sql.SQLException; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.concurrent.TimeoutException; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HRegionInfo; @@ -479,4 +481,9 @@ public class ConnectionlessQueryServicesImpl extends DelegateQueryServices imple return getProps().getInt(QueryServices.SEQUENCE_SALT_BUCKETS_ATTRIB, QueryServicesOptions.DEFAULT_SEQUENCE_TABLE_SALT_BUCKETS); } + + @Override + public void modifyTable(byte[] tableName, HTableDescriptor newDesc) throws IOException, + InterruptedException, TimeoutException { + } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/7578ee92/phoenix-core/src/main/java/org/apache/phoenix/query/DelegateConnectionQueryServices.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/DelegateConnectionQueryServices.java b/phoenix-core/src/main/java/org/apache/phoenix/query/DelegateConnectionQueryServices.java index ae0b689..a76738e 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/DelegateConnectionQueryServices.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/DelegateConnectionQueryServices.java @@ -17,10 +17,12 @@ */ package org.apache.phoenix.query; +import java.io.IOException; import java.sql.SQLException; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.concurrent.TimeoutException; import org.apache.hadoop.hbase.HRegionLocation; import org.apache.hadoop.hbase.HTableDescriptor; @@ -249,4 +251,10 @@ public class DelegateConnectionQueryServices extends DelegateQueryServices imple public int getSequenceSaltBuckets() { return getDelegate().getSequenceSaltBuckets(); } + + @Override + public void modifyTable(byte[] tableName, HTableDescriptor newDesc) throws IOException, + InterruptedException, TimeoutException { + getDelegate().modifyTable(tableName, newDesc); + } } \ No newline at end of file
