This is an automated email from the ASF dual-hosted git repository. alsuliman pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/asterixdb.git
The following commit(s) were added to refs/heads/master by this push: new 738ec5d [ASTERIXDB-2791][IDX] Use OptionalBoolean for unknown key option 738ec5d is described below commit 738ec5db3224ac571bfca374e4090b1f9100908a Author: Ali Alsuliman <ali.al.solai...@gmail.com> AuthorDate: Thu Aug 12 00:38:15 2021 +0300 [ASTERIXDB-2791][IDX] Use OptionalBoolean for unknown key option - user model changes: no - storage format changes: no - interface changes: no Change-Id: I1abfa1ce1ac6d3848a684a78c1da992cc2fd6ca1 Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/12784 Integration-Tests: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Tested-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Reviewed-by: Ali Alsuliman <ali.al.solai...@gmail.com> Reviewed-by: Murtadha Hubail <mhub...@apache.org> --- .../IntroduceSecondaryIndexInsertDeleteRule.java | 6 +- .../asterix/app/translator/QueryTranslator.java | 3 +- .../dataflow/CheckpointInSecondaryIndexTest.java | 3 +- .../test/dataflow/ConcurrentInsertTest.java | 5 +- .../test/dataflow/LSMFlushRecoveryTest.java | 3 +- .../test/dataflow/MultiPartitionLSMIndexTest.java | 3 +- .../common/statement/CreateIndexStatement.java | 9 +- .../lang/sqlpp/util/SqlppStatementUtil.java | 7 +- .../apache/asterix/metadata/entities/Index.java | 22 ++-- .../IndexTupleTranslator.java | 19 ++-- .../utils/SecondaryBTreeOperationsHelper.java | 5 +- .../IndexTupleTranslatorTest.java | 3 +- .../org/apache/hyracks/util/OptionalBoolean.java | 115 +++++++++++++++++++++ 13 files changed, 167 insertions(+), 36 deletions(-) diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java index 7567bbd..98c3edc 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java @@ -92,6 +92,7 @@ import org.apache.hyracks.algebricks.core.algebra.plan.ALogicalPlanImpl; import org.apache.hyracks.algebricks.core.algebra.util.OperatorManipulationUtil; import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule; import org.apache.hyracks.api.exceptions.SourceLocation; +import org.apache.hyracks.util.OptionalBoolean; /** * This rule matches the pattern: @@ -951,8 +952,9 @@ public class IntroduceSecondaryIndexInsertDeleteRule implements IAlgebraicRewrit if (index.isPrimaryKeyIndex()) { return createAnyUnknownFilterExpression(secondaryKeyVars, typeEnv, forceFilter); } else { - Boolean excludeUnknownKey = ((Index.ValueIndexDetails) index.getIndexDetails()).isExcludeUnknownKey(); - boolean excludeUnknown = excludeUnknownKey != null && excludeUnknownKey; + OptionalBoolean excludeUnknownKey = + ((Index.ValueIndexDetails) index.getIndexDetails()).isExcludeUnknownKey(); + boolean excludeUnknown = excludeUnknownKey.isPresent() && excludeUnknownKey.get(); return createAllUnknownFilterExpression(secondaryKeyVars, typeEnv, forceFilter, excludeUnknown); } } else { diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java index 173b6d4..3e0cf79 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java @@ -253,6 +253,7 @@ import org.apache.hyracks.control.common.controllers.CCConfig; import org.apache.hyracks.storage.am.common.dataflow.IndexDropOperatorDescriptor.DropOption; import org.apache.hyracks.storage.am.lsm.common.api.ILSMMergePolicyFactory; import org.apache.hyracks.storage.am.lsm.invertedindex.fulltext.TokenizerCategory; +import org.apache.hyracks.util.OptionalBoolean; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -1494,7 +1495,7 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen externalFilesSnapshot = ExternalIndexingOperations.getSnapshotFromExternalFileSystem(ds); // Add an entry for the files index Index.IndexCategory indexCategory = Index.IndexCategory.of(index.getIndexType()); - Boolean excludeUnknownKey = null; + OptionalBoolean excludeUnknownKey = OptionalBoolean.empty(); if (indexCategory == Index.IndexCategory.VALUE) { excludeUnknownKey = ((Index.ValueIndexDetails) index.getIndexDetails()).isExcludeUnknownKey(); } diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/dataflow/CheckpointInSecondaryIndexTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/dataflow/CheckpointInSecondaryIndexTest.java index caab0b8..3973dee 100644 --- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/dataflow/CheckpointInSecondaryIndexTest.java +++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/dataflow/CheckpointInSecondaryIndexTest.java @@ -76,6 +76,7 @@ import org.apache.hyracks.storage.am.lsm.common.api.ILSMIndexFileManager; import org.apache.hyracks.storage.am.lsm.common.impls.AbstractLSMIndex; import org.apache.hyracks.storage.am.lsm.common.impls.LSMComponentId; import org.apache.hyracks.storage.am.lsm.common.impls.NoMergePolicyFactory; +import org.apache.hyracks.util.OptionalBoolean; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; @@ -171,7 +172,7 @@ public class CheckpointInSecondaryIndexTest { partitioningKeys, null, null, null, false, null, null), null, DatasetType.INTERNAL, DATASET_ID, 0); secondaryIndex = new Index(dvName, DATASET_NAME, INDEX_NAME, INDEX_TYPE, INDEX_FIELD_NAMES, - INDEX_FIELD_INDICATORS, INDEX_FIELD_TYPES, false, false, false, 0, false); + INDEX_FIELD_INDICATORS, INDEX_FIELD_TYPES, false, false, false, 0, OptionalBoolean.of(false)); taskCtx = null; primaryIndexDataflowHelper = null; secondaryIndexDataflowHelper = null; diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/dataflow/ConcurrentInsertTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/dataflow/ConcurrentInsertTest.java index bea1791..e99e5d6 100644 --- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/dataflow/ConcurrentInsertTest.java +++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/dataflow/ConcurrentInsertTest.java @@ -51,6 +51,7 @@ import org.apache.hyracks.dataflow.common.data.accessors.ITupleReference; import org.apache.hyracks.storage.am.common.api.IIndexDataflowHelper; import org.apache.hyracks.storage.am.common.dataflow.IndexDataflowHelperFactory; import org.apache.hyracks.storage.am.lsm.btree.impl.TestLsmBtree; +import org.apache.hyracks.util.OptionalBoolean; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; @@ -129,7 +130,7 @@ public class ConcurrentInsertTest { StorageTestUtils.DATASET.getDatasetName(), "TestIndex", IndexType.BTREE, Arrays.asList(Arrays.asList(StorageTestUtils.RECORD_TYPE.getFieldNames()[1])), Arrays.asList(Index.RECORD_INDICATOR), Arrays.asList(BuiltinType.AINT64), false, false, false, 0, - false); + OptionalBoolean.of(false)); SecondaryIndexInfo secondaryIndexInfo = nc.createSecondaryIndex(primaryIndexInfo, secondaryIndexEntity, StorageTestUtils.STORAGE_MANAGER, 0); @@ -143,7 +144,7 @@ public class ConcurrentInsertTest { Index primaryKeyIndexEntity = new Index(StorageTestUtils.DATASET.getDataverseName(), StorageTestUtils.DATASET.getDatasetName(), "PrimaryKeyIndex", IndexType.BTREE, Arrays.asList(), - Arrays.asList(), Arrays.asList(), false, false, false, 0, null); + Arrays.asList(), Arrays.asList(), false, false, false, 0, OptionalBoolean.empty()); SecondaryIndexInfo primaryKeyIndexInfo = nc.createSecondaryIndex(primaryIndexInfo, primaryKeyIndexEntity, StorageTestUtils.STORAGE_MANAGER, 0); diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/dataflow/LSMFlushRecoveryTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/dataflow/LSMFlushRecoveryTest.java index f408758..d24d081 100644 --- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/dataflow/LSMFlushRecoveryTest.java +++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/dataflow/LSMFlushRecoveryTest.java @@ -70,6 +70,7 @@ import org.apache.hyracks.storage.am.lsm.common.api.ILSMIOOperation; import org.apache.hyracks.storage.am.lsm.common.api.ILSMIOOperationScheduler; import org.apache.hyracks.storage.am.lsm.common.api.ILSMMemoryComponent; import org.apache.hyracks.storage.am.lsm.common.impls.AsynchronousScheduler; +import org.apache.hyracks.util.OptionalBoolean; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.After; @@ -187,7 +188,7 @@ public class LSMFlushRecoveryTest { dataset = StorageTestUtils.DATASET; secondaryIndexEntity = new Index(dataset.getDataverseName(), dataset.getDatasetName(), SECONDARY_INDEX_NAME, SECONDARY_INDEX_TYPE, SECONDARY_INDEX_FIELD_NAMES, SECONDARY_INDEX_FIELD_INDICATORS, - SECONDARY_INDEX_FIELD_TYPES, false, false, false, 0, false); + SECONDARY_INDEX_FIELD_TYPES, false, false, false, 0, OptionalBoolean.of(false)); primaryIndexInfos = new PrimaryIndexInfo[NUM_PARTITIONS]; secondaryIndexInfo = new SecondaryIndexInfo[NUM_PARTITIONS]; diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/dataflow/MultiPartitionLSMIndexTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/dataflow/MultiPartitionLSMIndexTest.java index 42ddd95..6f9bed4 100644 --- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/dataflow/MultiPartitionLSMIndexTest.java +++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/dataflow/MultiPartitionLSMIndexTest.java @@ -70,6 +70,7 @@ import org.apache.hyracks.storage.am.lsm.common.api.ILSMDiskComponent; import org.apache.hyracks.storage.am.lsm.common.api.ILSMMemoryComponent; import org.apache.hyracks.storage.am.lsm.common.api.IVirtualBufferCache; import org.apache.hyracks.storage.am.lsm.common.impls.NoMergePolicyFactory; +import org.apache.hyracks.util.OptionalBoolean; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; @@ -161,7 +162,7 @@ public class MultiPartitionLSMIndexTest { partitioningKeys, null, null, null, false, null, null), null, DatasetType.INTERNAL, DATASET_ID, 0); secondaryIndex = new Index(dvName, DATASET_NAME, INDEX_NAME, INDEX_TYPE, INDEX_FIELD_NAMES, - INDEX_FIELD_INDICATORS, INDEX_FIELD_TYPES, false, false, false, 0, false); + INDEX_FIELD_INDICATORS, INDEX_FIELD_TYPES, false, false, false, 0, OptionalBoolean.of(false)); taskCtxs = new IHyracksTaskContext[NUM_PARTITIONS]; primaryIndexDataflowHelpers = new IIndexDataflowHelper[NUM_PARTITIONS]; secondaryIndexDataflowHelpers = new IIndexDataflowHelper[NUM_PARTITIONS]; diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateIndexStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateIndexStatement.java index 2c02812..a9f3a0b 100644 --- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateIndexStatement.java +++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateIndexStatement.java @@ -34,6 +34,7 @@ import org.apache.asterix.lang.common.visitor.base.ILangVisitor; import org.apache.hyracks.algebricks.common.utils.Pair; import org.apache.hyracks.algebricks.common.utils.Triple; import org.apache.hyracks.api.exceptions.SourceLocation; +import org.apache.hyracks.util.OptionalBoolean; public class CreateIndexStatement extends AbstractStatement { @@ -48,7 +49,7 @@ public class CreateIndexStatement extends AbstractStatement { private final int gramLength; // Specific to FullText indexes. private final String fullTextConfigName; - private final Boolean excludeUnknownKey; + private final OptionalBoolean excludeUnknownKey; public CreateIndexStatement(DataverseName dataverseName, Identifier datasetName, Identifier indexName, IndexType indexType, List<IndexedElement> indexedElements, boolean enforced, int gramLength, @@ -62,7 +63,7 @@ public class CreateIndexStatement extends AbstractStatement { this.gramLength = gramLength; this.ifNotExists = ifNotExists; this.fullTextConfigName = fullTextConfigName; - this.excludeUnknownKey = excludeUnknownKey; + this.excludeUnknownKey = OptionalBoolean.ofNullable(excludeUnknownKey); } public String getFullTextConfigName() { @@ -94,10 +95,10 @@ public class CreateIndexStatement extends AbstractStatement { } public boolean hasExcludeUnknownKey() { - return excludeUnknownKey != null; + return excludeUnknownKey.isPresent(); } - public Boolean isExcludeUnknownKey() { + public OptionalBoolean isExcludeUnknownKey() { return excludeUnknownKey; } diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppStatementUtil.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppStatementUtil.java index 7e1783b..437c299 100644 --- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppStatementUtil.java +++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppStatementUtil.java @@ -21,6 +21,7 @@ package org.apache.asterix.lang.sqlpp.util; import java.util.List; import org.apache.asterix.common.metadata.DataverseName; +import org.apache.hyracks.util.OptionalBoolean; public class SqlppStatementUtil { @@ -71,12 +72,12 @@ public class SqlppStatementUtil { @SuppressWarnings("squid:S1172") // unused variable public static StringBuilder getCreateIndexStatement(StringBuilder stringBuilder, DataverseName dataverseName, - String datasetName, String indexName, String fields, Boolean excludeUnknown, int version) { + String datasetName, String indexName, String fields, OptionalBoolean excludeUnknown, int version) { stringBuilder.append(CREATE_INDEX); enclose(stringBuilder, indexName).append(ON); StringBuilder appender = enclose(stringBuilder, dataverseName, datasetName).append(fields); - if (excludeUnknown != null) { - if (excludeUnknown) { + if (excludeUnknown.isPresent()) { + if (excludeUnknown.get()) { appender.append(EXCLUDE_UNKNOWN_KEY); } else { appender.append(INCLUDE_UNKNOWN_KEY); diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/Index.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/Index.java index 685dc85..6ca0c10 100644 --- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/Index.java +++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entities/Index.java @@ -38,6 +38,7 @@ import org.apache.asterix.om.types.IAType; import org.apache.asterix.om.utils.NonTaggedFormatUtil; import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException; import org.apache.hyracks.algebricks.common.utils.Pair; +import org.apache.hyracks.util.OptionalBoolean; /** * Metadata describing an index. @@ -82,7 +83,7 @@ public class Index implements IMetadataEntity<Index>, Comparable<Index> { public Index(DataverseName dataverseName, String datasetName, String indexName, IndexType indexType, List<List<String>> keyFieldNames, List<Integer> keyFieldSourceIndicators, List<IAType> keyFieldTypes, boolean overrideKeyFieldTypes, boolean isEnforced, boolean isPrimaryIndex, int pendingOp, - Boolean excludeUnknownKey) { + OptionalBoolean excludeUnknownKey) { this(dataverseName, datasetName, indexName, indexType, createSimpleIndexDetails(indexType, keyFieldNames, keyFieldSourceIndicators, keyFieldTypes, overrideKeyFieldTypes, excludeUnknownKey), @@ -92,9 +93,9 @@ public class Index implements IMetadataEntity<Index>, Comparable<Index> { public static Index createPrimaryIndex(DataverseName dataverseName, String datasetName, List<List<String>> keyFieldNames, List<Integer> keyFieldSourceIndicators, List<IAType> keyFieldTypes, int pendingOp) { - return new Index(dataverseName, datasetName, datasetName, IndexType.BTREE, - createSimpleIndexDetails(IndexType.BTREE, keyFieldNames, keyFieldSourceIndicators, keyFieldTypes, false, - null), + return new Index(dataverseName, + datasetName, datasetName, IndexType.BTREE, new ValueIndexDetails(keyFieldNames, + keyFieldSourceIndicators, keyFieldTypes, false, OptionalBoolean.empty()), false, true, pendingOp); } @@ -335,12 +336,12 @@ public class Index implements IMetadataEntity<Index>, Comparable<Index> { private final Boolean excludeUnknownKey; public ValueIndexDetails(List<List<String>> keyFieldNames, List<Integer> keyFieldSourceIndicators, - List<IAType> keyFieldTypes, boolean overrideKeyFieldTypes, Boolean excludeUnknownKey) { + List<IAType> keyFieldTypes, boolean overrideKeyFieldTypes, OptionalBoolean excludeUnknownKey) { this.keyFieldNames = keyFieldNames; this.keyFieldSourceIndicators = keyFieldSourceIndicators; this.keyFieldTypes = keyFieldTypes; this.overrideKeyFieldTypes = overrideKeyFieldTypes; - this.excludeUnknownKey = excludeUnknownKey; + this.excludeUnknownKey = excludeUnknownKey.isEmpty() ? null : excludeUnknownKey.get(); } @Override @@ -360,8 +361,8 @@ public class Index implements IMetadataEntity<Index>, Comparable<Index> { return keyFieldTypes; } - public Boolean isExcludeUnknownKey() { - return excludeUnknownKey; + public OptionalBoolean isExcludeUnknownKey() { + return OptionalBoolean.ofNullable(excludeUnknownKey); } @Override @@ -499,7 +500,7 @@ public class Index implements IMetadataEntity<Index>, Comparable<Index> { @Deprecated private static Index.IIndexDetails createSimpleIndexDetails(IndexType indexType, List<List<String>> keyFieldNames, List<Integer> keyFieldSourceIndicators, List<IAType> keyFieldTypes, boolean overrideKeyFieldTypes, - Boolean excludeUnknownKey) { + OptionalBoolean excludeUnknownKey) { if (indexType == null) { return null; } @@ -508,6 +509,9 @@ public class Index implements IMetadataEntity<Index>, Comparable<Index> { return new ValueIndexDetails(keyFieldNames, keyFieldSourceIndicators, keyFieldTypes, overrideKeyFieldTypes, excludeUnknownKey); case TEXT: + if (excludeUnknownKey.isPresent()) { + throw new IllegalArgumentException("excludeUnknownKey"); + } return new TextIndexDetails(keyFieldNames, keyFieldSourceIndicators, keyFieldTypes, overrideKeyFieldTypes, -1, null); default: diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/IndexTupleTranslator.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/IndexTupleTranslator.java index 3c322a4..9171937 100644 --- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/IndexTupleTranslator.java +++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/entitytupletranslators/IndexTupleTranslator.java @@ -65,6 +65,7 @@ import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer; import org.apache.hyracks.api.exceptions.HyracksDataException; import org.apache.hyracks.data.std.util.ArrayBackedValueStorage; import org.apache.hyracks.dataflow.common.data.accessors.ITupleReference; +import org.apache.hyracks.util.OptionalBoolean; import com.google.common.base.Strings; @@ -139,7 +140,7 @@ public class IndexTupleTranslator extends AbstractTupleTranslator<Index> { IndexType indexType = IndexType.valueOf( ((AString) indexRecord.getValueByPos(MetadataRecordTypes.INDEX_ARECORD_INDEXSTRUCTURE_FIELD_INDEX)) .getStringValue()); - Boolean isPrimaryIndex = + boolean isPrimaryIndex = ((ABoolean) indexRecord.getValueByPos(MetadataRecordTypes.INDEX_ARECORD_ISPRIMARY_FIELD_INDEX)) .getBoolean(); @@ -383,15 +384,16 @@ public class IndexTupleTranslator extends AbstractTupleTranslator<Index> { List<IAType> keyFieldTypes = searchKeyType.stream().map(l -> l.get(0)).collect(Collectors.toList()); // Read the exclude unknown key option if applicable for an index - Boolean excludeUnknownKey = null; + OptionalBoolean excludeUnknownKey = OptionalBoolean.empty(); boolean unknownKeyOptionAllowed = indexType == IndexType.BTREE && !isPrimaryIndex && !keyFieldNames.isEmpty(); if (unknownKeyOptionAllowed) { // default to always include unknowns for normal b-trees - excludeUnknownKey = false; + excludeUnknownKey = OptionalBoolean.FALSE(); int excludeUnknownKeyPos = indexRecord.getType().getFieldIndex(INDEX_EXCLUDE_UNKNOWN_FIELD_NAME); if (excludeUnknownKeyPos >= 0) { - excludeUnknownKey = ((ABoolean) indexRecord.getValueByPos(excludeUnknownKeyPos)).getBoolean(); + excludeUnknownKey = OptionalBoolean + .of(((ABoolean) indexRecord.getValueByPos(excludeUnknownKeyPos)).getBoolean()); } } indexDetails = new Index.ValueIndexDetails(keyFieldNames, keyFieldSourceIndicator, keyFieldTypes, @@ -768,15 +770,14 @@ public class IndexTupleTranslator extends AbstractTupleTranslator<Index> { boolean unknownKeyOptionAllowed = index.getIndexType() == IndexType.BTREE && !index.isPrimaryIndex() && !index.isPrimaryKeyIndex(); if (unknownKeyOptionAllowed) { - Boolean excludeUnknownKey = ((Index.ValueIndexDetails) index.getIndexDetails()).isExcludeUnknownKey(); - if (excludeUnknownKey == null) { - excludeUnknownKey = false; - } + OptionalBoolean excludeUnknownKey = + ((Index.ValueIndexDetails) index.getIndexDetails()).isExcludeUnknownKey(); + ABoolean bVal = excludeUnknownKey.isEmpty() ? ABoolean.FALSE : ABoolean.valueOf(excludeUnknownKey.get()); fieldValue.reset(); nameValue.reset(); aString.setValue(INDEX_EXCLUDE_UNKNOWN_FIELD_NAME); stringSerde.serialize(aString, nameValue.getDataOutput()); - booleanSerde.serialize(ABoolean.valueOf(excludeUnknownKey), fieldValue.getDataOutput()); + booleanSerde.serialize(bVal, fieldValue.getDataOutput()); recordBuilder.addField(nameValue, fieldValue); } } diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/SecondaryBTreeOperationsHelper.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/SecondaryBTreeOperationsHelper.java index 5a1a06e..bcd18a7 100644 --- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/SecondaryBTreeOperationsHelper.java +++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/SecondaryBTreeOperationsHelper.java @@ -54,6 +54,7 @@ import org.apache.hyracks.dataflow.std.connectors.OneToOneConnectorDescriptor; import org.apache.hyracks.dataflow.std.sort.ExternalSortOperatorDescriptor; import org.apache.hyracks.storage.am.common.dataflow.IIndexDataflowHelperFactory; import org.apache.hyracks.storage.am.common.dataflow.IndexDataflowHelperFactory; +import org.apache.hyracks.util.OptionalBoolean; public class SecondaryBTreeOperationsHelper extends SecondaryTreeIndexOperationsHelper { @@ -313,8 +314,8 @@ public class SecondaryBTreeOperationsHelper extends SecondaryTreeIndexOperations if (index.isPrimaryKeyIndex()) { return true; } else { - Boolean excludeUnknownKey = details.isExcludeUnknownKey(); - return excludeUnknownKey != null && excludeUnknownKey; + OptionalBoolean excludeUnknownKey = details.isExcludeUnknownKey(); + return excludeUnknownKey.isPresent() && excludeUnknownKey.get(); } } } diff --git a/asterixdb/asterix-metadata/src/test/java/org/apache/asterix/metadata/entitytupletranslators/IndexTupleTranslatorTest.java b/asterixdb/asterix-metadata/src/test/java/org/apache/asterix/metadata/entitytupletranslators/IndexTupleTranslatorTest.java index ad04bbe..edb360f 100644 --- a/asterixdb/asterix-metadata/src/test/java/org/apache/asterix/metadata/entitytupletranslators/IndexTupleTranslatorTest.java +++ b/asterixdb/asterix-metadata/src/test/java/org/apache/asterix/metadata/entitytupletranslators/IndexTupleTranslatorTest.java @@ -44,6 +44,7 @@ import org.apache.asterix.om.types.IAType; import org.apache.asterix.runtime.compression.CompressionManager; import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException; import org.apache.hyracks.dataflow.common.data.accessors.ITupleReference; +import org.apache.hyracks.util.OptionalBoolean; import org.junit.Assert; import org.junit.Test; @@ -73,7 +74,7 @@ public class IndexTupleTranslatorTest { Index index = new Index(dvTest, "d1", "i1", IndexType.BTREE, Collections.singletonList(Collections.singletonList("row_id")), indicator == null ? null : Collections.singletonList(indicator), - Collections.singletonList(BuiltinType.AINT64), false, false, false, 0, false); + Collections.singletonList(BuiltinType.AINT64), false, false, false, 0, OptionalBoolean.of(false)); MetadataNode mockMetadataNode = mock(MetadataNode.class); when(mockMetadataNode.getDatatype(any(), any(DataverseName.class), anyString())).thenReturn(new Datatype( diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/OptionalBoolean.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/OptionalBoolean.java new file mode 100644 index 0000000..b64a315 --- /dev/null +++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/OptionalBoolean.java @@ -0,0 +1,115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.hyracks.util; + +import java.util.NoSuchElementException; + +/** + * Provides functionality similar to {@link java.util.Optional} for the primitive boolean type + */ +public class OptionalBoolean { + private static final OptionalBoolean EMPTY = new OptionalBoolean(false) { + @Override + public boolean isPresent() { + return false; + } + + @Override + public boolean isEmpty() { + return true; + } + + @Override + public boolean equals(Object o) { + return o == this; + } + + @Override + public int hashCode() { + return -1; + } + + @Override + public boolean get() { + throw new NoSuchElementException(); + } + }; + + private static final OptionalBoolean TRUE = new OptionalBoolean(true); + private static final OptionalBoolean FALSE = new OptionalBoolean(false); + + private final boolean value; + + public static OptionalBoolean of(boolean value) { + return value ? TRUE : FALSE; + } + + public static OptionalBoolean ofNullable(Boolean value) { + return value == null ? EMPTY : value ? TRUE : FALSE; + } + + public static OptionalBoolean empty() { + return EMPTY; + } + + public static OptionalBoolean TRUE() { + return TRUE; + } + + public static OptionalBoolean FALSE() { + return FALSE; + } + + private OptionalBoolean(boolean value) { + this.value = value; + } + + public boolean isPresent() { + return true; + } + + public boolean isEmpty() { + return false; + } + + public boolean get() { + return value; + } + + public boolean getOrElse(boolean alternate) { + return isPresent() ? get() : alternate; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (this == EMPTY || o == EMPTY) + return false; + if (o == null || getClass() != o.getClass()) + return false; + OptionalBoolean that = (OptionalBoolean) o; + return value == that.value; + } + + @Override + public int hashCode() { + return value ? 1 : 0; + } +}