Repository: phoenix Updated Branches: refs/heads/4.x-HBase-0.98 4a7022066 -> 6e56eddc9
PHOENIX-2056 Ensure PK column from base table is added to any indexes on views Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/b95907ef Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/b95907ef Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/b95907ef Branch: refs/heads/4.x-HBase-0.98 Commit: b95907ef64c3d93c8c263d5a9f5b1533e4256ee6 Parents: 4a70220 Author: Samarth <samarth.j...@salesforce.com> Authored: Tue Jun 23 11:07:36 2015 -0700 Committer: Samarth <samarth.j...@salesforce.com> Committed: Tue Jun 23 11:07:36 2015 -0700 ---------------------------------------------------------------------- .../apache/phoenix/end2end/AlterTableIT.java | 170 ++++++++++++++++++- .../coprocessor/MetaDataEndpointImpl.java | 145 +++++++++++++++- .../java/org/apache/phoenix/util/ByteUtil.java | 10 +- 3 files changed, 305 insertions(+), 20 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/b95907ef/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java index 61dd6a9..1302c60 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java @@ -2303,13 +2303,23 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT { String alterBaseTable = "ALTER TABLE " + baseTable + " ADD NEW_PK varchar primary key "; globalConn.createStatement().execute(alterBaseTable); - + // verify that the new column new_pk is now part of the primary key for the entire hierarchy - assertTrue(checkColumnPartOfPk(globalConn.unwrap(PhoenixConnection.class), "PK1", baseTable)); - assertTrue(checkColumnPartOfPk(tenant1Conn.unwrap(PhoenixConnection.class), "PK1", view1)); - assertTrue(checkColumnPartOfPk(tenant1Conn.unwrap(PhoenixConnection.class), "PK1", view2)); - assertTrue(checkColumnPartOfPk(tenant2Conn.unwrap(PhoenixConnection.class), "PK1", view3)); - assertTrue(checkColumnPartOfPk(globalConn.unwrap(PhoenixConnection.class), "PK1", view4)); + + globalConn.createStatement().execute("SELECT * FROM " + baseTable); + assertTrue(checkColumnPartOfPk(globalConn.unwrap(PhoenixConnection.class), "NEW_PK", baseTable)); + + tenant1Conn.createStatement().execute("SELECT * FROM " + view1); + assertTrue(checkColumnPartOfPk(tenant1Conn.unwrap(PhoenixConnection.class), "NEW_PK", view1)); + + tenant1Conn.createStatement().execute("SELECT * FROM " + view2); + assertTrue(checkColumnPartOfPk(tenant1Conn.unwrap(PhoenixConnection.class), "NEW_PK", view2)); + + tenant2Conn.createStatement().execute("SELECT * FROM " + view3); + assertTrue(checkColumnPartOfPk(tenant2Conn.unwrap(PhoenixConnection.class), "NEW_PK", view3)); + + globalConn.createStatement().execute("SELECT * FROM " + view4); + assertTrue(checkColumnPartOfPk(globalConn.unwrap(PhoenixConnection.class), "NEW_PK", view4)); } finally { if (tenant1Conn != null) { @@ -2344,4 +2354,152 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT { tenantProps.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, tenantId); return DriverManager.getConnection(getUrl(), tenantProps); } + + @Test + public void testAddPKColumnToBaseTableWhoseViewsHaveIndices() throws Exception { + String baseTable = "testAddPKColumnToBaseTableWhoseViewsHaveIndices"; + String view1 = "view1"; + String view2 = "view2"; + String view3 = "view3"; + String tenant1 = "tenant1"; + String tenant2 = "tenant2"; + String view2Index = view2 + "_idx"; + String view3Index = view3 + "_idx"; + /* baseTable(mutli-tenant) + / \ + view1(tenant1) view3(tenant2, index) + / + view2(tenant1, index) + */ + try (Connection globalConn = DriverManager.getConnection(getUrl())) { + // make sure that the tables are empty, but reachable + globalConn + .createStatement() + .execute( + "CREATE TABLE " + + baseTable + + " (TENANT_ID VARCHAR NOT NULL, K1 varchar not null, V1 VARCHAR, V2 VARCHAR CONSTRAINT NAME_PK PRIMARY KEY(TENANT_ID, K1)) MULTI_TENANT = true "); + + } + try (Connection tenantConn = getTenantConnection(tenant1)) { + // create tenant specific view for tenant1 - view1 + tenantConn.createStatement().execute("CREATE VIEW " + view1 + " AS SELECT * FROM " + baseTable); + PhoenixConnection phxConn = tenantConn.unwrap(PhoenixConnection.class); + assertEquals(0, getTableSequenceNumber(phxConn, view1)); + assertEquals(2, getMaxKeySequenceNumber(phxConn, view1)); + + // create a view - view2 on view - view1 + tenantConn.createStatement().execute("CREATE VIEW " + view2 + " AS SELECT * FROM " + view1); + assertEquals(0, getTableSequenceNumber(phxConn, view2)); + assertEquals(2, getMaxKeySequenceNumber(phxConn, view2)); + + + // create an index on view2 + tenantConn.createStatement().execute("CREATE INDEX " + view2Index + " ON " + view2 + " (v1) include (v2)"); + assertEquals(0, getTableSequenceNumber(phxConn, view2Index)); + assertEquals(4, getMaxKeySequenceNumber(phxConn, view2Index)); + + } + try (Connection tenantConn = getTenantConnection(tenant2)) { + // create tenant specific view for tenant2 - view3 + tenantConn.createStatement().execute("CREATE VIEW " + view3 + " AS SELECT * FROM " + baseTable); + PhoenixConnection phxConn = tenantConn.unwrap(PhoenixConnection.class); + assertEquals(0, getTableSequenceNumber(phxConn, view3)); + assertEquals(2, getMaxKeySequenceNumber(phxConn, view3)); + + + // create an index on view3 + tenantConn.createStatement().execute("CREATE INDEX " + view3Index + " ON " + view3 + " (v1) include (v2)"); + assertEquals(0, getTableSequenceNumber(phxConn, view3Index)); + assertEquals(4, getMaxKeySequenceNumber(phxConn, view3Index)); + + + } + + // alter the base table by adding 1 non-pk and 2 pk columns + try (Connection globalConn = DriverManager.getConnection(getUrl())) { + globalConn.createStatement().execute("ALTER TABLE " + baseTable + " ADD v3 VARCHAR, k2 VARCHAR PRIMARY KEY, k3 VARCHAR PRIMARY KEY"); + assertEquals(4, getMaxKeySequenceNumber(globalConn.unwrap(PhoenixConnection.class), baseTable)); + + // Upsert records in the base table + String upsert = "UPSERT INTO " + baseTable + " (TENANT_ID, K1, K2, K3, V1, V2, V3) VALUES (?, ?, ?, ?, ?, ?, ?)"; + PreparedStatement stmt = globalConn.prepareStatement(upsert); + stmt.setString(1, tenant1); + stmt.setString(2, "K1"); + stmt.setString(3, "K2"); + stmt.setString(4, "K3"); + stmt.setString(5, "V1"); + stmt.setString(6, "V2"); + stmt.setString(7, "V3"); + stmt.executeUpdate(); + stmt.setString(1, tenant2); + stmt.setString(2, "K11"); + stmt.setString(3, "K22"); + stmt.setString(4, "K33"); + stmt.setString(5, "V11"); + stmt.setString(6, "V22"); + stmt.setString(7, "V33"); + stmt.executeUpdate(); + globalConn.commit(); + } + + // Verify now that the sequence number of data table, indexes and views have changed. + // Also verify that the newly added pk columns show up as pk columns of data table, indexes and views. + try (Connection tenantConn = getTenantConnection(tenant1)) { + + ResultSet rs = tenantConn.createStatement().executeQuery("SELECT K2, K3, V3 FROM " + view1); + PhoenixConnection phxConn = tenantConn.unwrap(PhoenixConnection.class); + assertTrue(checkColumnPartOfPk(phxConn, "k2", view1)); + assertTrue(checkColumnPartOfPk(phxConn, "k3", view1)); + assertEquals(1, getTableSequenceNumber(phxConn, view1)); + assertEquals(4, getMaxKeySequenceNumber(phxConn, view1)); + verifyNewColumns(rs, "K2", "K3", "V3"); + + + rs = tenantConn.createStatement().executeQuery("SELECT K2, K3, V3 FROM " + view2); + assertTrue(checkColumnPartOfPk(phxConn, "k2", view2)); + assertTrue(checkColumnPartOfPk(phxConn, "k3", view2)); + assertEquals(1, getTableSequenceNumber(phxConn, view2)); + assertEquals(4, getMaxKeySequenceNumber(phxConn, view2)); + verifyNewColumns(rs, "K2", "K3", "V3"); + + assertTrue(checkColumnPartOfPk(phxConn, IndexUtil.getIndexColumnName(null, "k2"), view2Index)); + assertTrue(checkColumnPartOfPk(phxConn, IndexUtil.getIndexColumnName(null, "k3"), view2Index)); + assertEquals(1, getTableSequenceNumber(phxConn, view2Index)); + assertEquals(6, getMaxKeySequenceNumber(phxConn, view2Index)); + } + try (Connection tenantConn = getTenantConnection(tenant2)) { + ResultSet rs = tenantConn.createStatement().executeQuery("SELECT K2, K3, V3 FROM " + view3); + PhoenixConnection phxConn = tenantConn.unwrap(PhoenixConnection.class); + assertTrue(checkColumnPartOfPk(phxConn, "k2", view3)); + assertTrue(checkColumnPartOfPk(phxConn, "k3", view3)); + assertEquals(1, getTableSequenceNumber(phxConn, view3)); + verifyNewColumns(rs, "K22", "K33", "V33"); + + assertTrue(checkColumnPartOfPk(phxConn, IndexUtil.getIndexColumnName(null, "k2"), view3Index)); + assertTrue(checkColumnPartOfPk(phxConn, IndexUtil.getIndexColumnName(null, "k3"), view3Index)); + assertEquals(1, getTableSequenceNumber(phxConn, view3Index)); + assertEquals(6, getMaxKeySequenceNumber(phxConn, view3Index)); + } + } + + private static long getTableSequenceNumber(PhoenixConnection conn, String tableName) throws SQLException { + PTable table = conn.getMetaDataCache().getTable(new PTableKey(conn.getTenantId(), SchemaUtil.normalizeIdentifier(tableName))); + return table.getSequenceNumber(); + } + + private static short getMaxKeySequenceNumber(PhoenixConnection conn, String tableName) throws SQLException { + PTable table = conn.getMetaDataCache().getTable(new PTableKey(conn.getTenantId(), SchemaUtil.normalizeIdentifier(tableName))); + return SchemaUtil.getMaxKeySeq(table); + } + + private static void verifyNewColumns(ResultSet rs, String ... values) throws SQLException { + assertTrue(rs.next()); + int i = 1; + for (String value : values) { + assertEquals(value, rs.getString(i++)); + } + assertFalse(rs.next()); + } + } http://git-wip-us.apache.org/repos/asf/phoenix/blob/b95907ef/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java index f80a69d..af0c7de 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java @@ -62,7 +62,9 @@ import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.VIEW_INDEX_ID_BYTE import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.VIEW_STATEMENT_BYTES; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.VIEW_TYPE_BYTES; import static org.apache.phoenix.query.QueryConstants.DIVORCED_VIEW_BASE_COLUMN_COUNT; +import static org.apache.phoenix.query.QueryConstants.SEPARATOR_BYTE_ARRAY; import static org.apache.phoenix.schema.PTableType.INDEX; +import static org.apache.phoenix.util.ByteUtil.EMPTY_BYTE_ARRAY; import static org.apache.phoenix.util.SchemaUtil.getVarCharLength; import static org.apache.phoenix.util.SchemaUtil.getVarChars; @@ -166,11 +168,13 @@ import org.apache.phoenix.schema.types.PBoolean; import org.apache.phoenix.schema.types.PDataType; import org.apache.phoenix.schema.types.PInteger; import org.apache.phoenix.schema.types.PLong; +import org.apache.phoenix.schema.types.PSmallint; import org.apache.phoenix.schema.types.PVarbinary; import org.apache.phoenix.schema.types.PVarchar; import org.apache.phoenix.trace.util.Tracing; import org.apache.phoenix.util.ByteUtil; import org.apache.phoenix.util.EnvironmentEdgeManager; +import org.apache.phoenix.util.IndexUtil; import org.apache.phoenix.util.KeyValueUtil; import org.apache.phoenix.util.MetaDataUtil; import org.apache.phoenix.util.QueryUtil; @@ -1580,13 +1584,13 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso // lock the rows corresponding to views so that no other thread can modify the view meta-data RowLock viewRowLock = acquireLock(region, viewKey, locks); PTable view = doGetTable(viewKey, clientTimeStamp, viewRowLock); - if (view.getBaseColumnCount() == QueryConstants.DIVORCED_VIEW_BASE_COLUMN_COUNT) { // if a view has divorced itself from the base table, we don't allow schema changes // to be propagated to it. return; } int deltaNumberOfColumns = 0; + short deltaNumPkColsSoFar = 0; for (Mutation m : tableMetadata) { byte[][] rkmd = new byte[5][]; int pkCount = getVarChars(m.getRow(), rkmd); @@ -1595,16 +1599,133 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso && Bytes.compareTo(tableName, rkmd[TABLE_NAME_INDEX]) == 0) { Put p = (Put)m; - byte[] k = ByteUtil.concat(viewKey, QueryConstants.SEPARATOR_BYTE_ARRAY, rkmd[COLUMN_NAME_INDEX], - QueryConstants.SEPARATOR_BYTE_ARRAY, rkmd[FAMILY_NAME_INDEX]); - Put viewColumnDefinitionPut = new Put(k, clientTimeStamp); + byte[] columnKey = ByteUtil.concat(viewKey, QueryConstants.SEPARATOR_BYTE_ARRAY, rkmd[COLUMN_NAME_INDEX]); + if (rkmd[FAMILY_NAME_INDEX] != null) { + columnKey = ByteUtil.concat(columnKey, QueryConstants.SEPARATOR_BYTE_ARRAY, rkmd[FAMILY_NAME_INDEX]); + } + Put viewColumnDefinitionPut = new Put(columnKey, clientTimeStamp); for (Cell cell : p.getFamilyCellMap().values().iterator().next()) { - viewColumnDefinitionPut.add(CellUtil.createCell(k, CellUtil.cloneFamily(cell), + viewColumnDefinitionPut.add(CellUtil.createCell(columnKey, CellUtil.cloneFamily(cell), CellUtil.cloneQualifier(cell), cell.getTimestamp(), cell.getTypeByte(), CellUtil.cloneValue(cell))); } deltaNumberOfColumns++; mutationsForAddingColumnsToViews.add(viewColumnDefinitionPut); + if (rkmd[FAMILY_NAME_INDEX] == null && rkmd[COLUMN_NAME_INDEX] != null) { + /* + * If adding a pk column to the base table (and hence the view), see if there are any indexes on + * the view. If yes, then generate puts for the index header row and column rows. + */ + deltaNumPkColsSoFar++; + for (PTable index : view.getIndexes()) { + int oldNumberOfColsInIndex = index.getColumns().size(); + + byte[] indexColumnKey = ByteUtil.concat(getViewIndexHeaderRowKey(index), + QueryConstants.SEPARATOR_BYTE_ARRAY, + IndexUtil.getIndexColumnName(rkmd[FAMILY_NAME_INDEX], rkmd[COLUMN_NAME_INDEX])); + Put indexColumnDefinitionPut = new Put(indexColumnKey, clientTimeStamp); + + // Set the index specific data type for the column + List<Cell> dataTypes = viewColumnDefinitionPut + .get(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES, + PhoenixDatabaseMetaData.DATA_TYPE_BYTES); + if (dataTypes != null && dataTypes.size() > 0) { + Cell dataType = dataTypes.get(0); + int dataColumnDataType = PInteger.INSTANCE.getCodec().decodeInt( + dataType.getValueArray(), dataType.getValueOffset(), SortOrder.ASC); + int indexColumnDataType = IndexUtil.getIndexColumnDataType(true, + PDataType.fromTypeId(dataColumnDataType)).getSqlType(); + byte[] indexColumnDataTypeBytes = new byte[PInteger.INSTANCE.getByteSize()]; + PInteger.INSTANCE.getCodec().encodeInt(indexColumnDataType, indexColumnDataTypeBytes, 0); + indexColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES, + PhoenixDatabaseMetaData.DATA_TYPE_BYTES, indexColumnDataTypeBytes); + } + + // Set precision + List<Cell> decimalDigits = viewColumnDefinitionPut.get( + PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES, + PhoenixDatabaseMetaData.DECIMAL_DIGITS_BYTES); + if (decimalDigits != null && decimalDigits.size() > 0) { + Cell decimalDigit = decimalDigits.get(0); + indexColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES, + PhoenixDatabaseMetaData.DECIMAL_DIGITS_BYTES, decimalDigit.getValueArray()); + } + + // Set size + List<Cell> columnSizes = viewColumnDefinitionPut.get( + PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES, + PhoenixDatabaseMetaData.COLUMN_SIZE_BYTES); + if (columnSizes != null && columnSizes.size() > 0) { + Cell columnSize = columnSizes.get(0); + indexColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES, + PhoenixDatabaseMetaData.COLUMN_SIZE_BYTES, columnSize.getValueArray()); + } + + // Set sort order + List<Cell> sortOrders = viewColumnDefinitionPut.get(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES, + PhoenixDatabaseMetaData.SORT_ORDER_BYTES); + if (sortOrders != null && sortOrders.size() > 0) { + Cell sortOrder = sortOrders.get(0); + indexColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES, + PhoenixDatabaseMetaData.SORT_ORDER_BYTES, sortOrder.getValueArray()); + } + + // Set data table name + List<Cell> dataTableNames = viewColumnDefinitionPut.get(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES, + PhoenixDatabaseMetaData.DATA_TABLE_NAME_BYTES); + if (dataTableNames != null && dataTableNames.size() > 0) { + Cell dataTableName = dataTableNames.get(0); + indexColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES, + PhoenixDatabaseMetaData.DATA_TABLE_NAME_BYTES, dataTableName.getValueArray()); + } + + // Set the ordinal position of the new column. + byte[] ordinalPositionBytes = new byte[PInteger.INSTANCE.getByteSize()]; + int ordinalPositionOfNewCol = oldNumberOfColsInIndex + deltaNumPkColsSoFar; + PInteger.INSTANCE.getCodec().encodeInt(ordinalPositionOfNewCol, ordinalPositionBytes, 0); + indexColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES, + PhoenixDatabaseMetaData.ORDINAL_POSITION_BYTES, ordinalPositionBytes); + + // New PK columns have to be nullable after the first DDL + byte[] isNullableBytes = PBoolean.INSTANCE.toBytes(true); + indexColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES, + PhoenixDatabaseMetaData.NULLABLE_BYTES, isNullableBytes); + + // Set the key sequence for the pk column to be added + short currentKeySeq = SchemaUtil.getMaxKeySeq(index); + short newKeySeq = (short)(currentKeySeq + deltaNumPkColsSoFar); + byte[] keySeqBytes = new byte[PSmallint.INSTANCE.getByteSize()]; + PSmallint.INSTANCE.getCodec().encodeShort(newKeySeq, keySeqBytes, 0); + indexColumnDefinitionPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES, + PhoenixDatabaseMetaData.KEY_SEQ_BYTES, keySeqBytes); + + mutationsForAddingColumnsToViews.add(indexColumnDefinitionPut); + } + } + } + } + if (deltaNumPkColsSoFar > 0) { + for (PTable index : view.getIndexes()) { + byte[] indexHeaderRowKey = getViewIndexHeaderRowKey(index); + Put indexHeaderRowMutation = new Put(indexHeaderRowKey); + + // increment sequence number + long newSequenceNumber = index.getSequenceNumber() + 1; + byte[] newSequenceNumberPtr = new byte[PLong.INSTANCE.getByteSize()]; + PLong.INSTANCE.getCodec().encodeLong(newSequenceNumber, newSequenceNumberPtr, 0); + indexHeaderRowMutation.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES, + PhoenixDatabaseMetaData.TABLE_SEQ_NUM_BYTES, newSequenceNumberPtr); + + // increase the column count + int newColumnCount = index.getColumns().size() + deltaNumPkColsSoFar; + byte[] newColumnCountPtr = new byte[PInteger.INSTANCE.getByteSize()]; + PInteger.INSTANCE.getCodec().encodeInt(newColumnCount, newColumnCountPtr, 0); + indexHeaderRowMutation.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES, + PhoenixDatabaseMetaData.COLUMN_COUNT_BYTES, newColumnCountPtr); + + // add index row header key to the invalidate list to force clients to fetch the latest meta-data + invalidateList.add(new ImmutableBytesPtr(indexHeaderRowKey)); + mutationsForAddingColumnsToViews.add(indexHeaderRowMutation); } } @@ -1631,7 +1752,10 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso int newPosition = column.getPosition() + deltaNumberOfColumns + 1; byte[] k = ByteUtil.concat(viewKey, QueryConstants.SEPARATOR_BYTE_ARRAY, column.getName() - .getBytes(), QueryConstants.SEPARATOR_BYTE_ARRAY, column.getFamilyName() != null ? column.getFamilyName().getBytes() : null); + .getBytes()); + if (column.getFamilyName() != null) { + k = ByteUtil.concat(k, QueryConstants.SEPARATOR_BYTE_ARRAY, column.getFamilyName().getBytes()); + } Put positionUpdatePut = new Put(k, clientTimeStamp); byte[] ptr = new byte[PInteger.INSTANCE.getByteSize()]; @@ -1644,7 +1768,14 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso invalidateList.add(new ImmutableBytesPtr(viewKey)); } } - + + private byte[] getViewIndexHeaderRowKey(PTable index) { + byte[] tenantIdBytes = index.getKey().getTenantId() != null ? index.getKey().getTenantId().getBytes() : EMPTY_BYTE_ARRAY; + byte[] schemaNameBytes = index.getSchemaName() != null ? index.getSchemaName().getBytes() : EMPTY_BYTE_ARRAY; + byte[] tableNameBytes = index.getTableName().getBytes(); + return ByteUtil.concat(tenantIdBytes, SEPARATOR_BYTE_ARRAY, schemaNameBytes, SEPARATOR_BYTE_ARRAY, tableNameBytes); + } + @Override public void addColumn(RpcController controller, AddColumnRequest request, RpcCallback<MetaDataResponse> done) { http://git-wip-us.apache.org/repos/asf/phoenix/blob/b95907ef/phoenix-core/src/main/java/org/apache/phoenix/util/ByteUtil.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/ByteUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/ByteUtil.java index 1f4a285..1e3516d 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/util/ByteUtil.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/util/ByteUtil.java @@ -253,17 +253,13 @@ public class ByteUtil { public static byte[] concat(byte[] first, byte[]... rest) { int totalLength = first.length; for (byte[] array : rest) { - if (array != null) { - totalLength += array.length; - } + totalLength += array.length; } byte[] result = Arrays.copyOf(first, totalLength); int offset = first.length; for (byte[] array : rest) { - if (array != null) { - System.arraycopy(array, 0, result, offset, array.length); - offset += array.length; - } + System.arraycopy(array, 0, result, offset, array.length); + offset += array.length; } return result; }