phoenix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jamestay...@apache.org
Subject [37/41] PHOENIX-130 Separate execution of slow (integration) tests from fast unit tests (GabrielReid)
Date Wed, 12 Mar 2014 22:50:31 GMT
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/34f94a64/phoenix-core/src/it/java/org/apache/phoenix/end2end/DeleteIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/DeleteIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/DeleteIT.java
new file mode 100644
index 0000000..6fa85d8
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/DeleteIT.java
@@ -0,0 +1,382 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.end2end;
+
+import static org.apache.phoenix.util.TestUtil.PHOENIX_JDBC_URL;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.phoenix.util.QueryUtil;
+import org.junit.Test;
+
+public class DeleteIT extends BaseHBaseManagedTimeIT {
+    private static final int NUMBER_OF_ROWS = 20;
+    private static final int NTH_ROW_NULL = 5;
+    
+    private static void initTableValues(Connection conn) throws SQLException {
+        ensureTableCreated(getUrl(),"IntIntKeyTest");
+        String upsertStmt = "UPSERT INTO IntIntKeyTest VALUES(?,?)";
+        PreparedStatement stmt = conn.prepareStatement(upsertStmt);
+        for (int i = 0; i < NUMBER_OF_ROWS; i++) {
+            stmt.setInt(1, i);
+            if (i % NTH_ROW_NULL != 0) {
+                stmt.setInt(2, i * 10);
+            } else {
+                stmt.setNull(2, Types.INTEGER);
+            }
+            stmt.execute();
+        }
+        conn.commit();
+    }
+
+    @Test
+    public void testDeleteFilterNoAutoCommit() throws Exception {
+        testDeleteFilter(false);
+    }
+    
+    @Test
+    public void testDeleteFilterAutoCommit() throws Exception {
+        testDeleteFilter(true);
+    }
+    
+    private void testDeleteFilter(boolean autoCommit) throws Exception {
+        Connection conn = DriverManager.getConnection(PHOENIX_JDBC_URL);
+        initTableValues(conn);
+        
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT count(*) FROM IntIntKeyTest");
+        assertTrue(rs.next());
+        assertEquals(NUMBER_OF_ROWS, rs.getInt(1));
+
+        String deleteStmt ;
+        conn.setAutoCommit(autoCommit);
+        deleteStmt = "DELETE FROM IntIntKeyTest WHERE 20 = j";
+        assertEquals(1,conn.createStatement().executeUpdate(deleteStmt));
+        if (!autoCommit) {
+            conn.commit();
+        }
+        
+        String query = "SELECT count(*) FROM IntIntKeyTest";
+        rs = conn.createStatement().executeQuery(query);
+        assertTrue(rs.next());
+        assertEquals(NUMBER_OF_ROWS - 1, rs.getInt(1));
+    }
+    
+    private static void assertIndexUsed (Connection conn, String query, String indexName, boolean expectedToBeUsed) throws SQLException {
+        assertIndexUsed(conn, query, Collections.emptyList(), indexName, expectedToBeUsed);
+    }
+
+    private static void assertIndexUsed (Connection conn, String query, List<Object> binds, String indexName, boolean expectedToBeUsed) throws SQLException {
+            PreparedStatement stmt = conn.prepareStatement("EXPLAIN " + query);
+            for (int i = 0; i < binds.size(); i++) {
+                stmt.setObject(i+1, binds.get(i));
+            }
+            ResultSet rs = stmt.executeQuery();
+            String explainPlan = QueryUtil.getExplainPlan(rs);
+            assertEquals(expectedToBeUsed, explainPlan.contains(" SCAN OVER " + indexName));
+   }
+    
+    private void testDeleteRange(boolean autoCommit, boolean createIndex) throws Exception {
+        Connection conn = DriverManager.getConnection(PHOENIX_JDBC_URL);
+        initTableValues(conn);
+        
+        String indexName = "IDX";
+        if (createIndex) {
+            conn.createStatement().execute("CREATE INDEX IF NOT EXISTS idx ON IntIntKeyTest(j)");
+        }
+        
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT count(*) FROM IntIntKeyTest");
+        assertTrue(rs.next());
+        assertEquals(NUMBER_OF_ROWS, rs.getInt(1));
+
+        rs = conn.createStatement().executeQuery("SELECT i FROM IntIntKeyTest WHERE j IS NULL");
+        int i = 0, isNullCount = 0;
+        while (rs.next()) {
+            assertEquals(i,rs.getInt(1));
+            i += NTH_ROW_NULL;
+            isNullCount++;
+        }
+        rs = conn.createStatement().executeQuery("SELECT count(*) FROM IntIntKeyTest WHERE j IS NOT NULL");
+        assertTrue(rs.next());
+        assertEquals(NUMBER_OF_ROWS-isNullCount, rs.getInt(1));
+
+        String deleteStmt ;
+        PreparedStatement stmt;
+        conn.setAutoCommit(autoCommit);
+        deleteStmt = "DELETE FROM IntIntKeyTest WHERE i >= ? and i < ?";
+        assertIndexUsed(conn, deleteStmt, Arrays.<Object>asList(5,10), indexName, false);
+        stmt = conn.prepareStatement(deleteStmt);
+        stmt.setInt(1, 5);
+        stmt.setInt(2, 10);
+        stmt.execute();
+        if (!autoCommit) {
+            conn.commit();
+        }
+        
+        String query = "SELECT count(*) FROM IntIntKeyTest";
+        assertIndexUsed(conn, query, indexName, createIndex);
+        query = "SELECT count(*) FROM IntIntKeyTest";
+        rs = conn.createStatement().executeQuery(query);
+        assertTrue(rs.next());
+        assertEquals(NUMBER_OF_ROWS - (10-5), rs.getInt(1));
+        
+        deleteStmt = "DELETE FROM IntIntKeyTest WHERE j IS NULL";
+        stmt = conn.prepareStatement(deleteStmt);
+        assertIndexUsed(conn, deleteStmt, indexName, createIndex);
+        stmt.execute();
+        if (!autoCommit) {
+            conn.commit();
+        }
+        rs = conn.createStatement().executeQuery("SELECT count(*) FROM IntIntKeyTest");
+        assertTrue(rs.next());
+        assertEquals(NUMBER_OF_ROWS - (10-5)-isNullCount+1, rs.getInt(1));
+    }
+    
+    @Test
+    public void testDeleteRangeNoAutoCommitNoIndex() throws Exception {
+        testDeleteRange(false, false);
+    }
+    
+    @Test
+    public void testDeleteRangeAutoCommitNoIndex() throws Exception {
+        testDeleteRange(true, false);
+    }
+    
+    @Test
+    public void testDeleteRangeNoAutoCommitWithIndex() throws Exception {
+        testDeleteRange(false, true);
+    }
+    
+    @Test
+    public void testDeleteRangeAutoCommitWithIndex() throws Exception {
+        testDeleteRange(true, true);
+    }
+    
+    @Test
+    public void testDeleteAllFromTableWithIndexAutoCommitSalting() throws SQLException {
+        testDeleteAllFromTableWithIndex(true, true);
+    }
+    
+    @Test
+    public void testDeleteAllFromTableWithIndexAutoCommitNoSalting() throws SQLException {
+        testDeleteAllFromTableWithIndex(true, false);
+    }
+    
+    @Test
+    public void testDeleteAllFromTableWithIndexNoAutoCommitNoSalting() throws SQLException {
+        testDeleteAllFromTableWithIndex(false,false);
+    }
+    
+    @Test
+    public void testDeleteAllFromTableWithIndexNoAutoCommitSalted() throws SQLException {
+        testDeleteAllFromTableWithIndex(false, true);
+    }
+    
+    private void testDeleteAllFromTableWithIndex(boolean autoCommit, boolean isSalted) throws SQLException {
+        Connection con = null;
+        try {
+            con = DriverManager.getConnection(getUrl());
+            con.setAutoCommit(autoCommit);
+
+            Statement stm = con.createStatement();
+            stm.execute("CREATE TABLE IF NOT EXISTS web_stats (" +
+            		"HOST CHAR(2) NOT NULL," +
+            		"DOMAIN VARCHAR NOT NULL, " +
+            		"FEATURE VARCHAR NOT NULL, " +
+            		"DATE DATE NOT NULL, \n" + 
+            		"USAGE.CORE BIGINT," +
+            		"USAGE.DB BIGINT," +
+            		"STATS.ACTIVE_VISITOR INTEGER " +
+            		"CONSTRAINT PK PRIMARY KEY (HOST, DOMAIN, FEATURE, DATE))" + (isSalted ? " SALT_BUCKETS=3" : ""));
+            stm.execute("CREATE INDEX web_stats_idx ON web_stats (CORE,DB,ACTIVE_VISITOR)");
+            stm.close();
+
+            PreparedStatement psInsert = con
+                    .prepareStatement("UPSERT INTO web_stats(HOST, DOMAIN, FEATURE, DATE, CORE, DB, ACTIVE_VISITOR) VALUES(?,?, ? , ?, ?, ?, ?)");
+            psInsert.setString(1, "AA");
+            psInsert.setString(2, "BB");
+            psInsert.setString(3, "CC");
+            psInsert.setDate(4, new Date(0));
+            psInsert.setLong(5, 1L);
+            psInsert.setLong(6, 2L);
+            psInsert.setLong(7, 3);
+            psInsert.execute();
+            psInsert.close();
+            if (!autoCommit) {
+                con.commit();
+            }
+            
+            con.createStatement().execute("DELETE FROM web_stats");
+            if (!autoCommit) {
+                con.commit();
+            }
+            
+            ResultSet rs = con.createStatement().executeQuery("SELECT /*+ NO_INDEX */ count(*) FROM web_stats");
+            assertTrue(rs.next());
+            assertEquals(0, rs.getLong(1));
+
+            rs = con.createStatement().executeQuery("SELECT count(*) FROM web_stats_idx");
+            assertTrue(rs.next());
+            assertEquals(0, rs.getLong(1));
+
+        } finally {
+            try {
+                con.close();
+            } catch (Exception ex) {
+            }
+        }
+    }
+    
+    @Test
+    public void testDeleteRowFromTableWithImmutableIndex() throws SQLException {
+        Connection con = null;
+        try {
+            boolean autoCommit = false;
+            con = DriverManager.getConnection(getUrl());
+            con.setAutoCommit(autoCommit);
+
+            Statement stm = con.createStatement();
+            stm.execute("CREATE TABLE IF NOT EXISTS web_stats (" +
+                    "HOST CHAR(2) NOT NULL," +
+                    "DOMAIN VARCHAR NOT NULL, " +
+                    "FEATURE VARCHAR NOT NULL, " +
+                    "DATE DATE NOT NULL, \n" + 
+                    "USAGE.CORE BIGINT," +
+                    "USAGE.DB BIGINT," +
+                    "STATS.ACTIVE_VISITOR INTEGER " +
+                    "CONSTRAINT PK PRIMARY KEY (HOST, DOMAIN, FEATURE, DATE)) IMMUTABLE_ROWS=true");
+            stm.execute("CREATE INDEX web_stats_idx ON web_stats (DATE, FEATURE)");
+            stm.close();
+
+            Date date = new Date(0);
+            PreparedStatement psInsert = con
+                    .prepareStatement("UPSERT INTO web_stats(HOST, DOMAIN, FEATURE, DATE, CORE, DB, ACTIVE_VISITOR) VALUES(?,?, ? , ?, ?, ?, ?)");
+            psInsert.setString(1, "AA");
+            psInsert.setString(2, "BB");
+            psInsert.setString(3, "CC");
+            psInsert.setDate(4, date);
+            psInsert.setLong(5, 1L);
+            psInsert.setLong(6, 2L);
+            psInsert.setLong(7, 3);
+            psInsert.execute();
+            psInsert.close();
+            if (!autoCommit) {
+                con.commit();
+            }
+            
+            psInsert = con.prepareStatement("DELETE FROM web_stats WHERE (HOST, DOMAIN, FEATURE, DATE) = (?,?,?,?)");
+            psInsert.setString(1, "AA");
+            psInsert.setString(2, "BB");
+            psInsert.setString(3, "CC");
+            psInsert.setDate(4, date);
+            psInsert.execute();
+            if (!autoCommit) {
+                con.commit();
+            }
+            
+            ResultSet rs = con.createStatement().executeQuery("SELECT /*+ NO_INDEX */ count(*) FROM web_stats");
+            assertTrue(rs.next());
+            assertEquals(0, rs.getLong(1));
+
+            rs = con.createStatement().executeQuery("SELECT count(*) FROM web_stats_idx");
+            assertTrue(rs.next());
+            assertEquals(0, rs.getLong(1));
+
+        } finally {
+            try {
+                con.close();
+            } catch (Exception ex) {
+            }
+        }
+    }
+    
+    
+    @Test
+    public void testDeleteAllFromTableNoAutoCommit() throws SQLException {
+        testDeleteAllFromTable(false);
+    }
+
+    @Test
+    public void testDeleteAllFromTableAutoCommit() throws SQLException {
+        testDeleteAllFromTable(true);
+    }
+    
+    private void testDeleteAllFromTable(boolean autoCommit) throws SQLException {
+        Connection con = null;
+        try {
+            con = DriverManager.getConnection(getUrl());
+            con.setAutoCommit(autoCommit);
+
+            Statement stm = con.createStatement();
+            stm.execute("CREATE TABLE IF NOT EXISTS web_stats (" +
+                    "HOST CHAR(2) NOT NULL," +
+                    "DOMAIN VARCHAR NOT NULL, " +
+                    "FEATURE VARCHAR NOT NULL, " +
+                    "DATE DATE NOT NULL, \n" + 
+                    "USAGE.CORE BIGINT," +
+                    "USAGE.DB BIGINT," +
+                    "STATS.ACTIVE_VISITOR INTEGER " +
+                    "CONSTRAINT PK PRIMARY KEY (HOST, DOMAIN, FEATURE, DATE))");
+            stm.close();
+
+            PreparedStatement psInsert = con
+                    .prepareStatement("UPSERT INTO web_stats(HOST, DOMAIN, FEATURE, DATE, CORE, DB, ACTIVE_VISITOR) VALUES(?,?, ? , ?, ?, ?, ?)");
+            psInsert.setString(1, "AA");
+            psInsert.setString(2, "BB");
+            psInsert.setString(3, "CC");
+            psInsert.setDate(4, new Date(0));
+            psInsert.setLong(5, 1L);
+            psInsert.setLong(6, 2L);
+            psInsert.setLong(7, 3);
+            psInsert.execute();
+            psInsert.close();
+            if (!autoCommit) {
+                con.commit();
+            }
+            
+            con.createStatement().execute("DELETE FROM web_stats");
+            if (!autoCommit) {
+                con.commit();
+            }
+            
+            ResultSet rs = con.createStatement().executeQuery("SELECT /*+ NO_INDEX */ count(*) FROM web_stats");
+            assertTrue(rs.next());
+            assertEquals(0, rs.getLong(1));
+        } finally {
+            try {
+                con.close();
+            } catch (Exception ex) {
+            }
+        }
+    }
+}
+
+

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/34f94a64/phoenix-core/src/it/java/org/apache/phoenix/end2end/DistinctCountIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/DistinctCountIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/DistinctCountIT.java
new file mode 100644
index 0000000..8e77e71
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/DistinctCountIT.java
@@ -0,0 +1,437 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.end2end;
+
+import static org.apache.phoenix.util.TestUtil.*;
+import static org.junit.Assert.*;
+
+import java.math.BigDecimal;
+import java.sql.*;
+import java.util.Properties;
+
+import org.apache.phoenix.util.PhoenixRuntime;
+import org.junit.Test;
+
+public class DistinctCountIT extends BaseClientManagedTimeIT {
+
+    @Test
+    public void testDistinctCountOnColumn() throws Exception {
+        long ts = nextTimestamp();
+        String tenantId = getOrganizationId();
+        initATableValues(tenantId, null, getDefaultSplits(tenantId), null, ts);
+
+        String query = "SELECT count(DISTINCT A_STRING) FROM aTable";
+
+        Properties props = new Properties(TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 2)); // Execute at
+                                                                                     // timestamp 2
+        Connection conn = DriverManager.getConnection(PHOENIX_JDBC_URL, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(3, rs.getLong(1));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+
+    @Test
+    public void testDistinctCountOnRKColumn() throws Exception {
+        long ts = nextTimestamp();
+        String tenantId = getOrganizationId();
+        initATableValues(tenantId, null, getDefaultSplits(tenantId), null, ts);
+
+        String query = "SELECT count(DISTINCT ORGANIZATION_ID) FROM aTable";
+
+        Properties props = new Properties(TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 2)); // Execute at
+                                                                                     // timestamp 2
+        Connection conn = DriverManager.getConnection(PHOENIX_JDBC_URL, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(1, rs.getLong(1));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+
+    @Test
+    public void testDistinctCountWithGroupBy() throws Exception {
+        long ts = nextTimestamp();
+        String tenantId = getOrganizationId();
+        initATableValues(tenantId, null, getDefaultSplits(tenantId), null, ts);
+
+        String query = "SELECT A_STRING, count(DISTINCT B_STRING) FROM aTable group by A_STRING";
+
+        Properties props = new Properties(TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 2)); // Execute at
+                                                                                     // timestamp 2
+        Connection conn = DriverManager.getConnection(PHOENIX_JDBC_URL, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(A_VALUE, rs.getString(1));
+            assertEquals(2, rs.getLong(2));
+            assertTrue(rs.next());
+            assertEquals(B_VALUE, rs.getString(1));
+            assertEquals(1, rs.getLong(2));
+            assertTrue(rs.next());
+            assertEquals(C_VALUE, rs.getString(1));
+            assertEquals(1, rs.getLong(2));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+
+    @Test
+    public void testDistinctCountWithGroupByAndOrderBy() throws Exception {
+        long ts = nextTimestamp();
+        String tenantId = getOrganizationId();
+        initATableValues(tenantId, null, getDefaultSplits(tenantId), null, ts);
+
+        String query = "SELECT A_STRING, count(DISTINCT B_STRING) FROM aTable group by A_STRING order by A_STRING desc";
+
+        Properties props = new Properties(TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 2)); // Execute at
+                                                                                     // timestamp 2
+        Connection conn = DriverManager.getConnection(PHOENIX_JDBC_URL, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(C_VALUE, rs.getString(1));
+            assertEquals(1, rs.getLong(2));
+            assertTrue(rs.next());
+            assertEquals(B_VALUE, rs.getString(1));
+            assertEquals(1, rs.getLong(2));
+            assertTrue(rs.next());
+            assertEquals(A_VALUE, rs.getString(1));
+            assertEquals(2, rs.getLong(2));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+
+    @Test
+    public void testDistinctCountWithGroupByAndOrderByOnDistinctCount() throws Exception {
+        long ts = nextTimestamp();
+        String tenantId = getOrganizationId();
+        initATableValues(tenantId, null, getDefaultSplits(tenantId), null, ts);
+
+        String query = "SELECT A_STRING, count(DISTINCT B_STRING) as COUNT_B_STRING FROM aTable group by A_STRING order by COUNT_B_STRING";
+
+        Properties props = new Properties(TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 2)); // Execute at
+                                                                                     // timestamp 2
+        Connection conn = DriverManager.getConnection(PHOENIX_JDBC_URL, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(B_VALUE, rs.getString(1));
+            assertEquals(1, rs.getLong(2));
+            assertTrue(rs.next());
+            assertEquals(C_VALUE, rs.getString(1));
+            assertEquals(1, rs.getLong(2));
+            assertTrue(rs.next());
+            assertEquals(A_VALUE, rs.getString(1));
+            assertEquals(2, rs.getLong(2));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+
+    @Test
+    public void testDistinctCountWithGroupByOrdered() throws Exception {
+        long ts = nextTimestamp();
+        String tenantId = getOrganizationId();
+        String tenantId2 = "00D400000000XHP";
+        initATableValues(tenantId, tenantId2, getDefaultSplits(tenantId), null, ts);
+
+        String query = "SELECT organization_id, count(DISTINCT A_STRING) FROM aTable group by organization_id";
+
+        Properties props = new Properties(TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 2)); // Execute at
+                                                                                     // timestamp 2
+        Connection conn = DriverManager.getConnection(PHOENIX_JDBC_URL, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(tenantId, rs.getString(1));
+            assertEquals(3, rs.getLong(2));
+            assertTrue(rs.next());
+            assertEquals(tenantId2, rs.getString(1));
+            assertEquals(1, rs.getLong(2));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+
+    @Test
+    public void testDistinctCountOn2Columns() throws Exception {
+        long ts = nextTimestamp();
+        String tenantId = getOrganizationId();
+        initATableValues(tenantId, null, getDefaultSplits(tenantId), null, ts);
+
+        String query = "SELECT count(DISTINCT A_STRING), count(DISTINCT B_STRING) FROM aTable";
+
+        Properties props = new Properties(TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 2)); // Execute at
+                                                                                     // timestamp 2
+        Connection conn = DriverManager.getConnection(PHOENIX_JDBC_URL, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(3, rs.getLong(1));
+            assertEquals(2, rs.getLong(2));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+    
+    @Test
+    public void testDistinctCountONE() throws Exception {
+        long ts = nextTimestamp();
+        String tenantId = getOrganizationId();
+        initATableValues(tenantId, null, getDefaultSplits(tenantId), null, ts);
+
+        String query = "SELECT count(DISTINCT 1) FROM aTable";
+
+        Properties props = new Properties(TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 2)); // Execute at
+                                                                                     // timestamp 2
+        Connection conn = DriverManager.getConnection(PHOENIX_JDBC_URL, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(1, rs.getLong(1));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+    
+    @Test
+    public void testDistinctCountONEWithEmptyResult() throws Exception {
+        long ts = nextTimestamp();
+        String tenantId = getOrganizationId();
+        initATableValues(null, null, getDefaultSplits(tenantId), null, ts);
+
+        String query = "SELECT count(DISTINCT 1) FROM aTable";
+
+        Properties props = new Properties(TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 2)); // Execute at
+                                                                                     // timestamp 2
+        Connection conn = DriverManager.getConnection(PHOENIX_JDBC_URL, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(0, rs.getLong(1));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+    
+    protected static void initATableValues(String tenantId1, String tenantId2, byte[][] splits, Date date, Long ts) throws Exception {
+        if (ts == null) {
+            ensureTableCreated(getUrl(), ATABLE_NAME, splits);
+        } else {
+            ensureTableCreated(getUrl(), ATABLE_NAME, splits, ts-2);
+        }
+        
+        Properties props = new Properties();
+        if (ts != null) {
+            props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, ts.toString());
+        }
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        try {
+            // Insert all rows at ts
+            PreparedStatement stmt = conn.prepareStatement(
+                    "upsert into " +
+                    "ATABLE(" +
+                    "    ORGANIZATION_ID, " +
+                    "    ENTITY_ID, " +
+                    "    A_STRING, " +
+                    "    B_STRING, " +
+                    "    A_INTEGER, " +
+                    "    A_DATE, " +
+                    "    X_DECIMAL, " +
+                    "    X_LONG, " +
+                    "    X_INTEGER," +
+                    "    Y_INTEGER)" +
+                    "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+            if (tenantId1 != null) {
+                stmt.setString(1, tenantId1);
+                stmt.setString(2, ROW1);
+                stmt.setString(3, A_VALUE);
+                stmt.setString(4, B_VALUE);
+                stmt.setInt(5, 1);
+                stmt.setDate(6, date);
+                stmt.setBigDecimal(7, null);
+                stmt.setNull(8, Types.BIGINT);
+                stmt.setNull(9, Types.INTEGER);
+                stmt.setNull(10, Types.INTEGER);
+                stmt.execute();
+
+                stmt.setString(1, tenantId1);
+                stmt.setString(2, ROW2);
+                stmt.setString(3, A_VALUE);
+                stmt.setString(4, C_VALUE);
+                stmt.setInt(5, 2);
+                stmt.setDate(6, date == null ? null : new Date(date.getTime() + MILLIS_IN_DAY * 1));
+                stmt.setBigDecimal(7, null);
+                stmt.setNull(8, Types.BIGINT);
+                stmt.setNull(9, Types.INTEGER);
+                stmt.setNull(10, Types.INTEGER);
+                stmt.execute();
+
+                stmt.setString(1, tenantId1);
+                stmt.setString(2, ROW3);
+                stmt.setString(3, A_VALUE);
+                stmt.setString(4, C_VALUE);
+                stmt.setInt(5, 3);
+                stmt.setDate(6, date == null ? null : new Date(date.getTime() + MILLIS_IN_DAY * 2));
+                stmt.setBigDecimal(7, null);
+                stmt.setNull(8, Types.BIGINT);
+                stmt.setNull(9, Types.INTEGER);
+                stmt.setNull(10, Types.INTEGER);
+                stmt.execute();
+
+                stmt.setString(1, tenantId1);
+                stmt.setString(2, ROW4);
+                stmt.setString(3, A_VALUE);
+                stmt.setString(4, B_VALUE);
+                stmt.setInt(5, 4);
+                stmt.setDate(6, date == null ? null : date);
+                stmt.setBigDecimal(7, null);
+                stmt.setNull(8, Types.BIGINT);
+                stmt.setNull(9, Types.INTEGER);
+                stmt.setNull(10, Types.INTEGER);
+                stmt.execute();
+
+                stmt.setString(1, tenantId1);
+                stmt.setString(2, ROW5);
+                stmt.setString(3, B_VALUE);
+                stmt.setString(4, C_VALUE);
+                stmt.setInt(5, 5);
+                stmt.setDate(6, date == null ? null : new Date(date.getTime() + MILLIS_IN_DAY * 1));
+                stmt.setBigDecimal(7, null);
+                stmt.setNull(8, Types.BIGINT);
+                stmt.setNull(9, Types.INTEGER);
+                stmt.setNull(10, Types.INTEGER);
+                stmt.execute();
+
+                stmt.setString(1, tenantId1);
+                stmt.setString(2, ROW6);
+                stmt.setString(3, B_VALUE);
+                stmt.setString(4, C_VALUE);
+                stmt.setInt(5, 6);
+                stmt.setDate(6, date == null ? null : new Date(date.getTime() + MILLIS_IN_DAY * 2));
+                stmt.setBigDecimal(7, null);
+                stmt.setNull(8, Types.BIGINT);
+                stmt.setNull(9, Types.INTEGER);
+                stmt.setNull(10, Types.INTEGER);
+                stmt.execute();
+
+                stmt.setString(1, tenantId1);
+                stmt.setString(2, ROW7);
+                stmt.setString(3, B_VALUE);
+                stmt.setString(4, C_VALUE);
+                stmt.setInt(5, 7);
+                stmt.setDate(6, date == null ? null : date);
+                stmt.setBigDecimal(7, BigDecimal.valueOf(0.1));
+                stmt.setLong(8, 5L);
+                stmt.setInt(9, 5);
+                stmt.setNull(10, Types.INTEGER);
+                stmt.execute();
+
+                stmt.setString(1, tenantId1);
+                stmt.setString(2, ROW8);
+                stmt.setString(3, B_VALUE);
+                stmt.setString(4, C_VALUE);
+                stmt.setInt(5, 8);
+                stmt.setDate(6, date == null ? null : new Date(date.getTime() + MILLIS_IN_DAY * 1));
+                stmt.setBigDecimal(7, BigDecimal.valueOf(3.9));
+                long l = Integer.MIN_VALUE - 1L;
+                assert (l < Integer.MIN_VALUE);
+                stmt.setLong(8, l);
+                stmt.setInt(9, 4);
+                stmt.setNull(10, Types.INTEGER);
+                stmt.execute();
+
+                stmt.setString(1, tenantId1);
+                stmt.setString(2, ROW9);
+                stmt.setString(3, C_VALUE);
+                stmt.setString(4, C_VALUE);
+                stmt.setInt(5, 9);
+                stmt.setDate(6, date == null ? null : new Date(date.getTime() + MILLIS_IN_DAY * 2));
+                stmt.setBigDecimal(7, BigDecimal.valueOf(3.3));
+                l = Integer.MAX_VALUE + 1L;
+                assert (l > Integer.MAX_VALUE);
+                stmt.setLong(8, l);
+                stmt.setInt(9, 3);
+                stmt.setInt(10, 300);
+                stmt.execute();
+            }
+            if (tenantId2 != null) {
+                stmt.setString(1, tenantId2);
+                stmt.setString(2, ROW1);
+                stmt.setString(3, A_VALUE);
+                stmt.setString(4, B_VALUE);
+                stmt.setInt(5, 1);
+                stmt.setDate(6, date);
+                stmt.setBigDecimal(7, null);
+                stmt.setNull(8, Types.BIGINT);
+                stmt.setNull(9, Types.INTEGER);
+                stmt.setNull(10, Types.INTEGER);
+                stmt.execute();
+
+                stmt.setString(1, tenantId2);
+                stmt.setString(2, ROW2);
+                stmt.setString(3, A_VALUE);
+                stmt.setString(4, C_VALUE);
+                stmt.setInt(5, 2);
+                stmt.setDate(6, date == null ? null : new Date(date.getTime() + MILLIS_IN_DAY * 1));
+                stmt.setBigDecimal(7, null);
+                stmt.setNull(8, Types.BIGINT);
+                stmt.setNull(9, Types.INTEGER);
+                stmt.setNull(10, Types.INTEGER);
+                stmt.execute();
+            }
+            conn.commit();
+        } finally {
+            conn.close();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/34f94a64/phoenix-core/src/it/java/org/apache/phoenix/end2end/DynamicColumnIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/DynamicColumnIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/DynamicColumnIT.java
new file mode 100644
index 0000000..abe6221
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/DynamicColumnIT.java
@@ -0,0 +1,217 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.phoenix.end2end;
+
+import static org.apache.phoenix.util.TestUtil.HBASE_DYNAMIC_COLUMNS;
+import static org.apache.phoenix.util.TestUtil.HBASE_DYNAMIC_COLUMNS_SCHEMA_NAME;
+import static org.apache.phoenix.util.TestUtil.PHOENIX_JDBC_URL;
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.client.Row;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.query.ConnectionQueryServices;
+import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.schema.ColumnAlreadyExistsException;
+import org.apache.phoenix.schema.ColumnFamilyNotFoundException;
+import org.apache.phoenix.util.SchemaUtil;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Basic tests for Phoenix dynamic upserting
+ * 
+ * 
+ * @since 1.3
+ */
+
+public class DynamicColumnIT extends BaseClientManagedTimeIT {
+    private static final byte[] HBASE_DYNAMIC_COLUMNS_BYTES = SchemaUtil.getTableNameAsBytes(null, HBASE_DYNAMIC_COLUMNS);
+    private static final byte[] FAMILY_NAME = Bytes.toBytes(SchemaUtil.normalizeIdentifier("A"));
+    private static final byte[] FAMILY_NAME2 = Bytes.toBytes(SchemaUtil.normalizeIdentifier("B"));
+
+    @BeforeClass
+    public static void doBeforeTestSetup() throws Exception {
+        HBaseAdmin admin = driver.getConnectionQueryServices(getUrl(), TEST_PROPERTIES).getAdmin();
+        try {
+            try {
+                admin.disableTable(HBASE_DYNAMIC_COLUMNS_BYTES);
+                admin.deleteTable(HBASE_DYNAMIC_COLUMNS_BYTES);
+            } catch (org.apache.hadoop.hbase.TableNotFoundException e) {}
+            ensureTableCreated(getUrl(), HBASE_DYNAMIC_COLUMNS);
+            initTableValues();
+        } finally {
+            admin.close();
+        }
+    }
+
+    private static void initTableValues() throws Exception {
+        ConnectionQueryServices services = driver.getConnectionQueryServices(getUrl(), TEST_PROPERTIES);
+        HTableInterface hTable = services.getTable(SchemaUtil.getTableNameAsBytes(HBASE_DYNAMIC_COLUMNS_SCHEMA_NAME,HBASE_DYNAMIC_COLUMNS));
+        try {
+            // Insert rows using standard HBase mechanism with standard HBase "types"
+            List<Row> mutations = new ArrayList<Row>();
+            byte[] dv = Bytes.toBytes("DV");
+            byte[] first = Bytes.toBytes("F");
+            byte[] f1v1 = Bytes.toBytes("F1V1");
+            byte[] f1v2 = Bytes.toBytes("F1V2");
+            byte[] f2v1 = Bytes.toBytes("F2V1");
+            byte[] f2v2 = Bytes.toBytes("F2V2");
+            byte[] key = Bytes.toBytes("entry1");
+
+            Put put = new Put(key);
+            put.add(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, dv, Bytes.toBytes("default"));
+            put.add(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, first, Bytes.toBytes("first"));
+            put.add(FAMILY_NAME, f1v1, Bytes.toBytes("f1value1"));
+            put.add(FAMILY_NAME, f1v2, Bytes.toBytes("f1value2"));
+            put.add(FAMILY_NAME2, f2v1, Bytes.toBytes("f2value1"));
+            put.add(FAMILY_NAME2, f2v2, Bytes.toBytes("f2value2"));
+            mutations.add(put);
+
+            hTable.batch(mutations);
+
+        } finally {
+            hTable.close();
+        }
+        // Create Phoenix table after HBase table was created through the native APIs
+        // The timestamp of the table creation must be later than the timestamp of the data
+        ensureTableCreated(getUrl(), HBASE_DYNAMIC_COLUMNS);
+    }
+
+    /**
+     * Test a simple select with a dynamic Column
+     */
+    @Test
+    public void testDynamicColums() throws Exception {
+        String query = "SELECT * FROM HBASE_DYNAMIC_COLUMNS (DV varchar)";
+        String url = PHOENIX_JDBC_URL + ";";
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(url, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals("entry1", rs.getString(1));
+            assertEquals("first", rs.getString(2));
+            assertEquals("f1value1", rs.getString(3));
+            assertEquals("f1value2", rs.getString(4));
+            assertEquals("f2value1", rs.getString(5));
+            assertEquals("default", rs.getString(6));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+
+    /**
+     * Test a select with a colum family.column dynamic Column
+     */
+    @Test
+    public void testDynamicColumsFamily() throws Exception {
+        String query = "SELECT * FROM HBASE_DYNAMIC_COLUMNS (DV varchar,B.F2V2 varchar)";
+        String url = PHOENIX_JDBC_URL + ";";
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(url, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals("entry1", rs.getString(1));
+            assertEquals("first", rs.getString(2));
+            assertEquals("f1value1", rs.getString(3));
+            assertEquals("f1value2", rs.getString(4));
+            assertEquals("f2value1", rs.getString(5));
+            assertEquals("default", rs.getString(6));
+            assertEquals("f2value2", rs.getString(7));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+
+    /**
+     * Test a select with a colum family.column dynamic Column and check the value
+     */
+
+    @Test
+    public void testDynamicColumsSpecificQuery() throws Exception {
+        String query = "SELECT entry,F2V2 FROM HBASE_DYNAMIC_COLUMNS (DV varchar,B.F2V2 varchar)";
+        String url = PHOENIX_JDBC_URL + ";";
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(url, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals("entry1", rs.getString(1));
+            assertEquals("f2value2", rs.getString(2));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+
+    /**
+     * Test an upsert of prexisting schema defined columns and dynamic ones with different datatypes
+     */
+    @Test(expected = ColumnAlreadyExistsException.class)
+    public void testAmbiguousStaticSelect() throws Exception {
+        String upsertquery = "Select * FROM HBASE_DYNAMIC_COLUMNS(A.F1V1 INTEGER)";
+        String url = PHOENIX_JDBC_URL + ";";
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(url, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(upsertquery);
+            statement.executeQuery();
+        } finally {
+            conn.close();
+        }
+    }
+
+    /**
+     * Test a select of an undefined ColumnFamily dynamic columns
+     */
+    @Test(expected = ColumnFamilyNotFoundException.class)
+    public void testFakeCFDynamicUpsert() throws Exception {
+        String upsertquery = "Select * FROM HBASE_DYNAMIC_COLUMNS(fakecf.DynCol VARCHAR)";
+        String url = PHOENIX_JDBC_URL + ";";
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(url, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(upsertquery);
+            statement.executeQuery();
+        } finally {
+            conn.close();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/34f94a64/phoenix-core/src/it/java/org/apache/phoenix/end2end/DynamicFamilyIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/DynamicFamilyIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/DynamicFamilyIT.java
new file mode 100644
index 0000000..34c6b84
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/DynamicFamilyIT.java
@@ -0,0 +1,359 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.end2end;
+
+import static org.apache.phoenix.util.TestUtil.PHOENIX_JDBC_URL;
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Time;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.client.Row;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.util.Pair;
+import org.apache.phoenix.exception.PhoenixParserException;
+import org.apache.phoenix.exception.SQLExceptionCode;
+import org.apache.phoenix.query.ConnectionQueryServices;
+import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.schema.ColumnFamilyNotFoundException;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.util.ByteUtil;
+import org.apache.phoenix.util.SchemaUtil;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Basic tests for Phoenix dynamic family querying "cf.*"
+ * 
+ * 
+ * @since 1.2
+ */
+
+@edu.umd.cs.findbugs.annotations.SuppressWarnings(
+        value="RV_RETURN_VALUE_IGNORED", 
+        justification="Designed to ignore.")
+public class DynamicFamilyIT extends BaseHBaseManagedTimeIT {
+    private static final String WEB_STATS = "WEB_STATS";
+    private static final String WEB_STATS_SCHEMA_NAME = "";
+    private static final byte[] A_CF = Bytes.toBytes(SchemaUtil.normalizeIdentifier("A"));
+    private static final byte[] B_CF = Bytes.toBytes(SchemaUtil.normalizeIdentifier("B"));
+    private static final String USER_ID1 = "u0001";
+    private static final String USER_ID2 = "u0002";
+    private static final String USER_ID3 = "u0003";
+    private static final byte[] USER_ID1_BYTES = Bytes.toBytes(USER_ID1);
+    private static final byte[] USER_ID2_BYTES = Bytes.toBytes(USER_ID2);
+    private static final byte[] USER_ID3_BYTES = Bytes.toBytes(USER_ID3);
+    
+    private static final String MAX_CLICK_COUNT_PREFIX = SchemaUtil.normalizeIdentifier("MaxClickCount_");
+    private static final byte[] MAX_CLICK_COUNT_DYNCOL_PREFIX = Bytes.toBytes(MAX_CLICK_COUNT_PREFIX);
+    private static final Integer ENTRY1_CLICK_COUNT = 12;
+    private static final Integer ENTRY2_CLICK_COUNT = 34;
+    private static final Integer ENTRY3_CLICK_COUNT = 56;
+    
+    private static final String LAST_LOGIN_TIME_PREFIX = SchemaUtil.normalizeIdentifier("LastLoginTime_");
+    private static final byte[] LAST_LOGIN_TIME_DYNCOL_PREFIX = Bytes.toBytes(LAST_LOGIN_TIME_PREFIX);
+    
+    private static final Time ENTRY1_USER_ID1_LOGIN_TIME = new Time(System.currentTimeMillis()+60000);
+    private static final Time ENTRY1_USER_ID2_LOGIN_TIME = new Time(System.currentTimeMillis()+120000);
+    
+    private static final Time ENTRY2_USER_ID2_LOGIN_TIME = new Time(System.currentTimeMillis()+180000);
+    private static final Time ENTRY2_USER_ID3_LOGIN_TIME = new Time(System.currentTimeMillis()+240000);
+    
+    private static final Time ENTRY3_USER_ID1_LOGIN_TIME = new Time(System.currentTimeMillis()+300000);
+    private static final Time ENTRY3_USER_ID2_LOGIN_TIME = new Time(System.currentTimeMillis()+360000);
+    private static final Time ENTRY3_USER_ID3_LOGIN_TIME = new Time(System.currentTimeMillis()+420000);
+
+    @Before
+    public void doBeforeTestSetup() throws Exception {
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        String ddl = "create table if not exists  " + WEB_STATS
+                + "   (entry varchar not null primary key,"
+                + "    a.dummy varchar," 
+                + "    b.dummy varchar)";
+        conn.createStatement().execute(ddl);
+        conn.close();
+        initTableValues();
+    }
+
+    private static void initTableValues() throws Exception {
+        ConnectionQueryServices services = driver.getConnectionQueryServices(getUrl(), TEST_PROPERTIES);
+        HTableInterface hTable = services.getTable(SchemaUtil.getTableNameAsBytes(WEB_STATS_SCHEMA_NAME,WEB_STATS));
+        try {
+            // Insert rows using standard HBase mechanism with standard HBase "types"
+            Put put;
+            List<Row> mutations = new ArrayList<Row>();
+            put = new Put(Bytes.toBytes("entry1"));
+            put.add(A_CF, QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, ByteUtil.EMPTY_BYTE_ARRAY);
+            put.add(A_CF, ByteUtil.concat(MAX_CLICK_COUNT_DYNCOL_PREFIX, USER_ID2_BYTES), PDataType.INTEGER.toBytes(ENTRY1_CLICK_COUNT));
+            put.add(B_CF, ByteUtil.concat(LAST_LOGIN_TIME_DYNCOL_PREFIX, USER_ID1_BYTES), PDataType.TIME.toBytes(ENTRY1_USER_ID1_LOGIN_TIME));
+            put.add(B_CF, ByteUtil.concat(LAST_LOGIN_TIME_DYNCOL_PREFIX, USER_ID2_BYTES), PDataType.TIME.toBytes(ENTRY1_USER_ID2_LOGIN_TIME));
+            mutations.add(put);
+            
+            put = new Put(Bytes.toBytes("entry2"));
+            put.add(A_CF, QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, ByteUtil.EMPTY_BYTE_ARRAY);
+            put.add(A_CF, ByteUtil.concat(MAX_CLICK_COUNT_DYNCOL_PREFIX, USER_ID3_BYTES), PDataType.INTEGER.toBytes(ENTRY2_CLICK_COUNT));
+            put.add(B_CF, ByteUtil.concat(LAST_LOGIN_TIME_DYNCOL_PREFIX, USER_ID2_BYTES), PDataType.TIME.toBytes(ENTRY2_USER_ID2_LOGIN_TIME));
+            put.add(B_CF, ByteUtil.concat(LAST_LOGIN_TIME_DYNCOL_PREFIX, USER_ID3_BYTES), PDataType.TIME.toBytes(ENTRY2_USER_ID3_LOGIN_TIME));
+            mutations.add(put);
+            
+            put = new Put(Bytes.toBytes("entry3"));
+            put.add(A_CF, QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, ByteUtil.EMPTY_BYTE_ARRAY);
+            put.add(A_CF, ByteUtil.concat(MAX_CLICK_COUNT_DYNCOL_PREFIX, USER_ID1_BYTES), PDataType.INTEGER.toBytes(ENTRY3_CLICK_COUNT));
+            put.add(B_CF, ByteUtil.concat(LAST_LOGIN_TIME_DYNCOL_PREFIX, USER_ID1_BYTES), PDataType.TIME.toBytes(ENTRY3_USER_ID1_LOGIN_TIME));
+            put.add(B_CF, ByteUtil.concat(LAST_LOGIN_TIME_DYNCOL_PREFIX, USER_ID2_BYTES), PDataType.TIME.toBytes(ENTRY3_USER_ID2_LOGIN_TIME));
+            put.add(B_CF, ByteUtil.concat(LAST_LOGIN_TIME_DYNCOL_PREFIX, USER_ID3_BYTES), PDataType.TIME.toBytes(ENTRY3_USER_ID3_LOGIN_TIME));
+            mutations.add(put);
+
+            hTable.batch(mutations);
+
+        } finally {
+            hTable.close();
+        }
+    }
+
+    private static Pair<String,Integer> getMaxClickCountValue(ResultSet rs) throws SQLException {
+        ResultSetMetaData rsmd = rs.getMetaData();
+        for (int i = 1; i <= rsmd.getColumnCount(); i++) {
+            String colName = rsmd.getColumnName(i);
+            if (colName.startsWith(MAX_CLICK_COUNT_PREFIX)) {
+                String userId = colName.substring(MAX_CLICK_COUNT_PREFIX.length());
+                Integer clickCount = rs.getInt(colName);
+                return new Pair<String,Integer>(userId,clickCount);
+            }
+        }
+        return null;
+    }
+    
+    private static Time getLastLoginTimeValue(ResultSet rs, String userId) throws SQLException {
+        String colName = LAST_LOGIN_TIME_PREFIX + userId;
+        try {
+            return rs.getTime(colName);
+        } catch (SQLException e) {
+            // Ignore COLUMN_NOT_FOUND error b/c it means that this user didn't login
+            if (e.getErrorCode() == SQLExceptionCode.COLUMN_NOT_FOUND.getErrorCode()) {
+                return null;
+            }
+            throw e;
+        }
+    }
+    
+    /**
+     * Should project all of column family A columns qualifiers. Should also automatically be case insensitive,
+     * since it is a wildcard.
+     * @throws Exception
+     */
+    // FIXME @Test
+    public void testGetAllDynColsInFamily() throws Exception {
+        String query = "SELECT A.* FROM WEB_STATS WHERE entry='entry1'";
+        String url = PHOENIX_JDBC_URL + ";";
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(url, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            Pair<String,Integer> maxClickCountUserIdAndValue = getMaxClickCountValue(rs);
+            // This fails for two reasons: 1) all column qualifiers in column family A
+            // are not returned in the result, and 2) the dynamic columns are not available
+            // through ResultSetMetaData.
+            assertEquals(USER_ID2_BYTES,maxClickCountUserIdAndValue.getFirst());
+            assertEquals(ENTRY1_CLICK_COUNT,maxClickCountUserIdAndValue.getSecond());
+            
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+
+    /**
+     * Should project all of column family A columns qualifiers. Should also automatically be case insensitive,
+     * since it is a wildcard.
+     * @throws Exception
+     */
+    // FIXME @Test
+    public void testGetAllDynCols() throws Exception {
+        String query = "SELECT * FROM WEB_STATS WHERE entry='entry1'";
+        String url = PHOENIX_JDBC_URL + ";";
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(url, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            Pair<String,Integer> maxClickCountUserIdAndValue = getMaxClickCountValue(rs);
+            // This fails because the dynamic columns are not available through ResultSetMetaData
+            assertEquals(USER_ID2_BYTES,maxClickCountUserIdAndValue.getFirst());
+            assertEquals(ENTRY1_CLICK_COUNT,maxClickCountUserIdAndValue.getSecond());
+            
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+
+    /**
+     * Since the dynamic columns are not in double quotes, the column name is normalized by being upper cased.
+     * In this case, since USER_ID is case sensitive, it will not find the columns
+     */
+    @Test
+    public void testGetCaseInsensitiveDynCol() throws Exception {
+        String query = "SELECT B.* FROM WEB_STATS(" + 
+                "B." + LAST_LOGIN_TIME_PREFIX + USER_ID2 + " TIME," + 
+                "B." + LAST_LOGIN_TIME_PREFIX + USER_ID3 + " TIME) WHERE entry='entry2'";
+        String url = PHOENIX_JDBC_URL + ";";
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(url, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(null, getLastLoginTimeValue(rs, USER_ID2));
+            assertEquals(null, getLastLoginTimeValue(rs, USER_ID3));
+            assertEquals(null, getLastLoginTimeValue(rs, USER_ID1));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+
+    /**
+     * Since dynamic columns are not in double quotes, the column name is not normalized, but instead
+     * is left as is. This should succeed, since the user ID case is matched
+     */
+    // FIXME @Test
+    public void testGetCaseSensitiveDynCol() throws Exception {
+        String query = "SELECT B.* FROM WEB_STATS(" + 
+                "B.\"" + LAST_LOGIN_TIME_PREFIX + USER_ID2 + "\"" + " TIME," + 
+                "B.\"" + LAST_LOGIN_TIME_PREFIX + USER_ID3 + "\"" + " TIME) WHERE entry='entry2'";
+        String url = PHOENIX_JDBC_URL + ";";
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(url, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(ENTRY2_USER_ID2_LOGIN_TIME, getLastLoginTimeValue(rs, USER_ID2));
+            assertEquals(ENTRY2_USER_ID3_LOGIN_TIME, getLastLoginTimeValue(rs, USER_ID3));
+            assertEquals(null, getLastLoginTimeValue(rs, Bytes.toString(USER_ID1_BYTES)));
+
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+
+    /**
+     * We have to make sure that static columns that are projected are in the expected order.
+     * Dynamic columns should be projected as well, but we cannot guarantee their order.
+     * @throws Exception
+     */
+    // FIXME @Test
+    public void testProjectStaticAndDynamic() throws Exception {
+        String query = "SELECT ENTRY, A.DUMMY, B.DUMMY, A.*,B.* FROM WEB_STATS WHERE entry='entry3'";
+        String url = PHOENIX_JDBC_URL + ";";
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(url, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals("entry3", rs.getString(1));
+            assertEquals(null, rs.getString(2));
+            assertEquals(null, rs.getString(3));
+            Pair<String,Integer> clickCountUserIdAndValue = getMaxClickCountValue(rs);
+            assertEquals(USER_ID1_BYTES,clickCountUserIdAndValue.getFirst());
+            assertEquals(ENTRY3_CLICK_COUNT,clickCountUserIdAndValue.getSecond());
+            
+            assertEquals(ENTRY3_USER_ID1_LOGIN_TIME, getLastLoginTimeValue(rs, Bytes.toString(USER_ID1_BYTES)));
+            assertEquals(ENTRY3_USER_ID2_LOGIN_TIME, getLastLoginTimeValue(rs, Bytes.toString(USER_ID2_BYTES)));
+            assertEquals(ENTRY3_USER_ID3_LOGIN_TIME, getLastLoginTimeValue(rs, Bytes.toString(USER_ID3_BYTES)));
+
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+
+    @Test(expected = ColumnFamilyNotFoundException.class)
+    public void testDynamicFamilyException() throws Exception {
+        String query = "SELECT C.* FROM WEB_STATS";
+        String url = PHOENIX_JDBC_URL + ";";
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(url, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(query);
+            statement.executeQuery();
+        } finally {
+            conn.close();
+        }
+    }
+
+    @Test(expected = PhoenixParserException.class)
+    public void testDynamicFamilyFunctionException() throws Exception {
+        String query = "SELECT count(C.*) FROM WEB_STATS";
+        String url = PHOENIX_JDBC_URL + ";";
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(url, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(query);
+            statement.executeQuery();
+        } finally {
+            conn.close();
+        }
+    }
+
+    @Test
+    public void testSelectEntireColumnFamily() throws Exception {
+        ResultSet rs;
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.setAutoCommit(true);
+        conn.createStatement().execute("CREATE TABLE TESTTABLE (Id VARCHAR NOT NULL PRIMARY KEY, COLFAM1.A VARCHAR, COLFAM1.B VARCHAR, COLFAM2.A VARCHAR )");
+        conn.createStatement().execute("UPSERT INTO TESTTABLE (Id, COLFAM1.A, COLFAM1.B, COLFAM2.A) values ('row-2', '100', '200', '300')");
+        rs = conn.createStatement().executeQuery("SELECT COLFAM1.A,COLFAM1.B FROM TESTTABLE");
+        assertTrue(rs.next());
+        assertEquals("100",rs.getString(1));
+        assertEquals("200",rs.getString(2));
+        assertFalse(rs.next());
+
+        rs = conn.createStatement().executeQuery("SELECT COLFAM1.* FROM TESTTABLE");
+        assertTrue(rs.next());
+        assertEquals("100",rs.getString(1));
+        assertEquals("200",rs.getString(2));
+        assertFalse(rs.next());
+
+        rs = conn.createStatement().executeQuery("SELECT COLFAM1.*,COLFAM1.A FROM TESTTABLE");
+        assertTrue(rs.next());
+        assertEquals("100",rs.getString(1));
+        assertEquals("200",rs.getString(2));
+        assertFalse(rs.next());
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/34f94a64/phoenix-core/src/it/java/org/apache/phoenix/end2end/DynamicUpsertIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/DynamicUpsertIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/DynamicUpsertIT.java
new file mode 100644
index 0000000..2ca698c
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/DynamicUpsertIT.java
@@ -0,0 +1,225 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.end2end;
+
+import static org.apache.phoenix.util.TestUtil.PHOENIX_JDBC_URL;
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.*;
+
+import java.sql.*;
+import java.util.Properties;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.phoenix.exception.SQLExceptionCode;
+import org.apache.phoenix.schema.ColumnAlreadyExistsException;
+import org.apache.phoenix.schema.ColumnFamilyNotFoundException;
+
+/**
+ * Basic tests for Phoenix dynamic upserting
+ * 
+ * 
+ * @since 1.3
+ */
+
+public class DynamicUpsertIT extends BaseClientManagedTimeIT {
+
+    private static final String TABLE = "DynamicUpserts";
+    //private static final byte[] TABLE_BYTES = Bytes.toBytes(TABLE);
+
+    @BeforeClass
+    public static void doBeforeTestSetup() throws Exception {
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        String ddl = "create table if not exists  " + TABLE + "   (entry varchar not null primary key,"
+                + "    a.dummy varchar," + "    b.dummy varchar)";
+        conn.createStatement().execute(ddl);
+        conn.close();
+    }
+
+    /**
+     * Test a simple upsert with a dynamic Column
+     */
+    @Test
+    public void testUpsert() throws Exception {
+        String upsertquery = "UPSERT INTO " + TABLE
+                + " (entry, a.DynCol VARCHAR,a.dummy) VALUES ('dynEntry','DynValue','DynColValue')";
+        String selectquery = "SELECT DynCol FROM " + TABLE + " (a.DynCol VARCHAR) where entry='dynEntry'";
+        // String selectquery = "SELECT * FROM "+TABLE;
+
+        String url = PHOENIX_JDBC_URL + ";";
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(url, props);
+        conn.setAutoCommit(true);
+        try {
+            PreparedStatement statement = conn.prepareStatement(upsertquery);
+            int rowsInserted = statement.executeUpdate();
+            assertEquals(1, rowsInserted);
+
+            // since the upsert does not alter the schema check with a dynamicolumn
+            PreparedStatement selectStatement = conn.prepareStatement(selectquery);
+            ResultSet rs = selectStatement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals("DynValue", rs.getString(1));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+
+    /**
+     * Test an upsert of multiple dynamic Columns
+     */
+    @Test
+    public void testMultiUpsert() throws Exception {
+        String upsertquery = "UPSERT INTO " + TABLE
+                + " (entry, a.DynColA VARCHAR,b.DynColB varchar) VALUES('dynEntry','DynColValuea','DynColValueb')";
+        String selectquery = "SELECT DynColA,entry,DynColB FROM " + TABLE
+                + " (a.DynColA VARCHAR,b.DynColB VARCHAR) where entry='dynEntry'";
+
+        String url = PHOENIX_JDBC_URL + ";";
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(url, props);
+        conn.setAutoCommit(true);
+        try {
+            PreparedStatement statement = conn.prepareStatement(upsertquery);
+            int rowsInserted = statement.executeUpdate();
+            assertEquals(1, rowsInserted);
+
+            // since the upsert does not alter the schema check with a dynamicolumn
+            statement = conn.prepareStatement(selectquery);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals("DynColValuea", rs.getString(1));
+            assertEquals("dynEntry", rs.getString(2));
+            assertEquals("DynColValueb", rs.getString(3));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+
+    /**
+     * Test an upsert of a full row with dynamic Columns
+     */
+    @Test
+    public void testFullUpsert() throws Exception {
+        String upsertquery = "UPSERT INTO "
+                + TABLE
+                + " (a.DynColA VARCHAR,b.DynColB varchar) VALUES('dynEntry','aValue','bValue','DynColValuea','DynColValueb')";
+        String selectquery = "SELECT entry,DynColA,a.dummy,DynColB,b.dummy FROM " + TABLE
+                + " (a.DynColA VARCHAR,b.DynColB VARCHAR) where entry='dynEntry'";
+
+        String url = PHOENIX_JDBC_URL + ";";
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(url, props);
+        conn.setAutoCommit(true);
+        try {
+            PreparedStatement statement = conn.prepareStatement(upsertquery);
+            int rowsInserted = statement.executeUpdate();
+            assertEquals(1, rowsInserted);
+
+            // since the upsert does not alter the schema check with a dynamicolumn
+            statement = conn.prepareStatement(selectquery);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals("dynEntry", rs.getString(1));
+            assertEquals("DynColValuea", rs.getString(2));
+            assertEquals("aValue", rs.getString(3));
+            assertEquals("DynColValueb", rs.getString(4));
+            assertEquals("bValue", rs.getString(5));
+            assertFalse(rs.next());
+        } finally {
+            conn.close();
+        }
+    }
+
+    /**
+     * Test an upsert of a full row with dynamic Columns and unbalanced number of values
+     */
+    @Test
+    public void testFullUnbalancedUpsert() throws Exception {
+        String upsertquery = "UPSERT INTO " + TABLE
+                + " (a.DynCol VARCHAR,b.DynCol varchar) VALUES('dynEntry','aValue','bValue','dyncola')";
+
+        String url = PHOENIX_JDBC_URL + ";";
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(url, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(upsertquery);
+            statement.execute();
+            fail();
+        } catch (SQLException e) {
+            assertEquals(SQLExceptionCode.UPSERT_COLUMN_NUMBERS_MISMATCH.getErrorCode(),e.getErrorCode());
+        } finally {
+            conn.close();
+        }
+    }
+
+    /**
+     * Test an upsert of prexisting schema defined columns and dynamic ones with different datatypes
+     */
+    @Test(expected = ColumnAlreadyExistsException.class)
+    public void testAmbiguousStaticUpsert() throws Exception {
+        String upsertquery = "UPSERT INTO " + TABLE + " (a.dummy INTEGER,b.dummy INTEGER) VALUES(1,2)";
+        String url = PHOENIX_JDBC_URL + ";";
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(url, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(upsertquery);
+            statement.execute();
+        } finally {
+            conn.close();
+        }
+    }
+
+    /**
+     * Test an upsert of two conflicting dynamic columns
+     */
+    @Test(expected = ColumnAlreadyExistsException.class)
+    public void testAmbiguousDynamicUpsert() throws Exception {
+        String upsertquery = "UPSERT INTO " + TABLE + " (a.DynCol VARCHAR,a.DynCol INTEGER) VALUES('dynCol',1)";
+        String url = PHOENIX_JDBC_URL + ";";
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(url, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(upsertquery);
+            statement.execute();
+        } finally {
+            conn.close();
+        }
+    }
+
+    /**
+     * Test an upsert of an undefined ColumnFamily dynamic columns
+     */
+    @Test(expected = ColumnFamilyNotFoundException.class)
+    public void testFakeCFDynamicUpsert() throws Exception {
+        String upsertquery = "UPSERT INTO " + TABLE + " (fakecf.DynCol VARCHAR) VALUES('dynCol')";
+        String url = PHOENIX_JDBC_URL + ";";
+        Properties props = new Properties(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(url, props);
+        try {
+            PreparedStatement statement = conn.prepareStatement(upsertquery);
+            statement.execute();
+        } finally {
+            conn.close();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/34f94a64/phoenix-core/src/it/java/org/apache/phoenix/end2end/End2EndTestDriver.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/End2EndTestDriver.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/End2EndTestDriver.java
new file mode 100644
index 0000000..ed759f5
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/End2EndTestDriver.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2014 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.end2end;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.hadoop.hbase.ClassFinder;
+import org.apache.hadoop.hbase.ClassTestFinder;
+import org.apache.hadoop.hbase.IntegrationTestingUtility;
+import org.apache.hadoop.hbase.ClassFinder.FileNameFilter;
+import org.apache.hadoop.hbase.util.AbstractHBaseTool;
+import org.apache.hadoop.util.ToolRunner;
+import org.junit.internal.TextListener;
+import org.junit.runner.Description;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+
+/**
+ * This class drives the End2End tests suite execution against an
+ * already deployed distributed cluster.
+ */
+public class End2EndTestDriver extends AbstractHBaseTool {
+    
+    private static final String SHORT_REGEX_ARG = "r";
+    private static final String SKIP_TESTS = "n";
+    
+    private End2EndTestFilter end2endTestFilter = new End2EndTestFilter();
+    private boolean skipTests = false;
+    
+
+    public static void main(String[] args) throws Exception {
+      int ret = ToolRunner.run(new End2EndTestDriver(), args);
+      System.exit(ret);
+    }
+    
+    public static class End2EndFileNameFilter implements FileNameFilter {
+
+        @Override
+        public boolean isCandidateFile(String fileName, String absFilePath) {
+          return fileName.contains("Test");
+        }
+    };
+
+
+    public class End2EndTestFilter extends ClassTestFinder.TestClassFilter {
+      private Pattern testFilterRe = Pattern.compile(".*end2end.*");
+      public End2EndTestFilter() {
+        super();
+      }
+
+      public void setPattern(String pattern) {
+        testFilterRe = Pattern.compile(pattern);
+      }
+
+      @Override
+      public boolean isCandidateClass(Class<?> c) {
+        return testFilterRe.matcher(c.getName()).find() &&
+          // Our pattern will match the below NON-IntegrationTest. Rather than
+          // do exotic regex, just filter it out here
+          super.isCandidateClass(c);
+      }
+    }
+
+    @Override
+    protected void addOptions() {
+      addOptWithArg(SHORT_REGEX_ARG, 
+        "Java regex to use selecting tests to run: e.g. .*TestBig.*" +
+        " will select all tests that include TestBig in their name.  Default: " +
+        ".*end2end.*");
+      addOptNoArg(SKIP_TESTS, 
+          "Print list of End2End test suits without running them.");
+    }
+
+    @Override
+    protected void processOptions(CommandLine cmd) {
+      String testFilterString = cmd.getOptionValue(SHORT_REGEX_ARG, null);
+      if (testFilterString != null) {
+        end2endTestFilter.setPattern(testFilterString);
+      }
+      skipTests = cmd.hasOption(SKIP_TESTS);
+    }
+
+    /**
+     * Returns test classes annotated with @Category(IntegrationTests.class),
+     * according to the filter specific on the command line (if any).
+     */
+    private Class<?>[] findEnd2EndTestClasses()
+      throws ClassNotFoundException, LinkageError, IOException {
+      End2EndFileNameFilter nameFilter = new End2EndFileNameFilter();
+      ClassFinder classFinder = new ClassFinder(null, nameFilter, end2endTestFilter);
+      Set<Class<?>> classes = classFinder.findClasses("org.apache.phoenix.end2end", true);
+      return classes.toArray(new Class<?>[classes.size()]);
+    }
+
+
+    public static class End2EndTestListenter extends TextListener {
+        private final PrintStream fWriter;
+        List<String> completes;
+        public End2EndTestListenter(PrintStream writer) {
+            super(writer);
+            completes = new ArrayList<String>();
+            fWriter = writer;
+        }
+
+        @Override
+        protected void printHeader(long runTime) {
+            fWriter.println();
+            fWriter.println("=========== Test Result ===========");
+            fWriter.println("Time: " + elapsedTimeAsString(runTime));
+        }
+        
+        @Override
+        public void testStarted(Description description) {
+            fWriter.println();
+            fWriter.println("===> " + description.getDisplayName() + " starts");
+        }
+        
+        @Override
+        public void testFinished(Description description) throws Exception {
+            super.testFinished(description);
+            completes.add(description.getDisplayName());
+        }
+        
+        void printSummary(Result result){
+            Set<String> failures = new HashSet<String>();
+            for(Failure f : result.getFailures()){
+                failures.add(f.getTestHeader());
+            }
+            fWriter.println();
+            fWriter.println("==== Test Summary ====");
+            String status;
+            for(String curTest : completes){
+                status = "passed";
+                if(failures.contains(curTest)) {
+                    status = "failed";
+                }
+                fWriter.println(curTest + "   " + status + "!");
+            }
+        }
+        
+        @Override
+        public void testRunFinished(Result result) {
+            printHeader(result.getRunTime());
+            printFailures(result);
+            printSummary(result);
+            fWriter.println();
+            printFooter(result);
+        }
+    };
+
+    
+    @Override
+    protected int doWork() throws Exception {
+      //this is called from the command line, so we should set to use the distributed cluster
+      IntegrationTestingUtility.setUseDistributedCluster(conf);
+      Class<?>[] classes = findEnd2EndTestClasses();
+      System.out.println("Found " + classes.length + " end2end tests to run:");
+      for (Class<?> aClass : classes) {
+          System.out.println("  " + aClass);
+      }
+      if(skipTests) return 0;
+      
+      JUnitCore junit = new JUnitCore();
+      junit.addListener(new End2EndTestListenter(System.out));
+      Result result = junit.run(classes);
+
+      return result.wasSuccessful() ? 0 : 1;
+    }
+}


Mime
View raw message