com.datastax.driver.core.RegularStatement Maven / Gradle / Ivy
Show all versions of dse-java-driver-core Show documentation
/*
* Copyright DataStax, Inc.
*
* This software can be used solely with DataStax Enterprise. Please consult the license at
* http://www.datastax.com/terms/datastax-dse-driver-license-terms
*/
package com.datastax.driver.core;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Map;
import com.datastax.driver.core.Frame.Header;
import com.datastax.driver.core.Requests.QueryFlag;
import com.datastax.driver.core.exceptions.InvalidTypeException;
import com.datastax.driver.core.exceptions.UnsupportedProtocolVersionException;
import com.datastax.driver.core.querybuilder.BuiltStatement;
import com.datastax.driver.core.schemabuilder.SchemaStatement;
/**
* A regular (non-prepared and non batched) CQL statement.
*
* This class represents a query string along with query options (and optionally
* binary values, see {@code getValues}). It can be extended but {@link SimpleStatement}
* is provided as a simple implementation to build a {@code RegularStatement} directly
* from its query string.
*/
public abstract class RegularStatement extends Statement {
private volatile Token routingToken;
/**
* Creates a new RegularStatement.
*/
protected RegularStatement() {
}
/**
* Returns the query string for this statement.
*
* It is important to note that the query string is merely
* a CQL representation of this statement, but it does
* not convey all the information stored in {@link Statement}
* objects.
*
* For example, {@link Statement} objects carry numerous protocol-level
* settings, such as the {@link Statement#getConsistencyLevel() consistency level} to use,
* or the {@link Statement#isIdempotent() idempotence flag}, among others.
* None of these settings will be included in the resulting query string.
*
* Similarly, if values have been set on this statement because
* it has bind markers, these values will not appear in the resulting query string.
*
* Note: the consistency level was conveyed at CQL level in older versions
* of the CQL grammar, but since CASSANDRA-4734
* it is now a protocol-level setting and consequently does not appear in the query string.
*
* @param codecRegistry the codec registry that will be used if the actual
* implementation needs to serialize Java objects in the
* process of generating the query. Note that it might be
* possible to use the no-arg {@link #getQueryString()}
* depending on the type of statement this is called on.
* @return a valid CQL query string.
* @see #getQueryString()
*/
public abstract String getQueryString(CodecRegistry codecRegistry);
/**
* Returns the query string for this statement.
*
* This method calls {@link #getQueryString(CodecRegistry)} with {@link CodecRegistry#DEFAULT_INSTANCE}.
* Whether you should use this or the other variant depends on the type of statement this is
* called on:
*
* - for a {@link SimpleStatement} or {@link SchemaStatement}, the codec registry isn't
* actually needed, so it's always safe to use this method;
* - for a {@link BuiltStatement} you can use this method if you use no custom codecs, or if
* your custom codecs are registered with the default registry. Otherwise, use the other method and
* provide the registry that contains your codecs (see {@link BuiltStatement} for more explanations
* on why this is so);
* - for a {@link BatchStatement}, use the first rule if it contains no built statements,
* or the second rule otherwise.
*
*
* @return a valid CQL query string.
*/
public String getQueryString() {
return getQueryString(CodecRegistry.DEFAULT_INSTANCE);
}
/**
* The positional values to use for this statement.
*
* A statement can use either positional or named values, but not both. So if this method returns a non-null result,
* {@link #getNamedValues(ProtocolVersion, CodecRegistry)} will return {@code null}.
*
* Values for a RegularStatement (i.e. if either method does not return
* {@code null}) are not supported with the native protocol version 1: you
* will get an {@link UnsupportedProtocolVersionException} when submitting
* one if version 1 of the protocol is in use (i.e. if you've forced version
* 1 through {@link Cluster.Builder#withProtocolVersion} or you use
* Cassandra 1.2).
*
* @param protocolVersion the protocol version that will be used to serialize
* the values.
* @param codecRegistry the codec registry that will be used to serialize the
* values.
* @throws InvalidTypeException if one of the values is not of a type
* that can be serialized to a CQL3 type
* @see SimpleStatement#SimpleStatement(String, Object...)
*/
public abstract ByteBuffer[] getValues(ProtocolVersion protocolVersion, CodecRegistry codecRegistry);
/**
* The named values to use for this statement.
*
* A statement can use either positional or named values, but not both. So if this method returns a non-null result,
* {@link #getValues(ProtocolVersion, CodecRegistry)} will return {@code null}.
*
* Values for a RegularStatement (i.e. if either method does not return
* {@code null}) are not supported with the native protocol version 1: you
* will get an {@link UnsupportedProtocolVersionException} when submitting
* one if version 1 of the protocol is in use (i.e. if you've forced version
* 1 through {@link Cluster.Builder#withProtocolVersion} or you use
* Cassandra 1.2).
*
* @param protocolVersion the protocol version that will be used to serialize
* the values.
* @param codecRegistry the codec registry that will be used to serialize the
* values.
* @return the named values.
* @throws InvalidTypeException if one of the values is not of a type
* that can be serialized to a CQL3 type
* @see SimpleStatement#SimpleStatement(String, Map)
*/
public abstract Map getNamedValues(ProtocolVersion protocolVersion, CodecRegistry codecRegistry);
/**
* Whether or not this statement has values, that is if {@code getValues}
* will return {@code null} or not.
*
* @param codecRegistry the codec registry that will be used if the actual
* implementation needs to serialize Java objects in the
* process of determining if the query has values.
* Note that it might be possible to use the no-arg
* {@link #hasValues()} depending on the type of
* statement this is called on.
* @return {@code false} if both {@link #getValues(ProtocolVersion, CodecRegistry)}
* and {@link #getNamedValues(ProtocolVersion, CodecRegistry)} return {@code null}, {@code true}
* otherwise.
* @see #hasValues()
*/
public abstract boolean hasValues(CodecRegistry codecRegistry);
/**
* Whether this statement uses named values.
*
* @return {@code false} if {@link #getNamedValues(ProtocolVersion, CodecRegistry)} returns {@code null},
* {@code true} otherwise.
*/
public abstract boolean usesNamedValues();
/**
* Whether or not this statement has values, that is if {@code getValues}
* will return {@code null} or not.
*
* This method calls {@link #hasValues(CodecRegistry)} with {@link ProtocolVersion#NEWEST_SUPPORTED}.
* Whether you should use this or the other variant depends on the type of statement this is
* called on:
*
* - for a {@link SimpleStatement} or {@link SchemaStatement}, the codec registry isn't
* actually needed, so it's always safe to use this method;
* - for a {@link BuiltStatement} you can use this method if you use no custom codecs, or if
* your custom codecs are registered with the default registry. Otherwise, use the other method and
* provide the registry that contains your codecs (see {@link BuiltStatement} for more explanations
* on why this is so);
* - for a {@link BatchStatement}, use the first rule if it contains no built statements,
* or the second rule otherwise.
*
*
* @return {@code false} if {@link #getValues} returns {@code null}, {@code true}
* otherwise.
*/
public boolean hasValues() {
return hasValues(CodecRegistry.DEFAULT_INSTANCE);
}
@Override
public Token getRoutingToken() {
return routingToken;
}
/**
* Sets a routing token for this statement.
*
* @see #getRoutingToken()
*/
public RegularStatement setRoutingToken(Token routingToken) {
this.routingToken = routingToken;
return this;
}
/**
* Returns the keyspace this query operates on.
*
* Unless the keyspace has been explicitly set through a means such as {@link SimpleStatement#setKeyspace},
* this method will return {@code null} to avoid having to parse the query
* string.
*
* Note: This returns the internal representation of the keyspace.
* In the typical case, the internal representation is equivalent to
* the CQL representation. However, if you are using a keyspace that
* requires the use of quotes in CQL (a quoted identifier), i.e.: "MyKS",
* this method will return the unquoted representation instead, i.e. MyKS.
*
* @return the keyspace if set, {@code null} otherwise.
* @see Statement#getKeyspace
*/
@Override
public String getKeyspace() {
return null;
}
@Override
public int requestSizeInBytes(ProtocolVersion protocolVersion, CodecRegistry codecRegistry) {
int size = Header.lengthFor(protocolVersion);
try {
size += CBUtil.sizeOfLongString(getQueryString(codecRegistry));
switch (protocolVersion) {
case V1:
size += CBUtil.sizeOfConsistencyLevel(getConsistencyLevel());
break;
case V2:
case V3:
case V4:
case V5:
size += CBUtil.sizeOfConsistencyLevel(getConsistencyLevel());
size += QueryFlag.serializedSize(protocolVersion);
if (hasValues()) {
if (usesNamedValues()) {
size += CBUtil.sizeOfNamedValueList(getNamedValues(protocolVersion, codecRegistry));
} else {
size += CBUtil.sizeOfValueList(Arrays.asList(getValues(protocolVersion, codecRegistry)));
}
}
// Fetch size, serial CL and default timestamp also depend on session-level defaults (QueryOptions).
// We always count them to avoid having to inject QueryOptions here, at worst we overestimate by a
// few bytes.
size += 4; // fetch size
if (getPagingState() != null) {
size += CBUtil.sizeOfValue(getPagingState());
}
size += CBUtil.sizeOfConsistencyLevel(getSerialConsistencyLevel());
if (ProtocolFeature.CLIENT_TIMESTAMPS.isSupportedBy(protocolVersion)) {
size += 8; // timestamp
}
if (ProtocolFeature.CUSTOM_PAYLOADS.isSupportedBy(protocolVersion) && getOutgoingPayload() != null) {
size += CBUtil.sizeOfBytesMap(getOutgoingPayload());
}
break;
default:
throw protocolVersion.unsupported();
}
} catch (Exception e) {
size = -1;
}
return size;
}
/**
* Returns this statement as a CQL query string.
*
* It is important to note that the query string is merely
* a CQL representation of this statement, but it does
* not convey all the information stored in {@link Statement}
* objects.
*
* See the javadocs of {@link #getQueryString()} for more information.
*
* @return this statement as a CQL query string.
* @see #getQueryString()
*/
@Override
public String toString() {
return getQueryString();
}
}