phoenix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sama...@apache.org
Subject [2/2] phoenix git commit: Allow ALTER TABLE <table> SET command to update HTableDescriptor and HColumnDescriptor properties (Samarth Jain/Alicia Ying Shu)
Date Sat, 10 Jan 2015 00:35:48 GMT
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 <samarth.jain@salesforce.com>
Authored: Fri Jan 9 16:35:03 2015 -0800
Committer: Samarth <samarth.jain@salesforce.com>
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


Mime
View raw message