Repository: phoenix Updated Branches: refs/heads/txn 995e352c6 -> 8119bee57
Store whether or not a table is transactional in SYSTEM.CATALOG instead of in HTableDescriptor Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/8119bee5 Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/8119bee5 Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/8119bee5 Branch: refs/heads/txn Commit: 8119bee5787dc2973d9a1ea34a577984842fbab5 Parents: 995e352 Author: James Taylor <[email protected]> Authored: Wed Mar 11 16:24:19 2015 -0700 Committer: James Taylor <[email protected]> Committed: Wed Mar 11 16:24:19 2015 -0700 ---------------------------------------------------------------------- .../apache/phoenix/end2end/AlterTableIT.java | 20 ++- .../apache/phoenix/compile/FromCompiler.java | 4 +- .../apache/phoenix/compile/JoinCompiler.java | 2 +- .../compile/TupleProjectionCompiler.java | 6 +- .../coprocessor/MetaDataEndpointImpl.java | 8 +- .../coprocessor/generated/PTableProtos.java | 103 +++++++++++- .../phoenix/exception/SQLExceptionCode.java | 4 + .../apache/phoenix/execute/MutationState.java | 12 +- .../phoenix/iterate/TableResultIterator.java | 10 +- .../query/ConnectionQueryServicesImpl.java | 45 +++--- .../org/apache/phoenix/query/HTableFactory.java | 6 - .../apache/phoenix/query/QueryConstants.java | 6 +- .../org/apache/phoenix/query/QueryServices.java | 1 + .../phoenix/query/QueryServicesOptions.java | 4 +- .../apache/phoenix/schema/DelegateTable.java | 5 + .../apache/phoenix/schema/MetaDataClient.java | 156 +++++++++++-------- .../java/org/apache/phoenix/schema/PTable.java | 1 + .../org/apache/phoenix/schema/PTableImpl.java | 39 +++-- .../apache/phoenix/schema/TableProperty.java | 5 +- .../org/apache/phoenix/util/MetaDataUtil.java | 15 +- .../org/apache/phoenix/util/SchemaUtil.java | 23 +-- .../phoenix/compile/QueryCompilerTest.java | 2 +- phoenix-protocol/src/main/PTable.proto | 1 + 23 files changed, 324 insertions(+), 154 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/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 9c0171f..9e7a4a9 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 @@ -38,7 +38,6 @@ import java.util.Collections; import java.util.Map; import java.util.Properties; -import co.cask.tephra.hbase98.TransactionAwareHTable; import co.cask.tephra.hbase98.coprocessor.TransactionProcessor; import org.apache.hadoop.hbase.HColumnDescriptor; @@ -55,7 +54,6 @@ import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData; import org.apache.phoenix.query.QueryConstants; import org.apache.phoenix.schema.PTable; import org.apache.phoenix.schema.PTableKey; -import org.apache.phoenix.schema.TableAlreadyExistsException; import org.apache.phoenix.schema.TableNotFoundException; import org.apache.phoenix.util.IndexUtil; import org.apache.phoenix.util.PhoenixRuntime; @@ -2019,9 +2017,9 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT { String ddl = "CREATE TABLE TEST_TRANSACTIONAL_TABLE (k varchar primary key) transactional=true"; conn.createStatement().execute(ddl); PhoenixConnection pconn = conn.unwrap(PhoenixConnection.class); + PTable table = pconn.getMetaDataCache().getTable(new PTableKey(null, "TEST_TRANSACTIONAL_TABLE")); HTableInterface htable = pconn.getQueryServices().getTable(Bytes.toBytes("TEST_TRANSACTIONAL_TABLE")); - assertTrue(SchemaUtil.isTransactional(htable.getTableDescriptor())); - assertTrue(htable instanceof TransactionAwareHTable); + assertTrue(table.isTransactional()); assertTrue(htable.getTableDescriptor().getCoprocessors().contains(TransactionProcessor.class.getName())); HBaseAdmin admin = pconn.getQueryServices().getAdmin(); @@ -2032,15 +2030,15 @@ public class AlterTableIT extends BaseOwnClusterHBaseManagedTimeIT { ddl = "CREATE TABLE TXN_TEST_EXISTING (k varchar primary key) transactional=true"; conn.createStatement().execute(ddl); fail(); - } catch (TableAlreadyExistsException e) { + } catch (SQLException e) { + assertEquals(SQLExceptionCode.MAY_NOT_MAP_TO_EXISTING_TABLE_AS_TRANSACTIONAL.getErrorCode(), e.getErrorCode()); } - // stays transactional + // Should be ok, as HBase metadata should match existing metadata. ddl = "CREATE TABLE IF NOT EXISTS TEST_TRANSACTIONAL_TABLE (k varchar primary key)"; conn.createStatement().execute(ddl); - assertTrue(SchemaUtil.isTransactional(pconn.getQueryServices().getTable(Bytes.toBytes("TEST_TRANSACTIONAL_TABLE")).getTableDescriptor())); - // stays non transactional - ddl = "CREATE TABLE IF NOT EXISTS TXN_TEST_EXISTING (k varchar primary key) transactional=true"; - conn.createStatement().execute(ddl); - assertFalse(SchemaUtil.isTransactional(pconn.getQueryServices().getTable(Bytes.toBytes("TXN_TEST_EXISTING")).getTableDescriptor())); + table = pconn.getMetaDataCache().getTable(new PTableKey(null, "TEST_TRANSACTIONAL_TABLE")); + htable = pconn.getQueryServices().getTable(Bytes.toBytes("TEST_TRANSACTIONAL_TABLE")); + assertTrue(table.isTransactional()); + assertTrue(htable.getTableDescriptor().getCoprocessors().contains(TransactionProcessor.class.getName())); } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java index a57250e..e1f64f3 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java @@ -65,6 +65,7 @@ import org.apache.phoenix.schema.PColumnImpl; 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.PTableImpl; import org.apache.phoenix.schema.PTableKey; import org.apache.phoenix.schema.PTableType; @@ -72,7 +73,6 @@ import org.apache.phoenix.schema.ProjectedColumn; import org.apache.phoenix.schema.SortOrder; import org.apache.phoenix.schema.TableNotFoundException; import org.apache.phoenix.schema.TableRef; -import org.apache.phoenix.schema.PTable.IndexType; import org.apache.phoenix.util.Closeables; import org.apache.phoenix.util.IndexUtil; import org.apache.phoenix.util.LogUtil; @@ -485,7 +485,7 @@ public class FromCompiler { PTableType.SUBQUERY, null, MetaDataProtocol.MIN_TABLE_TIMESTAMP, PTable.INITIAL_SEQ_NUM, null, null, columns, null, null, Collections.<PTable>emptyList(), false, Collections.<PName>emptyList(), null, null, false, false, false, null, - null, null); + null, null, false); String alias = subselectNode.getAlias(); TableRef tableRef = new TableRef(alias, t, MetaDataProtocol.MIN_TABLE_TIMESTAMP, false); http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java index 98b7edb..daec761 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java @@ -1297,7 +1297,7 @@ public class JoinCompiler { return PTableImpl.makePTable(left.getTenantId(), left.getSchemaName(), PNameFactory.newName(SchemaUtil.getTableName(left.getName().getString(), right.getName().getString())), left.getType(), left.getIndexState(), left.getTimeStamp(), left.getSequenceNumber(), left.getPKName(), left.getBucketNum(), merged, - left.getParentSchemaName(), left.getParentTableName(), left.getIndexes(), left.isImmutableRows(), Collections.<PName>emptyList(), null, null, PTable.DEFAULT_DISABLE_WAL, left.isMultiTenant(), left.getStoreNulls(), left.getViewType(), left.getViewIndexId(), left.getIndexType()); + left.getParentSchemaName(), left.getParentTableName(), left.getIndexes(), left.isImmutableRows(), Collections.<PName>emptyList(), null, null, PTable.DEFAULT_DISABLE_WAL, left.isMultiTenant(), left.getStoreNulls(), left.getViewType(), left.getViewIndexId(), left.getIndexType(), left.isTransactional()); } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java index 72e2a26..b41107b 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java @@ -43,11 +43,11 @@ import org.apache.phoenix.schema.PColumn; 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.PTableImpl; import org.apache.phoenix.schema.PTableType; import org.apache.phoenix.schema.ProjectedColumn; import org.apache.phoenix.schema.TableRef; -import org.apache.phoenix.schema.PTable.IndexType; import org.apache.phoenix.util.IndexUtil; import org.apache.phoenix.util.SchemaUtil; @@ -151,7 +151,7 @@ public class TupleProjectionCompiler { table.getBucketNum(), projectedColumns, table.getParentSchemaName(), table.getParentName(), table.getIndexes(), table.isImmutableRows(), Collections.<PName>emptyList(), null, null, table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), - table.getIndexType()); + table.getIndexType(), table.isTransactional()); } public static PTable createProjectedTable(TableRef tableRef, List<ColumnRef> sourceColumnRefs, boolean retainPKColumns) throws SQLException { @@ -178,7 +178,7 @@ public class TupleProjectionCompiler { retainPKColumns ? table.getBucketNum() : null, projectedColumns, null, null, Collections.<PTable>emptyList(), table.isImmutableRows(), Collections.<PName>emptyList(), null, null, table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), - null); + null, table.isTransactional()); } // For extracting column references from single select statement http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/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 e234498..1a412c6 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 @@ -47,6 +47,7 @@ import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_NAME_INDEX; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_SEQ_NUM_BYTES; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_TYPE_BYTES; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TENANT_ID_INDEX; +import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TRANSACTIONAL_BYTES; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.VIEW_CONSTANT_BYTES; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.VIEW_INDEX_ID_BYTES; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.VIEW_STATEMENT_BYTES; @@ -196,6 +197,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso private static final KeyValue INDEX_TYPE_KV = KeyValue.createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, INDEX_TYPE_BYTES); private static final KeyValue INDEX_DISABLE_TIMESTAMP_KV = KeyValue.createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, INDEX_DISABLE_TIMESTAMP_BYTES); private static final KeyValue STORE_NULLS_KV = KeyValue.createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, STORE_NULLS_BYTES); + private static final KeyValue TRANSACTIONAL_KV = KeyValue.createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, TRANSACTIONAL_BYTES); private static final KeyValue EMPTY_KEYVALUE_KV = KeyValue.createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, QueryConstants.EMPTY_COLUMN_BYTES); private static final List<KeyValue> TABLE_KV_COLUMNS = Arrays.<KeyValue>asList( EMPTY_KEYVALUE_KV, @@ -215,6 +217,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso VIEW_INDEX_ID_KV, INDEX_TYPE_KV, INDEX_DISABLE_TIMESTAMP_KV, + TRANSACTIONAL_KV, STORE_NULLS_KV ); static { @@ -236,6 +239,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso private static final int VIEW_INDEX_ID_INDEX = TABLE_KV_COLUMNS.indexOf(VIEW_INDEX_ID_KV); private static final int INDEX_TYPE_INDEX = TABLE_KV_COLUMNS.indexOf(INDEX_TYPE_KV); private static final int STORE_NULLS_INDEX = TABLE_KV_COLUMNS.indexOf(STORE_NULLS_KV); + private static final int TRANSACTIONAL_INDEX = TABLE_KV_COLUMNS.indexOf(TRANSACTIONAL_KV); // KeyValues for Column private static final KeyValue DECIMAL_DIGITS_KV = KeyValue.createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, DECIMAL_DIGITS_BYTES); @@ -592,6 +596,8 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso boolean multiTenant = multiTenantKv == null ? false : Boolean.TRUE.equals(PBoolean.INSTANCE.toObject(multiTenantKv.getValueArray(), multiTenantKv.getValueOffset(), multiTenantKv.getValueLength())); Cell storeNullsKv = tableKeyValues[STORE_NULLS_INDEX]; boolean storeNulls = storeNullsKv == null ? false : Boolean.TRUE.equals(PBoolean.INSTANCE.toObject(storeNullsKv.getValueArray(), storeNullsKv.getValueOffset(), storeNullsKv.getValueLength())); + Cell transactionalKv = tableKeyValues[TRANSACTIONAL_INDEX]; + boolean transactional = transactionalKv == null ? false : Boolean.TRUE.equals(PBoolean.INSTANCE.toObject(transactionalKv.getValueArray(), transactionalKv.getValueOffset(), transactionalKv.getValueLength())); Cell viewTypeKv = tableKeyValues[VIEW_TYPE_INDEX]; ViewType viewType = viewTypeKv == null ? null : ViewType.fromSerializedValue(viewTypeKv.getValueArray()[viewTypeKv.getValueOffset()]); Cell viewIndexIdKv = tableKeyValues[VIEW_INDEX_ID_INDEX]; @@ -643,7 +649,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso return PTableImpl.makePTable(tenantId, schemaName, tableName, tableType, indexState, timeStamp, tableSeqNum, pkName, saltBucketNum, columns, tableType == INDEX ? schemaName : null, tableType == INDEX ? dataTableName : null, indexes, isImmutableRows, physicalTables, defaultFamilyName, viewStatement, - disableWAL, multiTenant, storeNulls, viewType, viewIndexId, indexType, stats); + disableWAL, multiTenant, storeNulls, viewType, viewIndexId, indexType, transactional, stats); } private PTable buildDeletedTable(byte[] key, ImmutableBytesPtr cacheKey, HRegion region, http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PTableProtos.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PTableProtos.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PTableProtos.java index 7d389ac..02b1fa3 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PTableProtos.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PTableProtos.java @@ -3108,6 +3108,16 @@ public final class PTableProtos { * <code>optional bool storeNulls = 24;</code> */ boolean getStoreNulls(); + + // optional bool transactional = 25; + /** + * <code>optional bool transactional = 25;</code> + */ + boolean hasTransactional(); + /** + * <code>optional bool transactional = 25;</code> + */ + boolean getTransactional(); } /** * Protobuf type {@code PTable} @@ -3298,6 +3308,11 @@ public final class PTableProtos { storeNulls_ = input.readBool(); break; } + case 200: { + bitField0_ |= 0x00100000; + transactional_ = input.readBool(); + break; + } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { @@ -3828,6 +3843,22 @@ public final class PTableProtos { return storeNulls_; } + // optional bool transactional = 25; + public static final int TRANSACTIONAL_FIELD_NUMBER = 25; + private boolean transactional_; + /** + * <code>optional bool transactional = 25;</code> + */ + public boolean hasTransactional() { + return ((bitField0_ & 0x00100000) == 0x00100000); + } + /** + * <code>optional bool transactional = 25;</code> + */ + public boolean getTransactional() { + return transactional_; + } + private void initFields() { schemaNameBytes_ = com.google.protobuf.ByteString.EMPTY; tableNameBytes_ = com.google.protobuf.ByteString.EMPTY; @@ -3853,6 +3884,7 @@ public final class PTableProtos { indexType_ = com.google.protobuf.ByteString.EMPTY; statsTimeStamp_ = 0L; storeNulls_ = false; + transactional_ = false; } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { @@ -3992,6 +4024,9 @@ public final class PTableProtos { if (((bitField0_ & 0x00080000) == 0x00080000)) { output.writeBool(24, storeNulls_); } + if (((bitField0_ & 0x00100000) == 0x00100000)) { + output.writeBool(25, transactional_); + } getUnknownFields().writeTo(output); } @@ -4102,6 +4137,10 @@ public final class PTableProtos { size += com.google.protobuf.CodedOutputStream .computeBoolSize(24, storeNulls_); } + if (((bitField0_ & 0x00100000) == 0x00100000)) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(25, transactional_); + } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; return size; @@ -4233,6 +4272,11 @@ public final class PTableProtos { result = result && (getStoreNulls() == other.getStoreNulls()); } + result = result && (hasTransactional() == other.hasTransactional()); + if (hasTransactional()) { + result = result && (getTransactional() + == other.getTransactional()); + } result = result && getUnknownFields().equals(other.getUnknownFields()); return result; @@ -4342,6 +4386,10 @@ public final class PTableProtos { hash = (37 * hash) + STORENULLS_FIELD_NUMBER; hash = (53 * hash) + hashBoolean(getStoreNulls()); } + if (hasTransactional()) { + hash = (37 * hash) + TRANSACTIONAL_FIELD_NUMBER; + hash = (53 * hash) + hashBoolean(getTransactional()); + } hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -4514,6 +4562,8 @@ public final class PTableProtos { bitField0_ = (bitField0_ & ~0x00400000); storeNulls_ = false; bitField0_ = (bitField0_ & ~0x00800000); + transactional_ = false; + bitField0_ = (bitField0_ & ~0x01000000); return this; } @@ -4654,6 +4704,10 @@ public final class PTableProtos { to_bitField0_ |= 0x00080000; } result.storeNulls_ = storeNulls_; + if (((from_bitField0_ & 0x01000000) == 0x01000000)) { + to_bitField0_ |= 0x00100000; + } + result.transactional_ = transactional_; result.bitField0_ = to_bitField0_; onBuilt(); return result; @@ -4820,6 +4874,9 @@ public final class PTableProtos { if (other.hasStoreNulls()) { setStoreNulls(other.getStoreNulls()); } + if (other.hasTransactional()) { + setTransactional(other.getTransactional()); + } this.mergeUnknownFields(other.getUnknownFields()); return this; } @@ -6424,6 +6481,39 @@ public final class PTableProtos { return this; } + // optional bool transactional = 25; + private boolean transactional_ ; + /** + * <code>optional bool transactional = 25;</code> + */ + public boolean hasTransactional() { + return ((bitField0_ & 0x01000000) == 0x01000000); + } + /** + * <code>optional bool transactional = 25;</code> + */ + public boolean getTransactional() { + return transactional_; + } + /** + * <code>optional bool transactional = 25;</code> + */ + public Builder setTransactional(boolean value) { + bitField0_ |= 0x01000000; + transactional_ = value; + onChanged(); + return this; + } + /** + * <code>optional bool transactional = 25;</code> + */ + public Builder clearTransactional() { + bitField0_ = (bitField0_ & ~0x01000000); + transactional_ = false; + onChanged(); + return this; + } + // @@protoc_insertion_point(builder_scope:PTable) } @@ -6470,7 +6560,7 @@ public final class PTableProtos { "values\030\002 \003(\014\022\033\n\023guidePostsByteCount\030\003 \001(" + "\003\022\025\n\rkeyBytesCount\030\004 \001(\003\022\027\n\017guidePostsCo", "unt\030\005 \001(\005\022!\n\013pGuidePosts\030\006 \001(\0132\014.PGuideP" + - "osts\"\266\004\n\006PTable\022\027\n\017schemaNameBytes\030\001 \002(\014" + + "osts\"\315\004\n\006PTable\022\027\n\017schemaNameBytes\030\001 \002(\014" + "\022\026\n\016tableNameBytes\030\002 \002(\014\022\036\n\ttableType\030\003 " + "\002(\0162\013.PTableType\022\022\n\nindexState\030\004 \001(\t\022\026\n\016" + "sequenceNumber\030\005 \002(\003\022\021\n\ttimeStamp\030\006 \002(\003\022" + @@ -6484,10 +6574,11 @@ public final class PTableProtos { "nt\030\022 \001(\014\022\025\n\rphysicalNames\030\023 \003(\014\022\020\n\010tenan" + "tId\030\024 \001(\014\022\023\n\013viewIndexId\030\025 \001(\005\022\021\n\tindexT" + "ype\030\026 \001(\014\022\026\n\016statsTimeStamp\030\027 \001(\003\022\022\n\nsto" + - "reNulls\030\030 \001(\010*A\n\nPTableType\022\n\n\006SYSTEM\020\000\022" + - "\010\n\004USER\020\001\022\010\n\004VIEW\020\002\022\t\n\005INDEX\020\003\022\010\n\004JOIN\020\004" + - "B@\n(org.apache.phoenix.coprocessor.gener" + - "atedB\014PTableProtosH\001\210\001\001\240\001\001" + "reNulls\030\030 \001(\010\022\025\n\rtransactional\030\031 \001(\010*A\n\n" + + "PTableType\022\n\n\006SYSTEM\020\000\022\010\n\004USER\020\001\022\010\n\004VIEW" + + "\020\002\022\t\n\005INDEX\020\003\022\010\n\004JOIN\020\004B@\n(org.apache.ph" + + "oenix.coprocessor.generatedB\014PTableProto" + + "sH\001\210\001\001\240\001\001" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -6511,7 +6602,7 @@ public final class PTableProtos { internal_static_PTable_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_PTable_descriptor, - new java.lang.String[] { "SchemaNameBytes", "TableNameBytes", "TableType", "IndexState", "SequenceNumber", "TimeStamp", "PkNameBytes", "BucketNum", "Columns", "Indexes", "IsImmutableRows", "GuidePosts", "DataTableNameBytes", "DefaultFamilyName", "DisableWAL", "MultiTenant", "ViewType", "ViewStatement", "PhysicalNames", "TenantId", "ViewIndexId", "IndexType", "StatsTimeStamp", "StoreNulls", }); + new java.lang.String[] { "SchemaNameBytes", "TableNameBytes", "TableType", "IndexState", "SequenceNumber", "TimeStamp", "PkNameBytes", "BucketNum", "Columns", "Indexes", "IsImmutableRows", "GuidePosts", "DataTableNameBytes", "DefaultFamilyName", "DisableWAL", "MultiTenant", "ViewType", "ViewStatement", "PhysicalNames", "TenantId", "ViewIndexId", "IndexType", "StatsTimeStamp", "StoreNulls", "Transactional", }); return null; } }; http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java b/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java index f4b4f98..207f80b 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java @@ -240,6 +240,10 @@ public enum SQLExceptionCode { NO_LOCAL_INDEXES(1054, "43A11", "Local secondary indexes are not supported for HBase versions " + MetaDataUtil.decodeHBaseVersionAsString(PhoenixDatabaseMetaData.MIN_LOCAL_SI_VERSION_DISALLOW) + " through " + MetaDataUtil.decodeHBaseVersionAsString(PhoenixDatabaseMetaData.MAX_LOCAL_SI_VERSION_DISALLOW) + " inclusive."), UNALLOWED_LOCAL_INDEXES(1055, "43A12", "Local secondary indexes are configured to not be allowed."), + + DEFAULT_COLUMN_FAMILY_ON_SHARED_TABLE(1056, "43A13", "Default column family not allowed on VIEW or shared INDEX"), + ONLY_TABLE_MAY_BE_DECLARED_TRANSACTIONAL(1070, "44A01", "Only tables may be declared as transactional"), + MAY_NOT_MAP_TO_EXISTING_TABLE_AS_TRANSACTIONAL(1071, "44A02", "An existing HBase table may not be mapped to as a transactional table"), /** Sequence related */ SEQUENCE_ALREADY_EXIST(1200, "42Z00", "Sequence already exists.", new Factory() { http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/phoenix-core/src/main/java/org/apache/phoenix/execute/MutationState.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/MutationState.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/MutationState.java index b98d705..4270ef9 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/execute/MutationState.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/MutationState.java @@ -17,6 +17,10 @@ */ package org.apache.phoenix.execute; +import static org.apache.phoenix.monitoring.PhoenixMetrics.SizeMetric.MUTATION_BATCH_SIZE; +import static org.apache.phoenix.monitoring.PhoenixMetrics.SizeMetric.MUTATION_BYTES; +import static org.apache.phoenix.monitoring.PhoenixMetrics.SizeMetric.MUTATION_COMMIT_TIME; + import java.io.IOException; import java.sql.SQLException; import java.util.Collections; @@ -24,6 +28,8 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import co.cask.tephra.hbase98.TransactionAwareHTable; + import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.client.HTableInterface; import org.apache.hadoop.hbase.client.Mutation; @@ -62,9 +68,6 @@ import org.slf4j.LoggerFactory; import com.google.common.collect.Iterators; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import static org.apache.phoenix.monitoring.PhoenixMetrics.SizeMetric.MUTATION_BYTES; -import static org.apache.phoenix.monitoring.PhoenixMetrics.SizeMetric.MUTATION_BATCH_SIZE; -import static org.apache.phoenix.monitoring.PhoenixMetrics.SizeMetric.MUTATION_COMMIT_TIME; /** * @@ -414,6 +417,9 @@ public class MutationState implements SQLCloseable { SQLException sqlE = null; HTableInterface hTable = connection.getQueryServices().getTable(htableName); + if (table.isTransactional()) { + hTable = new TransactionAwareHTable(hTable); + } try { logMutationSize(hTable, mutations, connection); MUTATION_BATCH_SIZE.update(mutations.size()); http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/phoenix-core/src/main/java/org/apache/phoenix/iterate/TableResultIterator.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/TableResultIterator.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/TableResultIterator.java index ea13dfd..91aa573 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/TableResultIterator.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/TableResultIterator.java @@ -21,9 +21,12 @@ import java.io.IOException; import java.sql.SQLException; import java.util.List; +import co.cask.tephra.hbase98.TransactionAwareHTable; + import org.apache.hadoop.hbase.client.HTableInterface; import org.apache.hadoop.hbase.client.Scan; import org.apache.phoenix.compile.StatementContext; +import org.apache.phoenix.schema.PTable; import org.apache.phoenix.schema.TableRef; import org.apache.phoenix.schema.tuple.Tuple; import org.apache.phoenix.util.Closeables; @@ -80,7 +83,12 @@ public class TableResultIterator extends ExplainTable implements ResultIterator public TableResultIterator(StatementContext context, TableRef tableRef, Scan scan, ScannerCreation creationMode) throws SQLException { super(context, tableRef); this.scan = scan; - htable = context.getConnection().getQueryServices().getTable(tableRef.getTable().getPhysicalName().getBytes()); + PTable table = tableRef.getTable(); + HTableInterface htable = context.getConnection().getQueryServices().getTable(table.getPhysicalName().getBytes()); + if (table.isTransactional()) { + htable = new TransactionAwareHTable(htable); + } + this.htable = htable; if (creationMode == ScannerCreation.IMMEDIATE) { getDelegate(false); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/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 8a8e072..f005c3d 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 @@ -606,8 +606,10 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement new HTableDescriptor(TableName.valueOf(tableName)); for (Entry<String,Object> entry : tableProps.entrySet()) { String key = entry.getKey(); - Object value = entry.getValue(); - tableDescriptor.setValue(key, value == null ? null : value.toString()); + if (!TableProperty.isPhoenixTableProperty(key)) { + Object value = entry.getValue(); + tableDescriptor.setValue(key, value == null ? null : value.toString()); + } } if (families.isEmpty()) { if (tableType != PTableType.VIEW) { @@ -638,11 +640,11 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement } } } - addCoprocessors(tableName, tableDescriptor, tableType); + addCoprocessors(tableName, tableDescriptor, tableType, tableProps); return tableDescriptor; } - private void addCoprocessors(byte[] tableName, HTableDescriptor descriptor, PTableType tableType) throws SQLException { + private void addCoprocessors(byte[] tableName, HTableDescriptor descriptor, PTableType tableType, Map<String,Object> tableProps) throws SQLException { // The phoenix jar must be available on HBase classpath int priority = props.getInt(QueryServices.COPROCESSOR_PRIORITY_ATTRIB, QueryServicesOptions.DEFAULT_COPROCESSOR_PRIORITY); try { @@ -705,7 +707,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement } } - if (SchemaUtil.isTransactional(descriptor) && !descriptor.hasCoprocessor(TransactionProcessor.class.getName())) { + if (Boolean.TRUE.equals(tableProps.get(TableProperty.TRANSACTIONAL.name())) && !descriptor.hasCoprocessor(TransactionProcessor.class.getName())) { descriptor.addCoprocessor(TransactionProcessor.class.getName(), null, priority - 10, null); } } catch (IOException e) { @@ -863,8 +865,11 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement checkClientServerCompatibility(); } - if (!modifyExistingMetaData || existingDesc.equals(newDesc)) { - return existingDesc; + if (!modifyExistingMetaData) { + return existingDesc; // Caller already knows that no metadata was changed + } + if (existingDesc.equals(newDesc)) { + return null; // Indicate that no metadata was changed } // Don't allow TRANSACTIONAL attribute to change, as we may have issued @@ -1209,6 +1214,17 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement // For views this will ensure that metadata already exists // For tables and indexes, this will create the metadata if it doesn't already exist tableDescriptor = ensureTableCreated(tableName, tableType, tableProps, families, splits, true); + // This means the HTable already existed and is transactional which is an error case for now, + // as the timestamps are likely not scaled and the table may have delete markers (which isn't + // handled by Tephra currently). It's possible that we could allow this, but only allow queries + // after a major compaction and some conversion process runs. + ImmutableBytesWritable ptr = new ImmutableBytesWritable(); + boolean isTransactional = MetaDataUtil.isTransactional(m, kvBuilder, ptr); + if (tableDescriptor != null && isTransactional) { + throw new SQLExceptionInfo.Builder(SQLExceptionCode.MAY_NOT_MAP_TO_EXISTING_TABLE_AS_TRANSACTIONAL) + .setSchemaName(Bytes.toString(schemaBytes)).setTableName(Bytes.toString(tableBytes)) + .build().buildException(); + } } ImmutableBytesWritable ptr = new ImmutableBytesWritable(); if (tableType == PTableType.INDEX) { // Index on view @@ -1263,12 +1279,6 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement return rpcCallback.get(); } }); - // This means the HTable already existed and is transactional which is an - // error case unless IF NOT EXISTS was supplied (which the caller will check). - Object isTransactional = tableProps.get(PhoenixDatabaseMetaData.TRANSACTIONAL); - if (tableDescriptor != null && Boolean.TRUE.equals(isTransactional) != SchemaUtil.isTransactional(tableDescriptor)) { - return new MetaDataMutationResult(MutationCode.TABLE_ALREADY_EXISTS, result.getMutationTime(), result.getTable()); - } return result; } @@ -1470,13 +1480,6 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement SQLException sqlE = null; if (tableDescriptor != null) { try { - if (SchemaUtil.hasTransactional(tableDescriptor)) { - throw new SQLExceptionInfo.Builder( - SQLExceptionCode.SET_UNSUPPORTED_PROP_ON_ALTER_TABLE) - .setMessage(PhoenixDatabaseMetaData.TRANSACTIONAL) - .setSchemaName(table.getSchemaName().getString()) - .setTableName(table.getTableName().getString()).build().buildException(); - } boolean pollingNotNeeded = (!tableProps.isEmpty() && families.isEmpty() && colFamiliesForPColumnsToBeAdded.isEmpty()); modifyTable(table.getPhysicalName().getBytes(), tableDescriptor, !pollingNotNeeded); } catch (IOException e) { @@ -2020,7 +2023,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement public MutationState updateData(MutationPlan plan) throws SQLException { PTable table = plan.getContext().getCurrentTable().getTable(); HTableDescriptor desc = this.getTableDescriptor(table.getPhysicalName().getBytes()); - if (SchemaUtil.isTransactional(desc)) { + if (table.isTransactional()) { return new MutationState(1, plan.getConnection()); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/phoenix-core/src/main/java/org/apache/phoenix/query/HTableFactory.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/HTableFactory.java b/phoenix-core/src/main/java/org/apache/phoenix/query/HTableFactory.java index 4e1c089..f44fb09 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/HTableFactory.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/HTableFactory.java @@ -20,11 +20,8 @@ package org.apache.phoenix.query; import java.io.IOException; import java.util.concurrent.ExecutorService; -import co.cask.tephra.hbase98.TransactionAwareHTable; - import org.apache.hadoop.hbase.client.HConnection; import org.apache.hadoop.hbase.client.HTableInterface; -import org.apache.phoenix.util.SchemaUtil; /** * Creates clients to access HBase tables. @@ -51,9 +48,6 @@ public interface HTableFactory { @Override public HTableInterface getTable(byte[] tableName, HConnection connection, ExecutorService pool) throws IOException { HTableInterface htable = connection.getTable(tableName, pool); - if (SchemaUtil.isTransactional(htable.getTableDescriptor())) { - return new TransactionAwareHTable(htable); - } return htable; } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java index 6470b72..b317d77 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java @@ -63,7 +63,6 @@ import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.PK_NAME; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.REF_GENERATION; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.REGION_NAME; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.REMARKS; -import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.STORE_NULLS; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SALT_BUCKETS; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SCOPE_CATALOG; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SCOPE_SCHEMA; @@ -76,6 +75,7 @@ import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SOURCE_DATA_TYPE; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SQL_DATA_TYPE; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SQL_DATETIME_SUB; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.START_WITH; +import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.STORE_NULLS; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_CATALOG_SCHEMA; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_CATALOG_TABLE; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_STATS_TABLE; @@ -84,6 +84,7 @@ import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_SCHEM; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_SEQ_NUM; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_TYPE; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TENANT_ID; +import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TRANSACTIONAL; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TYPE_NAME; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TYPE_SEQUENCE; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.VIEW_CONSTANT; @@ -230,7 +231,8 @@ public interface QueryConstants { IS_AUTOINCREMENT + " VARCHAR," + INDEX_TYPE + " UNSIGNED_TINYINT," + INDEX_DISABLE_TIMESTAMP + " BIGINT," + - STORE_NULLS + " BOOLEAN," + + STORE_NULLS + " BOOLEAN," + + TRANSACTIONAL + " BOOLEAN," + "CONSTRAINT " + SYSTEM_TABLE_PK_NAME + " PRIMARY KEY (" + TENANT_ID + "," + TABLE_SCHEM + "," + TABLE_NAME + "," + COLUMN_NAME + "," + COLUMN_FAMILY + "))\n" + HConstants.VERSIONS + "=" + MetaDataProtocol.DEFAULT_MAX_META_DATA_VERSIONS + ",\n" + http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java index 2eab5dd..0d2c36f 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServices.java @@ -153,6 +153,7 @@ public interface QueryServices extends SQLCloseable { public static final String DEFAULT_KEEP_DELETED_CELLS_ATTRIB = "phoenix.table.default.keep.deleted.cells"; public static final String DEFAULT_STORE_NULLS_ATTRIB = "phoenix.table.default.store.nulls"; public static final String METRICS_ENABLED = "phoenix.query.metrics.enabled"; + public static final String DEFAULT_TRANSACTIONAL_ATTRIB = "phoenix.transactions.default.enabled"; /** * Get executor service used for parallel scans http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java index 8cd740a..1e0de9d 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryServicesOptions.java @@ -41,6 +41,7 @@ import static org.apache.phoenix.query.QueryServices.MAX_SERVER_CACHE_TIME_TO_LI import static org.apache.phoenix.query.QueryServices.MAX_SERVER_METADATA_CACHE_SIZE_ATTRIB; import static org.apache.phoenix.query.QueryServices.MAX_SPOOL_TO_DISK_BYTES_ATTRIB; import static org.apache.phoenix.query.QueryServices.MAX_TENANT_MEMORY_PERC_ATTRIB; +import static org.apache.phoenix.query.QueryServices.METRICS_ENABLED; import static org.apache.phoenix.query.QueryServices.MIN_STATS_UPDATE_FREQ_MS_ATTRIB; import static org.apache.phoenix.query.QueryServices.MUTATE_BATCH_SIZE_ATTRIB; import static org.apache.phoenix.query.QueryServices.NUM_RETRIES_FOR_SCHEMA_UPDATE_CHECK; @@ -61,7 +62,6 @@ import static org.apache.phoenix.query.QueryServices.STATS_USE_CURRENT_TIME_ATTR import static org.apache.phoenix.query.QueryServices.THREAD_POOL_SIZE_ATTRIB; import static org.apache.phoenix.query.QueryServices.THREAD_TIMEOUT_MS_ATTRIB; import static org.apache.phoenix.query.QueryServices.USE_INDEXES_ATTRIB; -import static org.apache.phoenix.query.QueryServices.METRICS_ENABLED; import java.util.Map.Entry; @@ -181,8 +181,10 @@ public class QueryServicesOptions { public static final boolean DEFAULT_STORE_NULLS = false; // TODO Change this to true as part of PHOENIX-1543 + // We'll also need this for transactions to work correctly public static final boolean DEFAULT_AUTO_COMMIT = false; public static final boolean DEFAULT_IS_METRICS_ENABLED = true; + public static final boolean DEFAULT_TRANSACTIONAL = false; private final Configuration config; http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/phoenix-core/src/main/java/org/apache/phoenix/schema/DelegateTable.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/DelegateTable.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/DelegateTable.java index b719aae..89c2283 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/DelegateTable.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/DelegateTable.java @@ -236,4 +236,9 @@ public class DelegateTable implements PTable { public PName getParentSchemaName() { return delegate.getParentSchemaName(); } + + @Override + public boolean isTransactional() { + return delegate.isTransactional(); + } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/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 b2b1bc9..54a5c7e 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 @@ -58,6 +58,7 @@ import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_SCHEM; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_SEQ_NUM; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_TYPE; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TENANT_ID; +import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TRANSACTIONAL; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.VIEW_CONSTANT; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.VIEW_INDEX_ID; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.VIEW_STATEMENT; @@ -198,8 +199,9 @@ public class MetaDataClient { VIEW_TYPE + "," + VIEW_INDEX_ID + "," + INDEX_TYPE + "," + - STORE_NULLS + - ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + STORE_NULLS + "," + + TRANSACTIONAL + + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; private static final String CREATE_LINK = "UPSERT INTO " + SYSTEM_CATALOG_SCHEMA + ".\"" + SYSTEM_CATALOG_TABLE + "\"( " + TENANT_ID + "," + @@ -1204,54 +1206,58 @@ public class MetaDataClient { String tenantIdStr = tenantId == null ? null : connection.getTenantId().getString(); boolean multiTenant = false; boolean storeNulls = false; + boolean transactional = false; Integer saltBucketNum = null; String defaultFamilyName = null; boolean isImmutableRows = false; List<PName> physicalNames = Collections.emptyList(); boolean addSaltColumn = false; - if (parent != null && tableType == PTableType.INDEX) { - // Index on view - // TODO: Can we support a multi-tenant index directly on a multi-tenant - // table instead of only a view? We don't have anywhere to put the link - // from the table to the index, though. - if (indexType == IndexType.LOCAL || (parent.getType() == PTableType.VIEW && parent.getViewType() != ViewType.MAPPED)) { - PName physicalName = parent.getPhysicalName(); - saltBucketNum = parent.getBucketNum(); - addSaltColumn = (saltBucketNum != null && indexType != IndexType.LOCAL); - defaultFamilyName = parent.getDefaultFamilyName() == null ? null : parent.getDefaultFamilyName().getString(); - if (indexType == IndexType.LOCAL) { - saltBucketNum = null; - // Set physical name of local index table - physicalNames = Collections.singletonList(PNameFactory.newName(MetaDataUtil.getLocalIndexPhysicalName(physicalName.getBytes()))); - } else { - // Set physical name of view index table - physicalNames = Collections.singletonList(PNameFactory.newName(MetaDataUtil.getViewIndexPhysicalName(physicalName.getBytes()))); + if (parent != null) { + transactional = parent.isTransactional(); + storeNulls = parent.getStoreNulls(); + if (tableType == PTableType.INDEX) { + // Index on view + // TODO: Can we support a multi-tenant index directly on a multi-tenant + // table instead of only a view? We don't have anywhere to put the link + // from the table to the index, though. + if (indexType == IndexType.LOCAL || (parent.getType() == PTableType.VIEW && parent.getViewType() != ViewType.MAPPED)) { + PName physicalName = parent.getPhysicalName(); + saltBucketNum = parent.getBucketNum(); + addSaltColumn = (saltBucketNum != null && indexType != IndexType.LOCAL); + defaultFamilyName = parent.getDefaultFamilyName() == null ? null : parent.getDefaultFamilyName().getString(); + if (indexType == IndexType.LOCAL) { + saltBucketNum = null; + // Set physical name of local index table + physicalNames = Collections.singletonList(PNameFactory.newName(MetaDataUtil.getLocalIndexPhysicalName(physicalName.getBytes()))); + } else { + // Set physical name of view index table + physicalNames = Collections.singletonList(PNameFactory.newName(MetaDataUtil.getViewIndexPhysicalName(physicalName.getBytes()))); + } } + + multiTenant = parent.isMultiTenant(); + parentTableName = parent.getTableName().getString(); + // Pass through data table sequence number so we can check it hasn't changed + PreparedStatement incrementStatement = connection.prepareStatement(INCREMENT_SEQ_NUM); + incrementStatement.setString(1, connection.getTenantId() == null ? null : connection.getTenantId().getString()); + incrementStatement.setString(2, schemaName); + incrementStatement.setString(3, parentTableName); + incrementStatement.setLong(4, parent.getSequenceNumber()); + incrementStatement.execute(); + // Get list of mutations and add to table meta data that will be passed to server + // to guarantee order. This row will always end up last + tableMetaData.addAll(connection.getMutationState().toMutations().next().getSecond()); + connection.rollback(); + + // Add row linking from data table row to index table row + PreparedStatement linkStatement = connection.prepareStatement(CREATE_LINK); + linkStatement.setString(1, connection.getTenantId() == null ? null : connection.getTenantId().getString()); + linkStatement.setString(2, schemaName); + linkStatement.setString(3, parentTableName); + linkStatement.setString(4, tableName); + linkStatement.setByte(5, LinkType.INDEX_TABLE.getSerializedValue()); + linkStatement.execute(); } - - multiTenant = parent.isMultiTenant(); - storeNulls = parent.getStoreNulls(); - parentTableName = parent.getTableName().getString(); - // Pass through data table sequence number so we can check it hasn't changed - PreparedStatement incrementStatement = connection.prepareStatement(INCREMENT_SEQ_NUM); - incrementStatement.setString(1, connection.getTenantId() == null ? null : connection.getTenantId().getString()); - incrementStatement.setString(2, schemaName); - incrementStatement.setString(3, parentTableName); - incrementStatement.setLong(4, parent.getSequenceNumber()); - incrementStatement.execute(); - // Get list of mutations and add to table meta data that will be passed to server - // to guarantee order. This row will always end up last - tableMetaData.addAll(connection.getMutationState().toMutations().next().getSecond()); - connection.rollback(); - - // Add row linking from data table row to index table row - PreparedStatement linkStatement = connection.prepareStatement(CREATE_LINK); - linkStatement.setString(1, connection.getTenantId() == null ? null : connection.getTenantId().getString()); - linkStatement.setString(2, schemaName); - linkStatement.setString(3, parentTableName); - linkStatement.setString(4, tableName); - linkStatement.setByte(5, LinkType.INDEX_TABLE.getSerializedValue()); - linkStatement.execute(); } PrimaryKeyConstraint pkConstraint = statement.getPrimaryKeyConstraint(); @@ -1284,7 +1290,7 @@ public class MetaDataClient { // Although unusual, it's possible to set a mapped VIEW as having immutable rows. // This tells Phoenix that you're managing the index maintenance yourself. if (tableType != PTableType.INDEX && (tableType != PTableType.VIEW || viewType == ViewType.MAPPED)) { - Boolean isImmutableRowsProp = (Boolean) tableProps.remove(PTable.IS_IMMUTABLE_ROWS_PROP_NAME); + Boolean isImmutableRowsProp = (Boolean) tableProps.get(PTable.IS_IMMUTABLE_ROWS_PROP_NAME); if (isImmutableRowsProp == null) { isImmutableRows = connection.getQueryServices().getProps().getBoolean(QueryServices.IMMUTABLE_ROWS_ATTRIB, QueryServicesOptions.DEFAULT_IMMUTABLE_ROWS); } else { @@ -1294,7 +1300,7 @@ public class MetaDataClient { // Can't set any of these on views or shared indexes on views if (tableType != PTableType.VIEW && indexId == null) { - saltBucketNum = (Integer) tableProps.remove(PhoenixDatabaseMetaData.SALT_BUCKETS); + saltBucketNum = (Integer) tableProps.get(PhoenixDatabaseMetaData.SALT_BUCKETS); if (saltBucketNum != null) { if (saltBucketNum < 0 || saltBucketNum > SaltingUtil.MAX_BUCKET_NUM) { throw new SQLExceptionInfo.Builder(SQLExceptionCode.INVALID_BUCKET_NUM).build().buildException(); @@ -1311,35 +1317,56 @@ public class MetaDataClient { addSaltColumn = (saltBucketNum != null); } - boolean removedProp = false; // Can't set MULTI_TENANT or DEFAULT_COLUMN_FAMILY_NAME on an INDEX or a non mapped VIEW if (tableType != PTableType.INDEX && (tableType != PTableType.VIEW || viewType == ViewType.MAPPED)) { - Boolean multiTenantProp = (Boolean) tableProps.remove(PhoenixDatabaseMetaData.MULTI_TENANT); + Boolean multiTenantProp = (Boolean) tableProps.get(PhoenixDatabaseMetaData.MULTI_TENANT); multiTenant = Boolean.TRUE.equals(multiTenantProp); - defaultFamilyName = (String)tableProps.remove(PhoenixDatabaseMetaData.DEFAULT_COLUMN_FAMILY_NAME); - removedProp = (defaultFamilyName != null); + defaultFamilyName = (String)tableProps.get(PhoenixDatabaseMetaData.DEFAULT_COLUMN_FAMILY_NAME); } boolean disableWAL = false; - Boolean disableWALProp = (Boolean) tableProps.remove(PhoenixDatabaseMetaData.DISABLE_WAL); + Boolean disableWALProp = (Boolean) tableProps.get(PhoenixDatabaseMetaData.DISABLE_WAL); if (disableWALProp != null) { disableWAL = disableWALProp; } - Boolean storeNullsProp = (Boolean) tableProps.remove(PhoenixDatabaseMetaData.STORE_NULLS); - storeNulls = storeNullsProp == null - ? connection.getQueryServices().getProps().getBoolean( - QueryServices.DEFAULT_STORE_NULLS_ATTRIB, - QueryServicesOptions.DEFAULT_STORE_NULLS) - : storeNullsProp; + Boolean storeNullsProp = (Boolean) tableProps.get(PhoenixDatabaseMetaData.STORE_NULLS); + if (storeNullsProp == null) { + if (parent == null) { + storeNulls = connection.getQueryServices().getProps().getBoolean( + QueryServices.DEFAULT_STORE_NULLS_ATTRIB, + QueryServicesOptions.DEFAULT_STORE_NULLS); + } + } else { + storeNulls = storeNullsProp; + } + Boolean transactionalProp = (Boolean) tableProps.get(PhoenixDatabaseMetaData.TRANSACTIONAL); + if (transactionalProp != null && parent != null) { + throw new SQLExceptionInfo.Builder(SQLExceptionCode.ONLY_TABLE_MAY_BE_DECLARED_TRANSACTIONAL) + .setSchemaName(schemaName).setTableName(tableName) + .build().buildException(); + } + if (parent == null) { + if (transactionalProp == null) { + transactional = connection.getQueryServices().getProps().getBoolean( + QueryServices.DEFAULT_TRANSACTIONAL_ATTRIB, + QueryServicesOptions.DEFAULT_TRANSACTIONAL); + } else { + transactional = transactionalProp; + } + } // Delay this check as it is supported to have IMMUTABLE_ROWS and SALT_BUCKETS defined on views - if ((statement.getTableType() == PTableType.VIEW || indexId != null) && !tableProps.isEmpty()) { - throw new SQLExceptionInfo.Builder(SQLExceptionCode.VIEW_WITH_PROPERTIES).build() - .buildException(); - } - if (removedProp) { - tableProps.put(PhoenixDatabaseMetaData.DEFAULT_COLUMN_FAMILY_NAME, defaultFamilyName); + if (statement.getTableType() == PTableType.VIEW || indexId != null) { + if (tableProps.get(PhoenixDatabaseMetaData.DEFAULT_COLUMN_FAMILY_NAME) != null) { + throw new SQLExceptionInfo.Builder(SQLExceptionCode.DEFAULT_COLUMN_FAMILY_ON_SHARED_TABLE) + .setSchemaName(schemaName).setTableName(tableName) + .build().buildException(); + } + if (SchemaUtil.hasHTableDescriptorProps(tableProps)) { + throw new SQLExceptionInfo.Builder(SQLExceptionCode.VIEW_WITH_PROPERTIES).build() + .buildException(); + } } List<ColumnDef> colDefs = statement.getColumnDefs(); @@ -1561,7 +1588,7 @@ public class MetaDataClient { Collections.<PTable>emptyList(), isImmutableRows, Collections.<PName>emptyList(), defaultFamilyName == null ? null : PNameFactory.newName(defaultFamilyName), null, - Boolean.TRUE.equals(disableWAL), false, false, null, indexId, indexType); + Boolean.TRUE.equals(disableWAL), false, false, null, indexId, indexType, false); connection.addTable(table); } else if (tableType == PTableType.INDEX && indexId == null) { if (tableProps.get(HTableDescriptor.MAX_FILESIZE) == null) { @@ -1658,6 +1685,7 @@ public class MetaDataClient { tableUpsert.setByte(18, indexType.getSerializedValue()); } tableUpsert.setBoolean(19, storeNulls); + tableUpsert.setBoolean(20, transactional); tableUpsert.execute(); tableMetaData.addAll(connection.getMutationState().toMutations().next().getSecond()); @@ -1712,7 +1740,7 @@ public class MetaDataClient { PTable.INITIAL_SEQ_NUM, pkName == null ? null : PNameFactory.newName(pkName), saltBucketNum, columns, dataTableName == null ? null : newSchemaName, dataTableName == null ? null : PNameFactory.newName(dataTableName), Collections.<PTable>emptyList(), isImmutableRows, physicalNames, defaultFamilyName == null ? null : PNameFactory.newName(defaultFamilyName), viewStatement, Boolean.TRUE.equals(disableWAL), multiTenant, storeNulls, viewType, - indexId, indexType); + indexId, indexType, transactional); result = new MetaDataMutationResult(code, result.getMutationTime(), table, true); addTableToCache(result); return table; http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/phoenix-core/src/main/java/org/apache/phoenix/schema/PTable.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTable.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTable.java index d0fea88..6b7f8c6 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTable.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTable.java @@ -314,6 +314,7 @@ public interface PTable { boolean isWALDisabled(); boolean isMultiTenant(); boolean getStoreNulls(); + boolean isTransactional(); ViewType getViewType(); String getViewStatement(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java index 658ff23..163daa2 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java @@ -119,6 +119,7 @@ public class PTableImpl implements PTable { private boolean disableWAL; private boolean multiTenant; private boolean storeNulls; + private boolean isTransactional; private ViewType viewType; private Short viewIndexId; private int estimatedSize; @@ -192,7 +193,7 @@ public class PTableImpl implements PTable { table.getTenantId(), table.getSchemaName(), table.getTableName(), table.getType(), table.getIndexState(), timeStamp, table.getSequenceNumber(), table.getPKName(), table.getBucketNum(), getColumnsToClone(table), parentSchemaName, table.getParentTableName(), indexes, table.isImmutableRows(), table.getPhysicalNames(), table.getDefaultFamilyName(), viewStatement, - table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.getTableStats()); + table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.isTransactional(), table.getTableStats()); } public static PTableImpl makePTable(PTable table, List<PColumn> columns) throws SQLException { @@ -200,7 +201,7 @@ public class PTableImpl implements PTable { table.getTenantId(), table.getSchemaName(), table.getTableName(), table.getType(), table.getIndexState(), table.getTimeStamp(), table.getSequenceNumber(), table.getPKName(), table.getBucketNum(), columns, table.getParentSchemaName(), table.getParentTableName(), table.getIndexes(), table.isImmutableRows(), table.getPhysicalNames(), table.getDefaultFamilyName(), table.getViewStatement(), - table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.getTableStats()); + table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.isTransactional(), table.getTableStats()); } public static PTableImpl makePTable(PTable table, long timeStamp, long sequenceNumber, List<PColumn> columns) throws SQLException { @@ -208,7 +209,7 @@ public class PTableImpl implements PTable { table.getTenantId(), table.getSchemaName(), table.getTableName(), table.getType(), table.getIndexState(), timeStamp, sequenceNumber, table.getPKName(), table.getBucketNum(), columns, table.getParentSchemaName(), table.getParentTableName(), table.getIndexes(), table.isImmutableRows(), table.getPhysicalNames(), table.getDefaultFamilyName(), table.getViewStatement(), table.isWALDisabled(), - table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.getTableStats()); + table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.isTransactional(), table.getTableStats()); } public static PTableImpl makePTable(PTable table, long timeStamp, long sequenceNumber, List<PColumn> columns, boolean isImmutableRows) throws SQLException { @@ -216,7 +217,7 @@ public class PTableImpl implements PTable { table.getTenantId(), table.getSchemaName(), table.getTableName(), table.getType(), table.getIndexState(), timeStamp, sequenceNumber, table.getPKName(), table.getBucketNum(), columns, table.getParentSchemaName(), table.getParentTableName(), table.getIndexes(), isImmutableRows, table.getPhysicalNames(), table.getDefaultFamilyName(), table.getViewStatement(), - table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.getTableStats()); + table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.isTransactional(), table.getTableStats()); } public static PTableImpl makePTable(PTable table, long timeStamp, long sequenceNumber, List<PColumn> columns, boolean isImmutableRows, boolean isWalDisabled, boolean isMultitenant, boolean storeNulls) throws SQLException { @@ -224,7 +225,7 @@ public class PTableImpl implements PTable { table.getTenantId(), table.getSchemaName(), table.getTableName(), table.getType(), table.getIndexState(), timeStamp, sequenceNumber, table.getPKName(), table.getBucketNum(), columns, table.getParentSchemaName(), table.getParentTableName(), table.getIndexes(), isImmutableRows, table.getPhysicalNames(), table.getDefaultFamilyName(), table.getViewStatement(), - isWalDisabled, isMultitenant, storeNulls, table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.getTableStats()); + isWalDisabled, isMultitenant, storeNulls, table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.isTransactional(), table.getTableStats()); } public static PTableImpl makePTable(PTable table, PIndexState state) throws SQLException { @@ -233,7 +234,7 @@ public class PTableImpl implements PTable { table.getSequenceNumber(), table.getPKName(), table.getBucketNum(), getColumnsToClone(table), table.getParentSchemaName(), table.getParentTableName(), table.getIndexes(), table.isImmutableRows(), table.getPhysicalNames(), table.getDefaultFamilyName(), table.getViewStatement(), - table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.getTableStats()); + table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.isTransactional(), table.getTableStats()); } public static PTableImpl makePTable(PTable table, PTableStats stats) throws SQLException { @@ -242,28 +243,28 @@ public class PTableImpl implements PTable { table.getSequenceNumber(), table.getPKName(), table.getBucketNum(), getColumnsToClone(table), table.getParentSchemaName(), table.getParentTableName(), table.getIndexes(), table.isImmutableRows(), table.getPhysicalNames(), table.getDefaultFamilyName(), table.getViewStatement(), - table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), stats); + table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), table.getIndexType(), table.isTransactional(), stats); } public static PTableImpl makePTable(PName tenantId, PName schemaName, PName tableName, PTableType type, PIndexState state, long timeStamp, long sequenceNumber, PName pkName, Integer bucketNum, List<PColumn> columns, PName dataSchemaName, PName dataTableName, List<PTable> indexes, boolean isImmutableRows, List<PName> physicalNames, PName defaultFamilyName, String viewExpression, boolean disableWAL, boolean multiTenant, - boolean storeNulls, ViewType viewType, Short viewIndexId, IndexType indexType) throws SQLException { + boolean storeNulls, ViewType viewType, Short viewIndexId, IndexType indexType, boolean isTransactional) throws SQLException { return new PTableImpl(tenantId, schemaName, tableName, type, state, timeStamp, sequenceNumber, pkName, bucketNum, columns, dataSchemaName, dataTableName, indexes, isImmutableRows, physicalNames, defaultFamilyName, viewExpression, disableWAL, multiTenant, storeNulls, viewType, viewIndexId, - indexType, PTableStats.EMPTY_STATS); + indexType, isTransactional, PTableStats.EMPTY_STATS); } public static PTableImpl makePTable(PName tenantId, PName schemaName, PName tableName, PTableType type, PIndexState state, long timeStamp, long sequenceNumber, PName pkName, Integer bucketNum, List<PColumn> columns, PName dataSchemaName, PName dataTableName, List<PTable> indexes, boolean isImmutableRows, List<PName> physicalNames, PName defaultFamilyName, String viewExpression, - boolean disableWAL, boolean multiTenant, boolean storeNulls, ViewType viewType, Short viewIndexId, IndexType indexType, @NotNull PTableStats stats) + boolean disableWAL, boolean multiTenant, boolean storeNulls, ViewType viewType, Short viewIndexId, IndexType indexType, boolean isTransactional, @NotNull PTableStats stats) throws SQLException { return new PTableImpl(tenantId, schemaName, tableName, type, state, timeStamp, sequenceNumber, pkName, bucketNum, columns, dataSchemaName, dataTableName, indexes, isImmutableRows, physicalNames, - defaultFamilyName, viewExpression, disableWAL, multiTenant, storeNulls, viewType, viewIndexId, indexType, stats); + defaultFamilyName, viewExpression, disableWAL, multiTenant, storeNulls, viewType, viewIndexId, indexType, isTransactional, stats); } private PTableImpl(PName tenantId, PName schemaName, PName tableName, PTableType type, PIndexState state, @@ -271,10 +272,10 @@ public class PTableImpl implements PTable { PName parentSchemaName, PName parentTableName, List<PTable> indexes, boolean isImmutableRows, List<PName> physicalNames, PName defaultFamilyName, String viewExpression, boolean disableWAL, boolean multiTenant, boolean storeNulls, ViewType viewType, Short viewIndexId, IndexType indexType, - PTableStats stats) throws SQLException { + boolean isTransactional, PTableStats stats) throws SQLException { init(tenantId, schemaName, tableName, type, state, timeStamp, sequenceNumber, pkName, bucketNum, columns, stats, schemaName, parentTableName, indexes, isImmutableRows, physicalNames, defaultFamilyName, - viewExpression, disableWAL, multiTenant, storeNulls, viewType, viewIndexId, indexType); + viewExpression, disableWAL, multiTenant, storeNulls, viewType, viewIndexId, indexType, isTransactional); } @Override @@ -302,7 +303,7 @@ public class PTableImpl implements PTable { PName pkName, Integer bucketNum, List<PColumn> columns, PTableStats stats, PName parentSchemaName, PName parentTableName, List<PTable> indexes, boolean isImmutableRows, List<PName> physicalNames, PName defaultFamilyName, String viewExpression, boolean disableWAL, boolean multiTenant, boolean storeNulls, ViewType viewType, Short viewIndexId, - IndexType indexType ) throws SQLException { + IndexType indexType, boolean isTransactional ) throws SQLException { Preconditions.checkNotNull(schemaName); Preconditions.checkArgument(tenantId==null || tenantId.getBytes().length > 0); // tenantId should be null or not empty int estimatedSize = SizedUtil.OBJECT_SIZE * 2 + 23 * SizedUtil.POINTER_SIZE + 4 * SizedUtil.INT_SIZE + 2 * SizedUtil.LONG_SIZE + 2 * SizedUtil.INT_OBJECT_SIZE + @@ -331,6 +332,7 @@ public class PTableImpl implements PTable { this.viewType = viewType; this.viewIndexId = viewIndexId; this.indexType = indexType; + this.isTransactional = isTransactional; this.tableStats = stats; List<PColumn> pkColumns; PColumn[] allColumns; @@ -950,6 +952,7 @@ public class PTableImpl implements PTable { boolean disableWAL = table.getDisableWAL(); boolean multiTenant = table.getMultiTenant(); boolean storeNulls = table.getStoreNulls(); + boolean isTransactional = table.getTransactional(); ViewType viewType = null; String viewStatement = null; List<PName> physicalNames = Collections.emptyList(); @@ -971,7 +974,7 @@ public class PTableImpl implements PTable { result.init(tenantId, schemaName, tableName, tableType, indexState, timeStamp, sequenceNumber, pkName, (bucketNum == NO_SALTING) ? null : bucketNum, columns, stats, schemaName,dataTableName, indexes, isImmutableRows, physicalNames, defaultFamilyName, viewStatement, disableWAL, - multiTenant, storeNulls, viewType, viewIndexId, indexType); + multiTenant, storeNulls, viewType, viewIndexId, indexType, isTransactional); return result; } catch (SQLException e) { throw new RuntimeException(e); // Impossible @@ -1051,6 +1054,7 @@ public class PTableImpl implements PTable { builder.setDisableWAL(table.isWALDisabled()); builder.setMultiTenant(table.isMultiTenant()); builder.setStoreNulls(table.getStoreNulls()); + builder.setTransactional(table.isTransactional()); if(table.getType() == PTableType.VIEW){ builder.setViewType(HBaseZeroCopyByteString.wrap(new byte[]{table.getViewType().getSerializedValue()})); builder.setViewStatement(HBaseZeroCopyByteString.wrap(PVarchar.INSTANCE.toBytes(table.getViewStatement()))); @@ -1079,4 +1083,9 @@ public class PTableImpl implements PTable { return parentSchemaName; } + @Override + public boolean isTransactional() { + return isTransactional; + } + } http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/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 c429ac4..3c96405 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 @@ -46,7 +46,10 @@ public enum TableProperty { TTL(HColumnDescriptor.TTL, COLUMN_FAMILY_NOT_ALLOWED_FOR_TTL, true, CANNOT_ALTER_PROPERTY, false), - STORE_NULLS(PhoenixDatabaseMetaData.STORE_NULLS, COLUMN_FAMILY_NOT_ALLOWED_TABLE_PROPERTY, true, false); + STORE_NULLS(PhoenixDatabaseMetaData.STORE_NULLS, COLUMN_FAMILY_NOT_ALLOWED_TABLE_PROPERTY, true, false), + + TRANSACTIONAL(PhoenixDatabaseMetaData.TRANSACTIONAL, COLUMN_FAMILY_NOT_ALLOWED_TABLE_PROPERTY, false, CANNOT_ALTER_PROPERTY, false), + ; private final String propertyName; http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/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 c1aa2cc..529c80a 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 @@ -49,16 +49,16 @@ import org.apache.phoenix.hbase.index.util.VersionUtil; import org.apache.phoenix.jdbc.PhoenixConnection; import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData; import org.apache.phoenix.query.QueryConstants; -import org.apache.phoenix.schema.types.PBoolean; -import org.apache.phoenix.schema.types.PDataType; -import org.apache.phoenix.schema.types.PLong; import org.apache.phoenix.schema.PName; -import org.apache.phoenix.schema.types.PSmallint; import org.apache.phoenix.schema.PTable; import org.apache.phoenix.schema.PTableType; import org.apache.phoenix.schema.SequenceKey; import org.apache.phoenix.schema.SortOrder; import org.apache.phoenix.schema.TableNotFoundException; +import org.apache.phoenix.schema.types.PBoolean; +import org.apache.phoenix.schema.types.PDataType; +import org.apache.phoenix.schema.types.PLong; +import org.apache.phoenix.schema.types.PSmallint; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -259,6 +259,13 @@ public class MetaDataUtil { return false; } + public static boolean isTransactional(Mutation m, KeyValueBuilder builder, ImmutableBytesWritable ptr) { + if (getMutationValue(m, PhoenixDatabaseMetaData.TRANSACTIONAL_BYTES, builder, ptr)) { + return Boolean.TRUE.equals(PBoolean.INSTANCE.toObject(ptr)); + } + return false; + } + public static boolean isSalted(Mutation m, KeyValueBuilder builder, ImmutableBytesWritable ptr) { return MetaDataUtil.getMutationValue(m, PhoenixDatabaseMetaData.SALT_BUCKETS_BYTES, builder, ptr); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java index a94e8ef..47db678 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java @@ -29,11 +29,11 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Properties; import javax.annotation.Nullable; -import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding; import org.apache.hadoop.hbase.util.Bytes; @@ -57,6 +57,7 @@ import org.apache.phoenix.schema.RowKeySchema; import org.apache.phoenix.schema.RowKeySchema.RowKeySchemaBuilder; import org.apache.phoenix.schema.SaltingUtil; import org.apache.phoenix.schema.SortOrder; +import org.apache.phoenix.schema.TableProperty; import org.apache.phoenix.schema.ValueSchema.Field; import org.apache.phoenix.schema.types.PDataType; import org.apache.phoenix.schema.types.PVarbinary; @@ -371,16 +372,6 @@ public class SchemaUtil { .getName().getBytesPtr(); } - public static boolean isTransactional(HTableDescriptor descriptor) { - byte[] isTransactional = descriptor.getValue(PhoenixDatabaseMetaData.TRANSACTIONAL_BYTES); - return (isTransactional != null && Boolean.TRUE.toString().equalsIgnoreCase(Bytes.toString(isTransactional))); - } - - public static boolean hasTransactional(HTableDescriptor descriptor) { - byte[] isTransactional = descriptor.getValue(PhoenixDatabaseMetaData.TRANSACTIONAL_BYTES); - return (isTransactional != null); - } - public static boolean isMetaTable(byte[] tableName) { return Bytes.compareTo(tableName, SYSTEM_CATALOG_NAME_BYTES) == 0; } @@ -689,4 +680,14 @@ public class SchemaUtil { checkArgument(!isNullOrEmpty(columnName), "Column name cannot be null or empty"); return columnFamilyName == null ? ("\"" + columnName + "\"") : ("\"" + columnFamilyName + "\"" + QueryConstants.NAME_SEPARATOR + "\"" + columnName + "\""); } + + public static boolean hasHTableDescriptorProps(Map<String, Object> tableProps) { + int pTablePropCount = 0; + for (String prop : tableProps.keySet()) { + if (TableProperty.isPhoenixTableProperty(prop)) { + pTablePropCount++; + } + } + return tableProps.size() - pTablePropCount > 0; + } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java index 4accd38..7c36245 100644 --- a/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java +++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java @@ -1473,7 +1473,7 @@ public class QueryCompilerTest extends BaseConnectionlessQueryTest { statement.execute("create local index my_idx on example (fn) DEFAULT_COLUMN_FAMILY='F'"); fail(); } catch (SQLException e) { - assertEquals(SQLExceptionCode.VIEW_WITH_PROPERTIES.getErrorCode(),e.getErrorCode()); + assertEquals(SQLExceptionCode.DEFAULT_COLUMN_FAMILY_ON_SHARED_TABLE.getErrorCode(),e.getErrorCode()); } statement.execute("create local index my_idx on example (fn)"); } finally { http://git-wip-us.apache.org/repos/asf/phoenix/blob/8119bee5/phoenix-protocol/src/main/PTable.proto ---------------------------------------------------------------------- diff --git a/phoenix-protocol/src/main/PTable.proto b/phoenix-protocol/src/main/PTable.proto index 348631f..ababd23 100644 --- a/phoenix-protocol/src/main/PTable.proto +++ b/phoenix-protocol/src/main/PTable.proto @@ -83,4 +83,5 @@ message PTable { optional bytes indexType = 22; optional int64 statsTimeStamp = 23; optional bool storeNulls = 24; + optional bool transactional = 25; }
