All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.datastax.oss.driver.api.core.data.GettableByIndex Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.datastax.oss.driver.api.core.data;

import com.datastax.oss.driver.api.core.metadata.token.Token;
import com.datastax.oss.driver.api.core.type.DataType;
import com.datastax.oss.driver.api.core.type.DataTypes;
import com.datastax.oss.driver.api.core.type.codec.CodecNotFoundException;
import com.datastax.oss.driver.api.core.type.codec.PrimitiveBooleanCodec;
import com.datastax.oss.driver.api.core.type.codec.PrimitiveByteCodec;
import com.datastax.oss.driver.api.core.type.codec.PrimitiveDoubleCodec;
import com.datastax.oss.driver.api.core.type.codec.PrimitiveFloatCodec;
import com.datastax.oss.driver.api.core.type.codec.PrimitiveIntCodec;
import com.datastax.oss.driver.api.core.type.codec.PrimitiveLongCodec;
import com.datastax.oss.driver.api.core.type.codec.PrimitiveShortCodec;
import com.datastax.oss.driver.api.core.type.codec.TypeCodec;
import com.datastax.oss.driver.api.core.type.reflect.GenericType;
import com.datastax.oss.driver.internal.core.metadata.token.ByteOrderedToken;
import com.datastax.oss.driver.internal.core.metadata.token.Murmur3Token;
import com.datastax.oss.driver.internal.core.metadata.token.RandomToken;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

/** A data structure that provides methods to retrieve its values via an integer index. */
public interface GettableByIndex extends AccessibleByIndex {

  /**
   * Returns the raw binary representation of the {@code i}th value.
   *
   * 

This is primarily for internal use; you'll likely want to use one of the typed getters * instead, to get a higher-level Java representation. * * @return the raw value, or {@code null} if the CQL value is {@code NULL}. For performance * reasons, this is the actual instance used internally. If you read data from the buffer, * make sure to {@link ByteBuffer#duplicate() duplicate} it beforehand, or only use relative * methods. If you change the buffer's index or its contents in any way, any other getter * invocation for this value will have unpredictable results. * @throws IndexOutOfBoundsException if the index is invalid. */ @Nullable ByteBuffer getBytesUnsafe(int i); /** * Indicates whether the {@code i}th value is a CQL {@code NULL}. * * @throws IndexOutOfBoundsException if the index is invalid. */ default boolean isNull(int i) { return getBytesUnsafe(i) == null; } /** * Returns the {@code i}th value, using the given codec for the conversion. * *

This method completely bypasses the {@link #codecRegistry()}, and forces the driver to use * the given codec instead. This can be useful if the codec would collide with a previously * registered one, or if you want to use the codec just once without registering it. * *

It is the caller's responsibility to ensure that the given codec is appropriate for the * conversion. Failing to do so will result in errors at runtime. * * @throws IndexOutOfBoundsException if the index is invalid. */ @Nullable default ValueT get(int i, TypeCodec codec) { return codec.decode(getBytesUnsafe(i), protocolVersion()); } /** * Returns the {@code i}th value, converting it to the given Java type. * *

The {@link #codecRegistry()} will be used to look up a codec to handle the conversion. * *

This variant is for generic Java types. If the target type is not generic, use {@link * #get(int, Class)} instead, which may perform slightly better. * * @throws IndexOutOfBoundsException if the index is invalid. * @throws CodecNotFoundException if no codec can perform the conversion. */ @Nullable default ValueT get(int i, GenericType targetType) { DataType cqlType = getType(i); TypeCodec codec = codecRegistry().codecFor(cqlType, targetType); return get(i, codec); } /** * Returns the {@code i}th value, converting it to the given Java type. * *

The {@link #codecRegistry()} will be used to look up a codec to handle the conversion. * *

If the target type is generic, use {@link #get(int, GenericType)} instead. * * @throws IndexOutOfBoundsException if the index is invalid. * @throws CodecNotFoundException if no codec can perform the conversion. */ @Nullable default ValueT get(int i, Class targetClass) { // This is duplicated from the GenericType variant, because we want to give the codec registry // a chance to process the unwrapped class directly, if it can do so in a more efficient way. DataType cqlType = getType(i); TypeCodec codec = codecRegistry().codecFor(cqlType, targetClass); return get(i, codec); } /** * Returns the {@code i}th value, converting it to the most appropriate Java type. * *

The {@link #codecRegistry()} will be used to look up a codec to handle the conversion. * *

Use this method to dynamically inspect elements when types aren't known in advance, for * instance if you're writing a generic row logger. If you know the target Java type, it is * generally preferable to use typed variants, such as the ones for built-in types ({@link * #getBoolean(int)}, {@link #getInt(int)}, etc.), or {@link #get(int, Class)} and {@link * #get(int, GenericType)} for custom types. * *

The definition of "most appropriate" is unspecified, and left to the appreciation of the * {@link #codecRegistry()} implementation. By default, the driver uses the mapping described in * the other {@code getXxx()} methods (for example {@link #getString(int) String for text, varchar * and ascii}, etc). * * @throws IndexOutOfBoundsException if the index is invalid. * @throws CodecNotFoundException if no codec can perform the conversion. */ @Nullable default Object getObject(int i) { DataType cqlType = getType(i); TypeCodec codec = codecRegistry().codecFor(cqlType); return codec.decode(getBytesUnsafe(i), protocolVersion()); } /** * Returns the {@code i}th value as a Java primitive boolean. * *

By default, this works with CQL type {@code boolean}. * *

Note that, due to its signature, this method cannot return {@code null}. If the CQL value is * {@code NULL}, it will return {@code false}. If this doesn't work for you, either call {@link * #isNull(int)} before calling this method, or use {@code get(i, Boolean.class)} instead. * * @throws IndexOutOfBoundsException if the index is invalid. */ default boolean getBoolean(int i) { DataType cqlType = getType(i); TypeCodec codec = codecRegistry().codecFor(cqlType, Boolean.class); if (codec instanceof PrimitiveBooleanCodec) { return ((PrimitiveBooleanCodec) codec).decodePrimitive(getBytesUnsafe(i), protocolVersion()); } else { Boolean value = get(i, codec); return value == null ? false : value; } } /** * @deprecated this method only exists to ease the transition from driver 3, it is an alias for * {@link #getBoolean(int)}. */ @Deprecated default boolean getBool(int i) { return getBoolean(i); } /** * Returns the {@code i}th value as a Java primitive byte. * *

By default, this works with CQL type {@code tinyint}. * *

Note that, due to its signature, this method cannot return {@code null}. If the CQL value is * {@code NULL}, it will return {@code 0}. If this doesn't work for you, either call {@link * #isNull(int)} before calling this method, or use {@code get(i, Byte.class)} instead. * * @throws IndexOutOfBoundsException if the index is invalid. */ default byte getByte(int i) { DataType cqlType = getType(i); TypeCodec codec = codecRegistry().codecFor(cqlType, Byte.class); if (codec instanceof PrimitiveByteCodec) { return ((PrimitiveByteCodec) codec).decodePrimitive(getBytesUnsafe(i), protocolVersion()); } else { Byte value = get(i, codec); return value == null ? 0 : value; } } /** * Returns the {@code i}th value as a Java primitive double. * *

By default, this works with CQL type {@code double}. * *

Note that, due to its signature, this method cannot return {@code null}. If the CQL value is * {@code NULL}, it will return {@code 0.0}. If this doesn't work for you, either call {@link * #isNull(int)} before calling this method, or use {@code get(i, Double.class)} instead. * * @throws IndexOutOfBoundsException if the index is invalid. */ default double getDouble(int i) { DataType cqlType = getType(i); TypeCodec codec = codecRegistry().codecFor(cqlType, Double.class); if (codec instanceof PrimitiveDoubleCodec) { return ((PrimitiveDoubleCodec) codec).decodePrimitive(getBytesUnsafe(i), protocolVersion()); } else { Double value = get(i, codec); return value == null ? 0 : value; } } /** * Returns the {@code i}th value as a Java primitive float. * *

By default, this works with CQL type {@code float}. * *

Note that, due to its signature, this method cannot return {@code null}. If the CQL value is * {@code NULL}, it will return {@code 0.0}. If this doesn't work for you, either call {@link * #isNull(int)} before calling this method, or use {@code get(i, Float.class)} instead. * * @throws IndexOutOfBoundsException if the index is invalid. */ default float getFloat(int i) { DataType cqlType = getType(i); TypeCodec codec = codecRegistry().codecFor(cqlType, Float.class); if (codec instanceof PrimitiveFloatCodec) { return ((PrimitiveFloatCodec) codec).decodePrimitive(getBytesUnsafe(i), protocolVersion()); } else { Float value = get(i, codec); return value == null ? 0 : value; } } /** * Returns the {@code i}th value as a Java primitive integer. * *

By default, this works with CQL type {@code int}. * *

Note that, due to its signature, this method cannot return {@code null}. If the CQL value is * {@code NULL}, it will return {@code 0}. If this doesn't work for you, either call {@link * #isNull(int)} before calling this method, or use {@code get(i, Integer.class)} instead. * * @throws IndexOutOfBoundsException if the index is invalid. */ default int getInt(int i) { DataType cqlType = getType(i); TypeCodec codec = codecRegistry().codecFor(cqlType, Integer.class); if (codec instanceof PrimitiveIntCodec) { return ((PrimitiveIntCodec) codec).decodePrimitive(getBytesUnsafe(i), protocolVersion()); } else { Integer value = get(i, codec); return value == null ? 0 : value; } } /** * Returns the {@code i}th value as a Java primitive long. * *

By default, this works with CQL types {@code bigint} and {@code counter}. * *

Note that, due to its signature, this method cannot return {@code null}. If the CQL value is * {@code NULL}, it will return {@code 0}. If this doesn't work for you, either call {@link * #isNull(int)} before calling this method, or use {@code get(i, Long.class)} instead. * * @throws IndexOutOfBoundsException if the index is invalid. */ default long getLong(int i) { DataType cqlType = getType(i); TypeCodec codec = codecRegistry().codecFor(cqlType, Long.class); if (codec instanceof PrimitiveLongCodec) { return ((PrimitiveLongCodec) codec).decodePrimitive(getBytesUnsafe(i), protocolVersion()); } else { Long value = get(i, codec); return value == null ? 0 : value; } } /** * Returns the {@code i}th value as a Java primitive short. * *

By default, this works with CQL type {@code smallint}. * *

Note that, due to its signature, this method cannot return {@code null}. If the CQL value is * {@code NULL}, it will return {@code 0}. If this doesn't work for you, either call {@link * #isNull(int)} before calling this method, or use {@code get(i, Short.class)} instead. * * @throws IndexOutOfBoundsException if the index is invalid. */ default short getShort(int i) { DataType cqlType = getType(i); TypeCodec codec = codecRegistry().codecFor(cqlType, Short.class); if (codec instanceof PrimitiveShortCodec) { return ((PrimitiveShortCodec) codec).decodePrimitive(getBytesUnsafe(i), protocolVersion()); } else { Short value = get(i, codec); return value == null ? 0 : value; } } /** * Returns the {@code i}th value as a Java instant. * *

By default, this works with CQL type {@code timestamp}. * * @throws IndexOutOfBoundsException if the index is invalid. */ @Nullable default Instant getInstant(int i) { return get(i, Instant.class); } /** * Returns the {@code i}th value as a Java local date. * *

By default, this works with CQL type {@code date}. * * @throws IndexOutOfBoundsException if the index is invalid. */ @Nullable default LocalDate getLocalDate(int i) { return get(i, LocalDate.class); } /** * Returns the {@code i}th value as a Java local time. * *

By default, this works with CQL type {@code time}. * * @throws IndexOutOfBoundsException if the index is invalid. */ @Nullable default LocalTime getLocalTime(int i) { return get(i, LocalTime.class); } /** * Returns the {@code i}th value as a Java byte buffer. * *

By default, this works with CQL type {@code blob}. * * @throws IndexOutOfBoundsException if the index is invalid. */ @Nullable default ByteBuffer getByteBuffer(int i) { return get(i, ByteBuffer.class); } /** * Returns the {@code i}th value as a Java string. * *

By default, this works with CQL types {@code text}, {@code varchar} and {@code ascii}. * * @throws IndexOutOfBoundsException if the index is invalid. */ @Nullable default String getString(int i) { return get(i, String.class); } /** * Returns the {@code i}th value as a Java big integer. * *

By default, this works with CQL type {@code varint}. * * @throws IndexOutOfBoundsException if the index is invalid. */ @Nullable default BigInteger getBigInteger(int i) { return get(i, BigInteger.class); } /** * Returns the {@code i}th value as a Java big decimal. * *

By default, this works with CQL type {@code decimal}. * * @throws IndexOutOfBoundsException if the index is invalid. */ @Nullable default BigDecimal getBigDecimal(int i) { return get(i, BigDecimal.class); } /** * Returns the {@code i}th value as a Java UUID. * *

By default, this works with CQL types {@code uuid} and {@code timeuuid}. * * @throws IndexOutOfBoundsException if the index is invalid. */ @Nullable default UUID getUuid(int i) { return get(i, UUID.class); } /** * Returns the {@code i}th value as a Java IP address. * *

By default, this works with CQL type {@code inet}. * * @throws IndexOutOfBoundsException if the index is invalid. */ @Nullable default InetAddress getInetAddress(int i) { return get(i, InetAddress.class); } /** * Returns the {@code i}th value as a duration. * *

By default, this works with CQL type {@code duration}. * * @throws IndexOutOfBoundsException if the index is invalid. */ @Nullable default CqlDuration getCqlDuration(int i) { return get(i, CqlDuration.class); } /** * Returns the {@code i}th value as a vector. * *

By default, this works with CQL type {@code vector}. * * @throws IndexOutOfBoundsException if the index is invalid. */ @Nullable default CqlVector getVector( int i, @NonNull Class elementsClass) { return get(i, GenericType.vectorOf(elementsClass)); } /** * Returns the {@code i}th value as a token. * *

Note that, for simplicity, this method relies on the CQL type of the column to pick the * correct token implementation. Therefore it must only be called on columns of the type that * matches the partitioner in use for this cluster: {@code bigint} for {@code Murmur3Partitioner}, * {@code blob} for {@code ByteOrderedPartitioner}, and {@code varint} for {@code * RandomPartitioner}. Calling it for the wrong type will produce corrupt tokens that are unusable * with this driver instance. * * @throws IndexOutOfBoundsException if the index is invalid. * @throws IllegalArgumentException if the column type can not be converted to a known token type. */ @Nullable default Token getToken(int i) { DataType type = getType(i); // Simply enumerate all known implementations. This goes against the concept of TokenFactory, // but injecting the factory here is too much of a hassle. // The only issue is if someone uses a custom partitioner, but this is highly unlikely, and even // then they can get the value manually as a workaround. if (type.equals(DataTypes.BIGINT)) { return isNull(i) ? null : new Murmur3Token(getLong(i)); } else if (type.equals(DataTypes.BLOB)) { return isNull(i) ? null : new ByteOrderedToken(getByteBuffer(i)); } else if (type.equals(DataTypes.VARINT)) { return isNull(i) ? null : new RandomToken(getBigInteger(i)); } else { throw new IllegalArgumentException("Can't convert CQL type " + type + " into a token"); } } /** * Returns the {@code i}th value as a Java list. * *

By default, this works with CQL type {@code list}. * *

This method is provided for convenience when the element type is a non-generic type. For * more complex list types, use {@link #get(int, GenericType)}. * *

Apache Cassandra does not make any distinction between an empty collection and {@code null}. * Whether this method will return an empty collection or {@code null} will depend on the codec * used; by default, the driver's built-in codecs all return empty collections. * * @throws IndexOutOfBoundsException if the index is invalid. */ @Nullable default List getList(int i, @NonNull Class elementsClass) { return get(i, GenericType.listOf(elementsClass)); } /** * Returns the {@code i}th value as a Java set. * *

By default, this works with CQL type {@code set}. * *

This method is provided for convenience when the element type is a non-generic type. For * more complex set types, use {@link #get(int, GenericType)}. * *

Apache Cassandra does not make any distinction between an empty collection and {@code null}. * Whether this method will return an empty collection or {@code null} will depend on the codec * used; by default, the driver's built-in codecs all return empty collections. * * @throws IndexOutOfBoundsException if the index is invalid. */ @Nullable default Set getSet(int i, @NonNull Class elementsClass) { return get(i, GenericType.setOf(elementsClass)); } /** * Returns the {@code i}th value as a Java map. * *

By default, this works with CQL type {@code map}. * *

This method is provided for convenience when the element type is a non-generic type. For * more complex map types, use {@link #get(int, GenericType)}. * *

Apache Cassandra does not make any distinction between an empty collection and {@code null}. * Whether this method will return an empty collection or {@code null} will depend on the codec * used; by default, the driver's built-in codecs all return empty collections. * * @throws IndexOutOfBoundsException if the index is invalid. */ @Nullable default Map getMap( int i, @NonNull Class keyClass, @NonNull Class valueClass) { return get(i, GenericType.mapOf(keyClass, valueClass)); } /** * Returns the {@code i}th value as a user defined type value. * *

By default, this works with CQL user-defined types. * * @throws IndexOutOfBoundsException if the index is invalid. */ @Nullable default UdtValue getUdtValue(int i) { return get(i, UdtValue.class); } /** * Returns the {@code i}th value as a tuple value. * *

By default, this works with CQL tuples. * * @throws IndexOutOfBoundsException if the index is invalid. */ @Nullable default TupleValue getTupleValue(int i) { return get(i, TupleValue.class); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy