This is an automated email from the ASF dual-hosted git repository.
adelapena pushed a commit to branch cassandra-5.0
in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/cassandra-5.0 by this push:
new 6befb178aa Remove support for empty values on the vector data type
6befb178aa is described below
commit 6befb178aa0b7ad669f5c30e8b53fdd69a225a7a
Author: Andrés de la Peña <[email protected]>
AuthorDate: Fri Sep 22 14:09:35 2023 +0100
Remove support for empty values on the vector data type
patch by Andrés de la Peña; reviewed by David Capwell and Maxwell Guo for
CASSANDRA-18876
---
CHANGES.txt | 1 +
src/java/org/apache/cassandra/cql3/Constants.java | 2 +-
.../db/marshal/AbstractCompositeType.java | 6 +++
.../cassandra/db/marshal/AbstractTimeUUIDType.java | 7 ++++
.../apache/cassandra/db/marshal/AbstractType.java | 2 +-
.../apache/cassandra/db/marshal/BooleanType.java | 7 ++++
.../org/apache/cassandra/db/marshal/ByteType.java | 6 ---
.../org/apache/cassandra/db/marshal/BytesType.java | 6 +++
.../cassandra/db/marshal/CollectionType.java | 6 ---
.../cassandra/db/marshal/CounterColumnType.java | 7 ++++
.../apache/cassandra/db/marshal/DecimalType.java | 7 ++++
.../apache/cassandra/db/marshal/DoubleType.java | 7 ++++
.../apache/cassandra/db/marshal/DurationType.java | 6 ---
.../org/apache/cassandra/db/marshal/FloatType.java | 7 ++++
.../cassandra/db/marshal/InetAddressType.java | 7 ++++
.../org/apache/cassandra/db/marshal/Int32Type.java | 7 ++++
.../apache/cassandra/db/marshal/IntegerType.java | 7 ++++
.../cassandra/db/marshal/LexicalUUIDType.java | 7 ++++
.../org/apache/cassandra/db/marshal/LongType.java | 7 ++++
.../org/apache/cassandra/db/marshal/ShortType.java | 6 ---
.../cassandra/db/marshal/SimpleDateType.java | 6 ---
.../apache/cassandra/db/marshal/StringType.java | 6 +++
.../org/apache/cassandra/db/marshal/TimeType.java | 6 ---
.../apache/cassandra/db/marshal/TimestampType.java | 6 +++
.../org/apache/cassandra/db/marshal/TupleType.java | 6 +++
.../org/apache/cassandra/db/marshal/UUIDType.java | 7 ++++
.../apache/cassandra/db/marshal/VectorType.java | 44 +++++++++++++++-------
.../cql3/validation/operations/CQLVectorTest.java | 43 +++++++++++++++++++++
28 files changed, 190 insertions(+), 52 deletions(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index bca22c4580..12c8fbc0e3 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
5.0-alpha2
+ * Remove support for empty values on the vector data type (CASSANDRA-18876)
* Upgrade Dropwizard Metrics to 4.2.19 (CASSANDRA-14667)
* Upgrade caffeine cache and fix CIDR permissions cache invalidation
(CASSANDRA-18805)
* Remove deprecated properties in CompressionParams (CASSANDRA-18742)
diff --git a/src/java/org/apache/cassandra/cql3/Constants.java
b/src/java/org/apache/cassandra/cql3/Constants.java
index 03341d22bd..be81bed3b0 100644
--- a/src/java/org/apache/cassandra/cql3/Constants.java
+++ b/src/java/org/apache/cassandra/cql3/Constants.java
@@ -292,7 +292,7 @@ public abstract class Constants
public AssignmentTestable.TestResult testAssignment(String keyspace,
ColumnSpecification receiver)
{
CQL3Type receiverType = receiver.type.asCQL3Type();
- if (receiverType.isCollection() || receiverType.isUDT())
+ if (receiverType.isCollection() || receiverType.isUDT() ||
receiverType.isVector())
return AssignmentTestable.TestResult.NOT_ASSIGNABLE;
if (!(receiverType instanceof CQL3Type.Native))
diff --git
a/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java
b/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java
index 350c124fa1..170363594f 100644
--- a/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java
+++ b/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java
@@ -41,6 +41,12 @@ public abstract class AbstractCompositeType extends
AbstractType<ByteBuffer>
super(ComparisonType.CUSTOM);
}
+ @Override
+ public boolean allowsEmpty()
+ {
+ return true;
+ }
+
public <VL, VR> int compareCustom(VL left, ValueAccessor<VL> accessorL, VR
right, ValueAccessor<VR> accessorR)
{
if (accessorL.isEmpty(left) || accessorR.isEmpty(right))
diff --git a/src/java/org/apache/cassandra/db/marshal/AbstractTimeUUIDType.java
b/src/java/org/apache/cassandra/db/marshal/AbstractTimeUUIDType.java
index 1c4088ee97..35778aff24 100644
--- a/src/java/org/apache/cassandra/db/marshal/AbstractTimeUUIDType.java
+++ b/src/java/org/apache/cassandra/db/marshal/AbstractTimeUUIDType.java
@@ -42,6 +42,13 @@ public abstract class AbstractTimeUUIDType<T> extends
TemporalType<T>
super(ComparisonType.CUSTOM);
} // singleton
+ @Override
+ public boolean allowsEmpty()
+ {
+ return true;
+ }
+
+ @Override
public boolean isEmptyValueMeaningless()
{
return true;
diff --git a/src/java/org/apache/cassandra/db/marshal/AbstractType.java
b/src/java/org/apache/cassandra/db/marshal/AbstractType.java
index 3f4124011b..fe8b549837 100644
--- a/src/java/org/apache/cassandra/db/marshal/AbstractType.java
+++ b/src/java/org/apache/cassandra/db/marshal/AbstractType.java
@@ -512,7 +512,7 @@ public abstract class AbstractType<T> implements
Comparator<ByteBuffer>, Assignm
*/
public boolean allowsEmpty()
{
- return true;
+ return false;
}
public boolean isNull(ByteBuffer bb)
diff --git a/src/java/org/apache/cassandra/db/marshal/BooleanType.java
b/src/java/org/apache/cassandra/db/marshal/BooleanType.java
index acaba5ba7a..471aa8dc2d 100644
--- a/src/java/org/apache/cassandra/db/marshal/BooleanType.java
+++ b/src/java/org/apache/cassandra/db/marshal/BooleanType.java
@@ -38,6 +38,13 @@ public class BooleanType extends AbstractType<Boolean>
BooleanType() {super(ComparisonType.CUSTOM);} // singleton
+ @Override
+ public boolean allowsEmpty()
+ {
+ return true;
+ }
+
+ @Override
public boolean isEmptyValueMeaningless()
{
return true;
diff --git a/src/java/org/apache/cassandra/db/marshal/ByteType.java
b/src/java/org/apache/cassandra/db/marshal/ByteType.java
index 720168bcb3..614bdf9052 100644
--- a/src/java/org/apache/cassandra/db/marshal/ByteType.java
+++ b/src/java/org/apache/cassandra/db/marshal/ByteType.java
@@ -46,12 +46,6 @@ public class ByteType extends NumberType<Byte>
super(ComparisonType.CUSTOM);
} // singleton
- @Override
- public boolean allowsEmpty()
- {
- return false;
- }
-
public <VL, VR> int compareCustom(VL left, ValueAccessor<VL> accessorL, VR
right, ValueAccessor<VR> accessorR)
{
return accessorL.getByte(left, 0) - accessorR.getByte(right, 0);
diff --git a/src/java/org/apache/cassandra/db/marshal/BytesType.java
b/src/java/org/apache/cassandra/db/marshal/BytesType.java
index b5c5cc8bdf..7ad0280e55 100644
--- a/src/java/org/apache/cassandra/db/marshal/BytesType.java
+++ b/src/java/org/apache/cassandra/db/marshal/BytesType.java
@@ -38,6 +38,12 @@ public class BytesType extends AbstractType<ByteBuffer>
BytesType() {super(ComparisonType.BYTE_ORDER);} // singleton
+ @Override
+ public boolean allowsEmpty()
+ {
+ return true;
+ }
+
public ByteBuffer fromString(String source)
{
try
diff --git a/src/java/org/apache/cassandra/db/marshal/CollectionType.java
b/src/java/org/apache/cassandra/db/marshal/CollectionType.java
index 5e546cbc96..0f140fea06 100644
--- a/src/java/org/apache/cassandra/db/marshal/CollectionType.java
+++ b/src/java/org/apache/cassandra/db/marshal/CollectionType.java
@@ -93,12 +93,6 @@ public abstract class CollectionType<T> extends
AbstractType<T>
protected abstract List<ByteBuffer> serializedValues(Iterator<Cell<?>>
cells);
- @Override
- public boolean allowsEmpty()
- {
- return false;
- }
-
@Override
public abstract CollectionSerializer<T> getSerializer();
diff --git a/src/java/org/apache/cassandra/db/marshal/CounterColumnType.java
b/src/java/org/apache/cassandra/db/marshal/CounterColumnType.java
index b5ce7d829e..c0e1465bf1 100644
--- a/src/java/org/apache/cassandra/db/marshal/CounterColumnType.java
+++ b/src/java/org/apache/cassandra/db/marshal/CounterColumnType.java
@@ -37,6 +37,13 @@ public class CounterColumnType extends NumberType<Long>
CounterColumnType() {super(ComparisonType.NOT_COMPARABLE);} // singleton
+ @Override
+ public boolean allowsEmpty()
+ {
+ return true;
+ }
+
+ @Override
public boolean isEmptyValueMeaningless()
{
return true;
diff --git a/src/java/org/apache/cassandra/db/marshal/DecimalType.java
b/src/java/org/apache/cassandra/db/marshal/DecimalType.java
index 51d2561aa6..00da39ac35 100644
--- a/src/java/org/apache/cassandra/db/marshal/DecimalType.java
+++ b/src/java/org/apache/cassandra/db/marshal/DecimalType.java
@@ -65,6 +65,13 @@ public class DecimalType extends NumberType<BigDecimal>
DecimalType() {super(ComparisonType.CUSTOM);} // singleton
+ @Override
+ public boolean allowsEmpty()
+ {
+ return true;
+ }
+
+ @Override
public boolean isEmptyValueMeaningless()
{
return true;
diff --git a/src/java/org/apache/cassandra/db/marshal/DoubleType.java
b/src/java/org/apache/cassandra/db/marshal/DoubleType.java
index e1062dc538..eff3bf744d 100644
--- a/src/java/org/apache/cassandra/db/marshal/DoubleType.java
+++ b/src/java/org/apache/cassandra/db/marshal/DoubleType.java
@@ -42,6 +42,13 @@ public class DoubleType extends NumberType<Double>
DoubleType() {super(ComparisonType.CUSTOM);} // singleton
+ @Override
+ public boolean allowsEmpty()
+ {
+ return true;
+ }
+
+ @Override
public boolean isEmptyValueMeaningless()
{
return true;
diff --git a/src/java/org/apache/cassandra/db/marshal/DurationType.java
b/src/java/org/apache/cassandra/db/marshal/DurationType.java
index 9353b2f6b7..0c46617554 100644
--- a/src/java/org/apache/cassandra/db/marshal/DurationType.java
+++ b/src/java/org/apache/cassandra/db/marshal/DurationType.java
@@ -46,12 +46,6 @@ public class DurationType extends AbstractType<Duration>
super(ComparisonType.BYTE_ORDER);
} // singleton
- @Override
- public boolean allowsEmpty()
- {
- return false;
- }
-
public ByteBuffer fromString(String source) throws MarshalException
{
// Return an empty ByteBuffer for an empty string.
diff --git a/src/java/org/apache/cassandra/db/marshal/FloatType.java
b/src/java/org/apache/cassandra/db/marshal/FloatType.java
index abed92960d..216b077811 100644
--- a/src/java/org/apache/cassandra/db/marshal/FloatType.java
+++ b/src/java/org/apache/cassandra/db/marshal/FloatType.java
@@ -43,6 +43,13 @@ public class FloatType extends NumberType<Float>
FloatType() {super(ComparisonType.CUSTOM);} // singleton
+ @Override
+ public boolean allowsEmpty()
+ {
+ return true;
+ }
+
+ @Override
public boolean isEmptyValueMeaningless()
{
return true;
diff --git a/src/java/org/apache/cassandra/db/marshal/InetAddressType.java
b/src/java/org/apache/cassandra/db/marshal/InetAddressType.java
index 820e0c2f77..64e178d989 100644
--- a/src/java/org/apache/cassandra/db/marshal/InetAddressType.java
+++ b/src/java/org/apache/cassandra/db/marshal/InetAddressType.java
@@ -41,6 +41,13 @@ public class InetAddressType extends
AbstractType<InetAddress>
InetAddressType() {super(ComparisonType.BYTE_ORDER);} // singleton
+ @Override
+ public boolean allowsEmpty()
+ {
+ return true;
+ }
+
+ @Override
public boolean isEmptyValueMeaningless()
{
return true;
diff --git a/src/java/org/apache/cassandra/db/marshal/Int32Type.java
b/src/java/org/apache/cassandra/db/marshal/Int32Type.java
index 68c32ad90e..c76d310764 100644
--- a/src/java/org/apache/cassandra/db/marshal/Int32Type.java
+++ b/src/java/org/apache/cassandra/db/marshal/Int32Type.java
@@ -46,6 +46,13 @@ public class Int32Type extends NumberType<Integer>
super(ComparisonType.CUSTOM);
} // singleton
+ @Override
+ public boolean allowsEmpty()
+ {
+ return true;
+ }
+
+ @Override
public boolean isEmptyValueMeaningless()
{
return true;
diff --git a/src/java/org/apache/cassandra/db/marshal/IntegerType.java
b/src/java/org/apache/cassandra/db/marshal/IntegerType.java
index 99fac1640d..2c4b791d83 100644
--- a/src/java/org/apache/cassandra/db/marshal/IntegerType.java
+++ b/src/java/org/apache/cassandra/db/marshal/IntegerType.java
@@ -80,6 +80,13 @@ public final class IntegerType extends NumberType<BigInteger>
IntegerType() {super(ComparisonType.CUSTOM);}/* singleton */
+ @Override
+ public boolean allowsEmpty()
+ {
+ return true;
+ }
+
+ @Override
public boolean isEmptyValueMeaningless()
{
return true;
diff --git a/src/java/org/apache/cassandra/db/marshal/LexicalUUIDType.java
b/src/java/org/apache/cassandra/db/marshal/LexicalUUIDType.java
index 498ca49584..e37f8e2f21 100644
--- a/src/java/org/apache/cassandra/db/marshal/LexicalUUIDType.java
+++ b/src/java/org/apache/cassandra/db/marshal/LexicalUUIDType.java
@@ -47,6 +47,13 @@ public class LexicalUUIDType extends AbstractType<UUID>
super(ComparisonType.CUSTOM);
} // singleton
+ @Override
+ public boolean allowsEmpty()
+ {
+ return true;
+ }
+
+ @Override
public boolean isEmptyValueMeaningless()
{
return true;
diff --git a/src/java/org/apache/cassandra/db/marshal/LongType.java
b/src/java/org/apache/cassandra/db/marshal/LongType.java
index e0348fdb11..97b9f75468 100644
--- a/src/java/org/apache/cassandra/db/marshal/LongType.java
+++ b/src/java/org/apache/cassandra/db/marshal/LongType.java
@@ -43,6 +43,13 @@ public class LongType extends NumberType<Long>
LongType() {super(ComparisonType.CUSTOM);} // singleton
+ @Override
+ public boolean allowsEmpty()
+ {
+ return true;
+ }
+
+ @Override
public boolean isEmptyValueMeaningless()
{
return true;
diff --git a/src/java/org/apache/cassandra/db/marshal/ShortType.java
b/src/java/org/apache/cassandra/db/marshal/ShortType.java
index bd7c2fd653..96047daf73 100644
--- a/src/java/org/apache/cassandra/db/marshal/ShortType.java
+++ b/src/java/org/apache/cassandra/db/marshal/ShortType.java
@@ -46,12 +46,6 @@ public class ShortType extends NumberType<Short>
super(ComparisonType.CUSTOM);
} // singleton
- @Override
- public boolean allowsEmpty()
- {
- return false;
- }
-
public <VL, VR> int compareCustom(VL left, ValueAccessor<VL> accessorL, VR
right, ValueAccessor<VR> accessorR)
{
int diff = accessorL.getByte(left, 0) - accessorR.getByte(right, 0);
diff --git a/src/java/org/apache/cassandra/db/marshal/SimpleDateType.java
b/src/java/org/apache/cassandra/db/marshal/SimpleDateType.java
index 54eabafc0c..a474d39a81 100644
--- a/src/java/org/apache/cassandra/db/marshal/SimpleDateType.java
+++ b/src/java/org/apache/cassandra/db/marshal/SimpleDateType.java
@@ -43,12 +43,6 @@ public class SimpleDateType extends TemporalType<Integer>
SimpleDateType() {super(ComparisonType.BYTE_ORDER);} // singleton
- @Override
- public boolean allowsEmpty()
- {
- return false;
- }
-
@Override
public <V> ByteSource asComparableBytes(ValueAccessor<V> accessor, V data,
Version version)
{
diff --git a/src/java/org/apache/cassandra/db/marshal/StringType.java
b/src/java/org/apache/cassandra/db/marshal/StringType.java
index d823632b73..dd21bedc49 100644
--- a/src/java/org/apache/cassandra/db/marshal/StringType.java
+++ b/src/java/org/apache/cassandra/db/marshal/StringType.java
@@ -27,6 +27,12 @@ public abstract class StringType extends AbstractType<String>
super(comparisonType);
}
+ @Override
+ public boolean allowsEmpty()
+ {
+ return true;
+ }
+
public ByteBuffer concat(String left, String right)
{
return decompose(left + right);
diff --git a/src/java/org/apache/cassandra/db/marshal/TimeType.java
b/src/java/org/apache/cassandra/db/marshal/TimeType.java
index 2a87808f1b..67cf7dbceb 100644
--- a/src/java/org/apache/cassandra/db/marshal/TimeType.java
+++ b/src/java/org/apache/cassandra/db/marshal/TimeType.java
@@ -47,12 +47,6 @@ public class TimeType extends TemporalType<Long>
private TimeType() {super(ComparisonType.BYTE_ORDER);} // singleton
- @Override
- public boolean allowsEmpty()
- {
- return false;
- }
-
public ByteBuffer fromString(String source) throws MarshalException
{
return decompose(TimeSerializer.timeStringToLong(source));
diff --git a/src/java/org/apache/cassandra/db/marshal/TimestampType.java
b/src/java/org/apache/cassandra/db/marshal/TimestampType.java
index 67976769bd..54d88bd0da 100644
--- a/src/java/org/apache/cassandra/db/marshal/TimestampType.java
+++ b/src/java/org/apache/cassandra/db/marshal/TimestampType.java
@@ -55,6 +55,12 @@ public class TimestampType extends TemporalType<Date>
private TimestampType() {super(ComparisonType.CUSTOM);} // singleton
+ @Override
+ public boolean allowsEmpty()
+ {
+ return true;
+ }
+
public boolean isEmptyValueMeaningless()
{
return true;
diff --git a/src/java/org/apache/cassandra/db/marshal/TupleType.java
b/src/java/org/apache/cassandra/db/marshal/TupleType.java
index 79f921920d..0a03936da7 100644
--- a/src/java/org/apache/cassandra/db/marshal/TupleType.java
+++ b/src/java/org/apache/cassandra/db/marshal/TupleType.java
@@ -76,6 +76,12 @@ public class TupleType extends AbstractType<ByteBuffer>
this.serializer = new TupleSerializer(fieldSerializers(types));
}
+ @Override
+ public boolean allowsEmpty()
+ {
+ return true;
+ }
+
private static List<TypeSerializer<?>>
fieldSerializers(List<AbstractType<?>> types)
{
int size = types.size();
diff --git a/src/java/org/apache/cassandra/db/marshal/UUIDType.java
b/src/java/org/apache/cassandra/db/marshal/UUIDType.java
index c949524613..a5abd92234 100644
--- a/src/java/org/apache/cassandra/db/marshal/UUIDType.java
+++ b/src/java/org/apache/cassandra/db/marshal/UUIDType.java
@@ -59,6 +59,13 @@ public class UUIDType extends AbstractType<UUID>
super(ComparisonType.CUSTOM);
}
+ @Override
+ public boolean allowsEmpty()
+ {
+ return true;
+ }
+
+ @Override
public boolean isEmptyValueMeaningless()
{
return true;
diff --git a/src/java/org/apache/cassandra/db/marshal/VectorType.java
b/src/java/org/apache/cassandra/db/marshal/VectorType.java
index 7caf02e3bb..204c603d28 100644
--- a/src/java/org/apache/cassandra/db/marshal/VectorType.java
+++ b/src/java/org/apache/cassandra/db/marshal/VectorType.java
@@ -25,6 +25,8 @@ import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
+import javax.annotation.Nullable;
+
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.cql3.Term;
import org.apache.cassandra.cql3.Vectors;
@@ -172,10 +174,10 @@ public final class VectorType<T> extends
AbstractType<List<T>>
public <V> V decomposeAsFloat(ValueAccessor<V> accessor, float[] value)
{
+ if (value == null)
+ rejectNullOrEmptyValue();
if (!(elementType instanceof FloatType))
throw new IllegalStateException("Attempted to read as float, but
element type is " + elementType.asCQL3Type());
- if (value == null)
- return null;
if (value.length != dimension)
throw new IllegalArgumentException(String.format("Attempted to add
float vector of dimension %d to %s", value.length, asCQL3Type()));
// TODO : should we use TypeSizes to be consistent with other code?
Its the same value at the end of the day...
@@ -215,7 +217,8 @@ public final class VectorType<T> extends
AbstractType<List<T>>
public <V> V fromComparableBytes(ValueAccessor<V> accessor,
ByteSource.Peekable comparableBytes, ByteComparable.Version version)
{
if (comparableBytes == null)
- return accessor.empty();
+ rejectNullOrEmptyValue();
+
assert version != ByteComparable.Version.LEGACY; // legacy translation
is not reversible
List<V> buffers = new ArrayList<>();
@@ -358,6 +361,11 @@ public final class VectorType<T> extends
AbstractType<List<T>>
if (remaining > 0)
throw new MarshalException("Unexpected " + remaining + "
extraneous bytes after " + asCQL3Type() + " value");
}
+
+ private static void rejectNullOrEmptyValue()
+ {
+ throw new MarshalException("Invalid empty vector value");
+ }
public abstract class VectorSerializer extends TypeSerializer<List<T>>
{
@@ -390,6 +398,13 @@ public final class VectorType<T> extends
AbstractType<List<T>>
{
return (Class) List.class;
}
+
+ @Override
+ public <V> boolean isNull(@Nullable V buffer, ValueAccessor<V>
accessor)
+ {
+ // we don't allow empty vectors, so we can just check for null
+ return buffer == null;
+ }
}
private class FixedLengthSerializer extends VectorSerializer
@@ -404,8 +419,6 @@ public final class VectorType<T> extends
AbstractType<List<T>>
{
if (elementType.isByteOrderComparable)
return ValueAccessor.compare(left, accessorL, right,
accessorR);
- if (accessorL.isEmpty(left) || accessorR.isEmpty(right))
- return Boolean.compare(accessorR.isEmpty(right),
accessorL.isEmpty(left));
int offset = 0;
int elementLength = elementType.valueLengthIfFixed();
for (int i = 0; i < dimension; i++)
@@ -443,7 +456,8 @@ public final class VectorType<T> extends
AbstractType<List<T>>
public <V> V serializeRaw(List<V> value, ValueAccessor<V> accessor)
{
if (value == null)
- return accessor.empty();
+ rejectNullOrEmptyValue();
+
check(value);
int size = elementType.valueLengthIfFixed();
@@ -458,7 +472,8 @@ public final class VectorType<T> extends
AbstractType<List<T>>
public ByteBuffer serialize(List<T> value)
{
if (value == null)
- return ByteBufferUtil.EMPTY_BYTE_BUFFER;
+ rejectNullOrEmptyValue();
+
check(value);
ByteBuffer bb =
ByteBuffer.allocate(elementType.valueLengthIfFixed() * dimension);
@@ -492,7 +507,8 @@ public final class VectorType<T> extends
AbstractType<List<T>>
public <V> void validate(V input, ValueAccessor<V> accessor) throws
MarshalException
{
if (accessor.isEmpty(input))
- return;
+ rejectNullOrEmptyValue();
+
int offset = 0;
int elementSize = elementType.valueLengthIfFixed();
@@ -520,9 +536,6 @@ public final class VectorType<T> extends
AbstractType<List<T>>
public <VL, VR> int compareCustom(VL left, ValueAccessor<VL> accessorL,
VR right, ValueAccessor<VR>
accessorR)
{
- if (accessorL.isEmpty(left) || accessorR.isEmpty(right))
- return Boolean.compare(accessorR.isEmpty(right),
accessorL.isEmpty(left));
-
int leftOffset = 0;
int rightOffset = 0;
for (int i = 0; i < dimension; i++)
@@ -584,7 +597,8 @@ public final class VectorType<T> extends
AbstractType<List<T>>
public <V> V serializeRaw(List<V> value, ValueAccessor<V> accessor)
{
if (value == null)
- return accessor.empty();
+ rejectNullOrEmptyValue();
+
check(value);
V bb = accessor.allocate(value.stream().mapToInt(v -> sizeOf(v,
accessor)).sum());
@@ -598,7 +612,8 @@ public final class VectorType<T> extends
AbstractType<List<T>>
public ByteBuffer serialize(List<T> value)
{
if (value == null)
- return ByteBufferUtil.EMPTY_BYTE_BUFFER;
+ rejectNullOrEmptyValue();
+
check(value);
List<ByteBuffer> bbs = new ArrayList<>(dimension);
@@ -630,7 +645,8 @@ public final class VectorType<T> extends
AbstractType<List<T>>
public <V> void validate(V input, ValueAccessor<V> accessor) throws
MarshalException
{
if (accessor.isEmpty(input))
- return;
+ rejectNullOrEmptyValue();
+
int offset = 0;
for (int i = 0; i < dimension; i++)
{
diff --git
a/test/unit/org/apache/cassandra/cql3/validation/operations/CQLVectorTest.java
b/test/unit/org/apache/cassandra/cql3/validation/operations/CQLVectorTest.java
index cf88d32d93..42daab6ada 100644
---
a/test/unit/org/apache/cassandra/cql3/validation/operations/CQLVectorTest.java
+++
b/test/unit/org/apache/cassandra/cql3/validation/operations/CQLVectorTest.java
@@ -20,6 +20,7 @@ package org.apache.cassandra.cql3.validation.operations;
import java.math.BigInteger;
import java.nio.ByteBuffer;
+import java.util.List;
import org.junit.Assert;
import org.junit.Test;
@@ -34,6 +35,7 @@ import org.apache.cassandra.db.marshal.Int32Type;
import org.apache.cassandra.db.marshal.VectorType;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.transport.ProtocolVersion;
+import org.apache.cassandra.utils.ByteBufferUtil;
import org.assertj.core.api.Assertions;
import static java.lang.String.format;
@@ -261,6 +263,47 @@ public class CQLVectorTest extends CQLTester.InMemory
test.run();
}
+ @Test
+ public void nullValues()
+ {
+ assertAcceptsNullValues("int"); // fixed length
+ assertAcceptsNullValues("float"); // fixed length with
special/optimized treatment
+ assertAcceptsNullValues("text"); // variable length
+ }
+
+ private void assertAcceptsNullValues(String type)
+ {
+ createTable(format("CREATE TABLE %%s (k int primary key, v vector<%s,
2>)", type));
+
+ execute("INSERT INTO %s (k, v) VALUES (0, null)");
+ assertRows(execute("SELECT * FROM %s"), row(0, null));
+
+ execute("INSERT INTO %s (k, v) VALUES (0, ?)", (List<Integer>) null);
+ assertRows(execute("SELECT * FROM %s"), row(0, null));
+ }
+
+ @Test
+ public void emptyValues() throws Throwable
+ {
+ assertRejectsEmptyValues("int"); // fixed length
+ assertRejectsEmptyValues("float"); // fixed length with
special/optimized treatment
+ assertRejectsEmptyValues("text"); // variable length
+ }
+
+ private void assertRejectsEmptyValues(String type) throws Throwable
+ {
+ createTable(format("CREATE TABLE %%s (k int primary key, v vector<%s,
2>)", type));
+
+ assertInvalidThrowMessage(format("Invalid HEX constant (0x) for \"v\"
of type vector<%s, 2>", type),
+ InvalidRequestException.class,
+ "INSERT INTO %s (k, v) VALUES (0, 0x)");
+
+ assertInvalidThrowMessage("Invalid empty vector value",
+ InvalidRequestException.class,
+ "INSERT INTO %s (k, v) VALUES (0, ?)",
+ ByteBufferUtil.EMPTY_BYTE_BUFFER);
+ }
+
@Test
public void functions()
{
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]