PHOENIX-3522 Altering the mutability of a parent table does not propagate to the child views
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/2e7670ca Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/2e7670ca Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/2e7670ca Branch: refs/heads/calcite Commit: 2e7670cacb12839cdc14f8dea5177c9bf9501dab Parents: 683e1f0 Author: Thomas D'Silva <tdsi...@salesforce.com> Authored: Wed Dec 7 23:59:11 2016 -0800 Committer: Thomas D'Silva <tdsi...@salesforce.com> Committed: Fri Dec 9 12:48:32 2016 -0800 ---------------------------------------------------------------------- .../phoenix/end2end/AlterTableWithViewsIT.java | 40 +++++++++++++++++ .../coprocessor/MetaDataEndpointImpl.java | 46 ++++++++++++++++++-- .../apache/phoenix/schema/TableProperty.java | 12 +++++ 3 files changed, 94 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/2e7670ca/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableWithViewsIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableWithViewsIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableWithViewsIT.java index e6bf2d2..6e4f5c0 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableWithViewsIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableWithViewsIT.java @@ -42,6 +42,7 @@ import org.apache.phoenix.jdbc.PhoenixConnection; import org.apache.phoenix.query.QueryConstants; import org.apache.phoenix.schema.PName; import org.apache.phoenix.schema.PNameFactory; +import org.apache.phoenix.schema.PTable; import org.apache.phoenix.schema.PTableKey; import org.apache.phoenix.schema.PTableType; import org.junit.Test; @@ -97,6 +98,45 @@ public class AlterTableWithViewsIT extends ParallelStatsDisabledIT { } @Test + public void testAlterPropertiesOfParentTable() throws Exception { + try (Connection conn = DriverManager.getConnection(getUrl()); + Connection viewConn = isMultiTenant ? DriverManager.getConnection(TENANT_SPECIFIC_URL1) : conn ) { + String tableName = generateUniqueName(); + String viewOfTable = tableName + "_VIEW"; + String ddlFormat = "CREATE TABLE IF NOT EXISTS " + tableName + " (" + + " %s ID char(1) NOT NULL," + + " COL1 integer NOT NULL," + + " COL2 bigint NOT NULL," + + " CONSTRAINT NAME_PK PRIMARY KEY (%s ID, COL1, COL2)" + + " ) %s"; + conn.createStatement().execute(generateDDL(ddlFormat)); + viewConn.createStatement().execute("CREATE VIEW " + viewOfTable + " ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR ) AS SELECT * FROM " + tableName); + + PhoenixConnection phoenixConn = conn.unwrap(PhoenixConnection.class); + PTable table = phoenixConn.getTable(new PTableKey(null, tableName)); + PName tenantId = isMultiTenant ? PNameFactory.newName("tenant1") : null; + assertFalse(table.isImmutableRows()); + assertEquals(0, table.getUpdateCacheFrequency()); + PTable viewTable = viewConn.unwrap(PhoenixConnection.class).getTable(new PTableKey(tenantId, viewOfTable)); + assertFalse(viewTable.isImmutableRows()); + assertEquals(0, viewTable.getUpdateCacheFrequency()); + + conn.createStatement().execute("ALTER TABLE " + tableName + " SET IMMUTABLE_ROWS=true, UPDATE_CACHE_FREQUENCY=123"); + // query the view to force the table cache to be updated + viewConn.createStatement().execute("SELECT * FROM "+viewOfTable); + + phoenixConn = conn.unwrap(PhoenixConnection.class); + table = phoenixConn.getTable(new PTableKey(null, tableName)); + assertTrue(table.isImmutableRows()); + assertEquals(123, table.getUpdateCacheFrequency()); + + viewTable = viewConn.unwrap(PhoenixConnection.class).getTable(new PTableKey(tenantId, viewOfTable)); + assertTrue(viewTable.isImmutableRows()); + assertEquals(123, viewTable.getUpdateCacheFrequency()); + } + } + + @Test public void testDropColumnsFromBaseTableWithView() throws Exception { try (Connection conn = DriverManager.getConnection(getUrl()); Connection viewConn = isMultiTenant ? DriverManager.getConnection(TENANT_SPECIFIC_URL1) : conn ) { http://git-wip-us.apache.org/repos/asf/phoenix/blob/2e7670ca/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 ebe774c..56ec0e4 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 @@ -78,7 +78,6 @@ import static org.apache.phoenix.util.SchemaUtil.getVarCharLength; import static org.apache.phoenix.util.SchemaUtil.getVarChars; import java.io.IOException; -import java.sql.DriverManager; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; @@ -200,6 +199,7 @@ import org.apache.phoenix.schema.SequenceKey; import org.apache.phoenix.schema.SequenceNotFoundException; import org.apache.phoenix.schema.SortOrder; import org.apache.phoenix.schema.TableNotFoundException; +import org.apache.phoenix.schema.TableProperty; import org.apache.phoenix.schema.TableRef; import org.apache.phoenix.schema.tuple.ResultTuple; import org.apache.phoenix.schema.types.PBinary; @@ -2150,20 +2150,39 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso return false; } - private MetaDataMutationResult addColumnsToChildViews(PTable basePhysicalTable, List<Mutation> tableMetadata, List<Mutation> mutationsForAddingColumnsToViews, byte[] schemaName, byte[] tableName, + private MetaDataMutationResult addColumnsAndTablePropertiesToChildViews(PTable basePhysicalTable, List<Mutation> tableMetadata, List<Mutation> mutationsForAddingColumnsToViews, byte[] schemaName, byte[] tableName, List<ImmutableBytesPtr> invalidateList, long clientTimeStamp, TableViewFinderResult childViewsResult, Region region, List<RowLock> locks) throws IOException, SQLException { - List<PutWithOrdinalPosition> columnPutsForBaseTable = new ArrayList<>(tableMetadata.size()); + List<PutWithOrdinalPosition> columnPutsForBaseTable = Lists.newArrayListWithExpectedSize(tableMetadata.size()); + List<Cell> tablePropertyCells = Lists.newArrayListWithExpectedSize(tableMetadata.size()); // Isolate the puts relevant to adding columns. Also figure out what kind of columns are being added. for (Mutation m : tableMetadata) { if (m instanceof Put) { byte[][] rkmd = new byte[5][]; int pkCount = getVarChars(m.getRow(), rkmd); + // check if this put is for adding a column if (pkCount > COLUMN_NAME_INDEX && Bytes.compareTo(schemaName, rkmd[SCHEMA_NAME_INDEX]) == 0 && Bytes.compareTo(tableName, rkmd[TABLE_NAME_INDEX]) == 0) { columnPutsForBaseTable.add(new PutWithOrdinalPosition((Put)m, getInteger((Put)m, TABLE_FAMILY_BYTES, ORDINAL_POSITION_BYTES))); } + // check if the put is for a table property + else if (pkCount <= COLUMN_NAME_INDEX + && Bytes.compareTo(schemaName, rkmd[SCHEMA_NAME_INDEX]) == 0 + && Bytes.compareTo(tableName, rkmd[TABLE_NAME_INDEX]) == 0) { + for (Cell cell : m.getFamilyCellMap().get(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES)) { + for (TableProperty tableProp : TableProperty.values()) { + byte[] propNameBytes = Bytes.toBytes(tableProp.getPropertyName()); + if (Bytes.compareTo(propNameBytes, 0, propNameBytes.length, cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength())==0 + && tableProp.isValidOnView() && tableProp.isMutable()) { + Cell tablePropCell = CellUtil.createCell(cell.getRow(), CellUtil.cloneFamily(cell), + CellUtil.cloneQualifier(cell), cell.getTimestamp(), cell.getTypeByte(), + CellUtil.cloneValue(cell)); + tablePropertyCells.add(tablePropCell); + } + } + } + } } } // Sort the puts by ordinal position @@ -2186,6 +2205,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso List<PColumn> viewPkCols = new ArrayList<>(view.getPKColumns()); boolean addingExistingPkCol = false; int numCols = view.getColumns().size(); + // add the new columns to the child view for (PutWithOrdinalPosition p : columnPutsForBaseTable) { Put baseTableColumnPut = p.put; PColumn existingViewColumn = null; @@ -2332,6 +2352,24 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso addViewIndexesHeaderRowMutations(mutationsForAddingColumnsToViews, invalidateList, clientTimeStamp, view, deltaNumPkColsSoFar); + // set table properties in child view + if (!tablePropertyCells.isEmpty()) { + Put viewHeaderRowPut = new Put(viewKey, clientTimeStamp); + for (Cell tablePropertyCell : tablePropertyCells) { + viewHeaderRowPut.add(CellUtil.createCell(viewKey, CellUtil.cloneFamily(tablePropertyCell), + CellUtil.cloneQualifier(tablePropertyCell), clientTimeStamp, tablePropertyCell.getTypeByte(), + CellUtil.cloneValue(tablePropertyCell))); + } + byte[] viewSequencePtr = new byte[PLong.INSTANCE.getByteSize()]; + PLong.INSTANCE.getCodec().encodeLong(view.getSequenceNumber() + 1, viewSequencePtr, 0); + viewHeaderRowPut.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES, + PhoenixDatabaseMetaData.TABLE_SEQ_NUM_BYTES, clientTimeStamp, viewSequencePtr); + // invalidate the view so that it is removed from the cache + invalidateList.add(new ImmutableBytesPtr(viewKey)); + + mutationsForAddingColumnsToViews.add(viewHeaderRowPut); + } + /* * Increment the sequence number by 1 if: * 1) For a diverged view, there were columns (pk columns) added to the view. @@ -2789,7 +2827,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso EnvironmentEdgeManager.currentTimeMillis(), null); } else { mutationsForAddingColumnsToViews = new ArrayList<>(childViewsResult.getResults().size() * tableMetaData.size()); - MetaDataMutationResult mutationResult = addColumnsToChildViews(table, tableMetaData, mutationsForAddingColumnsToViews, schemaName, tableName, invalidateList, clientTimeStamp, + MetaDataMutationResult mutationResult = addColumnsAndTablePropertiesToChildViews(table, tableMetaData, mutationsForAddingColumnsToViews, schemaName, tableName, invalidateList, clientTimeStamp, childViewsResult, region, locks); // return if we were not able to add the column successfully if (mutationResult!=null) http://git-wip-us.apache.org/repos/asf/phoenix/blob/2e7670ca/phoenix-core/src/main/java/org/apache/phoenix/schema/TableProperty.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/TableProperty.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/TableProperty.java index 26a7718..4f24c92 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/TableProperty.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/TableProperty.java @@ -156,4 +156,16 @@ public enum TableProperty { } } + public String getPropertyName() { + return propertyName; + } + + public boolean isValidOnView() { + return isValidOnView; + } + + public boolean isMutable() { + return isMutable; + } + }