PHOENIX-2356 Set TRANSACTIONAL to true for derived views when transitioning to transactional table
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/93acc278 Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/93acc278 Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/93acc278 Branch: refs/heads/calcite Commit: 93acc2788049b12ecda4b962dfdde9f0b6ed4fed Parents: a8238f9 Author: Thomas D'Silva <tdsi...@salesforce.com> Authored: Fri Dec 4 12:09:04 2015 -0800 Committer: Thomas D'Silva <tdsi...@salesforce.com> Committed: Mon Dec 7 12:04:59 2015 -0800 ---------------------------------------------------------------------- .../phoenix/end2end/AlterTableWithViewsIT.java | 48 +++++++++++++++++++- .../coprocessor/MetaDataEndpointImpl.java | 43 +++++++++++------- 2 files changed, 73 insertions(+), 18 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/93acc278/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 3f311ea..e3d78ea 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 @@ -34,9 +34,11 @@ import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.List; +import java.util.Map; import java.util.Properties; import org.apache.hadoop.hbase.HTableDescriptor; +import org.apache.hadoop.hbase.client.HTableInterface; import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.compile.QueryPlan; import org.apache.phoenix.exception.SQLExceptionCode; @@ -44,19 +46,32 @@ import org.apache.phoenix.jdbc.PhoenixConnection; import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData; import org.apache.phoenix.jdbc.PhoenixStatement; import org.apache.phoenix.query.QueryConstants; +import org.apache.phoenix.query.QueryServices; import org.apache.phoenix.schema.PColumn; import org.apache.phoenix.schema.PTable; import org.apache.phoenix.schema.PTableKey; import org.apache.phoenix.schema.PTableType; import org.apache.phoenix.util.IndexUtil; import org.apache.phoenix.util.PhoenixRuntime; +import org.apache.phoenix.util.ReadOnlyProps; import org.apache.phoenix.util.SchemaUtil; -import org.junit.Assert; +import org.junit.BeforeClass; import org.junit.Test; +import co.cask.tephra.hbase11.coprocessor.TransactionProcessor; + import com.google.common.base.Objects; +import com.google.common.collect.Maps; public class AlterTableWithViewsIT extends BaseHBaseManagedTimeIT { + + @BeforeClass + @Shadower(classBeingShadowed = BaseHBaseManagedTimeIT.class) + public static void doSetup() throws Exception { + Map<String,String> props = Maps.newHashMapWithExpectedSize(1); + props.put(QueryServices.TRANSACTIONS_ENABLED, Boolean.toString(true)); + setUpTestDriver(new ReadOnlyProps(props.entrySet().iterator())); + } @Test public void testAddNewColumnsToBaseTableWithViews() throws Exception { @@ -1096,6 +1111,37 @@ public class AlterTableWithViewsIT extends BaseHBaseManagedTimeIT { } } + @Test + public void testMakeBaseTableTransactional() throws Exception { + try (Connection conn = DriverManager.getConnection(getUrl())) { + conn.createStatement().execute("CREATE TABLE IF NOT EXISTS TABLEWITHVIEW (" + + " ID char(1) NOT NULL," + + " COL1 integer NOT NULL," + + " COL2 bigint NOT NULL," + + " CONSTRAINT NAME_PK PRIMARY KEY (ID, COL1, COL2)" + + " )"); + assertTableDefinition(conn, "TABLEWITHVIEW", PTableType.TABLE, null, 0, 3, QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT, "ID", "COL1", "COL2"); + + conn.createStatement().execute("CREATE VIEW VIEWOFTABLE ( VIEW_COL1 DECIMAL(10,2), VIEW_COL2 VARCHAR ) AS SELECT * FROM TABLEWITHVIEW"); + assertTableDefinition(conn, "VIEWOFTABLE", PTableType.VIEW, "TABLEWITHVIEW", 0, 5, 3, "ID", "COL1", "COL2", "VIEW_COL1", "VIEW_COL2"); + + HTableInterface htable = conn.unwrap(PhoenixConnection.class).getQueryServices().getTable(Bytes.toBytes("TABLEWITHVIEW")); + assertFalse(htable.getTableDescriptor().getCoprocessors().contains(TransactionProcessor.class.getName())); + assertFalse(conn.unwrap(PhoenixConnection.class).getTable(new PTableKey(null, "TABLEWITHVIEW")).isTransactional()); + assertFalse(conn.unwrap(PhoenixConnection.class).getTable(new PTableKey(null, "VIEWOFTABLE")).isTransactional()); + + // make the base table transactional + conn.createStatement().execute("ALTER TABLE TABLEWITHVIEW SET TRANSACTIONAL=true"); + // query the view to force the table cache to be updated + conn.createStatement().execute("SELECT * FROM VIEWOFTABLE"); + htable = conn.unwrap(PhoenixConnection.class).getQueryServices().getTable(Bytes.toBytes("TABLEWITHVIEW")); + assertTrue(htable.getTableDescriptor().getCoprocessors().contains(TransactionProcessor.class.getName())); + assertTrue(conn.unwrap(PhoenixConnection.class).getTable(new PTableKey(null, "TABLEWITHVIEW")).isTransactional()); + assertTrue(conn.unwrap(PhoenixConnection.class).getTable(new PTableKey(null, "VIEWOFTABLE")).isTransactional()); + } + + } + private static long getTableSequenceNumber(PhoenixConnection conn, String tableName) throws SQLException { PTable table = conn.getTable(new PTableKey(conn.getTenantId(), SchemaUtil.normalizeIdentifier(tableName))); return table.getSequenceNumber(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/93acc278/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 7c80f23..f997149 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 @@ -1805,7 +1805,22 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso return columnKey; } - MetaDataMutationResult addRowsToChildViews(PTable basePhysicalTable, List<Mutation> tableMetadata, List<Mutation> mutationsForAddingColumnsToViews, byte[] schemaName, byte[] tableName, + private boolean switchAttribute(PTable table, boolean currAttribute, List<Mutation> tableMetaData, byte[] attrQualifier) { + for (Mutation m : tableMetaData) { + if (m instanceof Put) { + Put p = (Put)m; + List<Cell> cells = p.get(TABLE_FAMILY_BYTES, attrQualifier); + if (cells != null && cells.size() > 0) { + Cell cell = cells.get(0); + boolean newAttribute = (boolean)PBoolean.INSTANCE.toObject(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()); + return currAttribute != newAttribute; + } + } + } + return false; + } + + private MetaDataMutationResult addRowsToChildViews(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()); @@ -2043,6 +2058,15 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso if (view.rowKeyOrderOptimizable()) { UpgradeUtil.addRowKeyOrderOptimizableCell(mutationsForAddingColumnsToViews, viewKey, clientTimeStamp); } + + // if switching from from non tx to tx + if (!basePhysicalTable.isTransactional() && switchAttribute(basePhysicalTable, basePhysicalTable.isTransactional(), tableMetadata, TRANSACTIONAL_BYTES)) { + invalidateList.add(new ImmutableBytesPtr(viewKey)); + Put put = new Put(viewKey); + put.add(PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES, + TRANSACTIONAL_BYTES, clientTimeStamp, PBoolean.INSTANCE.toBytes(true)); + mutationsForAddingColumnsToViews.add(put); + } } return null; } @@ -2267,7 +2291,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso if (!childViewsResult.allViewsInSingleRegion() || table.getBaseColumnCount() == 0 || !request.hasClientVersion() - || switchTenancy(table, tableMetaData)) { + || switchAttribute(table, table.isMultiTenant(), tableMetaData, MULTI_TENANT_BYTES)) { return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null); } else { @@ -2354,21 +2378,6 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso tableMetaData.addAll(mutationsForAddingColumnsToViews); return null; } - - private boolean switchTenancy(PTable table, List<Mutation> tableMetaData) { - for (Mutation m : tableMetaData) { - if (m instanceof Put) { - Put p = (Put)m; - List<Cell> cells = p.get(TABLE_FAMILY_BYTES, MULTI_TENANT_BYTES); - if (cells != null && cells.size() > 0) { - Cell cell = cells.get(0); - boolean isMutlitenantProp = (boolean)PBoolean.INSTANCE.toObject(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()); - return table.isMultiTenant() != isMutlitenantProp; - } - } - } - return false; - } }); if (result != null) { done.run(MetaDataMutationResult.toProto(result));