You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by ja...@apache.org on 2015/02/07 01:13:25 UTC

[1/3] phoenix git commit: PHOENIX-1644 Check for min HBase version before creating local index and provide means of disabling usage

Repository: phoenix
Updated Branches:
  refs/heads/master 2d7703339 -> 9db37bd90


PHOENIX-1644 Check for min HBase version before creating local index and provide means of disabling usage


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/54c4ed80
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/54c4ed80
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/54c4ed80

Branch: refs/heads/master
Commit: 54c4ed80869f6ac0011a65d1247285cfae0a6759
Parents: f3c675b
Author: James Taylor <jt...@salesforce.com>
Authored: Fri Feb 6 14:43:04 2015 -0800
Committer: James Taylor <jt...@salesforce.com>
Committed: Fri Feb 6 14:59:01 2015 -0800

----------------------------------------------------------------------
 .../phoenix/end2end/DisableLocalIndexIT.java    | 99 ++++++++++++++++++++
 .../phoenix/exception/SQLExceptionCode.java     |  3 +
 .../phoenix/jdbc/PhoenixDatabaseMetaData.java   |  5 +-
 .../query/ConnectionQueryServicesImpl.java      |  8 ++
 .../org/apache/phoenix/query/HTableFactory.java |  3 +-
 .../org/apache/phoenix/query/QueryServices.java |  1 +
 .../phoenix/query/QueryServicesOptions.java     |  1 +
 .../apache/phoenix/schema/MetaDataClient.java   | 13 ++-
 8 files changed, 127 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/54c4ed80/phoenix-core/src/it/java/org/apache/phoenix/end2end/DisableLocalIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/DisableLocalIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/DisableLocalIndexIT.java
new file mode 100644
index 0000000..5f18a1c
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/DisableLocalIndexIT.java
@@ -0,0 +1,99 @@
+/*
+ * 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.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.exception.SQLExceptionCode;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.phoenix.query.QueryServices;
+import org.apache.phoenix.util.MetaDataUtil;
+import org.apache.phoenix.util.PhoenixRuntime;
+import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.ReadOnlyProps;
+import org.apache.phoenix.util.TestUtil;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.google.common.collect.Maps;
+
+public class DisableLocalIndexIT extends BaseHBaseManagedTimeIT {
+    @BeforeClass
+    @Shadower(classBeingShadowed = BaseHBaseManagedTimeIT.class)
+    public static void doSetup() throws Exception {
+        Map<String,String> props = Maps.newHashMapWithExpectedSize(1);
+        // Must update config before starting server
+        props.put(QueryServices.ALLOW_LOCAL_INDEX_ATTRIB, Boolean.FALSE.toString());
+        setUpTestDriver(new ReadOnlyProps(props.entrySet().iterator()));
+    }
+
+    @Test
+    public void testDisabledLocalIndexes() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.setAutoCommit(true);
+        String tableName = "DISABLE_LOCAL_INDEX_TEST";
+        conn.createStatement().execute("CREATE TABLE " + tableName + " (k1 VARCHAR NOT NULL, k2 VARCHAR, CONSTRAINT PK PRIMARY KEY(K1,K2)) MULTI_TENANT=true");
+        conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('t1','x')");
+        conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('t2','y')");
+        HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin();
+        assertFalse(admin.tableExists(Bytes.toBytes(MetaDataUtil.LOCAL_INDEX_TABLE_PREFIX + tableName)));
+        admin.close();
+        try {
+            HTableInterface t = conn.unwrap(PhoenixConnection.class).getQueryServices().getTable(Bytes.toBytes(MetaDataUtil.LOCAL_INDEX_TABLE_PREFIX + tableName));
+            t.getTableDescriptor(); // Exception no longer thrown by getTable, but instead need to force an RPC
+            fail("Local index table should not have been created");
+        } catch (org.apache.hadoop.hbase.TableNotFoundException e) {
+            //expected
+        } finally {
+            admin.close();
+        }
+        
+        Properties props = PropertiesUtil.deepCopy(TestUtil.TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, "t1");
+        Connection tsconn = DriverManager.getConnection(getUrl(), props);
+        
+        tsconn.createStatement().execute("CREATE VIEW A.BAR(V1 VARCHAR) AS SELECT * FROM " + tableName);
+        tsconn.createStatement().execute("CREATE INDEX I1 ON A.BAR(V1)");
+        tsconn.unwrap(PhoenixConnection.class).getQueryServices().getTable(Bytes.toBytes(MetaDataUtil.VIEW_INDEX_TABLE_PREFIX + tableName));
+
+        try {
+            conn.createStatement().execute("CREATE LOCAL INDEX I2 ON " + tableName + "(k2)");
+            fail("Should not allow creation of local index");
+        } catch (SQLException e) {
+            assertEquals(SQLExceptionCode.UNALLOWED_LOCAL_INDEXES.getErrorCode(), e.getErrorCode());
+        }
+        try {
+            tsconn.createStatement().execute("CREATE LOCAL INDEX I2 ON A.BAR(k2, v1)");
+            fail("Should not allow creation of local index");
+        } catch (SQLException e) {
+            assertEquals(SQLExceptionCode.UNALLOWED_LOCAL_INDEXES.getErrorCode(), e.getErrorCode());
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/54c4ed80/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 8a6b8d0..19e7cdf 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
@@ -236,6 +236,9 @@ public enum SQLExceptionCode {
     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"),
     
+    NO_LOCAL_INDEXES(1054, "43A11", "Local secondary indexes are only supported for HBase version " + MetaDataUtil.decodeHBaseVersionAsString(PhoenixDatabaseMetaData.LOCAL_SI_VERSION_THRESHOLD) + " and above."),
+    UNALLOWED_LOCAL_INDEXES(1055, "43A12", "Local secondary indexes are configured to not be allowed."),
+
     /** Sequence related */
     SEQUENCE_ALREADY_EXIST(1200, "42Z00", "Sequence already exists.", new Factory() {
         @Override

http://git-wip-us.apache.org/repos/asf/phoenix/blob/54c4ed80/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java
index b26f408..7ac2bb6 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java
@@ -52,17 +52,17 @@ import org.apache.phoenix.iterate.DelegateResultIterator;
 import org.apache.phoenix.iterate.MaterializedResultIterator;
 import org.apache.phoenix.iterate.ResultIterator;
 import org.apache.phoenix.query.QueryConstants;
-import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.schema.PDatum;
 import org.apache.phoenix.schema.PName;
 import org.apache.phoenix.schema.PTable.LinkType;
 import org.apache.phoenix.schema.PTableType;
-import org.apache.phoenix.schema.types.PVarchar;
 import org.apache.phoenix.schema.RowKeyValueAccessor;
 import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.schema.tuple.ResultTuple;
 import org.apache.phoenix.schema.tuple.SingleKeyValueTuple;
 import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PVarchar;
 import org.apache.phoenix.util.ByteUtil;
 import org.apache.phoenix.util.KeyValueUtil;
 import org.apache.phoenix.util.SchemaUtil;
@@ -274,6 +274,7 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho
     public static final int ESSENTIAL_FAMILY_VERSION_THRESHOLD = VersionUtil.encodeVersion("0", "94", "7");
     // Version below which we should disallow usage of mutable secondary indexing.
     public static final int MUTABLE_SI_VERSION_THRESHOLD = VersionUtil.encodeVersion("0", "94", "10");
+    public static final int LOCAL_SI_VERSION_THRESHOLD = VersionUtil.encodeVersion("0", "98", "9");
     /** Version below which we fall back on the generic KeyValueBuilder */
     public static final int CLIENT_KEY_VALUE_BUILDER_THRESHOLD = VersionUtil.encodeVersion("0", "94", "14");
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/54c4ed80/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 97efc43..6d58f57 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
@@ -1069,6 +1069,14 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
     }
 
     private void ensureLocalIndexTableCreated(byte[] physicalTableName, Map<String, Object> tableProps, List<Pair<byte[], Map<String, Object>>> families, byte[][] splits) throws SQLException, TableAlreadyExistsException {
+        
+        // If we're not allowing local indexes or the hbase version is too low,
+        // don't create the local index table
+        if (   !this.getProps().getBoolean(QueryServices.ALLOW_LOCAL_INDEX_ATTRIB, QueryServicesOptions.DEFAULT_ALLOW_LOCAL_INDEX) 
+            || getLowestClusterHBaseVersion() < PhoenixDatabaseMetaData.LOCAL_SI_VERSION_THRESHOLD) {
+                    return;
+        }
+        
         tableProps.put(MetaDataUtil.IS_LOCAL_INDEX_TABLE_PROP_NAME, TRUE_BYTES_AS_STRING);
         HTableDescriptor desc = ensureTableCreated(physicalTableName, PTableType.TABLE, tableProps, families, splits, true);
         if (desc != null) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/54c4ed80/phoenix-core/src/main/java/org/apache/phoenix/query/HTableFactory.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/HTableFactory.java b/phoenix-core/src/main/java/org/apache/phoenix/query/HTableFactory.java
index 447267c..7a10683 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/HTableFactory.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/HTableFactory.java
@@ -21,7 +21,6 @@ import java.io.IOException;
 import java.util.concurrent.ExecutorService;
 
 import org.apache.hadoop.hbase.client.HConnection;
-import org.apache.hadoop.hbase.client.HTable;
 import org.apache.hadoop.hbase.client.HTableInterface;
 
 /**
@@ -48,7 +47,7 @@ public interface HTableFactory {
     static class HTableFactoryImpl implements HTableFactory {
         @Override
         public HTableInterface getTable(byte[] tableName, HConnection connection, ExecutorService pool) throws IOException {
-            return new HTable(tableName, connection, pool);
+            return connection.getTable(tableName, pool);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/54c4ed80/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java
index ce9016d..d21695d 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java
@@ -123,6 +123,7 @@ public interface QueryServices extends SQLCloseable {
     public static final String MIN_INDEX_PRIOIRTY_ATTRIB = "phoenix.regionserver.index.priority.min";
     public static final String MAX_INDEX_PRIOIRTY_ATTRIB = "phoenix.regionserver.index.priority.max";
     public static final String INDEX_HANDLER_COUNT_ATTRIB = "phoenix.regionserver.index.handler.count";
+    public static final String ALLOW_LOCAL_INDEX_ATTRIB = "phoenix.index.allowLocalIndex";
 
     // Config parameters for for configuring tracing
     public static final String TRACING_FREQ_ATTRIB = "phoenix.trace.frequency";

http://git-wip-us.apache.org/repos/asf/phoenix/blob/54c4ed80/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java
index 5913796..0f9139f 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java
@@ -144,6 +144,7 @@ public class QueryServicesOptions {
      */
     public static final int DEFAULT_INDEX_MIN_PRIORITY = 1000;
     public static final int DEFAULT_INDEX_HANDLER_COUNT = 30;
+    public static final boolean DEFAULT_ALLOW_LOCAL_INDEX = true;
 
     public static final int DEFAULT_TRACING_PAGE_SIZE = 100;
     /**

http://git-wip-us.apache.org/repos/asf/phoenix/blob/54c4ed80/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
index 09d2f66..effdb54 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
@@ -909,6 +909,16 @@ public class MetaDataClient {
         boolean retry = true;
         Short indexId = null;
         boolean allocateIndexId = false;
+        boolean isLocalIndex = statement.getIndexType() == IndexType.LOCAL;
+        int hbaseVersion = connection.getQueryServices().getLowestClusterHBaseVersion();
+        if (isLocalIndex) {
+            if (!connection.getQueryServices().getProps().getBoolean(QueryServices.ALLOW_LOCAL_INDEX_ATTRIB, QueryServicesOptions.DEFAULT_ALLOW_LOCAL_INDEX)) {
+                throw new SQLExceptionInfo.Builder(SQLExceptionCode.UNALLOWED_LOCAL_INDEXES).setTableName(indexTableName.getTableName()).build().buildException();
+            }
+            if (hbaseVersion < PhoenixDatabaseMetaData.LOCAL_SI_VERSION_THRESHOLD) {
+                throw new SQLExceptionInfo.Builder(SQLExceptionCode.NO_LOCAL_INDEXES).setTableName(indexTableName.getTableName()).build().buildException();
+            }
+        }
         while (true) {
             try {
                 ColumnResolver resolver = FromCompiler.getResolver(statement, connection);
@@ -920,7 +930,6 @@ public class MetaDataClient {
                         throw new SQLFeatureNotSupportedException("An index may only be created for a VIEW through a tenant-specific connection");
                     }
                 }
-                int hbaseVersion = connection.getQueryServices().getLowestClusterHBaseVersion();
                 if (!dataTable.isImmutableRows()) {
                     if (hbaseVersion < PhoenixDatabaseMetaData.MUTABLE_SI_VERSION_THRESHOLD) {
                         throw new SQLExceptionInfo.Builder(SQLExceptionCode.NO_MUTABLE_INDEXES).setTableName(indexTableName.getTableName()).build().buildException();
@@ -960,7 +969,7 @@ public class MetaDataClient {
                  * 1) for a local index, as all local indexes will reside in the same HBase table
                  * 2) for a view on an index.
                  */
-                if (statement.getIndexType() == IndexType.LOCAL || (dataTable.getType() == PTableType.VIEW && dataTable.getViewType() != ViewType.MAPPED)) {
+                if (isLocalIndex || (dataTable.getType() == PTableType.VIEW && dataTable.getViewType() != ViewType.MAPPED)) {
                     allocateIndexId = true;
                     // Next add index ID column
                     PDataType dataType = MetaDataUtil.getViewIndexIdDataType();


[2/3] phoenix git commit: PHOENIX-1620 Add API for getting tenant ID from an HBase row of a Phoenix table

Posted by ja...@apache.org.
PHOENIX-1620 Add API for getting tenant ID from an HBase row of a Phoenix table


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/f3c675bf
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/f3c675bf
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/f3c675bf

Branch: refs/heads/master
Commit: f3c675bf735d7d4e4534433f3406af15360ed5d9
Parents: 2d77033
Author: James Taylor <jt...@salesforce.com>
Authored: Fri Feb 6 11:14:26 2015 -0800
Committer: James Taylor <jt...@salesforce.com>
Committed: Fri Feb 6 14:59:01 2015 -0800

----------------------------------------------------------------------
 .../phoenix/end2end/PhoenixRuntimeIT.java       | 138 +++++++++++++++++++
 .../org/apache/phoenix/util/PhoenixRuntime.java |  39 +++++-
 .../org/apache/phoenix/util/SchemaUtil.java     |   4 +
 .../java/org/apache/phoenix/query/BaseTest.java |  20 ++-
 .../apache/phoenix/util/PhoenixRuntimeTest.java |  58 ++++++++
 5 files changed, 255 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/f3c675bf/phoenix-core/src/it/java/org/apache/phoenix/end2end/PhoenixRuntimeIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/PhoenixRuntimeIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/PhoenixRuntimeIT.java
new file mode 100644
index 0000000..234ea1c
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/PhoenixRuntimeIT.java
@@ -0,0 +1,138 @@
+/*
+ * 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.jdbc.PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.ResultScanner;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+import org.apache.hadoop.hbase.filter.Filter;
+import org.apache.hadoop.hbase.filter.FilterList;
+import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter;
+import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData;
+import org.apache.phoenix.schema.PTableType;
+import org.apache.phoenix.schema.tuple.ResultTuple;
+import org.apache.phoenix.schema.types.PVarchar;
+import org.apache.phoenix.util.MetaDataUtil;
+import org.apache.phoenix.util.PhoenixRuntime;
+import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.TestUtil;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+public class PhoenixRuntimeIT extends BaseHBaseManagedTimeIT {
+    private static void assertTenantIds(Expression e, HTableInterface htable, Filter filter, String[] tenantIds) throws IOException {
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        Scan scan = new Scan();
+        scan.setFilter(filter);
+        ResultScanner scanner = htable.getScanner(scan);
+        Result result = null;
+        ResultTuple tuple = new ResultTuple();
+        List<String> actualTenantIds = Lists.newArrayListWithExpectedSize(tenantIds.length);
+        List<String> expectedTenantIds = Arrays.asList(tenantIds);
+        while ((result = scanner.next()) != null) {
+            tuple.setResult(result);
+            e.evaluate(tuple, ptr);
+            String tenantId = (String)PVarchar.INSTANCE.toObject(ptr);
+            actualTenantIds.add(tenantId == null ? "" : tenantId);
+        }
+        // Need to sort because of salting
+        Collections.sort(actualTenantIds);
+        assertEquals(expectedTenantIds, actualTenantIds);
+    }
+    
+    @Test
+    public void testGetTenantIdExpressionForSaltedTable() throws Exception {
+        testGetTenantIdExpression(true);
+    }
+    
+    @Test
+    public void testGetTenantIdExpressionForUnsaltedTable() throws Exception {
+        testGetTenantIdExpression(false);
+    }
+    
+    private static Filter getUserTableAndViewsFilter() {
+        SingleColumnValueFilter tableFilter = new SingleColumnValueFilter(TABLE_FAMILY_BYTES, PhoenixDatabaseMetaData.TABLE_TYPE_BYTES, CompareOp.EQUAL, Bytes.toBytes(PTableType.TABLE.getSerializedValue()));
+        tableFilter.setFilterIfMissing(true);
+        SingleColumnValueFilter viewFilter = new SingleColumnValueFilter(TABLE_FAMILY_BYTES, PhoenixDatabaseMetaData.TABLE_TYPE_BYTES, CompareOp.EQUAL, Bytes.toBytes(PTableType.VIEW.getSerializedValue()));
+        viewFilter.setFilterIfMissing(true);
+        FilterList filter = new FilterList(FilterList.Operator.MUST_PASS_ONE, Arrays.asList(new Filter[] {tableFilter, viewFilter}));
+        return filter;
+    }
+    
+    private void testGetTenantIdExpression(boolean isSalted) throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.setAutoCommit(true);
+        String tableName = "FOO_" + (isSalted ? "SALTED" : "UNSALTED");
+        conn.createStatement().execute("CREATE TABLE " + tableName + " (k1 VARCHAR NOT NULL, k2 VARCHAR, CONSTRAINT PK PRIMARY KEY(K1,K2)) MULTI_TENANT=true" + (isSalted ? ",SALT_BUCKETS=3" : ""));
+        conn.createStatement().execute("CREATE SEQUENCE s1");
+        conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('t1','x')");
+        conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('t2','y')");
+        
+        Properties props = PropertiesUtil.deepCopy(TestUtil.TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, "t1");
+        Connection tsconn = DriverManager.getConnection(getUrl(), props);
+        tsconn.createStatement().execute("CREATE SEQUENCE s1");
+        Expression e1 = PhoenixRuntime.getTenantIdExpression(tsconn, PhoenixDatabaseMetaData.SEQUENCE_FULLNAME);
+        HTableInterface htable1 = tsconn.unwrap(PhoenixConnection.class).getQueryServices().getTable(PhoenixDatabaseMetaData.SEQUENCE_FULLNAME_BYTES);
+        assertTenantIds(e1, htable1, new FirstKeyOnlyFilter(), new String[] {"", "t1"} );
+        
+        tsconn.createStatement().execute("CREATE VIEW A.BAR(V1 VARCHAR) AS SELECT * FROM " + tableName);
+        Expression e2 = PhoenixRuntime.getTenantIdExpression(tsconn, PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME);
+        HTableInterface htable2 = conn.unwrap(PhoenixConnection.class).getQueryServices().getTable(PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME_BYTES);
+        assertTenantIds(e2, htable2, getUserTableAndViewsFilter(), new String[] {"", "t1"} );
+        
+        Expression e3 = PhoenixRuntime.getTenantIdExpression(conn, tableName);
+        HTableInterface htable3 = conn.unwrap(PhoenixConnection.class).getQueryServices().getTable(Bytes.toBytes(tableName));
+        assertTenantIds(e3, htable3, new FirstKeyOnlyFilter(), new String[] {"t1", "t2"} );
+        
+        conn.createStatement().execute("CREATE TABLE BAS (k1 VARCHAR PRIMARY KEY)");
+        Expression e4 = PhoenixRuntime.getTenantIdExpression(conn, "BAS");
+        assertNull(e4);
+
+        tsconn.createStatement().execute("CREATE INDEX I1 ON A.BAR(V1)");
+        Expression e5 = PhoenixRuntime.getTenantIdExpression(tsconn, "A.I1");
+        HTableInterface htable5 = tsconn.unwrap(PhoenixConnection.class).getQueryServices().getTable(Bytes.toBytes(MetaDataUtil.VIEW_INDEX_TABLE_PREFIX + tableName));
+        assertTenantIds(e5, htable5, new FirstKeyOnlyFilter(), new String[] {"t1"} );
+
+        conn.createStatement().execute("CREATE INDEX I2 ON " + tableName + "(k2)");
+        Expression e6 = PhoenixRuntime.getTenantIdExpression(conn, "I2");
+        HTableInterface htable6 = conn.unwrap(PhoenixConnection.class).getQueryServices().getTable(Bytes.toBytes("I2"));
+        assertTenantIds(e6, htable6, new FirstKeyOnlyFilter(), new String[] {"t1", "t2"} );
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f3c675bf/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java b/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
index b2d7851..02a2776 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
@@ -28,6 +28,7 @@ import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
@@ -56,6 +57,7 @@ import org.apache.phoenix.coprocessor.MetaDataProtocol.MutationCode;
 import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.expression.LiteralExpression;
 import org.apache.phoenix.expression.OrderByExpression;
+import org.apache.phoenix.expression.RowKeyColumnExpression;
 import org.apache.phoenix.jdbc.PhoenixConnection;
 import org.apache.phoenix.jdbc.PhoenixPreparedStatement;
 import org.apache.phoenix.query.QueryConstants;
@@ -66,13 +68,15 @@ import org.apache.phoenix.schema.KeyValueSchema.KeyValueSchemaBuilder;
 import org.apache.phoenix.schema.MetaDataClient;
 import org.apache.phoenix.schema.PColumn;
 import org.apache.phoenix.schema.PColumnFamily;
-import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.schema.PTable;
+import org.apache.phoenix.schema.PTable.IndexType;
 import org.apache.phoenix.schema.PTableKey;
 import org.apache.phoenix.schema.PTableType;
 import org.apache.phoenix.schema.RowKeySchema;
+import org.apache.phoenix.schema.RowKeyValueAccessor;
 import org.apache.phoenix.schema.TableNotFoundException;
 import org.apache.phoenix.schema.ValueBitSet;
+import org.apache.phoenix.schema.types.PDataType;
 
 import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableList;
@@ -927,5 +931,38 @@ public class PhoenixRuntime {
         }
         return pColumn;
     }
+    
+    /**
+     * Get expression that may be used to evaluate the tenant ID of a given row in a
+     * multi-tenant table. Both the SYSTEM.CATALOG table and the SYSTEM.SEQUENCE
+     * table are considered multi-tenant.
+     * @param conn open Phoenix connection
+     * @param fullTableName full table name
+     * @return An expression that may be evaluated for a row in the provided table or
+     * null if the table is not a multi-tenant table. 
+     * @throws SQLException if the table name is not found, a TableNotFoundException
+     * is thrown. If a multi-tenant local index is supplied a SQLFeatureNotSupportedException
+     * is thrown.
+     */
+    public static Expression getTenantIdExpression(Connection conn, String fullTableName) throws SQLException {
+        PTable table = getTable(conn, fullTableName);
+        // TODO: consider setting MULTI_TENANT = true for SYSTEM.CATALOG and SYSTEM.SEQUENCE
+        if (!SchemaUtil.isMetaTable(table) && !SchemaUtil.isSequenceTable(table) && !table.isMultiTenant()) {
+            return null;
+        }
+        if (table.getIndexType() == IndexType.LOCAL) {
+            /*
+             * With some hackery, we could deduce the tenant ID from a multi-tenant local index,
+             * however it's not clear that we'd want to maintain the same prefixing of the region
+             * start key, as the region boundaries may end up being different on a cluster being
+             * replicated/backed-up to (which is the use case driving the method).
+             */
+            throw new SQLFeatureNotSupportedException();
+        }
+        
+        int pkPosition = table.getBucketNum() == null ? 0 : 1;
+        List<PColumn> pkColumns = table.getPKColumns();
+        return new RowKeyColumnExpression(pkColumns.get(pkPosition), new RowKeyValueAccessor(pkColumns, pkPosition));
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f3c675bf/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
index 9ab0692..afd61ad 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
@@ -376,6 +376,10 @@ public class SchemaUtil {
         return Bytes.compareTo(tableName, PhoenixDatabaseMetaData.SEQUENCE_FULLNAME_BYTES) == 0;
     }
 
+    public static boolean isSequenceTable(PTable table) {
+        return PhoenixDatabaseMetaData.SEQUENCE_FULLNAME.equals(table.getName().getString());
+    }
+
     public static boolean isMetaTable(PTable table) {
         return PhoenixDatabaseMetaData.SYSTEM_CATALOG_SCHEMA.equals(table.getSchemaName().getString()) && PhoenixDatabaseMetaData.SYSTEM_CATALOG_TABLE.equals(table.getTableName().getString());
     }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f3c675bf/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java b/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
index f81c3a9..9947440 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
@@ -821,14 +821,28 @@ public abstract class BaseTest {
         }
     }
     
-    private static void deletePriorSequences(long ts, Connection conn) throws Exception {
+    private static void deletePriorSequences(long ts, Connection globalConn) throws Exception {
         // TODO: drop tenant-specific sequences too
-        ResultSet rs = conn.createStatement().executeQuery("SELECT " 
+        ResultSet rs = globalConn.createStatement().executeQuery("SELECT " 
+                + PhoenixDatabaseMetaData.TENANT_ID + ","
                 + PhoenixDatabaseMetaData.SEQUENCE_SCHEMA + "," 
                 + PhoenixDatabaseMetaData.SEQUENCE_NAME 
                 + " FROM " + PhoenixDatabaseMetaData.SEQUENCE_FULLNAME_ESCAPED);
+        String lastTenantId = null;
+        Connection conn = globalConn;
         while (rs.next()) {
-            conn.createStatement().execute("DROP SEQUENCE " + SchemaUtil.getEscapedTableName(rs.getString(1), rs.getString(2)));
+            String tenantId = rs.getString(1);
+            if (tenantId != null && !tenantId.equals(lastTenantId))  {
+                if (lastTenantId != null) {
+                    conn.close();
+                }
+                // Open tenant-specific connection when we find a new one
+                Properties props = new Properties(globalConn.getClientInfo());
+                props.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, tenantId);
+                conn = DriverManager.getConnection(url, props);
+                lastTenantId = tenantId;
+            }
+            conn.createStatement().execute("DROP SEQUENCE " + SchemaUtil.getEscapedTableName(rs.getString(2), rs.getString(3)));
         }
     }
     

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f3c675bf/phoenix-core/src/test/java/org/apache/phoenix/util/PhoenixRuntimeTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/util/PhoenixRuntimeTest.java b/phoenix-core/src/test/java/org/apache/phoenix/util/PhoenixRuntimeTest.java
index a642e80..c1f3244 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/util/PhoenixRuntimeTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/util/PhoenixRuntimeTest.java
@@ -20,6 +20,7 @@ package org.apache.phoenix.util;
 
 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;
@@ -27,6 +28,7 @@ import static org.junit.Assert.fail;
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
+import java.sql.SQLFeatureNotSupportedException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Properties;
@@ -34,7 +36,10 @@ import java.util.Properties;
 import org.apache.commons.lang.exception.ExceptionUtils;
 import org.apache.hadoop.hbase.util.Pair;
 import org.apache.phoenix.compile.QueryPlan;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData;
 import org.apache.phoenix.query.BaseConnectionlessQueryTest;
+import org.apache.phoenix.schema.TableNotFoundException;
 import org.apache.phoenix.schema.types.PDataType;
 import org.junit.Test;
 
@@ -155,4 +160,57 @@ public class PhoenixRuntimeTest extends BaseConnectionlessQueryTest {
             fail("Failed sql: " + sb.toString() + ExceptionUtils.getStackTrace(e));
         }
     }
+    
+    @Test
+    public void testGetTenantIdExpression() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        Expression e1 = PhoenixRuntime.getTenantIdExpression(conn, PhoenixDatabaseMetaData.SYSTEM_STATS_NAME);
+        assertNull(e1);
+        Expression e2 = PhoenixRuntime.getTenantIdExpression(conn, PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME);
+        assertNotNull(e2);
+
+        Expression e3 = PhoenixRuntime.getTenantIdExpression(conn, PhoenixDatabaseMetaData.SEQUENCE_FULLNAME);
+        assertNotNull(e3);
+        
+        conn.createStatement().execute("CREATE TABLE FOO (k VARCHAR PRIMARY KEY)");
+        Expression e4 = PhoenixRuntime.getTenantIdExpression(conn, "FOO");
+        assertNull(e4);
+        
+        conn.createStatement().execute("CREATE TABLE A.BAR (k1 VARCHAR NOT NULL, k2 VARCHAR, CONSTRAINT PK PRIMARY KEY(K1,K2)) MULTI_TENANT=true");
+        Expression e5 = PhoenixRuntime.getTenantIdExpression(conn, "A.BAR");
+        assertNotNull(e5);
+
+        conn.createStatement().execute("CREATE INDEX I1 ON A.BAR (K2)");
+        Expression e5A = PhoenixRuntime.getTenantIdExpression(conn, "A.I1");
+        assertNotNull(e5A);
+        
+        conn.createStatement().execute("CREATE TABLE BAS (k1 VARCHAR NOT NULL, k2 VARCHAR, CONSTRAINT PK PRIMARY KEY(K1,K2)) MULTI_TENANT=true, SALT_BUCKETS=3");
+        Expression e6 = PhoenixRuntime.getTenantIdExpression(conn, "BAS");
+        assertNotNull(e6);
+        
+        conn.createStatement().execute("CREATE INDEX I2 ON BAS (K2)");
+        Expression e6A = PhoenixRuntime.getTenantIdExpression(conn, "I2");
+        assertNotNull(e6A);
+        
+        try {
+            PhoenixRuntime.getTenantIdExpression(conn, "NOT.ATABLE");
+            fail();
+        } catch (TableNotFoundException e) {
+            // Expected
+        }
+        
+        Properties props = PropertiesUtil.deepCopy(TestUtil.TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, "t1");
+        Connection tsconn = DriverManager.getConnection(getUrl(), props);
+        tsconn.createStatement().execute("CREATE VIEW V(V1 VARCHAR) AS SELECT * FROM BAS");
+        Expression e7 = PhoenixRuntime.getTenantIdExpression(tsconn, "V");
+        assertNotNull(e7);
+        tsconn.createStatement().execute("CREATE LOCAL INDEX I3 ON V (V1)");
+        try {
+            PhoenixRuntime.getTenantIdExpression(tsconn, "I3");
+            fail();
+        } catch (SQLFeatureNotSupportedException e) {
+            // Expected
+        }
+    }
 }


[3/3] phoenix git commit: PHOENIX-1643 Ensure index usage is backward compatible for 4.2 client against 4.3 server (Thomas D'Silva)

Posted by ja...@apache.org.
PHOENIX-1643 Ensure index usage is backward compatible for 4.2 client against 4.3 server (Thomas D'Silva)


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/9db37bd9
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/9db37bd9
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/9db37bd9

Branch: refs/heads/master
Commit: 9db37bd90005695c703f9d092651891a5e39a80a
Parents: 54c4ed8
Author: James Taylor <jt...@salesforce.com>
Authored: Fri Feb 6 16:08:43 2015 -0800
Committer: James Taylor <jt...@salesforce.com>
Committed: Fri Feb 6 16:08:43 2015 -0800

----------------------------------------------------------------------
 .../apache/phoenix/index/IndexMaintainer.java   |  9 ++------
 .../parse/IndexExpressionParseNodeRewriter.java |  6 ++---
 .../org/apache/phoenix/schema/PColumnImpl.java  |  2 +-
 .../java/org/apache/phoenix/util/IndexUtil.java | 16 +++++++------
 .../org/apache/phoenix/util/SchemaUtil.java     | 24 ++++++++++++--------
 5 files changed, 29 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/9db37bd9/phoenix-core/src/main/java/org/apache/phoenix/index/IndexMaintainer.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/index/IndexMaintainer.java b/phoenix-core/src/main/java/org/apache/phoenix/index/IndexMaintainer.java
index 31f6c76..7199dad 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/index/IndexMaintainer.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/index/IndexMaintainer.java
@@ -282,9 +282,6 @@ public class IndexMaintainer implements Writable, Iterable<ColumnReference> {
         int indexedExpressionCount = 0;
         for (int i = indexPosOffset; i<index.getPKColumns().size();i++) {
         	PColumn indexColumn = index.getPKColumns().get(i);
-        	if (!IndexUtil.isIndexColumn(indexColumn)) {
-                continue;
-            }
         	String indexColumnName = indexColumn.getName().getString();
             String dataFamilyName = IndexUtil.getDataColumnFamilyName(indexColumnName);
             String dataColumnName = IndexUtil.getDataColumnName(indexColumnName);
@@ -341,14 +338,12 @@ public class IndexMaintainer implements Writable, Iterable<ColumnReference> {
         IndexExpressionCompiler expressionIndexCompiler = new IndexExpressionCompiler(context);
         for (int i = indexPosOffset; i < index.getPKColumns().size(); i++) {
             PColumn indexColumn = index.getPKColumns().get(i);
-            if (!IndexUtil.isIndexColumn(indexColumn)) {
-                continue;
-            }
             int indexPos = i - indexPosOffset;
             Expression expression = null;
             try {
                 expressionIndexCompiler.reset();
-                ParseNode parseNode  = SQLParser.parseCondition(indexColumn.getExpressionStr());
+                String expressionStr = IndexUtil.getIndexColumnExpressionStr(indexColumn);
+                ParseNode parseNode  = SQLParser.parseCondition(expressionStr);
                 expression = parseNode.accept(expressionIndexCompiler);
             } catch (SQLException e) {
                 throw new RuntimeException(e); // Impossible

http://git-wip-us.apache.org/repos/asf/phoenix/blob/9db37bd9/phoenix-core/src/main/java/org/apache/phoenix/parse/IndexExpressionParseNodeRewriter.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/IndexExpressionParseNodeRewriter.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/IndexExpressionParseNodeRewriter.java
index efa3835..43cb9f3 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/IndexExpressionParseNodeRewriter.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/IndexExpressionParseNodeRewriter.java
@@ -71,10 +71,8 @@ public class IndexExpressionParseNodeRewriter extends ParseNodeRewriter {
         List<PColumn> pkColumns = index.getPKColumns();
 		for (int i=indexPosOffset; i<pkColumns.size(); ++i) {
         	PColumn column = pkColumns.get(i);
-            if (column.getExpressionStr()==null) {
-                continue;
-            }
-            ParseNode expressionParseNode = SQLParser.parseCondition(column.getExpressionStr());
+        	String expressionStr = IndexUtil.getIndexColumnExpressionStr(column);
+            ParseNode expressionParseNode  = SQLParser.parseCondition(expressionStr);
             columnParseNodeVisitor.reset();
             expressionParseNode.accept(columnParseNodeVisitor);
             String colName = column.getName().getString();

http://git-wip-us.apache.org/repos/asf/phoenix/blob/9db37bd9/phoenix-core/src/main/java/org/apache/phoenix/schema/PColumnImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/PColumnImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/PColumnImpl.java
index 11cc53d..ac044df 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/PColumnImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/PColumnImpl.java
@@ -38,7 +38,7 @@ public class PColumnImpl implements PColumn {
     private byte[] viewConstant;
     private boolean isViewReferenced;
     private String expressionStr;
-
+    
     public PColumnImpl() {
     }
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/9db37bd9/phoenix-core/src/main/java/org/apache/phoenix/util/IndexUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/IndexUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/IndexUtil.java
index 8dd4f4d..c058eb8 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/IndexUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/IndexUtil.java
@@ -137,12 +137,9 @@ public class IndexUtil {
         return name.substring(0,name.indexOf(INDEX_COLUMN_NAME_SEP));
     }
 
-    public static String getDataColumnFullName(String name) {
+    public static String getCaseSensitiveDataColumnFullName(String name) {
         int index = name.indexOf(INDEX_COLUMN_NAME_SEP) ;
-        if (index == 0) {
-            return name.substring(index+1);
-        }
-        return SchemaUtil.getColumnDisplayName(name.substring(0, index), name.substring(index+1));
+        return SchemaUtil.getCaseSensitiveColumnDisplayName(name.substring(0, index), name.substring(index+1));
     }
 
     public static String getIndexColumnName(String dataColumnFamilyName, String dataColumnName) {
@@ -272,8 +269,8 @@ public class IndexUtil {
         return column.getName().getString().startsWith(INDEX_COLUMN_NAME_SEP);
     }
     
-    public static boolean isIndexColumn(PColumn column) {
-        return column.getName().getString().contains(INDEX_COLUMN_NAME_SEP);
+    public static boolean isIndexColumn(String name) {
+        return name.contains(INDEX_COLUMN_NAME_SEP);
     }
     
     public static boolean getViewConstantValue(PColumn column, ImmutableBytesWritable ptr) {
@@ -627,4 +624,9 @@ public class IndexUtil {
             result.set(i, newCell);
         }
     }
+    
+    public static String getIndexColumnExpressionStr(PColumn col) {
+        return col.getExpressionStr() == null ? IndexUtil.getCaseSensitiveDataColumnFullName(col.getName().getString())
+                : col.getExpressionStr();
+    }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/9db37bd9/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
index afd61ad..c9574e3 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java
@@ -206,14 +206,16 @@ public class SchemaUtil {
     }
 
     public static String getTableName(String schemaName, String tableName) {
-        return getName(schemaName,tableName);
+        return getName(schemaName,tableName, false);
     }
 
-    private static String getName(String optionalQualifier, String name) {
+    private static String getName(String optionalQualifier, String name, boolean caseSensitive) {
+        String cq = caseSensitive ? "\"" + name + "\"" : name;
         if (optionalQualifier == null || optionalQualifier.isEmpty()) {
-            return name;
+            return cq;
         }
-        return optionalQualifier + QueryConstants.NAME_SEPARATOR + name;
+        String cf = caseSensitive ? "\"" + optionalQualifier + "\"" : optionalQualifier;
+        return cf + QueryConstants.NAME_SEPARATOR + cq;
     }
 
     public static String getTableName(byte[] schemaName, byte[] tableName) {
@@ -225,21 +227,25 @@ public class SchemaUtil {
     }
 
     public static String getColumnDisplayName(String cf, String cq) {
-        return getName(cf == null || cf.isEmpty() ? null : cf, cq);
+        return getName(cf == null || cf.isEmpty() ? null : cf, cq, false);
+    }
+    
+    public static String getCaseSensitiveColumnDisplayName(String cf, String cq) {
+        return getName(cf == null || cf.isEmpty() ? null : cf, cq, true);
     }
 
     public static String getMetaDataEntityName(String schemaName, String tableName, String familyName, String columnName) {
         if ((schemaName == null || schemaName.isEmpty()) && (tableName == null || tableName.isEmpty())) {
-            return getName(familyName, columnName);
+            return getName(familyName, columnName, false);
         }
         if ((familyName == null || familyName.isEmpty()) && (columnName == null || columnName.isEmpty())) {
-            return getName(schemaName, tableName);
+            return getName(schemaName, tableName, false);
         }
-        return getName(getName(schemaName, tableName), getName(familyName, columnName));
+        return getName(getName(schemaName, tableName, false), getName(familyName, columnName, false), false);
     }
 
     public static String getColumnName(String familyName, String columnName) {
-        return getName(familyName, columnName);
+        return getName(familyName, columnName, false);
     }
 
     public static byte[] getTableNameAsBytes(String schemaName, String tableName) {