phoenix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sama...@apache.org
Subject phoenix git commit: PHOENIX-2276 Creating index on a global view on a multi-tenant table fails with NPE
Date Fri, 17 Jun 2016 03:34:05 GMT
Repository: phoenix
Updated Branches:
  refs/heads/4.x-HBase-0.98 601dae52c -> f92dc9fb2


PHOENIX-2276 Creating index on a global view on a multi-tenant table fails with NPE


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

Branch: refs/heads/4.x-HBase-0.98
Commit: f92dc9fb21b8d85eaaac3db0642cf40dd92ca7dc
Parents: 601dae5
Author: Samarth <samarth.jain@salesforce.com>
Authored: Thu Jun 16 20:33:53 2016 -0700
Committer: Samarth <samarth.jain@salesforce.com>
Committed: Thu Jun 16 20:33:53 2016 -0700

----------------------------------------------------------------------
 .../end2end/BaseTenantSpecificViewIndexIT.java  |   4 +-
 .../end2end/TenantSpecificViewIndexIT.java      |   6 +-
 .../phoenix/end2end/index/ViewIndexIT.java      |  34 ++++
 .../apache/phoenix/cache/ServerCacheClient.java |  40 ++--
 .../apache/phoenix/compile/DeleteCompiler.java  |   8 +-
 .../apache/phoenix/compile/UpsertCompiler.java  |  40 ++--
 .../apache/phoenix/compile/WhereOptimizer.java  |  29 +--
 .../apache/phoenix/execute/BaseQueryPlan.java   |   4 +-
 .../apache/phoenix/index/IndexMaintainer.java   |  18 +-
 .../query/ConnectionQueryServicesImpl.java      | 194 ++++++++++++++++++-
 .../apache/phoenix/schema/MetaDataClient.java   |  21 +-
 .../org/apache/phoenix/util/MetaDataUtil.java   |   2 +-
 .../org/apache/phoenix/util/PhoenixRuntime.java |   3 +-
 .../java/org/apache/phoenix/util/ScanUtil.java  |   8 +-
 .../TenantSpecificViewIndexCompileTest.java     |   6 +-
 .../util/TenantIdByteConversionTest.java        |   2 +-
 16 files changed, 325 insertions(+), 94 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/f92dc9fb/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseTenantSpecificViewIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseTenantSpecificViewIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseTenantSpecificViewIndexIT.java
index 9f25531..0703e82 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseTenantSpecificViewIndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseTenantSpecificViewIndexIT.java
@@ -140,9 +140,9 @@ public class BaseTenantSpecificViewIndexIT extends BaseHBaseManagedTimeIT {
                             + "CLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
         } else {
             String expected = saltBuckets == null ? 
-                    "CLIENT PARALLEL 1-WAY RANGE SCAN OVER _IDX_T ['" + tenantId + "',-32768,'" + valuePrefix + "v2-1']\n"
+                    "CLIENT PARALLEL 1-WAY RANGE SCAN OVER _IDX_T [-32768,'" + tenantId + "','" + valuePrefix + "v2-1']\n"
                             + "    SERVER FILTER BY FIRST KEY ONLY" :
-                    "CLIENT PARALLEL 3-WAY RANGE SCAN OVER _IDX_T [0,'" + tenantId + "',-32768,'" + valuePrefix + "v2-1']\n"
+                    "CLIENT PARALLEL 3-WAY RANGE SCAN OVER _IDX_T [0,-32768,'" + tenantId + "','" + valuePrefix + "v2-1']\n"
                   + "    SERVER FILTER BY FIRST KEY ONLY\n"
                   + "CLIENT MERGE SORT";
             assertEquals(expected, QueryUtil.getExplainPlan(rs));

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f92dc9fb/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificViewIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificViewIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificViewIndexIT.java
index 61092e3..a48f396 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificViewIndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificViewIndexIT.java
@@ -199,14 +199,14 @@ public class TenantSpecificViewIndexIT extends BaseTenantSpecificViewIndexIT {
         rs = conn.createStatement().executeQuery("explain select pk2,col1 from " + viewName + " where col1='f'");
         if (localIndex) {
             assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER "
-                    + Bytes.toString(SchemaUtil.getPhysicalHBaseTableName(tableName, isNamespaceMapped, PTableType.TABLE).getBytes()) + " ['"
-                    + tenantId + "',1,'f']\n" + "    SERVER FILTER BY FIRST KEY ONLY\n" + "CLIENT MERGE SORT",
+                    + Bytes.toString(SchemaUtil.getPhysicalHBaseTableName(tableName, isNamespaceMapped, PTableType.TABLE).getBytes()) + " [1,'"
+                    + tenantId + "','f']\n" + "    SERVER FILTER BY FIRST KEY ONLY\n" + "CLIENT MERGE SORT",
                     QueryUtil.getExplainPlan(rs));
         } else {
             assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER "
                     + Bytes.toString(MetaDataUtil.getViewIndexPhysicalName(SchemaUtil
                             .getPhysicalHBaseTableName(tableName, isNamespaceMapped, PTableType.TABLE).getBytes()))
-                    + " ['" + tenantId + "',-32768,'f']\n" + "    SERVER FILTER BY FIRST KEY ONLY",
+                    + " [-32768,'" + tenantId + "','f']\n" + "    SERVER FILTER BY FIRST KEY ONLY",
                     QueryUtil.getExplainPlan(rs));
         }
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f92dc9fb/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ViewIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ViewIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ViewIndexIT.java
index 75938e4..85f3941 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ViewIndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ViewIndexIT.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertFalse;
 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;
@@ -33,9 +34,11 @@ import java.util.Properties;
 
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.phoenix.compile.QueryPlan;
 import org.apache.phoenix.end2end.BaseHBaseManagedTimeIT;
 import org.apache.phoenix.end2end.Shadower;
 import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData;
+import org.apache.phoenix.jdbc.PhoenixStatement;
 import org.apache.phoenix.query.QueryServices;
 import org.apache.phoenix.schema.PNameFactory;
 import org.apache.phoenix.util.MetaDataUtil;
@@ -191,4 +194,35 @@ public class ViewIndexIT extends BaseHBaseManagedTimeIT {
         assertTrue(rs.next());
         assertFalse(rs.next());
     }
+    
+    @Test
+    public void testCreatingIndexOnGlobalView() throws Exception {
+        String baseTable = "testCreatingIndexOnGlobalView".toUpperCase();
+        String globalView = "globalView".toUpperCase();
+        String globalViewIdx = "globalView_idx".toUpperCase();
+        try (Connection conn = DriverManager.getConnection(getUrl())) {
+            conn.createStatement().execute("CREATE TABLE " + baseTable + " (TENANT_ID CHAR(15) NOT NULL, PK2 DATE NOT NULL, PK3 INTEGER NOT NULL, KV1 VARCHAR, KV2 VARCHAR, KV3 CHAR(15) CONSTRAINT PK PRIMARY KEY(TENANT_ID, PK2 ROW_TIMESTAMP, PK3)) MULTI_TENANT=true");
+            conn.createStatement().execute("CREATE VIEW " + globalView + " AS SELECT * FROM " + baseTable);
+            conn.createStatement().execute("CREATE INDEX " + globalViewIdx + " ON " + globalView + " (PK3 DESC, KV3) INCLUDE (KV1)");
+            PreparedStatement stmt = conn.prepareStatement("UPSERT INTO  " + globalView + " (TENANT_ID, PK2, PK3, KV1, KV3) VALUES (?, ?, ?, ?, ?)");
+            stmt.setString(1, "tenantId");
+            stmt.setDate(2, new Date(100));
+            stmt.setInt(3, 1);
+            stmt.setString(4, "KV1");
+            stmt.setString(5, "KV3");
+            stmt.executeUpdate();
+            conn.commit();
+            
+            // Verify that query against the global view index works
+            stmt = conn.prepareStatement("SELECT KV1 FROM  " + globalView + " WHERE PK3 = ? AND KV3 = ?");
+            stmt.setInt(1, 1);
+            stmt.setString(2, "KV3");
+            ResultSet rs = stmt.executeQuery();
+            QueryPlan plan = stmt.unwrap(PhoenixStatement.class).getQueryPlan();
+            assertTrue(plan.getTableRef().getTable().getName().getString().equals(globalViewIdx));
+            assertTrue(rs.next());
+            assertEquals("KV1", rs.getString(1));
+            assertFalse(rs.next());
+        }
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f92dc9fb/phoenix-core/src/main/java/org/apache/phoenix/cache/ServerCacheClient.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/cache/ServerCacheClient.java b/phoenix-core/src/main/java/org/apache/phoenix/cache/ServerCacheClient.java
index aea15c2..d88b094 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/cache/ServerCacheClient.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/cache/ServerCacheClient.java
@@ -195,18 +195,22 @@ public class ServerCacheClient {
                                                     BlockingRpcCallback<AddServerCacheResponse> rpcCallback =
                                                             new BlockingRpcCallback<AddServerCacheResponse>();
                                                     AddServerCacheRequest.Builder builder = AddServerCacheRequest.newBuilder();
-                                                    if(connection.getTenantId() != null){
+                                                    final byte[] tenantIdBytes;
+                                                    if(cacheUsingTable.isMultiTenant()) {
                                                         try {
-                                                            byte[] tenantIdBytes =
+                                                            tenantIdBytes = connection.getTenantId() == null ? null :
                                                                     ScanUtil.getTenantIdBytes(
                                                                             cacheUsingTable.getRowKeySchema(),
-                                                                            cacheUsingTable.getBucketNum()!=null,
-                                                                            connection.getTenantId(),
-                                                                            cacheUsingTable.isMultiTenant());
-                                                            builder.setTenantId(ByteStringer.wrap(tenantIdBytes));
+                                                                            cacheUsingTable.getBucketNum() != null,
+                                                                            connection.getTenantId(), cacheUsingTable.getViewIndexId() != null);
                                                         } catch (SQLException e) {
-                                                            new IOException(e);
+                                                            throw new IOException(e);
                                                         }
+                                                    } else {
+                                                        tenantIdBytes = connection.getTenantId() == null ? null : connection.getTenantId().getBytes();
+                                                    }
+                                                    if (tenantIdBytes != null) {
+                                                        builder.setTenantId(ByteStringer.wrap(tenantIdBytes));
                                                     }
                                                     builder.setCacheId(ByteStringer.wrap(cacheId));
                                                     builder.setCachePtr(org.apache.phoenix.protobuf.ProtobufUtil.toProto(cachePtr));
@@ -325,20 +329,24 @@ public class ServerCacheClient {
     							BlockingRpcCallback<RemoveServerCacheResponse> rpcCallback =
     									new BlockingRpcCallback<RemoveServerCacheResponse>();
     							RemoveServerCacheRequest.Builder builder = RemoveServerCacheRequest.newBuilder();
-    							if(connection.getTenantId() != null){
+                                final byte[] tenantIdBytes;
+                                if(cacheUsingTable.isMultiTenant()) {
                                     try {
-                                        byte[] tenantIdBytes =
+                                        tenantIdBytes = connection.getTenantId() == null ? null :
                                                 ScanUtil.getTenantIdBytes(
                                                         cacheUsingTable.getRowKeySchema(),
-                                                        cacheUsingTable.getBucketNum()!=null,
-                                                        connection.getTenantId(),
-                                                        cacheUsingTable.isMultiTenant());
-                                        builder.setTenantId(ByteStringer.wrap(tenantIdBytes));
+                                                        cacheUsingTable.getBucketNum() != null,
+                                                        connection.getTenantId(), cacheUsingTable.getViewIndexId() != null);
                                     } catch (SQLException e) {
-                                        new IOException(e);
+                                        throw new IOException(e);
                                     }
-    							}
-    							builder.setCacheId(ByteStringer.wrap(cacheId));
+                                } else {
+                                    tenantIdBytes = connection.getTenantId() == null ? null : connection.getTenantId().getBytes();
+                                }
+                                if (tenantIdBytes != null) {
+                                    builder.setTenantId(ByteStringer.wrap(tenantIdBytes));
+                                }
+                                builder.setCacheId(ByteStringer.wrap(cacheId));
     							instance.removeServerCache(controller, builder.build(), rpcCallback);
     							if(controller.getFailedOn() != null) {
     								throw controller.getFailedOn();

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f92dc9fb/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
index 696b74f..504f994 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
@@ -107,7 +107,7 @@ public class DeleteCompiler {
         PName tenantId = connection.getTenantId();
         byte[] tenantIdBytes = null;
         if (tenantId != null) {
-            tenantIdBytes = ScanUtil.getTenantIdBytes(table.getRowKeySchema(), table.getBucketNum() != null, tenantId);
+            tenantIdBytes = ScanUtil.getTenantIdBytes(table.getRowKeySchema(), table.getBucketNum() != null, tenantId, table.getViewIndexId() != null);
         }
         final boolean isAutoCommit = connection.getAutoCommit();
         ConnectionQueryServices services = connection.getQueryServices();
@@ -125,12 +125,12 @@ public class DeleteCompiler {
         boolean isSharedViewIndex = table.getViewIndexId() != null;
         int offset = (table.getBucketNum() == null ? 0 : 1);
         byte[][] values = new byte[pkColumns.size()][];
-        if (isMultiTenant) {
-            values[offset++] = tenantIdBytes;
-        }
         if (isSharedViewIndex) {
             values[offset++] = MetaDataUtil.getViewIndexIdDataType().toBytes(table.getViewIndexId());
         }
+        if (isMultiTenant) {
+            values[offset++] = tenantIdBytes;
+        }
         try (PhoenixResultSet rs = new PhoenixResultSet(iterator, projector, childContext)) {
             int rowCount = 0;
             while (rs.next()) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f92dc9fb/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
index 90efbad..ccd1c1b 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
@@ -325,18 +325,18 @@ public class UpsertCompiler {
                     targetColumns = Lists.newArrayListWithExpectedSize(columnIndexesToBe.length);
                     targetColumns.addAll(Collections.<PColumn>nCopies(columnIndexesToBe.length, null));
                     int minPKPos = 0;
-                    if (isTenantSpecific) {
-                        PColumn tenantColumn = table.getPKColumns().get(minPKPos);
-                        columnIndexesToBe[minPKPos] = tenantColumn.getPosition();
-                        targetColumns.set(minPKPos, tenantColumn);
-                        minPKPos++;
-                    }
                     if (isSharedViewIndex) {
                         PColumn indexIdColumn = table.getPKColumns().get(minPKPos);
                         columnIndexesToBe[minPKPos] = indexIdColumn.getPosition();
                         targetColumns.set(minPKPos, indexIdColumn);
                         minPKPos++;
                     }
+                    if (isTenantSpecific) {
+                        PColumn tenantColumn = table.getPKColumns().get(minPKPos);
+                        columnIndexesToBe[minPKPos] = tenantColumn.getPosition();
+                        targetColumns.set(minPKPos, tenantColumn);
+                        minPKPos++;
+                    }
                     for (int i = posOffset, j = 0; i < allColumnsToBe.size(); i++) {
                         PColumn column = allColumnsToBe.get(i);
                         if (SchemaUtil.isPKColumn(column)) {
@@ -366,6 +366,13 @@ public class UpsertCompiler {
                     Arrays.fill(pkSlotIndexesToBe, -1); // TODO: necessary? So we'll get an AIOB exception if it's not replaced
                     BitSet pkColumnsSet = new BitSet(table.getPKColumns().size());
                     int i = 0;
+                    if (isSharedViewIndex) {
+                        PColumn indexIdColumn = table.getPKColumns().get(i + posOffset);
+                        columnIndexesToBe[i] = indexIdColumn.getPosition();
+                        pkColumnsSet.set(pkSlotIndexesToBe[i] = i + posOffset);
+                        targetColumns.set(i, indexIdColumn);
+                        i++;
+                    }
                     // Add tenant column directly, as we don't want to resolve it as this will fail
                     if (isTenantSpecific) {
                         PColumn tenantColumn = table.getPKColumns().get(i + posOffset);
@@ -374,13 +381,6 @@ public class UpsertCompiler {
                         targetColumns.set(i, tenantColumn);
                         i++;
                     }
-                    if (isSharedViewIndex) {
-                        PColumn indexIdColumn = table.getPKColumns().get(i + posOffset);
-                        columnIndexesToBe[i] = indexIdColumn.getPosition();
-                        pkColumnsSet.set(pkSlotIndexesToBe[i] = i + posOffset);
-                        targetColumns.set(i, indexIdColumn);
-                        i++;
-                    }
                     for (ColumnName colName : columnNodes) {
                         ColumnRef ref = resolver.resolveColumn(null, colName.getFamilyName(), colName.getColumnName());
                         PColumn column = ref.getColumn();
@@ -811,13 +811,13 @@ public class UpsertCompiler {
         /////////////////////////////////////////////////////////////////////
         final byte[][] values = new byte[nValuesToSet][];
         int nodeIndex = 0;
-        if (isTenantSpecific) {
-            PName tenantId = connection.getTenantId();
-            values[nodeIndex++] = ScanUtil.getTenantIdBytes(table.getRowKeySchema(), table.getBucketNum() != null, tenantId);
-        }
         if (isSharedViewIndex) {
             values[nodeIndex++] = MetaDataUtil.getViewIndexIdDataType().toBytes(table.getViewIndexId());
         }
+        if (isTenantSpecific) {
+            PName tenantId = connection.getTenantId();
+            values[nodeIndex++] = ScanUtil.getTenantIdBytes(table.getRowKeySchema(), table.getBucketNum() != null, tenantId, isSharedViewIndex);
+        }
         
         final int nodeIndexOffset = nodeIndex;
         // Allocate array based on size of all columns in table,
@@ -1006,12 +1006,12 @@ public class UpsertCompiler {
             return select;
         }
         List<AliasedNode> selectNodes = newArrayListWithCapacity(select.getSelect().size() + 1 + addViewColumns.size());
-        if (table.isMultiTenant() && tenantId != null) {
-            selectNodes.add(new AliasedNode(null, new LiteralParseNode(tenantId)));
-        }
         if (table.getViewIndexId() != null) {
             selectNodes.add(new AliasedNode(null, new LiteralParseNode(table.getViewIndexId())));
         }
+        if (table.isMultiTenant() && tenantId != null) {
+            selectNodes.add(new AliasedNode(null, new LiteralParseNode(tenantId)));
+        }
         selectNodes.addAll(select.getSelect());
         for (PColumn column : addViewColumns) {
             byte[] byteValue = column.getViewConstant();

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f92dc9fb/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
index e1e3c53..8c2a216 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereOptimizer.java
@@ -114,8 +114,10 @@ public class WhereOptimizer {
     	boolean isSalted = nBuckets != null;
     	RowKeySchema schema = table.getRowKeySchema();
     	boolean isMultiTenant = tenantId != null && table.isMultiTenant();
+    	boolean isSharedIndex = table.getViewIndexId() != null;
+    	
     	if (isMultiTenant) {
-            tenantIdBytes = ScanUtil.getTenantIdBytes(schema, isSalted, tenantId);
+            tenantIdBytes = ScanUtil.getTenantIdBytes(schema, isSalted, tenantId, isSharedIndex);
     	}
 
         if (whereClause == null && (tenantId == null || !table.isMultiTenant()) && table.getViewIndexId() == null) {
@@ -187,6 +189,19 @@ public class WhereOptimizer {
             pkPos++;
         }
         
+        // Add unique index ID for shared indexes on views. This ensures
+        // that different indexes don't interleave.
+        if (hasViewIndex) {
+            byte[] viewIndexBytes = MetaDataUtil.getViewIndexIdDataType().toBytes(table.getViewIndexId());
+            KeyRange indexIdKeyRange = KeyRange.getKeyRange(viewIndexBytes);
+            cnf.add(singletonList(indexIdKeyRange));
+            if (hasMinMaxRange) {
+                System.arraycopy(viewIndexBytes, 0, minMaxRangePrefix, minMaxRangeOffset, viewIndexBytes.length);
+                minMaxRangeOffset += viewIndexBytes.length;
+            }
+            pkPos++;
+        }
+        
         // Add tenant data isolation for tenant-specific tables
         if (isMultiTenant) {
             KeyRange tenantIdKeyRange = KeyRange.getKeyRange(tenantIdBytes);
@@ -202,18 +217,6 @@ public class WhereOptimizer {
             }
             pkPos++;
         }
-        // Add unique index ID for shared indexes on views. This ensures
-        // that different indexes don't interleave.
-        if (hasViewIndex) {
-            byte[] viewIndexBytes = MetaDataUtil.getViewIndexIdDataType().toBytes(table.getViewIndexId());
-            KeyRange indexIdKeyRange = KeyRange.getKeyRange(viewIndexBytes);
-            cnf.add(singletonList(indexIdKeyRange));
-            if (hasMinMaxRange) {
-                System.arraycopy(viewIndexBytes, 0, minMaxRangePrefix, minMaxRangeOffset, viewIndexBytes.length);
-                minMaxRangeOffset += viewIndexBytes.length;
-            }
-            pkPos++;
-        }
         
         // Prepend minMaxRange with fixed column values so we can properly intersect the
         // range with the other range.

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f92dc9fb/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java
index e7b8b9e..757e304 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/BaseQueryPlan.java
@@ -272,8 +272,8 @@ public abstract class BaseQueryPlan implements QueryPlan {
             tenantIdBytes = connection.getTenantId() == null ? null :
                     ScanUtil.getTenantIdBytes(
                             table.getRowKeySchema(),
-                            table.getBucketNum()!=null,
-                            connection.getTenantId());
+                            table.getBucketNum() != null,
+                            connection.getTenantId(), table.getViewIndexId() != null);
         } else {
             tenantIdBytes = connection.getTenantId() == null ? null : connection.getTenantId().getBytes();
         }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f92dc9fb/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 6a316d9..db823de 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
@@ -476,6 +476,11 @@ public class IndexMaintainer implements Writable, Iterable<ColumnReference> {
             // Skip data table salt byte
             int maxRowKeyOffset = rowKeyPtr.getOffset() + rowKeyPtr.getLength();
             dataRowKeySchema.iterator(rowKeyPtr, ptr, dataPosOffset);
+            
+            if (viewIndexId != null) {
+                output.write(viewIndexId);
+            }
+            
             if (isMultiTenant) {
                 dataRowKeySchema.next(ptr, dataPosOffset, maxRowKeyOffset);
                 output.write(ptr.get(), ptr.getOffset(), ptr.getLength());
@@ -484,9 +489,6 @@ public class IndexMaintainer implements Writable, Iterable<ColumnReference> {
                 }
                 dataPosOffset++;
             }
-            if (viewIndexId != null) {
-                output.write(viewIndexId);
-            }
             
             // Write index row key
             for (int i = dataPosOffset; i < dataRowKeySchema.getFieldCount(); i++) {
@@ -714,11 +716,6 @@ public class IndexMaintainer implements Writable, Iterable<ColumnReference> {
             nIndexedColumns--;
         }
         int dataPosOffset = isDataTableSalted ? 1 : 0 ;
-        if (isMultiTenant) {
-            Field field = dataRowKeySchema.getField(dataPosOffset++);
-            builder.addField(field, field.isNullable(), field.getSortOrder());
-            nIndexedColumns--;
-        }
         if (viewIndexId != null) {
             nIndexedColumns--;
             builder.addField(new PDatum() {
@@ -750,6 +747,11 @@ public class IndexMaintainer implements Writable, Iterable<ColumnReference> {
                 
             }, false, SortOrder.getDefault());
         }
+        if (isMultiTenant) {
+            Field field = dataRowKeySchema.getField(dataPosOffset++);
+            builder.addField(field, field.isNullable(), field.getSortOrder());
+            nIndexedColumns--;
+        }
         
         Field[] indexFields = new Field[nIndexedColumns];
         BitSet viewConstantColumnBitSet = this.rowKeyMetaData.getViewConstantColumnBitSet();

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f92dc9fb/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 2e49122..fa2b335 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
@@ -22,7 +22,17 @@ import static org.apache.hadoop.hbase.HColumnDescriptor.TTL;
 import static org.apache.phoenix.coprocessor.MetaDataProtocol.PHOENIX_MAJOR_VERSION;
 import static org.apache.phoenix.coprocessor.MetaDataProtocol.PHOENIX_MINOR_VERSION;
 import static org.apache.phoenix.coprocessor.MetaDataProtocol.PHOENIX_PATCH_NUMBER;
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.COLUMN_FAMILY;
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.COLUMN_NAME;
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.DATA_TABLE_NAME;
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.INDEX_TYPE;
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.ORDINAL_POSITION;
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME_BYTES;
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_NAME;
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_SCHEM;
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TENANT_ID;
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.VIEW_INDEX_ID;
 import static org.apache.phoenix.query.QueryServicesOptions.DEFAULT_DROP_METADATA;
 import static org.apache.phoenix.query.QueryServicesOptions.DEFAULT_RENEW_LEASE_ENABLED;
 import static org.apache.phoenix.query.QueryServicesOptions.DEFAULT_RENEW_LEASE_THREAD_POOL_SIZE;
@@ -32,6 +42,8 @@ import static org.apache.phoenix.util.UpgradeUtil.upgradeTo4_5_0;
 
 import java.io.IOException;
 import java.lang.ref.WeakReference;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -157,6 +169,7 @@ import org.apache.phoenix.schema.PMetaDataImpl;
 import org.apache.phoenix.schema.PName;
 import org.apache.phoenix.schema.PNameFactory;
 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.ReadOnlyTableException;
@@ -894,7 +907,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
 
     private static interface RetriableOperation {
         boolean checkForCompletion() throws TimeoutException, IOException;
-        String getOperatioName();
+        String getOperationName();
     }
 
     private void pollForUpdatedTableDescriptor(final HBaseAdmin admin, final HTableDescriptor newTableDescriptor,
@@ -902,7 +915,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
         checkAndRetry(new RetriableOperation() {
 
             @Override
-            public String getOperatioName() {
+            public String getOperationName() {
                 return "UpdateOrNewTableDescriptor";
             }
 
@@ -933,7 +946,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
                 // Else, we swallow the exception and retry till we reach maxRetries.
                 if (numTries == 1 || numTries == maxRetries) {
                     watch.stop();
-                    TimeoutException toThrow = new TimeoutException("Operation " + op.getOperatioName()
+                    TimeoutException toThrow = new TimeoutException("Operation " + op.getOperationName()
                             + " didn't complete because of exception. Time elapsed: " + watch.elapsedMillis());
                     toThrow.initCause(ex);
                     throw toThrow;
@@ -946,13 +959,13 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
         watch.stop();
 
         if (!success) {
-            throw new TimeoutException("Operation  " + op.getOperatioName() + " didn't complete within "
+            throw new TimeoutException("Operation  " + op.getOperationName() + " didn't complete within "
                     + watch.elapsedMillis() + " ms "
                     + (numTries > 1 ? ("after trying " + numTries + (numTries > 1 ? "times." : "time.")) : ""));
         } else {
             if (logger.isDebugEnabled()) {
                 logger.debug("Operation "
-                        + op.getOperatioName()
+                        + op.getOperationName()
                         + " completed within "
                         + watch.elapsedMillis()
                         + "ms "
@@ -2489,6 +2502,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
                                             MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_8_0,
                                             PhoenixDatabaseMetaData.APPEND_ONLY_SCHEMA + " "
                                                     + PBoolean.INSTANCE.getSqlTypeName());
+                                    metaConnection = disableViewIndexes(metaConnection);
                                     ConnectionQueryServicesImpl.this.removeTable(null,
                                             PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME, null,
                                             MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_8_0);
@@ -2720,6 +2734,176 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
         }
         return metaConnection;
     }
+    
+    private PhoenixConnection disableViewIndexes(PhoenixConnection connParam) throws SQLException, IOException, InterruptedException, TimeoutException {
+        Properties props = PropertiesUtil.deepCopy(connParam.getClientInfo());
+        Long originalScn = null;
+        String str = props.getProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB);
+        if (str != null) {
+            originalScn = Long.valueOf(str);
+        }
+        // don't use the passed timestamp as scn because we want to query all view indexes up to now.
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(HConstants.LATEST_TIMESTAMP));
+        Set<String> physicalTables = new HashSet<>();
+        SQLException sqlEx = null;
+        PhoenixConnection globalConnection = null;
+        PhoenixConnection toReturn = null;
+        try {
+            globalConnection = new PhoenixConnection(connParam, this, props);
+            String tenantId = null;
+            try (HBaseAdmin admin = getAdmin()) {
+                String fetchViewIndexes = "SELECT " + TENANT_ID + ", " + TABLE_SCHEM + ", " + TABLE_NAME + 
+                        ", " + DATA_TABLE_NAME + " FROM " + SYSTEM_CATALOG_NAME + " WHERE " + VIEW_INDEX_ID
+                        + " IS NOT NULL AND " + INDEX_TYPE + "<>" + IndexType.LOCAL.getSerializedValue();
+                String disableIndexDDL = "ALTER INDEX %s ON %s DISABLE"; 
+                try (ResultSet rs = globalConnection.createStatement().executeQuery(fetchViewIndexes)) {
+                    while (rs.next()) {
+                        tenantId = rs.getString(1);
+                        String indexSchema = rs.getString(2);
+                        String indexName = rs.getString(3);
+                        String viewName = rs.getString(4);
+                        String fullIndexName = SchemaUtil.getTableName(indexSchema, indexName);
+                        PTable viewPTable = null;
+                        // Disable the view index and truncate the underlying hbase table. 
+                        // Users would need to rebuild the view indexes. 
+                        if (tenantId != null && !tenantId.isEmpty()) {
+                            Properties newProps = PropertiesUtil.deepCopy(globalConnection.getClientInfo());
+                            newProps.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, tenantId);
+                            PTable indexPTable = null;
+                            try (PhoenixConnection tenantConnection = new PhoenixConnection(globalConnection, this, newProps)) {
+                                viewPTable = PhoenixRuntime.getTable(tenantConnection, viewName);
+                                tenantConnection.createStatement().execute(String.format(disableIndexDDL, fullIndexName, viewName));
+                                indexPTable = PhoenixRuntime.getTable(tenantConnection, fullIndexName);
+                            }
+
+                            int offset = indexPTable.getBucketNum() != null ? 1 : 0;
+                            int existingTenantIdPosition = ++offset; // positions are stored 1 based
+                            int existingViewIdxIdPosition = ++offset;
+                            int newTenantIdPosition = existingViewIdxIdPosition;
+                            int newViewIdxPosition = existingTenantIdPosition;
+                            String tenantIdColumn = indexPTable.getColumns().get(existingTenantIdPosition - 1).getName().getString();
+                            int index = 0;
+                            String updatePosition =
+                                    "UPSERT INTO "
+                                            + SYSTEM_CATALOG_NAME
+                                            + " ( "
+                                            + TENANT_ID
+                                            + ","
+                                            + TABLE_SCHEM
+                                            + ","
+                                            + TABLE_NAME
+                                            + ","
+                                            + COLUMN_NAME
+                                            + ","
+                                            + COLUMN_FAMILY
+                                            + ","
+                                            + ORDINAL_POSITION
+                                            + ") SELECT "
+                                            + TENANT_ID
+                                            + ","
+                                            + TABLE_SCHEM
+                                            + ","
+                                            + TABLE_NAME
+                                            + ","
+                                            + COLUMN_NAME
+                                            + ","
+                                            + COLUMN_FAMILY
+                                            + ","
+                                            + "?"
+                                            + " FROM "
+                                            + SYSTEM_CATALOG_NAME
+                                            + " WHERE "
+                                            + TENANT_ID
+                                            + " = ? "
+                                            + " AND "
+                                            + TABLE_NAME
+                                            + " = ? "
+                                            + " AND "
+                                            + (indexSchema == null ? TABLE_SCHEM + " IS NULL" : TABLE_SCHEM + " = ? ") 
+                                            + " AND "
+                                            + COLUMN_NAME 
+                                            + " = ? ";
+                            // update view index position
+                            try (PreparedStatement s = globalConnection.prepareStatement(updatePosition)) {
+                                index = 0;
+                                s.setInt(++index, newViewIdxPosition);
+                                s.setString(++index, tenantId);
+                                s.setString(++index, indexName);
+                                if (indexSchema != null) {
+                                    s.setString(++index, indexSchema);
+                                }
+                                s.setString(++index, MetaDataUtil.getViewIndexIdColumnName());
+                                s.executeUpdate();
+                            }
+                            // update tenant id position
+                            try (PreparedStatement s = globalConnection.prepareStatement(updatePosition)) {
+                                index = 0;
+                                s.setInt(++index, newTenantIdPosition);
+                                s.setString(++index, tenantId);
+                                s.setString(++index, indexName);
+                                if (indexSchema != null) {
+                                    s.setString(++index, indexSchema);
+                                }
+                                s.setString(++index, tenantIdColumn);
+                                s.executeUpdate();
+                            }
+                            globalConnection.commit();
+                        } else {
+                            viewPTable = PhoenixRuntime.getTable(globalConnection, viewName);
+                            globalConnection.createStatement().execute(String.format(disableIndexDDL, fullIndexName, viewName));
+                        }
+                        String indexPhysicalTableName = MetaDataUtil.getViewIndexTableName(viewPTable.getPhysicalName().getString());
+                        if (physicalTables.add(indexPhysicalTableName)) {
+                            final TableName tableName = TableName.valueOf(indexPhysicalTableName);
+                            admin.disableTableAsync(tableName);
+                            checkAndRetry(new RetriableOperation() {
+                                @Override
+                                public boolean checkForCompletion() throws TimeoutException,
+                                IOException {
+                                    return admin.isTableDisabled(tableName);
+                                }
+
+                                @Override
+                                public String getOperationName() {
+                                    return "Disable table: " + tableName.getNameAsString();
+                                }
+
+                            });
+                            admin.truncateTable(tableName, false);
+                        }
+                    }
+                }
+            }
+            if (originalScn != null) {
+                props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(originalScn));
+            }
+            toReturn = new PhoenixConnection(globalConnection, this, props);
+        } catch (SQLException e) {
+            sqlEx = e;
+        } finally {
+            sqlEx = closeConnection(connParam, sqlEx);
+            sqlEx = closeConnection(globalConnection, sqlEx);
+            if (sqlEx != null) {
+                throw sqlEx;
+            }
+        }
+        return toReturn;
+    }
+    
+    
+    private static SQLException closeConnection(PhoenixConnection conn, SQLException sqlEx) {
+        SQLException toReturn = sqlEx;
+        try {
+            conn.close();
+        } catch (SQLException e) {
+            if (toReturn != null) {
+                toReturn.setNextException(e);
+            } else {
+                toReturn = e;
+            }
+        }
+        return toReturn;
+    }
 
     /**
      * Forces update of SYSTEM.CATALOG by setting column to existing value

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f92dc9fb/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 cacf687..3a4010b 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
@@ -1316,16 +1316,6 @@ public class MetaDataClient {
                 List<ColumnDefInPkConstraint> allPkColumns = Lists.newArrayListWithExpectedSize(unusedPkColumns.size());
                 List<ColumnDef> columnDefs = Lists.newArrayListWithExpectedSize(includedColumns.size() + indexParseNodeAndSortOrderList.size());
                 
-                if (dataTable.isMultiTenant()) {
-                    // Add tenant ID column as first column in index
-                    PColumn col = dataTable.getPKColumns().get(posOffset);
-                    RowKeyColumnExpression columnExpression = new RowKeyColumnExpression(col, new RowKeyValueAccessor(pkColumns, posOffset), col.getName().getString());
-                    unusedPkColumns.remove(columnExpression);
-                    PDataType dataType = IndexUtil.getIndexColumnDataType(col);
-                    ColumnName colName = ColumnName.caseSensitiveColumnName(IndexUtil.getIndexColumnName(col));
-                    allPkColumns.add(new ColumnDefInPkConstraint(colName, col.getSortOrder(), false));
-                    columnDefs.add(FACTORY.columnDef(colName, dataType.getSqlTypeName(), col.isNullable(), col.getMaxLength(), col.getScale(), false, SortOrder.getDefault(), col.getName().getString(), col.isRowTimestamp()));
-                }
                 /*
                  * Allocate an index ID in two circumstances:
                  * 1) for a local index, as all local indexes will reside in the same HBase table
@@ -1333,13 +1323,22 @@ public class MetaDataClient {
                  */
                 if (isLocalIndex || (dataTable.getType() == PTableType.VIEW && dataTable.getViewType() != ViewType.MAPPED)) {
                     allocateIndexId = true;
-                    // Next add index ID column
                     PDataType dataType = MetaDataUtil.getViewIndexIdDataType();
                     ColumnName colName = ColumnName.caseSensitiveColumnName(MetaDataUtil.getViewIndexIdColumnName());
                     allPkColumns.add(new ColumnDefInPkConstraint(colName, SortOrder.getDefault(), false));
                     columnDefs.add(FACTORY.columnDef(colName, dataType.getSqlTypeName(), false, null, null, false, SortOrder.getDefault(), null, false));
                 }
                 
+                if (dataTable.isMultiTenant()) {
+                    PColumn col = dataTable.getPKColumns().get(posOffset);
+                    RowKeyColumnExpression columnExpression = new RowKeyColumnExpression(col, new RowKeyValueAccessor(pkColumns, posOffset), col.getName().getString());
+                    unusedPkColumns.remove(columnExpression);
+                    PDataType dataType = IndexUtil.getIndexColumnDataType(col);
+                    ColumnName colName = ColumnName.caseSensitiveColumnName(IndexUtil.getIndexColumnName(col));
+                    allPkColumns.add(new ColumnDefInPkConstraint(colName, col.getSortOrder(), false));
+                    columnDefs.add(FACTORY.columnDef(colName, dataType.getSqlTypeName(), col.isNullable(), col.getMaxLength(), col.getScale(), false, SortOrder.getDefault(), col.getName().getString(), col.isRowTimestamp()));
+                }
+                
                 PhoenixStatement phoenixStatment = new PhoenixStatement(connection);
                 StatementContext context = new StatementContext(phoenixStatment, resolver);
                 IndexExpressionCompiler expressionIndexCompiler = new IndexExpressionCompiler(context);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f92dc9fb/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java
index c80b2fe..f3e432b 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/MetaDataUtil.java
@@ -93,7 +93,7 @@ public class MetaDataUtil {
     public static final String VIEW_INDEX_SEQUENCE_PREFIX = "_SEQ_";
     public static final String VIEW_INDEX_SEQUENCE_NAME_PREFIX = "_ID_";
     public static final byte[] VIEW_INDEX_SEQUENCE_PREFIX_BYTES = Bytes.toBytes(VIEW_INDEX_SEQUENCE_PREFIX);
-    public static final String VIEW_INDEX_ID_COLUMN_NAME = "_INDEX_ID";
+    private static final String VIEW_INDEX_ID_COLUMN_NAME = "_INDEX_ID";
     public static final String PARENT_TABLE_KEY = "PARENT_TABLE";
     public static final byte[] PARENT_TABLE_KEY_BYTES = Bytes.toBytes("PARENT_TABLE");
     

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f92dc9fb/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 45815bd..964c66b 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
@@ -1059,7 +1059,8 @@ public class PhoenixRuntime {
             throw new SQLFeatureNotSupportedException();
         }
         
-        int pkPosition = table.getBucketNum() == null ? 0 : 1;
+        // skip salt and viewIndexId columns.
+        int pkPosition = table.getBucketNum() == null ? 0 : 1 + (table.getViewIndexId() == 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/f92dc9fb/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
index f3e3d28..7a3014b 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
@@ -766,16 +766,16 @@ public class ScanUtil {
         return Bytes.compareTo(key, 0, nBytesToCheck, ZERO_BYTE_ARRAY, 0, nBytesToCheck) != 0;
     }
 
-    public static byte[] getTenantIdBytes(RowKeySchema schema, boolean isSalted, PName tenantId, boolean isMultiTenantTable)
+    public static byte[] getTenantIdBytes(RowKeySchema schema, boolean isSalted, PName tenantId, boolean isMultiTenantTable, boolean isSharedIndex)
             throws SQLException {
         return isMultiTenantTable ?
-                  getTenantIdBytes(schema, isSalted, tenantId)
+                  getTenantIdBytes(schema, isSalted, tenantId, isSharedIndex)
                 : tenantId.getBytes();
     }
 
-    public static byte[] getTenantIdBytes(RowKeySchema schema, boolean isSalted, PName tenantId)
+    public static byte[] getTenantIdBytes(RowKeySchema schema, boolean isSalted, PName tenantId, boolean isSharedIndex)
             throws SQLException {
-        int pkPos = isSalted ? 1 : 0;
+        int pkPos = (isSalted ? 1 : 0) + (isSharedIndex ? 1 : 0); 
         Field field = schema.getField(pkPos);
         PDataType dataType = field.getDataType();
         byte[] convertedValue;

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f92dc9fb/phoenix-core/src/test/java/org/apache/phoenix/compile/TenantSpecificViewIndexCompileTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/TenantSpecificViewIndexCompileTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/TenantSpecificViewIndexCompileTest.java
index 60584d7..d893707 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/compile/TenantSpecificViewIndexCompileTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/TenantSpecificViewIndexCompileTest.java
@@ -54,7 +54,7 @@ public class TenantSpecificViewIndexCompileTest extends BaseConnectionlessQueryT
         conn.createStatement().execute("CREATE INDEX i1 ON v(v2) INCLUDE(v1)");
         
         ResultSet rs = conn.createStatement().executeQuery("EXPLAIN SELECT v1,v2 FROM v WHERE v2 > 'a' ORDER BY v2");
-        assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER _IDX_T ['me',-32768,'a'] - ['me',-32768,*]",
+        assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER _IDX_T [-32768,'me','a'] - [-32768,'me',*]",
                 QueryUtil.getExplainPlan(rs));
     }
 
@@ -198,7 +198,7 @@ public class TenantSpecificViewIndexCompileTest extends BaseConnectionlessQueryT
         conn.createStatement().execute("CREATE INDEX i1 ON v(v2)");
         
         ResultSet rs = conn.createStatement().executeQuery("EXPLAIN SELECT v2 FROM v WHERE v2 > 'a' and k2 = 'a' ORDER BY v2,k2");
-        assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER _IDX_T ['me',-32766,'a'] - ['me',-32766,*]\n" + 
+        assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER _IDX_T [-32766,'me','a'] - [-32766,'me',*]\n" + 
                 "    SERVER FILTER BY FIRST KEY ONLY",
                 QueryUtil.getExplainPlan(rs));
         
@@ -231,7 +231,7 @@ public class TenantSpecificViewIndexCompileTest extends BaseConnectionlessQueryT
         
         // Confirm that a read-only view on an updatable view still optimizes out the read-only parts of the updatable view
         ResultSet rs = conn.createStatement().executeQuery("EXPLAIN SELECT v2 FROM v2 WHERE v3 > 'a' and k2 = 'a' ORDER BY v3,k2");
-        assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER _IDX_T ['me',-32767,'a'] - ['me',-32767,*]",
+        assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER _IDX_T [-32767,'me','a'] - [-32767,'me',*]",
                 QueryUtil.getExplainPlan(rs));
     }
     

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f92dc9fb/phoenix-core/src/test/java/org/apache/phoenix/util/TenantIdByteConversionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/util/TenantIdByteConversionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/util/TenantIdByteConversionTest.java
index 4d433aa..fb70d22 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/util/TenantIdByteConversionTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/util/TenantIdByteConversionTest.java
@@ -61,7 +61,7 @@ public class TenantIdByteConversionTest {
     @Test
     public void test() {
         try {
-            byte[] actualTenantIdBytes = ScanUtil.getTenantIdBytes(schema, isSalted, tenantId);
+            byte[] actualTenantIdBytes = ScanUtil.getTenantIdBytes(schema, isSalted, tenantId, false);
             assertArrayEquals(expectedTenantIdBytes, actualTenantIdBytes);
         } catch (SQLException ex) {
             fail(ex.getMessage());


Mime
View raw message