Repository: phoenix
Updated Branches:
  refs/heads/master 4f6ee74c0 -> 5097982b0


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/5097982b
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/5097982b
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/5097982b

Branch: refs/heads/master
Commit: 5097982b00b36b74fb328afaab02159e81b21af0
Parents: 4f6ee74
Author: Samarth <[email protected]>
Authored: Thu Jun 16 15:14:25 2016 -0700
Committer: Samarth <[email protected]>
Committed: Thu Jun 16 15:14:25 2016 -0700

----------------------------------------------------------------------
 .../end2end/BaseTenantSpecificViewIndexIT.java  |   4 +-
 .../end2end/TenantSpecificViewIndexIT.java      |   2 +-
 .../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, 323 insertions(+), 92 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/5097982b/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/5097982b/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 69d9140..f468d20 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
@@ -206,7 +206,7 @@ public class TenantSpecificViewIndexIT extends 
BaseTenantSpecificViewIndexIT {
             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/5097982b/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 7b6e476..4da62de 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/5097982b/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/5097982b/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/5097982b/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 7d60cd5..be6499b 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
@@ -334,18 +334,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)) {
@@ -375,6 +375,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);
@@ -383,13 +390,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();
@@ -820,13 +820,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,
@@ -1015,12 +1015,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/5097982b/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/5097982b/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 83e55ee..b940084 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
@@ -278,8 +278,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/5097982b/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/5097982b/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 56bd50c..d1cbdfc 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
@@ -21,7 +21,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;
@@ -31,6 +41,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;
@@ -156,6 +168,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;
@@ -893,7 +906,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,
@@ -901,7 +914,7 @@ public class ConnectionQueryServicesImpl extends 
DelegateQueryServices implement
         checkAndRetry(new RetriableOperation() {
 
             @Override
-            public String getOperatioName() {
+            public String getOperationName() {
                 return "UpdateOrNewTableDescriptor";
             }
 
@@ -932,7 +945,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;
@@ -945,13 +958,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 "
@@ -2493,6 +2506,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);
@@ -2710,6 +2724,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/5097982b/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/5097982b/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 9f2f9fa..ae81d37 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/5097982b/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 8cc536b..e68c8d4 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
@@ -1056,7 +1056,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/5097982b/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/5097982b/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 63e513b..27c30fc 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
@@ -50,7 +50,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));
     }
 
@@ -194,7 +194,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));
         
@@ -227,7 +227,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/5097982b/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());

Reply via email to