abhishek-chouhan commented on a change in pull request #699: PHOENIX-5496
Ensure that we handle all server-side mutation codes on the client
URL: https://github.com/apache/phoenix/pull/699#discussion_r377983558
##########
File path:
phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
##########
@@ -2957,149 +2958,180 @@ public boolean isViewReferenced() {
splits = SchemaUtil.processSplits(splits, pkColumns,
saltBucketNum, connection.getQueryServices().getProps().getBoolean(
QueryServices.FORCE_ROW_KEY_ORDER_ATTRIB,
QueryServicesOptions.DEFAULT_FORCE_ROW_KEY_ORDER));
}
- MetaDataMutationResult result =
connection.getQueryServices().createTable(
- tableMetaData,
- viewType == ViewType.MAPPED || allocateIndexId ?
physicalNames.get(0).getBytes() : null,
- tableType, tableProps, familyPropList, splits,
isNamespaceMapped, allocateIndexId,
- UpgradeUtil.isNoUpgradeSet(connection.getClientInfo()),
parent);
+
+ // Modularized this code for unit testing
+ MetaDataMutationResult result =
getCreateTableMutationResult(tableMetaData, viewType,
+ allocateIndexId, physicalNames, tableType, tableProps,
familyPropList, splits,
+ isNamespaceMapped, parent);
MutationCode code = result.getMutationCode();
- switch(code) {
+ if (code != MutationCode.TABLE_NOT_FOUND) {
+ boolean mutationResult =
handleCreateTableMutationCode(result, code, statement,
+ schemaName, tableName, parent);
+ if(mutationResult) {
+ return null;
+ }
+ }
+ // If the parent table of the view has the auto partition sequence
name attribute,
+ // set the view statement and relevant partition column attributes
correctly
+ if (parent!=null && parent.getAutoPartitionSeqName()!=null) {
+ final PColumn autoPartitionCol =
parent.getPKColumns().get(MetaDataUtil.getAutoPartitionColIndex(parent));
+ final Long autoPartitionNum =
Long.valueOf(result.getAutoPartitionNum());
+ columns.put(autoPartitionCol, new
DelegateColumn(autoPartitionCol) {
+ @Override
+ public byte[] getViewConstant() {
+ PDataType dataType = autoPartitionCol.getDataType();
+ Object val = dataType.toObject(autoPartitionNum,
PLong.INSTANCE);
+ byte[] bytes = new byte [dataType.getByteSize() + 1];
+ dataType.toBytes(val, bytes, 0);
+ return bytes;
+ }
+ @Override
+ public boolean isViewReferenced() {
+ return true;
+ }
+ });
+ String viewPartitionClause =
QueryUtil.getViewPartitionClause(MetaDataUtil.getAutoPartitionColumnName(parent),
autoPartitionNum);
+ if (viewStatement!=null) {
+ viewStatement = viewStatement + " AND " +
viewPartitionClause;
+ }
+ else {
+ viewStatement =
QueryUtil.getViewStatement(parent.getSchemaName().getString(),
parent.getTableName().getString(), viewPartitionClause);
+ }
+ }
+ PName newSchemaName = PNameFactory.newName(schemaName);
+ /*
+ * It doesn't hurt for the PTable of views to have the cqCounter.
However, views always rely on the
+ * parent table's counter to dole out encoded column qualifiers.
So setting the counter as NULL_COUNTER
+ * for extra safety.
+ */
+ EncodedCQCounter cqCounterToBe = tableType == PTableType.VIEW ?
NULL_COUNTER : cqCounter;
+ PTable table = new PTableImpl.Builder()
+ .setType(tableType)
+ .setState(indexState)
+ .setTimeStamp(timestamp != null ? timestamp :
result.getMutationTime())
+ .setIndexDisableTimestamp(0L)
+ .setSequenceNumber(PTable.INITIAL_SEQ_NUM)
+ .setImmutableRows(isImmutableRows)
+ .setViewStatement(viewStatement)
+ .setDisableWAL(Boolean.TRUE.equals(disableWAL))
+ .setMultiTenant(multiTenant)
+ .setStoreNulls(storeNulls)
+ .setViewType(viewType)
+ .setViewIndexIdType(viewIndexIdType)
+ .setViewIndexId(result.getViewIndexId())
+ .setIndexType(indexType)
+ .setTransactionProvider(transactionProvider)
+ .setUpdateCacheFrequency(updateCacheFrequency)
+ .setNamespaceMapped(isNamespaceMapped)
+ .setAutoPartitionSeqName(autoPartitionSeq)
+ .setAppendOnlySchema(isAppendOnlySchema)
+ .setImmutableStorageScheme(immutableStorageScheme == null ?
+ ImmutableStorageScheme.ONE_CELL_PER_COLUMN :
immutableStorageScheme)
+ .setQualifierEncodingScheme(encodingScheme == null ?
+ QualifierEncodingScheme.NON_ENCODED_QUALIFIERS :
encodingScheme)
+ .setBaseColumnCount(baseTableColumnCount)
+ .setEncodedCQCounter(cqCounterToBe)
+
.setUseStatsForParallelization(useStatsForParallelizationProp)
+ .setExcludedColumns(ImmutableList.of())
+ .setTenantId(tenantId)
+ .setSchemaName(newSchemaName)
+ .setTableName(PNameFactory.newName(tableName))
+ .setPkName(pkName == null ? null :
PNameFactory.newName(pkName))
+ .setDefaultFamilyName(defaultFamilyName == null ?
+ null : PNameFactory.newName(defaultFamilyName))
+ .setRowKeyOrderOptimizable(rowKeyOrderOptimizable)
+ .setBucketNum(saltBucketNum)
+ .setIndexes(Collections.emptyList())
+ .setParentSchemaName((parent == null) ? null :
parent.getSchemaName())
+ .setParentTableName((parent == null) ? null :
parent.getTableName())
+ .setPhysicalNames(physicalNames == null ?
+ ImmutableList.of() :
ImmutableList.copyOf(physicalNames))
+ .setColumns(columns.values())
+ .setViewTTL(viewTTL == null ? VIEW_TTL_NOT_DEFINED :
viewTTL)
+ .setViewTTLHighWaterMark(viewTTLHighWaterMark == null ?
MIN_VIEW_TTL_HWM : viewTTLHighWaterMark)
+ .setViewModifiedUpdateCacheFrequency(tableType ==
PTableType.VIEW &&
+ parent != null &&
+ parent.getUpdateCacheFrequency() !=
updateCacheFrequency)
+ .setViewModifiedUseStatsForParallelization(tableType ==
PTableType.VIEW &&
+ parent != null &&
+ parent.useStatsForParallelization()
+ != useStatsForParallelizationProp)
+ .setViewModifiedViewTTL(tableType == PTableType.VIEW &&
+ parent != null && viewTTL != null &&
+ parent.getViewTTL() != viewTTL)
+ .build();
+ result = new MetaDataMutationResult(code,
result.getMutationTime(), table, true);
+ addTableToCache(result);
+ return table;
+ } finally {
+ connection.setAutoCommit(wasAutoCommit);
+ deleteMutexCells(parentPhysicalSchemaName,
parentPhysicalTableName, acquiredColumnMutexSet);
+ }
+ }
+
+ @VisibleForTesting
+ public boolean handleCreateTableMutationCode(MetaDataMutationResult
result, MutationCode code,
+ CreateTableStatement statement, String schemaName, String
tableName,
+ PTable parent) throws SQLException {
+ switch(code) {
case TABLE_ALREADY_EXISTS:
- if (result.getTable() != null) { // Can happen for
transactional table that already exists as HBase table
+ if(result.getTable() != null) {
addTableToCache(result);
}
- if (!statement.ifNotExists()) {
+ if(!statement.ifNotExists()) {
throw new TableAlreadyExistsException(schemaName,
tableName, result.getTable());
}
- return null;
+ return true;
case NEWER_TABLE_FOUND:
// Add table to ConnectionQueryServices so it's cached, but
don't add
// it to this connection as we can't see it.
if (!statement.ifNotExists()) {
- throw new NewerTableAlreadyExistsException(schemaName,
tableName, result.getTable());
+ throw new NewerTableAlreadyExistsException(schemaName,
tableName,
+ result.getTable());
}
+ return false;
case UNALLOWED_TABLE_MUTATION:
- throw new
SQLExceptionInfo.Builder(SQLExceptionCode.CANNOT_MUTATE_TABLE)
-
.setSchemaName(schemaName).setTableName(tableName).build().buildException();
+
throwsSQLExceptionUtil("CANNOT_MUTATE_TABLE",schemaName,tableName);
case CONCURRENT_TABLE_MUTATION:
addTableToCache(result);
throw new ConcurrentTableMutationException(schemaName,
tableName);
case AUTO_PARTITION_SEQUENCE_NOT_FOUND:
throw new
SQLExceptionInfo.Builder(SQLExceptionCode.AUTO_PARTITION_SEQUENCE_UNDEFINED)
-
.setSchemaName(schemaName).setTableName(tableName).build().buildException();
+
.setSchemaName(schemaName).setTableName(tableName).build().buildException();
case CANNOT_COERCE_AUTO_PARTITION_ID:
- throw new
SQLExceptionInfo.Builder(SQLExceptionCode.CANNOT_COERCE_AUTO_PARTITION_ID)
-
.setSchemaName(schemaName).setTableName(tableName).build().buildException();
+ case UNABLE_TO_CREATE_CHILD_LINK:
+ case PARENT_TABLE_NOT_FOUND:
+ case TABLE_NOT_IN_REGION:
+ throwsSQLExceptionUtil(String.valueOf(code), schemaName,
tableName);
case TOO_MANY_INDEXES:
- throw new
SQLExceptionInfo.Builder(SQLExceptionCode.TOO_MANY_INDEXES)
-
.setSchemaName(SchemaUtil.getSchemaNameFromFullName(parent.getPhysicalName().getString()))
-
.setTableName(SchemaUtil.getTableNameFromFullName(parent.getPhysicalName().getString())).build()
- .buildException();
case UNABLE_TO_UPDATE_PARENT_TABLE:
- throw new
SQLExceptionInfo.Builder(SQLExceptionCode.UNABLE_TO_UPDATE_PARENT_TABLE)
-
.setSchemaName(SchemaUtil.getSchemaNameFromFullName(parent.getPhysicalName().getString()))
-
.setTableName(SchemaUtil.getTableNameFromFullName(parent.getPhysicalName().getString())).build()
- .buildException();
+ throwsSQLExceptionUtil(String.valueOf(code),
SchemaUtil.getSchemaNameFromFullName(
+
parent.getPhysicalName().getString()),SchemaUtil.getTableNameFromFullName(
+ parent.getPhysicalName().getString()));
default:
- // If the parent table of the view has the auto partition
sequence name attribute,
- // set the view statement and relevant partition column
attributes correctly
- if (parent!=null && parent.getAutoPartitionSeqName()!=null) {
- final PColumn autoPartitionCol =
parent.getPKColumns().get(MetaDataUtil.getAutoPartitionColIndex(parent));
- final Long autoPartitionNum =
Long.valueOf(result.getAutoPartitionNum());
- columns.put(autoPartitionCol, new
DelegateColumn(autoPartitionCol) {
- @Override
- public byte[] getViewConstant() {
- PDataType dataType =
autoPartitionCol.getDataType();
- Object val = dataType.toObject(autoPartitionNum,
PLong.INSTANCE);
- byte[] bytes = new byte [dataType.getByteSize() +
1];
- dataType.toBytes(val, bytes, 0);
- return bytes;
- }
- @Override
- public boolean isViewReferenced() {
- return true;
- }
- });
- String viewPartitionClause =
QueryUtil.getViewPartitionClause(MetaDataUtil.getAutoPartitionColumnName(parent),
autoPartitionNum);
- if (viewStatement!=null) {
- viewStatement = viewStatement + " AND " +
viewPartitionClause;
- }
- else {
- viewStatement =
QueryUtil.getViewStatement(parent.getSchemaName().getString(),
parent.getTableName().getString(), viewPartitionClause);
- }
- }
- PName newSchemaName = PNameFactory.newName(schemaName);
- /*
- * It doesn't hurt for the PTable of views to have the
cqCounter. However, views always rely on the
- * parent table's counter to dole out encoded column
qualifiers. So setting the counter as NULL_COUNTER
- * for extra safety.
- */
- EncodedCQCounter cqCounterToBe = tableType == PTableType.VIEW
? NULL_COUNTER : cqCounter;
- PTable table = new PTableImpl.Builder()
- .setType(tableType)
- .setState(indexState)
- .setTimeStamp(timestamp != null ? timestamp :
result.getMutationTime())
- .setIndexDisableTimestamp(0L)
- .setSequenceNumber(PTable.INITIAL_SEQ_NUM)
- .setImmutableRows(isImmutableRows)
- .setViewStatement(viewStatement)
- .setDisableWAL(Boolean.TRUE.equals(disableWAL))
- .setMultiTenant(multiTenant)
- .setStoreNulls(storeNulls)
- .setViewType(viewType)
- .setViewIndexIdType(viewIndexIdType)
- .setViewIndexId(result.getViewIndexId())
- .setIndexType(indexType)
- .setTransactionProvider(transactionProvider)
- .setUpdateCacheFrequency(updateCacheFrequency)
- .setNamespaceMapped(isNamespaceMapped)
- .setAutoPartitionSeqName(autoPartitionSeq)
- .setAppendOnlySchema(isAppendOnlySchema)
- .setImmutableStorageScheme(immutableStorageScheme ==
null ?
- ImmutableStorageScheme.ONE_CELL_PER_COLUMN :
immutableStorageScheme)
- .setQualifierEncodingScheme(encodingScheme == null ?
- QualifierEncodingScheme.NON_ENCODED_QUALIFIERS
: encodingScheme)
- .setBaseColumnCount(baseTableColumnCount)
- .setEncodedCQCounter(cqCounterToBe)
-
.setUseStatsForParallelization(useStatsForParallelizationProp)
- .setExcludedColumns(ImmutableList.of())
- .setTenantId(tenantId)
- .setSchemaName(newSchemaName)
- .setTableName(PNameFactory.newName(tableName))
- .setPkName(pkName == null ? null :
PNameFactory.newName(pkName))
- .setDefaultFamilyName(defaultFamilyName == null ?
- null : PNameFactory.newName(defaultFamilyName))
- .setRowKeyOrderOptimizable(rowKeyOrderOptimizable)
- .setBucketNum(saltBucketNum)
- .setIndexes(Collections.emptyList())
- .setParentSchemaName((parent == null) ? null :
parent.getSchemaName())
- .setParentTableName((parent == null) ? null :
parent.getTableName())
- .setPhysicalNames(physicalNames == null ?
- ImmutableList.of() :
ImmutableList.copyOf(physicalNames))
- .setColumns(columns.values())
- .setViewTTL(viewTTL == null ? VIEW_TTL_NOT_DEFINED :
viewTTL)
- .setViewTTLHighWaterMark(viewTTLHighWaterMark == null
? MIN_VIEW_TTL_HWM : viewTTLHighWaterMark)
- .setViewModifiedUpdateCacheFrequency(tableType ==
PTableType.VIEW &&
- parent != null &&
- parent.getUpdateCacheFrequency() !=
updateCacheFrequency)
- .setViewModifiedUseStatsForParallelization(tableType
== PTableType.VIEW &&
- parent != null &&
- parent.useStatsForParallelization()
- != useStatsForParallelizationProp)
- .setViewModifiedViewTTL(tableType == PTableType.VIEW
&&
- parent != null && viewTTL != null &&
- parent.getViewTTL() != viewTTL)
- .build();
- result = new MetaDataMutationResult(code,
result.getMutationTime(), table, true);
- addTableToCache(result);
- return table;
- }
- } finally {
- connection.setAutoCommit(wasAutoCommit);
- deleteMutexCells(parentPhysicalSchemaName,
parentPhysicalTableName, acquiredColumnMutexSet);
+ // Cannot use SQLExecptionInfo here since not all mutation
codes have their
+ // corresponding codes in the enum SQLExceptionCode
+ throw new SQLException("Exception occurred while creating
table Mutation code, "
Review comment:
We're throwing this exception if none of the cases cover this mutation code,
right? The exception message is incoorect in that case, since we're not
creating mutation code.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
With regards,
Apache Git Services