You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by al...@apache.org on 2026/08/25 02:22:44 UTC
(asterixdb) branch master updated: [ASTERIXDB-3760][OTH] Add coded error messages for vector idx
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits 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 e9a8091ce2 [ASTERIXDB-3760][OTH] Add coded error messages for vector idx
e9a8091ce2 is described below
commit e9a8091ce205ab485d830359bf085d689444406e
Author: Ali Alsuliman <al...@gmail.com>
AuthorDate: Thu Aug 20 17:13:21 2026 -0700
[ASTERIXDB-3760][OTH] Add coded error messages for vector idx
- user model changes: no
- storage format changes: no
- interface changes: no
[ASTERIXDB-3760][ASTERIXDB-3771][ASTERIXDB-3754]
Ext-ref: MB-73194, MB-72975
Co-Authored-By: Claude Opus 5 <no...@anthropic.com>
Change-Id: I2c9bc14fcaa8c850abda77cc320cddbd3c254f61
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/21586
Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
Reviewed-by: Ali Alsuliman <al...@gmail.com>
Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
Reviewed-by: Ian Maxon <im...@apache.org>
---
.../operators/physical/VectorSearchPOperator.java | 5 ++-
.../rules/am/VectorIndexAccessMethod.java | 7 ++-
.../asterix/common/exceptions/ErrorCode.java | 6 ++-
.../vector/OptimizedScalarQuantizationCodec.java | 52 ++++++++++++----------
.../vector/OptimizedScalarQuantizerFactory.java | 4 +-
.../src/main/resources/asx_errormsg/en.properties | 2 +
.../lang/common/util/VectorIndexDeclUtil.java | 4 +-
.../metadata/declared/MetadataProvider.java | 7 +--
.../metadata/utils/SampleOperationsHelper.java | 8 +++-
.../common/AOrderedListVectorBinaryAccessor.java | 28 +++++++-----
.../QuantizationConstantsAggregateDescriptor.java | 42 ++++++++++-------
...lKMeansPlusPlusCentroidsOperatorDescriptor.java | 32 ++++++-------
.../asterix/runtime/operators/KMeansUtils.java | 8 +++-
...reeBulkLoaderAndGroupingOperatorDescriptor.java | 35 ++++++++++-----
...eeStaticStructureCreatorOperatorDescriptor.java | 35 +++++++++------
...VectorComponentExtractorOperatorDescriptor.java | 3 +-
.../runtime/utils/VectorDistanceCalculation.java | 5 ++-
.../utils/VectorDistanceFunctionFactory.java | 2 +-
.../apache/hyracks/api/exceptions/ErrorCode.java | 3 ++
.../src/main/resources/errormsg/en.properties | 3 ++
.../DoubleArraySerializerDeserializer.java | 14 +++---
.../lsm/vector/dataflow/LSMVTreeLocalResource.java | 8 ++--
.../QuantizedIndexCreateOperatorDescriptor.java | 3 +-
.../dataflow/VTreeSearchOperatorNodePushable.java | 3 ++
.../storage/am/lsm/vector/impls/LSMVTree.java | 8 +++-
.../am/lsm/vector/impls/LSMVTreeDiskComponent.java | 12 ++---
.../am/lsm/vector/impls/LSMVTreeSearchCursor.java | 3 ++
.../lsm/vector/impls/LSMVTreeTopKSearchCursor.java | 8 +++-
.../am/lsm/vector/impls/PKOnlyTupleProjector.java | 6 ++-
.../vector/api/IVTreeDistanceFunctionFactory.java | 3 +-
.../storage/am/vector/frames/VTreeNSMFrame.java | 4 +-
.../hyracks/storage/am/vector/impls/VTree.java | 12 +++--
.../storage/am/vector/impls/VTreeBulkLoader.java | 4 +-
.../storage/am/vector/impls/VTreeFlushLoader.java | 8 +++-
.../storage/am/vector/impls/VTreeSearchCursor.java | 16 ++++++-
.../vector/impls/VTreeStaticStructureBuilder.java | 6 ++-
.../am/vector/utils/NoOpVectorQuantizer.java | 5 ++-
.../am/vector/TestDoubleArrayVectorAccessor.java | 4 +-
38 files changed, 267 insertions(+), 151 deletions(-)
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/algebra/operators/physical/VectorSearchPOperator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/algebra/operators/physical/VectorSearchPOperator.java
index 712e8b6b3d..477ec96ff4 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/algebra/operators/physical/VectorSearchPOperator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/algebra/operators/physical/VectorSearchPOperator.java
@@ -22,6 +22,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.metadata.declared.DataSourceId;
import org.apache.asterix.metadata.declared.DataSourceIndex;
import org.apache.asterix.metadata.declared.DatasetDataSource;
@@ -121,7 +123,8 @@ public class VectorSearchPOperator extends IndexSearchPOperator {
AbstractUnnestMapOperator unnestMap = (AbstractUnnestMapOperator) op;
ILogicalExpression unnestExpr = unnestMap.getExpressionRef().getValue();
if (unnestExpr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
- throw new AlgebricksException("Vector search unnest expression must be a function call");
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE,
+ "the vector search unnest expression is not a function call");
}
AbstractFunctionCallExpression unnestFuncExpr = (AbstractFunctionCallExpression) unnestExpr;
FunctionIdentifier funcIdent = unnestFuncExpr.getFunctionIdentifier();
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/VectorIndexAccessMethod.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/VectorIndexAccessMethod.java
index 1a0828ad9c..8fb528ca42 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/VectorIndexAccessMethod.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/VectorIndexAccessMethod.java
@@ -30,6 +30,8 @@ import java.util.Set;
import org.apache.asterix.common.annotations.AbstractExpressionAnnotationWithIndexNames;
import org.apache.asterix.common.annotations.AnnSearchPreferenceAnnotation;
import org.apache.asterix.common.config.DatasetConfig.IndexType;
+import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.common.vector.VectorSimilarityMetric;
import org.apache.asterix.metadata.entities.Dataset;
import org.apache.asterix.metadata.entities.Index;
@@ -344,8 +346,9 @@ public class VectorIndexAccessMethod implements IAccessMethod {
// there is no falling back to lookup-and-rerank from here. retainInput/retainNull are both
// false, which is exactly the case where createSecondaryIndexUnnestMap returns an
// UnnestMapOperator, so this is a broken invariant rather than an unsupported plan shape.
- throw new AlgebricksException("Vector index-only plan: expected an UnnestMapOperator from the "
- + "secondary index search but got " + secondaryIndexUnnestOp.getOperatorTag());
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE,
+ "the vector index-only plan expected an UnnestMapOperator from the secondary index "
+ + "search but got " + secondaryIndexUnnestOp.getOperatorTag());
} else {
UnnestMapOperator unnestMap = (UnnestMapOperator) secondaryIndexUnnestOp;
LogicalVariable distVar = context.newVar();
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
index 0dd540a26f..fdfa61fef4 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
@@ -364,11 +364,13 @@ public enum ErrorCode implements IError {
UPDATE_INSERT_POSITION_OUT_OF_BOUNDS(1252),
ASYNC_NOT_SUPPORTED_FOR_STATEMENT(1253),
UNSUPPORTED_FILE_IO_TYPE(1254),
- INVALID_FULL_SCAN_OPTION(1255),
+ INVALID_FULL_SCAN_OPTION(1255), // not used, remove if not shipped yet
INVALID_SAMPLE_METHOD(1256),
- COMPILATION_ANN_DISTANCE_METRIC_MISMATCH(1257),
+ COMPILATION_ANN_DISTANCE_METRIC_MISMATCH(1257), // not used, remove if not shipped yet
COMPILATION_VECTOR_INDEX_CREATION_FAILED(1258),
UNSUPPORTED_MULTIPLE_STATEMENTS_FOR_DELIVERY_MODE(1259),
+ UNSUPPORTED_VECTOR_ELEMENT_TYPE(1260),
+ VECTOR_DIMENSION_MISMATCH(1261),
// Feed errors
DATAFLOW_ILLEGAL_STATE(3001),
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/vector/OptimizedScalarQuantizationCodec.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/vector/OptimizedScalarQuantizationCodec.java
index 57d6e6412d..ae8d2942be 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/vector/OptimizedScalarQuantizationCodec.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/vector/OptimizedScalarQuantizationCodec.java
@@ -18,6 +18,10 @@
*/
package org.apache.asterix.common.vector;
+import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.exceptions.RuntimeDataException;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
/**
* Optimized scalar quantization (OSQ) utilities for vector indexes.
*
@@ -147,19 +151,18 @@ public final class OptimizedScalarQuantizationCodec {
* @param params Quantization parameters including bits, minQuantile, maxQuantile, alpha
* @param similarityFunction The similarity function type (recorded on the result)
* @return QuantizedVector containing quantized bytes and metadata
- * @throws IllegalArgumentException if vector is null or params are invalid
+ * @throws HyracksDataException if vector is null or params are invalid
*/
- public static QuantizedVector quantizeVector(double[] vector, Params params,
- SimilarityFunction similarityFunction) {
+ public static QuantizedVector quantizeVector(double[] vector, Params params, SimilarityFunction similarityFunction)
+ throws HyracksDataException {
if (vector == null) {
- throw new IllegalArgumentException("vector must be non-null");
+ throw new RuntimeDataException(ErrorCode.ILLEGAL_STATE, "A null vector reached the quantizer");
}
if (params == null) {
- throw new IllegalArgumentException("params must be non-null");
+ throw new RuntimeDataException(ErrorCode.ILLEGAL_STATE, "Null quantization params reached the quantizer");
}
if (vector.length != params.vectorDimensions) {
- throw new IllegalArgumentException(
- "vector dimension mismatch: expected " + params.vectorDimensions + ", got " + vector.length);
+ throw new RuntimeDataException(ErrorCode.VECTOR_DIMENSION_MISMATCH, params.vectorDimensions, vector.length);
}
final int bits = params.bits;
@@ -176,7 +179,8 @@ public final class OptimizedScalarQuantizationCodec {
} else if (bits <= 32) {
quantizedBytes = quantizeToInt(vector, minQ, maxQ, alpha, levels);
} else {
- throw new IllegalArgumentException("bits must be <= 32, got " + bits);
+ throw new RuntimeDataException(ErrorCode.ILLEGAL_STATE,
+ "Unsupported quantization bit width " + bits + "; the maximum is 32");
}
return new QuantizedVector(quantizedBytes, similarityFunction);
@@ -300,15 +304,15 @@ public final class OptimizedScalarQuantizationCodec {
* inverse mapping; bits and vectorDimensions for validation)
* @return double[] array where each element approximates the original value via
* inverse quantization: value = quantizedInt / alpha + minQuantile
- * @throws IllegalArgumentException if inputs are null or array length doesn't
- * match params
+ * @throws HyracksDataException if inputs are null or array length doesn't
+ * match params
*/
- public static double[] dequantizeToDoubleArray(Object quantizedBytes, Params params) {
+ public static double[] dequantizeToDoubleArray(Object quantizedBytes, Params params) throws HyracksDataException {
if (quantizedBytes == null) {
- throw new IllegalArgumentException("quantizedBytes must be non-null");
+ throw new RuntimeDataException(ErrorCode.ILLEGAL_STATE, "A null quantized vector reached the dequantizer");
}
if (params == null) {
- throw new IllegalArgumentException("params must be non-null");
+ throw new RuntimeDataException(ErrorCode.ILLEGAL_STATE, "Null quantization params reached the dequantizer");
}
final int dims = params.vectorDimensions;
@@ -319,12 +323,12 @@ public final class OptimizedScalarQuantizationCodec {
if (bits <= 8) {
// byte[] - treat as unsigned
if (!(quantizedBytes instanceof byte[])) {
- throw new IllegalArgumentException(
- "Expected byte[] for " + bits + " bits, got " + quantizedBytes.getClass().getName());
+ throw new RuntimeDataException(ErrorCode.ILLEGAL_STATE, "Expected a byte[] quantized vector for " + bits
+ + " bits, but got a " + quantizedBytes.getClass().getName());
}
byte[] bytes = (byte[]) quantizedBytes;
if (bytes.length != dims) {
- throw new IllegalArgumentException("Array length mismatch: expected " + dims + ", got " + bytes.length);
+ throw new RuntimeDataException(ErrorCode.VECTOR_DIMENSION_MISMATCH, dims, bytes.length);
}
for (int i = 0; i < dims; i++) {
result[i] = ((double) (bytes[i] & 0xFF)) / params.alpha + params.minQuantile;
@@ -332,13 +336,12 @@ public final class OptimizedScalarQuantizationCodec {
} else if (bits <= 16) {
// short[] - treat as unsigned
if (!(quantizedBytes instanceof short[])) {
- throw new IllegalArgumentException(
- "Expected short[] for " + bits + " bits, got " + quantizedBytes.getClass().getName());
+ throw new RuntimeDataException(ErrorCode.ILLEGAL_STATE, "Expected a short[] quantized vector for "
+ + bits + " bits, but got a " + quantizedBytes.getClass().getName());
}
short[] shorts = (short[]) quantizedBytes;
if (shorts.length != dims) {
- throw new IllegalArgumentException(
- "Array length mismatch: expected " + dims + ", got " + shorts.length);
+ throw new RuntimeDataException(ErrorCode.VECTOR_DIMENSION_MISMATCH, dims, shorts.length);
}
for (int i = 0; i < dims; i++) {
result[i] = ((double) (shorts[i] & 0xFFFF)) / params.alpha + params.minQuantile;
@@ -346,18 +349,19 @@ public final class OptimizedScalarQuantizationCodec {
} else if (bits <= 32) {
// int[] - treat as unsigned
if (!(quantizedBytes instanceof int[])) {
- throw new IllegalArgumentException(
- "Expected int[] for " + bits + " bits, got " + quantizedBytes.getClass().getName());
+ throw new RuntimeDataException(ErrorCode.ILLEGAL_STATE, "Expected an int[] quantized vector for " + bits
+ + " bits, but got a " + quantizedBytes.getClass().getName());
}
int[] ints = (int[]) quantizedBytes;
if (ints.length != dims) {
- throw new IllegalArgumentException("Array length mismatch: expected " + dims + ", got " + ints.length);
+ throw new RuntimeDataException(ErrorCode.VECTOR_DIMENSION_MISMATCH, dims, ints.length);
}
for (int i = 0; i < dims; i++) {
result[i] = ((double) (ints[i] & 0xFFFFFFFFL)) / params.alpha + params.minQuantile;
}
} else {
- throw new IllegalArgumentException("bits must be <= 32, got " + bits);
+ throw new RuntimeDataException(ErrorCode.ILLEGAL_STATE,
+ "Unsupported quantization bit width " + bits + "; the maximum is 32");
}
return result;
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/vector/OptimizedScalarQuantizerFactory.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/vector/OptimizedScalarQuantizerFactory.java
index f8b97738d0..6013952362 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/vector/OptimizedScalarQuantizerFactory.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/vector/OptimizedScalarQuantizerFactory.java
@@ -18,6 +18,7 @@
*/
package org.apache.asterix.common.vector;
+import org.apache.hyracks.api.exceptions.ErrorCode;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.storage.am.vector.api.IVTreeQuantizer;
import org.apache.hyracks.storage.am.vector.api.IVTreeQuantizerFactory;
@@ -51,7 +52,8 @@ public class OptimizedScalarQuantizerFactory implements IVTreeQuantizerFactory {
public IVTreeQuantizer createQuantizer(int vectorDimensions, VTreeQuantizationParams params)
throws HyracksDataException {
if (params == null) {
- throw HyracksDataException.create(new IllegalArgumentException("Quantization params must not be null"));
+ throw HyracksDataException.create(ErrorCode.ILLEGAL_STATE,
+ "Null quantization params reached the quantizer factory");
}
OptimizedScalarQuantizationCodec.Params p =
diff --git a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
index 5d349af163..0ff4d5a9e0 100644
--- a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
+++ b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
@@ -371,6 +371,8 @@
1257 = ANN distance metric '%1$s' does not match vector index '%2$s' (similarity in metadata: '%3$s')
1258 = Failed to create vector index. %1$s
1259 = %1$s execution is not supported for a request with multiple statements
+1260 = Unsupported type %1$s in the vector value; the supported element types are numbers
+1261 = Vector dimension mismatch: expected %1$s dimensions, but got %2$s
# Feed Errors
3001 = Illegal state.
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/VectorIndexDeclUtil.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/VectorIndexDeclUtil.java
index 35fe62a212..cb2fcad22b 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/VectorIndexDeclUtil.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/VectorIndexDeclUtil.java
@@ -112,8 +112,8 @@ public class VectorIndexDeclUtil {
private static void validateWithClauseFieldNames(AdmObjectNode node) throws CompilationException {
for (String name : node.getFieldNames()) {
if (!VectorIndexParameters.isKnown(name)) {
- throw new CompilationException("Failed to create vector index. Unknown field `" + name
- + "` in WITH clause. Allowed fields: " + VectorIndexParameters.nameList());
+ throw new CompilationException(ErrorCode.COMPILATION_VECTOR_INDEX_CREATION_FAILED, "Unknown field `"
+ + name + "` in WITH clause. Allowed fields: " + VectorIndexParameters.nameList());
}
}
}
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java
index 84909254e9..5b0832e186 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java
@@ -831,8 +831,8 @@ public class MetadataProvider implements IMetadataProvider<DataSourceId, String>
Index vectorIndex = MetadataManager.INSTANCE.getIndex(mdTxnCtx, dataset.getDatabaseName(),
dataset.getDataverseName(), dataset.getDatasetName(), indexName);
if (vectorIndex == null) {
- throw new AlgebricksException(
- "Code generation error: no index " + indexName + " for dataset " + dataset.getDatasetName());
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, "no index " + indexName
+ + " was found for collection " + dataset.getDatasetName() + " during code generation");
}
RecordDescriptor outputRecDesc = JobGenHelper.mkRecordDescriptor(typeEnv, opSchema, context);
@@ -1761,7 +1761,8 @@ public class MetadataProvider implements IMetadataProvider<DataSourceId, String>
return new Pair<>(op, partitioningProperties.getConstraints());
} catch (Exception e) {
- throw new AlgebricksException(e);
+ throw CompilationException.create(ErrorCode.COMPILATION_ERROR, e,
+ "failed to generate the vector index modification runtime: " + e.getMessage());
}
}
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/SampleOperationsHelper.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/SampleOperationsHelper.java
index ac5cd380e6..b365dba58a 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/SampleOperationsHelper.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/SampleOperationsHelper.java
@@ -27,6 +27,8 @@ import java.util.Set;
import org.apache.asterix.common.cluster.PartitioningProperties;
import org.apache.asterix.common.config.OptimizationConfUtil;
+import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.common.utils.StorageConstants;
import org.apache.asterix.formats.base.IDataFormat;
import org.apache.asterix.metadata.declared.MetadataProvider;
@@ -530,7 +532,9 @@ public class SampleOperationsHelper implements ISecondaryIndexOperationsHelper {
}
@Override
- public JobSpecification buildStaticStructureJobSpec() {
- throw new UnsupportedOperationException();
+ public JobSpecification buildStaticStructureJobSpec() throws AlgebricksException {
+ // Samples are BTrees; only vector indexes have a static-structure build phase.
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE,
+ "a static-structure job was requested for the sample index");
}
}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/AOrderedListVectorBinaryAccessor.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/AOrderedListVectorBinaryAccessor.java
index 3301b03291..6b4d4d3e3b 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/AOrderedListVectorBinaryAccessor.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/AOrderedListVectorBinaryAccessor.java
@@ -18,6 +18,8 @@
*/
package org.apache.asterix.dataflow.data.common;
+import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.exceptions.RuntimeDataException;
import org.apache.asterix.dataflow.data.nontagged.serde.AOrderedListSerializerDeserializer;
import org.apache.asterix.om.types.ATypeTag;
import org.apache.asterix.om.types.EnumDeserializer;
@@ -53,6 +55,9 @@ public class AOrderedListVectorBinaryAccessor implements IVTreeBinaryAccessor {
@Override
public double[] getVector() throws HyracksDataException {
if (data == null) {
+ // TODO(vector-errors): uncoded IllegalStateException -> surfaces to the user as "Internal error".
+ // Reachable only if a caller skips reset(); decide whether to keep it as an unchecked
+ // invariant or convert to RuntimeDataException(ErrorCode.ILLEGAL_STATE, ...).
throw new IllegalStateException("Accessor not initialized. Call reset() first.");
}
@@ -69,8 +74,12 @@ public class AOrderedListVectorBinaryAccessor implements IVTreeBinaryAccessor {
return vector;
}
+ @Override
public int getDimension() throws HyracksDataException {
if (data == null) {
+ // TODO(vector-errors): uncoded IllegalStateException -> surfaces to the user as "Internal error".
+ // Reachable only if a caller skips reset(); decide whether to keep it as an unchecked
+ // invariant or convert to RuntimeDataException(ErrorCode.ILLEGAL_STATE, ...).
throw new IllegalStateException("Accessor not initialized. Call reset() first.");
}
return listLength;
@@ -99,17 +108,12 @@ public class AOrderedListVectorBinaryAccessor implements IVTreeBinaryAccessor {
valueOffset = itemOffset + 1; // Skip type tag
}
- switch (actualType) {
- case DOUBLE:
- return DoublePointable.getDouble(data, valueOffset);
- case FLOAT:
- return FloatPointable.getFloat(data, valueOffset);
- case INTEGER:
- return IntegerPointable.getInteger(data, valueOffset);
- case BIGINT:
- return LongPointable.getLong(data, valueOffset);
- default:
- throw new HyracksDataException("Unsupported numeric type in vector: " + actualType);
- }
+ return switch (actualType) {
+ case DOUBLE -> DoublePointable.getDouble(data, valueOffset);
+ case FLOAT -> FloatPointable.getFloat(data, valueOffset);
+ case INTEGER -> IntegerPointable.getInteger(data, valueOffset);
+ case BIGINT -> LongPointable.getLong(data, valueOffset);
+ default -> throw new RuntimeDataException(ErrorCode.UNSUPPORTED_VECTOR_ELEMENT_TYPE, actualType);
+ };
}
}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/std/QuantizationConstantsAggregateDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/std/QuantizationConstantsAggregateDescriptor.java
index 9c644fc501..467fbdc66e 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/std/QuantizationConstantsAggregateDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/std/QuantizationConstantsAggregateDescriptor.java
@@ -24,6 +24,8 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.exceptions.RuntimeDataException;
import org.apache.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
import org.apache.asterix.dataflow.data.nontagged.serde.AFloatSerializerDeserializer;
import org.apache.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
@@ -176,51 +178,61 @@ public class QuantizationConstantsAggregateDescriptor extends AbstractAggregateF
int contentLength = valuesPointable.getContentLength();
if (contentLength < Integer.BYTES) {
- throw new HyracksDataException("Binary data too short: expected at least " + Integer.BYTES
- + " bytes for numValues, got " + contentLength);
+ throw new RuntimeDataException(ErrorCode.COMPILATION_VECTOR_INDEX_CREATION_FAILED,
+ "Quantization constants are too short: expected at least " + Integer.BYTES
+ + " bytes for numValues, got " + contentLength);
}
if (contentStartOffset + Integer.BYTES > valuesBytes.length) {
- throw new HyracksDataException("Out of bounds: trying to read numValues at offset " + contentStartOffset
- + ", but array length is " + valuesBytes.length);
+ throw new RuntimeDataException(ErrorCode.COMPILATION_VECTOR_INDEX_CREATION_FAILED,
+ "Quantization constants are out of bounds: reading numValues at offset " + contentStartOffset
+ + ", but the array length is " + valuesBytes.length);
}
int numValues = IntegerPointable.getInteger(valuesBytes, contentStartOffset);
if (numValues < 0) {
- throw new HyracksDataException("Invalid numValues: " + numValues + " (negative)");
+ throw new RuntimeDataException(ErrorCode.COMPILATION_VECTOR_INDEX_CREATION_FAILED,
+ "Quantization constants declare a negative value count: " + numValues);
}
if (numValues > 10000000) {
- throw new HyracksDataException("Invalid numValues: " + numValues + " (too large, possible corruption)");
+ throw new RuntimeDataException(ErrorCode.COMPILATION_VECTOR_INDEX_CREATION_FAILED,
+ "Quantization constants declare an implausibly large value count: " + numValues);
}
long expectedBytes = (long) Integer.BYTES + ((long) numValues * (long) Double.BYTES);
if (expectedBytes > Integer.MAX_VALUE) {
- throw new HyracksDataException("Calculated expected bytes exceeds Integer.MAX_VALUE: " + expectedBytes);
+ throw new RuntimeDataException(ErrorCode.COMPILATION_VECTOR_INDEX_CREATION_FAILED,
+ "Quantization constants require " + expectedBytes + " bytes, which exceeds the maximum "
+ + Integer.MAX_VALUE);
}
int expectedBytesInt = (int) expectedBytes;
if (expectedBytesInt > contentLength) {
- throw new HyracksDataException("Binary data too short: expected " + expectedBytesInt + " bytes, got "
- + contentLength + " (numValues=" + numValues + ")");
+ throw new RuntimeDataException(ErrorCode.COMPILATION_VECTOR_INDEX_CREATION_FAILED,
+ "Quantization constants are too short: expected " + expectedBytesInt + " bytes, got "
+ + contentLength + " for " + numValues + " values");
}
int lastByteOffset = contentStartOffset + expectedBytesInt - 1;
if (lastByteOffset >= valuesBytes.length) {
- throw new HyracksDataException("Out of bounds: trying to read up to offset " + lastByteOffset
- + ", but array length is " + valuesBytes.length);
+ throw new RuntimeDataException(ErrorCode.COMPILATION_VECTOR_INDEX_CREATION_FAILED,
+ "Quantization constants are out of bounds: reading up to offset " + lastByteOffset
+ + ", but the array length is " + valuesBytes.length);
}
int pointer = contentStartOffset + Integer.BYTES;
for (int i = 0; i < numValues; i++) {
if (pointer + Double.BYTES > contentStartOffset + contentLength) {
- throw new HyracksDataException("Out of bounds: trying to read double #" + (i + 1) + " at offset "
- + pointer + ", but content ends at " + (contentStartOffset + contentLength));
+ throw new RuntimeDataException(ErrorCode.COMPILATION_VECTOR_INDEX_CREATION_FAILED,
+ "Quantization constants are out of bounds: reading value #" + (i + 1) + " at offset "
+ + pointer + ", but the content ends at " + (contentStartOffset + contentLength));
}
if (pointer + Double.BYTES > valuesBytes.length) {
- throw new HyracksDataException("Out of bounds: trying to read double #" + (i + 1) + " at offset "
- + pointer + ", but array length is " + valuesBytes.length);
+ throw new RuntimeDataException(ErrorCode.COMPILATION_VECTOR_INDEX_CREATION_FAILED,
+ "Quantization constants are out of bounds: reading value #" + (i + 1) + " at offset "
+ + pointer + ", but the array length is " + valuesBytes.length);
}
double value = BufferSerDeUtil.getDouble(valuesBytes, pointer);
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/HierarchicalKMeansPlusPlusCentroidsOperatorDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/HierarchicalKMeansPlusPlusCentroidsOperatorDescriptor.java
index e632714117..db7398a2bc 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/HierarchicalKMeansPlusPlusCentroidsOperatorDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/HierarchicalKMeansPlusPlusCentroidsOperatorDescriptor.java
@@ -446,7 +446,7 @@ public final class HierarchicalKMeansPlusPlusCentroidsOperatorDescriptor extends
listAccessorConstant.reset(inputVal.getByteArray(), inputVal.getStartOffset());
try {
- double[] point = kMeansUtils.createPrimitveList(listAccessorConstant);
+ double[] point = kMeansUtils.createPrimitiveList(listAccessorConstant);
if (!hasIndexDimension(point)) {
tempIdx++;
continue;
@@ -461,7 +461,7 @@ public final class HierarchicalKMeansPlusPlusCentroidsOperatorDescriptor extends
// Accumulate sum (NO STORAGE)
totalDistance += minDist;
} catch (IOException e) {
- throw new RuntimeException(e);
+ throw HyracksDataException.create(e);
}
tempIdx++;
}
@@ -493,7 +493,7 @@ public final class HierarchicalKMeansPlusPlusCentroidsOperatorDescriptor extends
listAccessorConstant.reset(inputVal.getByteArray(), inputVal.getStartOffset());
try {
- double[] point = kMeansUtils.createPrimitveList(listAccessorConstant);
+ double[] point = kMeansUtils.createPrimitiveList(listAccessorConstant);
if (!hasIndexDimension(point)) {
currentIdx++;
continue;
@@ -516,7 +516,7 @@ public final class HierarchicalKMeansPlusPlusCentroidsOperatorDescriptor extends
sampledCount++;
}
} catch (IOException e) {
- throw new RuntimeException(e);
+ throw HyracksDataException.create(e);
}
currentIdx++;
}
@@ -555,7 +555,7 @@ public final class HierarchicalKMeansPlusPlusCentroidsOperatorDescriptor extends
listAccessorConstant.reset(inputVal.getByteArray(), inputVal.getStartOffset());
try {
- double[] point = kMeansUtils.createPrimitveList(listAccessorConstant);
+ double[] point = kMeansUtils.createPrimitiveList(listAccessorConstant);
if (!hasIndexDimension(point)) {
weightIdx++;
continue;
@@ -575,7 +575,7 @@ public final class HierarchicalKMeansPlusPlusCentroidsOperatorDescriptor extends
candidateWeights[nearestCandidate]++;
}
} catch (IOException e) {
- throw new RuntimeException(e);
+ throw HyracksDataException.create(e);
}
weightIdx++;
}
@@ -710,7 +710,7 @@ public final class HierarchicalKMeansPlusPlusCentroidsOperatorDescriptor extends
listAccessorConstant.reset(inputVal.getByteArray(), inputVal.getStartOffset());
try {
- double[] point = kMeansUtils.createPrimitveList(listAccessorConstant);
+ double[] point = kMeansUtils.createPrimitiveList(listAccessorConstant);
if (!hasIndexDimension(point)) {
currentIdx++;
continue;
@@ -729,7 +729,7 @@ public final class HierarchicalKMeansPlusPlusCentroidsOperatorDescriptor extends
assignments[currentIdx] = closestCentroid;
} catch (IOException e) {
- throw new RuntimeException(e);
+ throw HyracksDataException.create(e);
}
currentIdx++;
}
@@ -760,7 +760,7 @@ public final class HierarchicalKMeansPlusPlusCentroidsOperatorDescriptor extends
listAccessorConstant.reset(inputVal.getByteArray(), inputVal.getStartOffset());
try {
- double[] point = kMeansUtils.createPrimitveList(listAccessorConstant);
+ double[] point = kMeansUtils.createPrimitiveList(listAccessorConstant);
if (!hasIndexDimension(point)) {
currentIdx++;
continue;
@@ -773,7 +773,7 @@ public final class HierarchicalKMeansPlusPlusCentroidsOperatorDescriptor extends
counts[centroidIdx]++;
} catch (IOException e) {
- throw new RuntimeException(e);
+ throw HyracksDataException.create(e);
}
currentIdx++;
}
@@ -1068,7 +1068,7 @@ public final class HierarchicalKMeansPlusPlusCentroidsOperatorDescriptor extends
continue;
}
listAccessor.reset(inputVal.getByteArray(), inputVal.getStartOffset());
- double[] point = kMeansUtils.createPrimitveList(listAccessor);
+ double[] point = kMeansUtils.createPrimitiveList(listAccessor);
if (hasIndexDimension(point)) {
return point;
}
@@ -1103,7 +1103,7 @@ public final class HierarchicalKMeansPlusPlusCentroidsOperatorDescriptor extends
}
listAccessorConstant.reset(inputVal.getByteArray(), inputVal.getStartOffset());
- return kMeansUtils.createPrimitveList(listAccessorConstant);
+ return kMeansUtils.createPrimitiveList(listAccessorConstant);
}
currentIndex++;
}
@@ -1141,7 +1141,7 @@ public final class HierarchicalKMeansPlusPlusCentroidsOperatorDescriptor extends
if (ATYPETAGDESERIALIZER.deserialize(inputVal.getByteArray()[inputVal.getStartOffset()])
.isListType()) {
listAccessorConstant.reset(inputVal.getByteArray(), inputVal.getStartOffset());
- results.set(ti, kMeansUtils.createPrimitveList(listAccessorConstant));
+ results.set(ti, kMeansUtils.createPrimitiveList(listAccessorConstant));
}
ti++;
}
@@ -1462,11 +1462,7 @@ public final class HierarchicalKMeansPlusPlusCentroidsOperatorDescriptor extends
}
private static IVTreeDistanceFunction distanceFunctionFor(VectorSimilarityMetric metric) {
- try {
- return new VectorDistanceFunctionFactory(metric).createDistanceFunction();
- } catch (HyracksDataException e) {
- throw new IllegalStateException("Failed to build vector distance function for " + metric, e);
- }
+ return new VectorDistanceFunctionFactory(metric).createDistanceFunction();
}
};
}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/KMeansUtils.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/KMeansUtils.java
index e47350f7fb..01a9d10c99 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/KMeansUtils.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/KMeansUtils.java
@@ -20,6 +20,8 @@ package org.apache.asterix.runtime.operators;
import java.io.IOException;
+import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.exceptions.RuntimeDataException;
import org.apache.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
import org.apache.asterix.dataflow.data.nontagged.serde.AFloatSerializerDeserializer;
import org.apache.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
@@ -46,7 +48,8 @@ public class KMeansUtils {
}
// Euclidean Distance
- protected double[] createPrimitveList(ListAccessor listAccessor) throws IOException {
+ protected double[] createPrimitiveList(ListAccessor listAccessor) throws IOException {
+ // TODO(vector-errors): update consumers to create HyracksDataException.create(e);
ATypeTag typeTag = listAccessor.getItemType();
double[] primitiveArray = new double[listAccessor.size()];
storage.reset();
@@ -66,11 +69,12 @@ public class KMeansUtils {
ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(data[offset]);
return getValueFromTag(typeTag, data, offset);
} else {
- throw new HyracksDataException("Unsupported type tag for numeric vector extraction: " + derivedTypeTag);
+ throw new RuntimeDataException(ErrorCode.UNSUPPORTED_VECTOR_ELEMENT_TYPE, derivedTypeTag);
}
}
protected double getValueFromTag(ATypeTag typeTag, byte[] data, int offset) throws HyracksDataException {
+ // TODO(vector-index): refactor
return switch (typeTag) {
case TINYINT -> AInt8SerializerDeserializer.getByte(data, offset + 1);
case SMALLINT -> AInt16SerializerDeserializer.getShort(data, offset + 1);
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/VTreeBulkLoaderAndGroupingOperatorDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/VTreeBulkLoaderAndGroupingOperatorDescriptor.java
index e0e933c961..d63558b369 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/VTreeBulkLoaderAndGroupingOperatorDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/VTreeBulkLoaderAndGroupingOperatorDescriptor.java
@@ -18,6 +18,8 @@
*/
package org.apache.asterix.runtime.operators;
+import static org.apache.hyracks.api.exceptions.ErrorCode.ILLEGAL_STATE;
+
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.List;
@@ -126,8 +128,8 @@ public class VTreeBulkLoaderAndGroupingOperatorDescriptor extends AbstractSingle
// validation, IndexTupleTranslator at persist), so a missing/unsupported value here means a corrupt index.
VectorSimilarityMetric metric = (distanceType == null) ? null : VectorSimilarityMetric.fromAlias(distanceType);
if (metric == null) {
- throw new IllegalArgumentException(
- "Vector index has a missing or unsupported 'similarity' metric: " + distanceType);
+ throw HyracksDataException.create(ILLEGAL_STATE,
+ "The index has a missing or unsupported 'similarity' metric: " + distanceType);
}
return new VectorDistanceFunctionFactory(metric).createDistanceFunction();
}
@@ -339,7 +341,8 @@ public class VTreeBulkLoaderAndGroupingOperatorDescriptor extends AbstractSingle
private double[] extractEmbedding(ITupleReference tuple) throws HyracksDataException {
try {
if (tuple == null) {
- throw new IllegalArgumentException("Tuple cannot be null");
+ throw HyracksDataException.create(ILLEGAL_STATE,
+ "A null tuple reached the vector index bulk loader");
}
embeddingEval.evaluate((IFrameTupleReference) tuple, embeddingInputVal);
if (embeddingInputVal.getLength() == 0) {
@@ -351,7 +354,7 @@ public class VTreeBulkLoaderAndGroupingOperatorDescriptor extends AbstractSingle
return null;
}
embeddingListAccessor.reset(embeddingInputVal.getByteArray(), embeddingInputVal.getStartOffset());
- double[] embedding = embeddingKMeansUtils.createPrimitveList(embeddingListAccessor);
+ double[] embedding = embeddingKMeansUtils.createPrimitiveList(embeddingListAccessor);
if (embedding == null || embedding.length == 0) {
return null;
}
@@ -395,14 +398,15 @@ public class VTreeBulkLoaderAndGroupingOperatorDescriptor extends AbstractSingle
IIndex indexInstance = indexHelper.getIndexInstance();
if (!(indexInstance instanceof ILSMIndex)) {
- throw new HyracksDataException("Index is not an ILSMIndex instance, got: "
- + (indexInstance != null ? indexInstance.getClass().getName() : "null"));
+ throw HyracksDataException.create(ILLEGAL_STATE,
+ "The vector index resource is not an " + "ILSMIndex, but a "
+ + (indexInstance != null ? indexInstance.getClass().getName() : "null"));
}
ILSMIndex lsmIndex = (ILSMIndex) indexInstance;
if (!(lsmIndex instanceof LSMVTree)) {
- throw new HyracksDataException(
- "Index is not an LSMVTree instance, got: " + lsmIndex.getClass().getName());
+ throw HyracksDataException.create(ILLEGAL_STATE,
+ "The vector index resource is not an LSMVTree, but a " + lsmIndex.getClass().getName());
}
LSMVTree = (LSMVTree) lsmIndex;
@@ -441,6 +445,9 @@ public class VTreeBulkLoaderAndGroupingOperatorDescriptor extends AbstractSingle
// Get LocalResource from index helper (a genuine read failure propagates rather than defaulting)
LocalResource localResource = indexHelper.getResource();
if (localResource == null) {
+ // TODO(vector-errors): uncoded IllegalStateException -> reaches the user as "Internal error".
+ // A quantized vector index with no LocalResource is a broken invariant; decide whether to
+ // keep it unchecked or code it as ErrorCode.ILLEGAL_STATE / CORRUPTED_VECTOR_INDEX.
throw HyracksDataException.create(new IllegalStateException(
"Quantized VTree is missing its LocalResource; cannot read quantization params"));
}
@@ -459,12 +466,14 @@ public class VTreeBulkLoaderAndGroupingOperatorDescriptor extends AbstractSingle
}
if (vcResource == null) {
+ // TODO(vector-errors): uncoded IllegalStateException -> reaches the user as "Internal error".
throw HyracksDataException
.create(new IllegalStateException("Quantized VTree resource is not an LSMVTreeLocalResource: "
+ (resource == null ? "null" : resource.getClass().getName())));
}
if (!vcResource.hasQuantizationParams()) {
+ // TODO(vector-errors): uncoded IllegalStateException -> reaches the user as "Internal error".
throw HyracksDataException
.create(new IllegalStateException("Quantized VTree resource is missing quantization params"));
}
@@ -506,7 +515,7 @@ public class VTreeBulkLoaderAndGroupingOperatorDescriptor extends AbstractSingle
* @return QuantizedVector containing per-dimension quantized bytes (and metadata)
*/
private OptimizedScalarQuantizationCodec.QuantizedVector quantizeVector(double[] embedding,
- OptimizedScalarQuantizationCodec.Params params, String distanceMetric) {
+ OptimizedScalarQuantizationCodec.Params params, String distanceMetric) throws HyracksDataException {
if (embedding == null || params == null) {
return null;
}
@@ -521,18 +530,22 @@ public class VTreeBulkLoaderAndGroupingOperatorDescriptor extends AbstractSingle
throws HyracksDataException {
try {
if (queryVector == null) {
- throw new IllegalArgumentException("Query vector cannot be null");
+ throw HyracksDataException.create(ILLEGAL_STATE,
+ "A null query vector reached the vector index centroid search");
}
if (queryVector.length == 0) {
- throw new IllegalArgumentException("Query vector cannot be empty");
+ throw HyracksDataException.create(ILLEGAL_STATE,
+ "An empty query vector reached the vector index centroid search");
}
if (vcTreeAccessor == null) {
+ // TODO(vector-errors): uncoded IllegalStateException -> reaches the user as "Internal error".
throw new IllegalStateException("VTreeAccessor not initialized");
}
if (distanceFunction == null) {
+ // TODO(vector-errors): uncoded IllegalStateException -> reaches the user as "Internal error".
throw new IllegalStateException("DistanceFunction not initialized");
}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/VTreeStaticStructureCreatorOperatorDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/VTreeStaticStructureCreatorOperatorDescriptor.java
index 098d3c80fe..f4ef006539 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/VTreeStaticStructureCreatorOperatorDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/VTreeStaticStructureCreatorOperatorDescriptor.java
@@ -18,6 +18,8 @@
*/
package org.apache.asterix.runtime.operators;
+import static org.apache.hyracks.api.exceptions.ErrorCode.ILLEGAL_STATE;
+
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
@@ -25,6 +27,8 @@ import java.util.List;
import java.util.Map;
import org.apache.asterix.common.dataflow.DatasetLocalResource;
+import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.exceptions.RuntimeDataException;
import org.apache.asterix.common.ioopcallbacks.LSMIOOperationCallback;
import org.apache.asterix.common.vector.OptimizedScalarQuantizationCodec;
import org.apache.asterix.om.types.ATypeTag;
@@ -327,7 +331,8 @@ public class VTreeStaticStructureCreatorOperatorDescriptor extends AbstractOpera
}
if (embedding == null || embedding.length == 0) {
- throw new HyracksDataException("Failed to extract embedding from hierarchical tuple");
+ throw new RuntimeDataException(ErrorCode.COMPILATION_VECTOR_INDEX_CREATION_FAILED,
+ "Failed to extract an embedding from a centroid tuple");
}
// Check if this is a leaf level (maxLevel) - apply quantization only to leaf nodes
@@ -342,7 +347,8 @@ public class VTreeStaticStructureCreatorOperatorDescriptor extends AbstractOpera
}
} catch (Exception e) {
- throw new HyracksDataException("Failed to convert tuple to VCTreeBuilder format", e);
+ throw new RuntimeDataException(ErrorCode.COMPILATION_VECTOR_INDEX_CREATION_FAILED, e,
+ "Failed to convert a centroid tuple to the static-structure builder format");
}
}
@@ -411,8 +417,9 @@ public class VTreeStaticStructureCreatorOperatorDescriptor extends AbstractOpera
quantizedBytes[i * 4 + 3] = (byte) ints[i];
}
} else {
- throw new HyracksDataException(
- "Unexpected quantized bytes type: " + quantizedResult.quantizedBytes.getClass());
+ throw new RuntimeDataException(ErrorCode.COMPILATION_VECTOR_INDEX_CREATION_FAILED,
+ "Unexpected quantized-bytes type "
+ + quantizedResult.quantizedBytes.getClass().getName());
}
// Create 4-field tuple: [centroidId, embedding, quantizedBytes, neighborList].
@@ -467,10 +474,10 @@ public class VTreeStaticStructureCreatorOperatorDescriptor extends AbstractOpera
List<List<Integer>> centroidsPerCluster = new ArrayList<>();
if (levelDistribution == null || levelDistribution.isEmpty()) {
- throw HyracksDataException.create(
- new RuntimeException("Cannot build vector index: no training vectors were found. "
- + "Verify that the indexed field exists in the dataset and contains vector data, "
- + "and that sampling produced enough vectors for train_list_fraction."));
+ throw new RuntimeDataException(ErrorCode.COMPILATION_VECTOR_INDEX_CREATION_FAILED,
+ "No training vectors were found. Verify that the indexed field exists in the "
+ + "collection and contains vector data, and that sampling produced enough "
+ + "vectors for train_list_fraction");
}
// Find max level
@@ -571,14 +578,16 @@ public class VTreeStaticStructureCreatorOperatorDescriptor extends AbstractOpera
IIndex indexInstance = partitionHelper.getIndexInstance();
if (!(indexInstance instanceof ILSMIndex)) {
- throw new HyracksDataException("Index is not an ILSMIndex instance, got: "
- + (indexInstance != null ? indexInstance.getClass().getName() : "null"));
+ throw HyracksDataException.create(ILLEGAL_STATE,
+ "The vector index resource is not an ILSMIndex, but a "
+ + (indexInstance != null ? indexInstance.getClass().getName() : "null"));
}
ILSMIndex partitionLsmIndex = (ILSMIndex) indexInstance;
if (!(partitionLsmIndex instanceof LSMVTree)) {
- throw new HyracksDataException("Index is not an LSMVTree instance, got: "
- + partitionLsmIndex.getClass().getName());
+ throw HyracksDataException.create(ILLEGAL_STATE,
+ "The vector index resource is not an LSMVTree, but a "
+ + partitionLsmIndex.getClass().getName());
}
Map<String, Object> parameters = new HashMap<>();
@@ -678,7 +687,7 @@ public class VTreeStaticStructureCreatorOperatorDescriptor extends AbstractOpera
case BIGINT:
return LongPointable.getLong(data, start + 1);
default:
- throw new HyracksDataException("Unsupported numeric type: " + typeTag);
+ throw new RuntimeDataException(ErrorCode.UNSUPPORTED_VECTOR_ELEMENT_TYPE, typeTag);
}
}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/VectorComponentExtractorOperatorDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/VectorComponentExtractorOperatorDescriptor.java
index 0fd68f1037..9c26424e3a 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/VectorComponentExtractorOperatorDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/operators/VectorComponentExtractorOperatorDescriptor.java
@@ -200,7 +200,8 @@ public class VectorComponentExtractorOperatorDescriptor extends AbstractSingleAc
appender.reset(new VSizeFrame(ctx), true);
if (!appender.append(tupleBuilder.getFieldEndOffsets(), tupleBuilder.getByteArray(), 0,
tupleBuilder.getSize())) {
- throw HyracksDataException.create(new IOException("Tuple too large to fit in frame"));
+ throw new RuntimeDataException(ErrorCode.COMPILATION_VECTOR_INDEX_CREATION_FAILED,
+ "A vector is too large to fit in a single frame");
}
}
} catch (IOException e) {
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/utils/VectorDistanceCalculation.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/utils/VectorDistanceCalculation.java
index b7d7f9e817..59c0367d67 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/utils/VectorDistanceCalculation.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/utils/VectorDistanceCalculation.java
@@ -19,6 +19,8 @@
package org.apache.asterix.runtime.utils;
+import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.exceptions.RuntimeDataException;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.data.std.primitive.DoublePointable;
import org.apache.hyracks.dataflow.common.data.marshalling.DoubleArraySerializerDeserializer;
@@ -244,8 +246,7 @@ public class VectorDistanceCalculation {
private static int checkedLength(byte[] bytes, int offset, int length, double[] dst) throws HyracksDataException {
int len = DoubleArraySerializerDeserializer.readLength(bytes, offset, length);
if (dst != null && dst.length != len) {
- throw HyracksDataException.create(new IllegalArgumentException(
- "destination has " + dst.length + " elements but the encoded array has " + len));
+ throw new RuntimeDataException(ErrorCode.VECTOR_DIMENSION_MISMATCH, dst.length, len);
}
return len;
}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/utils/VectorDistanceFunctionFactory.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/utils/VectorDistanceFunctionFactory.java
index 429fb11a81..72c43de850 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/utils/VectorDistanceFunctionFactory.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/utils/VectorDistanceFunctionFactory.java
@@ -63,7 +63,7 @@ public class VectorDistanceFunctionFactory implements IVTreeDistanceFunctionFact
}
@Override
- public IVTreeDistanceFunction createDistanceFunction() throws HyracksDataException {
+ public IVTreeDistanceFunction createDistanceFunction() {
return functionFor(metric);
}
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java
index d83270f118..fd9bf738c4 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java
@@ -163,6 +163,9 @@ public enum ErrorCode implements IError {
EMPTY_TYPE_INFERRED(133),
SCHEMA_LIMIT_EXCEEDED(134),
FAILED_IO_OPERATION(135),
+ VECTOR_INDEX_BUILD_FAILED(136),
+ MALFORMED_VECTOR_INDEX(137),
+ UNEXPECTED_VECTOR_VALUE(138),
// Compilation error codes.
RULECOLLECTION_NOT_INSTANCE_OF_LIST(10000),
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties b/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties
index 8e16262c78..a8e0de33a9 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties
@@ -153,6 +153,9 @@
133 = Schema could not be inferred, empty types found in the result
134 = Schema Limit exceeded, maximum number of heterogeneous schemas allowed : '%1$s'
135 = An IO Operation has failed
+136 = Failed to build the vector index. %1$s
+137 = Malformed vector index. %1$s
+138 = Encountered unexpected vector. %1$s
10000 = The given rule collection %1$s is not an instance of the List class.
10001 = Cannot compose partition constraint %1$s with %2$s
diff --git a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/marshalling/DoubleArraySerializerDeserializer.java b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/marshalling/DoubleArraySerializerDeserializer.java
index 90acfde418..58430f0e56 100644
--- a/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/marshalling/DoubleArraySerializerDeserializer.java
+++ b/hyracks-fullstack/hyracks/hyracks-dataflow-common/src/main/java/org/apache/hyracks/dataflow/common/data/marshalling/DoubleArraySerializerDeserializer.java
@@ -20,10 +20,10 @@ package org.apache.hyracks.dataflow.common.data.marshalling;
import java.io.DataInput;
import java.io.DataOutput;
-import java.io.EOFException;
import java.io.IOException;
import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
+import org.apache.hyracks.api.exceptions.ErrorCode;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.data.std.primitive.DoublePointable;
import org.apache.hyracks.data.std.primitive.IntegerPointable;
@@ -96,14 +96,14 @@ public class DoubleArraySerializerDeserializer implements ISerializerDeserialize
*/
public static int readLength(byte[] bytes, int offset, int length) throws HyracksDataException {
if (length < Integer.BYTES) {
- throw HyracksDataException.create(new EOFException(
- "array field is " + length + " bytes, need at least " + Integer.BYTES + " for the length prefix"));
+ throw HyracksDataException.create(ErrorCode.MALFORMED_VECTOR_INDEX, "The encoded array field is " + length
+ + " bytes, but at least " + Integer.BYTES + " are needed for the length prefix");
}
int len = IntegerPointable.getInteger(bytes, offset);
long required = (long) Integer.BYTES + (long) len * Double.BYTES;
if (len < 0 || required > length) {
- throw HyracksDataException.create(new EOFException(
- "encoded array length " + len + " needs " + required + " bytes but the field is " + length));
+ throw HyracksDataException.create(ErrorCode.MALFORMED_VECTOR_INDEX, "The encoded array declares " + len
+ + " elements, needing " + required + " bytes, but the field is " + length + " bytes");
}
return len;
}
@@ -117,8 +117,8 @@ public class DoubleArraySerializerDeserializer implements ISerializerDeserialize
public static void readInto(byte[] bytes, int offset, int length, double[] dst) throws HyracksDataException {
int len = readLength(bytes, offset, length);
if (dst.length != len) {
- throw HyracksDataException.create(new IllegalArgumentException(
- "destination has " + dst.length + " elements but the encoded array has " + len));
+ throw HyracksDataException.create(ErrorCode.UNEXPECTED_VECTOR_VALUE,
+ "Expected to see " + dst.length + " elements but the encoded vector has " + len);
}
decode(bytes, offset, dst, len);
}
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/dataflow/LSMVTreeLocalResource.java b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/dataflow/LSMVTreeLocalResource.java
index e6f928702a..2c891aba65 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/dataflow/LSMVTreeLocalResource.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/dataflow/LSMVTreeLocalResource.java
@@ -186,14 +186,14 @@ public class LSMVTreeLocalResource extends LsmResource implements IQuantizedReso
// tripped through the resource registry on JSON read. A null here indicates a corrupted
// resource (e.g., a JSON file with the {@link #KEY_VECTOR_ACCESSOR_FACTORY} key missing).
if (vectorAccessorFactory == null) {
- throw new HyracksDataException("Vector accessor factory missing from LSMVTreeLocalResource (path=" + path
- + "); resource is corrupted or was written by an unsupported codebase version.");
+ throw HyracksDataException.create(ErrorCode.ILLEGAL_STATE,
+ "The vector accessor factory is missing from the resource at " + path);
}
// Distance-function factory is always supplied at DDL and round-tripped through the registry;
// a null indicates a corrupted or unsupported-version resource.
if (distanceFunctionFactory == null) {
- throw new HyracksDataException("Distance-function factory missing from LSMVTreeLocalResource (path=" + path
- + "); resource is corrupted or was written by an unsupported codebase version.");
+ throw HyracksDataException.create(ErrorCode.ILLEGAL_STATE,
+ "The distance-function factory is missing from the resource at " + path);
}
// Quantization params for lazy quantizer creation at query time
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/dataflow/QuantizedIndexCreateOperatorDescriptor.java b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/dataflow/QuantizedIndexCreateOperatorDescriptor.java
index 54d77a32aa..fbecb7caea 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/dataflow/QuantizedIndexCreateOperatorDescriptor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/dataflow/QuantizedIndexCreateOperatorDescriptor.java
@@ -179,7 +179,8 @@ public class QuantizedIndexCreateOperatorDescriptor extends AbstractSingleActivi
indexBuilder.build();
}
} else {
- throw new HyracksDataException("QuantizedIndexCreateOperator: No quantization constants received.");
+ throw HyracksDataException.create(ErrorCode.VECTOR_INDEX_BUILD_FAILED,
+ "No quantization constants were received");
}
}
}
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/dataflow/VTreeSearchOperatorNodePushable.java b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/dataflow/VTreeSearchOperatorNodePushable.java
index 849a869a16..f67733dd1c 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/dataflow/VTreeSearchOperatorNodePushable.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/dataflow/VTreeSearchOperatorNodePushable.java
@@ -265,6 +265,9 @@ public class VTreeSearchOperatorNodePushable extends IndexSearchOperatorNodePush
value = LongPointable.getLong(data, valueOffset);
break;
default:
+ // TODO(vector-errors): uncoded IllegalStateException -> reaches the user as "Internal error".
+ // The compiler types the query-parameters tuple, so a non-integer tag here is a plan bug
+ // rather than bad user input; confirm before coding it.
throw new IllegalStateException("Unexpected type tag " + typeTag + " for integer query parameter at "
+ "position " + fieldIndex + " of the vector-search query-parameters tuple");
}
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/LSMVTree.java b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/LSMVTree.java
index ac55787f31..f35746f147 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/LSMVTree.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/LSMVTree.java
@@ -252,6 +252,9 @@ public class LSMVTree extends AbstractLSMIndex implements ITreeIndex {
public LSMVTreeDiskComponent getStaticStructure() {
if (staticStructure == null) {
+ // TODO(vector-errors): uncoded IllegalStateException -> reaches the user as "Internal error".
+ // getStaticStructure() has no throws clause, so coding this needs a signature change; decide
+ // whether that is worth it or whether the invariant should stay unchecked.
throw new IllegalStateException("Static structure must be built before loading records");
}
return staticStructure;
@@ -375,9 +378,10 @@ public class LSMVTree extends AbstractLSMIndex implements ITreeIndex {
}
@Override
- public void scanDiskComponents(ILSMIndexOperationContext ictx, IIndexCursor cursor) {
+ public void scanDiskComponents(ILSMIndexOperationContext ictx, IIndexCursor cursor) throws HyracksDataException {
// Vector clustering trees don't support disk-component scanning the way BTrees do.
- throw new UnsupportedOperationException("Disk component scanning not supported for vector clustering trees");
+ throw HyracksDataException.create(ErrorCode.INVALID_OPERATOR_OPERATION, "scanDiskComponents",
+ LSMVTree.class.getSimpleName());
}
@Override
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/LSMVTreeDiskComponent.java b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/LSMVTreeDiskComponent.java
index 9cc0d83493..0799c3b927 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/LSMVTreeDiskComponent.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/LSMVTreeDiskComponent.java
@@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.apache.hyracks.api.exceptions.ErrorCode;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.control.common.controllers.NCConfig;
import org.apache.hyracks.storage.am.common.api.IMetadataPageManager;
@@ -178,9 +179,10 @@ public class LSMVTreeDiskComponent extends AbstractLSMDiskComponent {
Integer maxEntriesParam = (Integer) parameters.get(PARAM_MAX_ENTRIES_PER_PAGE);
if (numLevelsParam == null || clustersPerLevel == null || centroidsPerCluster == null
|| maxEntriesParam == null) {
- throw new HyracksDataException("static-structure bulk load requires non-null " + PARAM_NUM_LEVELS + ", "
- + PARAM_CLUSTERS_PER_LEVEL + ", " + PARAM_CENTROIDS_PER_CLUSTER + ", and "
- + PARAM_MAX_ENTRIES_PER_PAGE + " parameters");
+ throw HyracksDataException.create(ErrorCode.ILLEGAL_STATE,
+ "A static-structure bulk load requires non-null " + PARAM_NUM_LEVELS + ", "
+ + PARAM_CLUSTERS_PER_LEVEL + ", " + PARAM_CENTROIDS_PER_CLUSTER + " and "
+ + PARAM_MAX_ENTRIES_PER_PAGE + " parameters");
}
int numLevels = numLevelsParam;
int maxEntriesPerPage = maxEntriesParam;
@@ -198,8 +200,8 @@ public class LSMVTreeDiskComponent extends AbstractLSMDiskComponent {
private IChainedComponentBulkLoader createVTreeBulkLoader(ILSMIOOperation operation) throws HyracksDataException {
Object staticParam = operation.getParameters().get(PARAM_STATIC_STRUCTURE_COMPONENT);
if (!(staticParam instanceof LSMVTreeDiskComponent staticComponent)) {
- throw new HyracksDataException(
- PARAM_STATIC_STRUCTURE_COMPONENT + " must be provided in parameters for data loading");
+ throw HyracksDataException.create(ErrorCode.ILLEGAL_STATE,
+ PARAM_STATIC_STRUCTURE_COMPONENT + " must be provided in the parameters for data loading");
}
ITreeIndexAccessor staticAccessor =
staticComponent.getIndex().createAccessor(NoOpIndexAccessParameters.INSTANCE);
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/LSMVTreeSearchCursor.java b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/LSMVTreeSearchCursor.java
index 77598be05c..023b53ba60 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/LSMVTreeSearchCursor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/LSMVTreeSearchCursor.java
@@ -746,6 +746,9 @@ public class LSMVTreeSearchCursor extends LSMIndexSearchCursor {
// Merge ordering shares the exact <distance, PK> key with antimatter cancellation.
result = compareKey(cmp, tupleA, tupleB);
} catch (Throwable e) {
+ // Matches the LSMIndexSearchCursor / LSMRTree / LSMBTree comparator idiom: Comparator.compare
+ // cannot throw a checked exception. The cause is a coded HyracksDataException and
+ // ExceptionUtils.unwrap() follows it, so the error code survives to the user.
throw new IllegalArgumentException(e);
}
if (result != 0) {
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/LSMVTreeTopKSearchCursor.java b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/LSMVTreeTopKSearchCursor.java
index 1a51cc7e0e..2ad7b52f4e 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/LSMVTreeTopKSearchCursor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/LSMVTreeTopKSearchCursor.java
@@ -274,8 +274,8 @@ public class LSMVTreeTopKSearchCursor extends EnforcedIndexCursor implements IVe
this.quantizer = firstSearchCursor.getQuantizer();
if (this.queryVector == null) {
- throw HyracksDataException
- .create(new IllegalArgumentException("Query vector must be provided for naive blocked search"));
+ throw HyracksDataException.create(ErrorCode.ILLEGAL_STATE,
+ "A query vector is required for the vector index blocked search");
}
// computeApproximateDistance() dequantizes every candidate with these two, and they arrive
@@ -700,6 +700,7 @@ public class LSMVTreeTopKSearchCursor extends EnforcedIndexCursor implements IVe
@Override
protected void doNext() throws HyracksDataException {
if (!doHasNext()) {
+ // TODO(vector-errors): uncoded IllegalStateException -> reaches the user as "Internal error".
throw HyracksDataException.create(new IllegalStateException("No more tuples"));
}
drainIterator.next();
@@ -824,6 +825,9 @@ public class LSMVTreeTopKSearchCursor extends EnforcedIndexCursor implements IVe
}
}
} catch (Throwable e) {
+ // Matches the LSMIndexSearchCursor / LSMRTree / LSMBTree comparator idiom: Comparator.compare
+ // cannot throw a checked exception. The cause is a coded HyracksDataException and
+ // ExceptionUtils.unwrap() follows it, so the error code survives to the user.
throw new IllegalArgumentException(e);
}
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/PKOnlyTupleProjector.java b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/PKOnlyTupleProjector.java
index 3bff0f09ca..e58ae8b94b 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/PKOnlyTupleProjector.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-vtree/src/main/java/org/apache/hyracks/storage/am/lsm/vector/impls/PKOnlyTupleProjector.java
@@ -21,6 +21,8 @@ package org.apache.hyracks.storage.am.lsm.vector.impls;
import java.io.DataOutput;
import java.io.IOException;
+import org.apache.hyracks.api.exceptions.ErrorCode;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.dataflow.common.comm.io.ArrayTupleBuilder;
import org.apache.hyracks.dataflow.common.data.accessors.ITupleReference;
import org.apache.hyracks.storage.common.projection.ITupleProjector;
@@ -57,8 +59,8 @@ public class PKOnlyTupleProjector implements ITupleProjector {
int endField = numSecondaryKeys + numPrimaryKeys;
if (endField > totalFields) {
- throw new IOException("Invalid field range: trying to extract fields [" + startField + ", " + endField
- + ") from tuple with " + totalFields + " fields");
+ throw HyracksDataException.create(ErrorCode.ILLEGAL_STATE, "The primary-key projection needs fields ["
+ + startField + ", " + endField + ") of a tuple that only has " + totalFields + " fields");
}
for (int i = startField; i < endField; i++) {
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/api/IVTreeDistanceFunctionFactory.java b/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/api/IVTreeDistanceFunctionFactory.java
index 12229bb572..b37e8e071c 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/api/IVTreeDistanceFunctionFactory.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/api/IVTreeDistanceFunctionFactory.java
@@ -20,7 +20,6 @@ package org.apache.hyracks.storage.am.vector.api;
import java.io.Serializable;
-import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.api.io.IJsonSerializable;
/**
@@ -42,5 +41,5 @@ public interface IVTreeDistanceFunctionFactory extends Serializable, IJsonSerial
* index creation (it is determined by the embedding model) and baked into the concrete factory, so
* Hyracks never passes or is aware of a metric string. Must not return {@code null}.
*/
- IVTreeDistanceFunction createDistanceFunction() throws HyracksDataException;
+ IVTreeDistanceFunction createDistanceFunction();
}
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/frames/VTreeNSMFrame.java b/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/frames/VTreeNSMFrame.java
index 6574156cb4..bdec9eba50 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/frames/VTreeNSMFrame.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/frames/VTreeNSMFrame.java
@@ -19,6 +19,7 @@
package org.apache.hyracks.storage.am.vector.frames;
+import org.apache.hyracks.api.exceptions.ErrorCode;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.dataflow.common.data.accessors.ITupleReference;
import org.apache.hyracks.storage.am.common.api.ISlotManager;
@@ -127,7 +128,8 @@ public abstract class VTreeNSMFrame extends TreeIndexNSMFrame implements IVTreeF
IExtraPageBlockHelper extraPageBlockHelper, IBufferCache bufferCache) throws HyracksDataException {
// Generic split is not supported on VTree frames; subclasses that split (e.g. data/metadata frames)
// expose their own split(...) entry points with the right argument types.
- throw new HyracksDataException("Split operation not implemented for " + this.getClass().getSimpleName());
+ throw HyracksDataException.create(ErrorCode.INVALID_OPERATOR_OPERATION, "split",
+ this.getClass().getSimpleName());
}
@Override
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTree.java b/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTree.java
index 2a779e3294..0891328f1f 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTree.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTree.java
@@ -194,7 +194,8 @@ public class VTree extends AbstractTreeIndex {
public IIndexBulkLoader createBulkLoader(float fillFactor, boolean verifyInput, long numElementsHint,
boolean checkIfEmptyIndex, ISketchSampler sampler, IPageWriteCallback callback)
throws HyracksDataException {
- throw new UnsupportedOperationException();
+ throw HyracksDataException.create(ErrorCode.INVALID_OPERATOR_OPERATION, "createBulkLoader",
+ VTree.class.getSimpleName());
}
/**
@@ -1188,7 +1189,8 @@ public class VTree extends AbstractTreeIndex {
@Override
public void update(ITupleReference tuple) throws HyracksDataException {
ctx.setOperation(IndexOperation.UPDATE);
- throw new UnsupportedOperationException();
+ throw HyracksDataException.create(ErrorCode.INVALID_OPERATOR_OPERATION, "update",
+ VTree.class.getSimpleName());
}
@Override
@@ -1200,7 +1202,8 @@ public class VTree extends AbstractTreeIndex {
@Override
public void upsert(ITupleReference tuple) throws HyracksDataException {
- throw new UnsupportedOperationException();
+ throw HyracksDataException.create(ErrorCode.INVALID_OPERATOR_OPERATION, "upsert",
+ VTree.class.getSimpleName());
}
@Override
@@ -1383,7 +1386,8 @@ public class VTree extends AbstractTreeIndex {
@Override
public void diskOrderScan(ITreeIndexCursor cursor) throws HyracksDataException {
ctx.setOperation(IndexOperation.DISKORDERSCAN);
- throw new UnsupportedOperationException("Disk order scan not yet implemented");
+ throw HyracksDataException.create(ErrorCode.INVALID_OPERATOR_OPERATION, "diskOrderScan",
+ VTree.class.getSimpleName());
}
public VTreeOpContext getOpContext() {
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTreeBulkLoader.java b/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTreeBulkLoader.java
index d7698af75d..143caf7f0a 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTreeBulkLoader.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTreeBulkLoader.java
@@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map;
import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
+import org.apache.hyracks.api.exceptions.ErrorCode;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.data.std.primitive.IntegerPointable;
import org.apache.hyracks.data.std.primitive.LongPointable;
@@ -377,7 +378,8 @@ public class VTreeBulkLoader extends PageWriteFailureCallback implements IIndexB
} catch (HyracksDataException e) {
throw e;
} catch (Exception e) {
- throw new HyracksDataException("Failed to create directory entry", e);
+ throw HyracksDataException.create(ErrorCode.VECTOR_INDEX_BUILD_FAILED, e,
+ "Failed to create a directory entry");
}
}
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTreeFlushLoader.java b/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTreeFlushLoader.java
index 71cac4e50e..7670dbe9ff 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTreeFlushLoader.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTreeFlushLoader.java
@@ -18,6 +18,7 @@
*/
package org.apache.hyracks.storage.am.vector.impls;
+import org.apache.hyracks.api.exceptions.ErrorCode;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.data.std.primitive.LongPointable;
import org.apache.hyracks.dataflow.common.data.accessors.ITupleReference;
@@ -73,7 +74,8 @@ public class VTreeFlushLoader extends PageWriteFailureCallback implements IIndex
@Override
public void add(ITupleReference tuple) throws HyracksDataException {
- throw new UnsupportedOperationException("Use copyPage() instead");
+ throw HyracksDataException.create(ErrorCode.INVALID_OPERATOR_OPERATION, "add (use copyPage instead)",
+ VTreeFlushLoader.class.getSimpleName());
}
/**
@@ -237,7 +239,9 @@ public class VTreeFlushLoader extends PageWriteFailureCallback implements IIndex
@Override
public void end() throws HyracksDataException {
- throw new UnsupportedOperationException("Use end(numLeafCentroid, firstLeafCentroidId, rootPageId) instead");
+ throw HyracksDataException.create(ErrorCode.INVALID_OPERATOR_OPERATION,
+ "end (use end(numLeafCentroid, firstLeafCentroidId, rootPageId) instead)",
+ VTreeFlushLoader.class.getSimpleName());
}
@Override
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTreeSearchCursor.java b/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTreeSearchCursor.java
index e7019dbdd1..8a1e1aefe4 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTreeSearchCursor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTreeSearchCursor.java
@@ -27,6 +27,7 @@ import java.util.Map;
import java.util.Queue;
import java.util.Set;
+import org.apache.hyracks.api.exceptions.ErrorCode;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.dataflow.common.data.accessors.ITupleReference;
import org.apache.hyracks.storage.am.common.api.ITreeIndexFrameFactory;
@@ -291,6 +292,7 @@ public class VTreeSearchCursor extends EnforcedIndexCursor {
// value means the caller bypassed that path and the search cannot proceed safely.
this.distanceFunction = vectorState.getDistanceFunction();
if (this.distanceFunction == null) {
+ // TODO(vector-errors): uncoded IllegalStateException -> reaches the user as "Internal error".
throw new IllegalStateException(
"VTreeSearchCursor opened without a distance function on the initial state");
}
@@ -306,8 +308,8 @@ public class VTreeSearchCursor extends EnforcedIndexCursor {
// Query mode: Find closest cluster using DFS
// NOTE: Level-wise exploration is handled by LSM layer via openClusterById()
if (this.queryVector == null) {
- throw HyracksDataException
- .create(new IllegalArgumentException("Query vector must be provided for centroid finding"));
+ throw HyracksDataException.create(ErrorCode.ILLEGAL_STATE,
+ "A query vector is required for vector index centroid finding");
}
// Create navigation state for iterative DFS with shared visited set
@@ -370,9 +372,11 @@ public class VTreeSearchCursor extends EnforcedIndexCursor {
@Override
protected void doNext() throws HyracksDataException {
if (!isOpen) {
+ // TODO(vector-errors): uncoded IllegalStateException -> reaches the user as "Internal error".
throw HyracksDataException.create(new IllegalStateException("Cursor is not open"));
}
if (!doHasNext()) {
+ // TODO(vector-errors): uncoded IllegalStateException -> reaches the user as "Internal error".
throw HyracksDataException.create(new IllegalStateException("No more tuples"));
}
@@ -423,6 +427,9 @@ public class VTreeSearchCursor extends EnforcedIndexCursor {
this.totalLeafClusters = totalClusters;
if (this.totalLeafClusters == 0) {
+ // TODO(vector-errors): uncoded IllegalStateException -> reaches the user as "Internal error".
+ // An empty vector index is arguably a normal state a query should tolerate rather than an
+ // error; decide whether this should return "no results" instead.
throw HyracksDataException.create(new IllegalStateException("No leaf centroids found - empty index"));
}
@@ -466,6 +473,7 @@ public class VTreeSearchCursor extends EnforcedIndexCursor {
if (interiorFrame.getTupleCount() > 0) {
currentPageId = interiorFrame.getChildPageId(0);
} else {
+ // TODO(vector-errors): uncoded IllegalStateException -> reaches the user as "Internal error".
throw HyracksDataException
.create(new IllegalStateException("Empty interior page encountered during navigation"));
}
@@ -858,6 +866,7 @@ public class VTreeSearchCursor extends EnforcedIndexCursor {
*/
private IVTreeMetadataFrame createMetadataFrame() {
if (metadataFrameFactory == null) {
+ // TODO(vector-errors): uncoded IllegalStateException -> reaches the user as "Internal error".
throw new IllegalStateException("Metadata frame factory not set");
}
return (IVTreeMetadataFrame) metadataFrameFactory.createFrame();
@@ -868,6 +877,7 @@ public class VTreeSearchCursor extends EnforcedIndexCursor {
*/
private IVTreeDataFrame createDataFrame() {
if (dataFrameFactory == null) {
+ // TODO(vector-errors): uncoded IllegalStateException -> reaches the user as "Internal error".
throw new IllegalStateException("Data frame factory not set");
}
return (IVTreeDataFrame) dataFrameFactory.createFrame();
@@ -996,6 +1006,7 @@ public class VTreeSearchCursor extends EnforcedIndexCursor {
*/
private IVTreeInteriorFrame createInteriorFrame() {
if (interiorFrameFactory == null) {
+ // TODO(vector-errors): uncoded IllegalStateException -> reaches the user as "Internal error".
throw new IllegalStateException("Interior frame factory not set");
}
return (IVTreeInteriorFrame) interiorFrameFactory.createFrame();
@@ -1003,6 +1014,7 @@ public class VTreeSearchCursor extends EnforcedIndexCursor {
private IVTreeLeafFrame createLeafFrame() {
if (leafFrameFactory == null) {
+ // TODO(vector-errors): uncoded IllegalStateException -> reaches the user as "Internal error".
throw new IllegalStateException("Leaf frame factory not set");
}
return (IVTreeLeafFrame) leafFrameFactory.createFrame();
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTreeStaticStructureBuilder.java b/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTreeStaticStructureBuilder.java
index 9ae0488944..fbefdc002d 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTreeStaticStructureBuilder.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/impls/VTreeStaticStructureBuilder.java
@@ -25,6 +25,7 @@ import java.util.List;
import java.util.Map;
import java.util.TreeSet;
+import org.apache.hyracks.api.exceptions.ErrorCode;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.data.std.primitive.IntegerPointable;
import org.apache.hyracks.data.std.primitive.LongPointable;
@@ -237,6 +238,7 @@ public class VTreeStaticStructureBuilder extends PageWriteFailureCallback implem
int childClusterIndex = computeChildClusterIndex();
int childPageId = firstPageIdOfCluster[currentLevel + 1][childClusterIndex];
if (childPageId < 0) {
+ // TODO(vector-errors): uncoded IllegalStateException -> reaches the user as "Internal error".
throw new IllegalStateException(
"Child page id not yet recorded for level=" + (currentLevel + 1) + ", cluster=" + childClusterIndex
+ ". Input must be in bottom-up order (leaf level first, root last).");
@@ -302,7 +304,8 @@ public class VTreeStaticStructureBuilder extends PageWriteFailureCallback implem
return entryTupleRef;
} catch (Exception e) {
LOGGER.log(Level.TRACE, "Error creating entry tuple: {}", e.getMessage());
- throw new HyracksDataException("Failed to create entry tuple", e);
+ throw HyracksDataException.create(ErrorCode.VECTOR_INDEX_BUILD_FAILED, e,
+ "Failed to create an entry tuple");
}
}
@@ -528,6 +531,7 @@ public class VTreeStaticStructureBuilder extends PageWriteFailureCallback implem
// also the page with the highest id since the root level is processed last.
int rootPageId = firstPageIdOfCluster[0][0];
if (rootPageId < 0) {
+ // TODO(vector-errors): uncoded IllegalStateException -> reaches the user as "Internal error".
throw HyracksDataException
.create(new IllegalStateException("Root page id was never recorded; static structure incomplete."));
}
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/utils/NoOpVectorQuantizer.java b/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/utils/NoOpVectorQuantizer.java
index 33a97bb043..dcdd4252fd 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/utils/NoOpVectorQuantizer.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-vtree/src/main/java/org/apache/hyracks/storage/am/vector/utils/NoOpVectorQuantizer.java
@@ -20,6 +20,7 @@ package org.apache.hyracks.storage.am.vector.utils;
import java.nio.ByteBuffer;
+import org.apache.hyracks.api.exceptions.ErrorCode;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.storage.am.vector.api.IVTreeQuantizer;
@@ -43,8 +44,8 @@ public class NoOpVectorQuantizer implements IVTreeQuantizer {
// caller failed to strip a length prefix (or passed a truncated buffer). Fail loudly here
// (test-only helper) rather than silently dropping trailing bytes.
if (quantizedBytes.length % Double.BYTES != 0) {
- throw new IllegalArgumentException("quantizedBytes length " + quantizedBytes.length
- + " is not a multiple of Double.BYTES (" + Double.BYTES + ")");
+ throw HyracksDataException.create(ErrorCode.ILLEGAL_STATE, "The quantized vector is "
+ + quantizedBytes.length + " bytes, which is not a multiple of " + Double.BYTES);
}
int count = quantizedBytes.length / Double.BYTES;
diff --git a/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/vector/TestDoubleArrayVectorAccessor.java b/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/vector/TestDoubleArrayVectorAccessor.java
index 98ec7e321e..698c76072a 100644
--- a/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/vector/TestDoubleArrayVectorAccessor.java
+++ b/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/vector/TestDoubleArrayVectorAccessor.java
@@ -22,6 +22,7 @@ package org.apache.hyracks.storage.am.vector;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
+import org.apache.hyracks.api.exceptions.ErrorCode;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.api.io.IPersistedResourceRegistry;
import org.apache.hyracks.dataflow.common.data.marshalling.DoubleArraySerializerDeserializer;
@@ -64,7 +65,8 @@ public class TestDoubleArrayVectorAccessor implements IVTreeBinaryAccessor {
public int getDimension() throws HyracksDataException {
// Format: [int:length][double:v0]...
if (length < Integer.BYTES) {
- throw new HyracksDataException("Invalid vector data: too short to read dimension");
+ throw HyracksDataException.create(ErrorCode.UNEXPECTED_VECTOR_VALUE,
+ "The vector data is too short to read a dimension");
}
return ((data[start] & 0xFF) << 24) | ((data[start + 1] & 0xFF) << 16) | ((data[start + 2] & 0xFF) << 8)
| (data[start + 3] & 0xFF);