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

com.datastax.driver.core.SimpleStatement Maven / Gradle / Ivy

Go to download

A driver for Apache Cassandra 1.2+ that works exclusively with the Cassandra Query Language version 3 (CQL3) and Cassandra's binary protocol.

The newest version!
/*
 *      Copyright (C) 2012 DataStax Inc.
 *
 *   Licensed 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.driver.core;

import java.nio.ByteBuffer;

/**
 * A simple {@code RegularStatement} implementation built directly from a query
 * string.
 */
public class SimpleStatement extends RegularStatement {

    private final String query;
    private final ByteBuffer[] values;

    private volatile ByteBuffer routingKey;
    private volatile String keyspace;

    /**
     * Creates a new {@code SimpleStatement} with the provided query string (and no values).
     *
     * @param query the query string.
     */
    public SimpleStatement(String query) {
        this.query = query;
        this.values = null;
    }

    /**
     * Creates a new {@code SimpleStatement} with the provided query string and values.
     * 

* This version of SimpleStatement is useful when you do not want to execute a * query only once (and thus do not want to resort to prepared statement), but * do not want to convert all column values to string (typically, if you have blob * values, encoding them to a hexadecimal string is not very efficient). In * that case, you can provide a query string with bind marker to this constructor * along with the values for those bind variables. When executed, the server will * prepare the provided, bind the provided values to that prepare statement and * execute the resulting statement. Thus, *

     *   session.execute(new SimpleStatement(query, value1, value2, value3));
     * 
* is functionally equivalent to *
     *   PreparedStatement ps = session.prepare(query);
     *   session.execute(ps.bind(value1, value2, value3));
     * 
* except that the former version: *
    *
  • Requires only one round-trip to a Cassandra node.
  • *
  • Does not left any prepared statement stored in memory (neither client or * server side) once it has been executed.
  • *
*

* Note that the type of the {@code values} provided to this method will * not be validated by the driver as is done by {@link BoundStatement#bind} since * {@code query} is not parsed (and hence the driver cannot know what those value * should be). If too much or too little values are provided or if a value is not * a valid one for the variable it is bound to, an * {@link com.datastax.driver.core.exceptions.InvalidQueryException} will be thrown * by Cassandra at execution time. An {@code IllegalArgumentException} may be * thrown by this constructor however if one of the value does not correspond to * any CQL3 type (for instance, if it is a custom class). * * @param query the query string. * @param values values required for the execution of {@code query}. * * @throws IllegalArgumentException if one of {@code values} is not of a type * corresponding to a CQL3 type, i.e. is not a Class that could be returned * by {@link DataType#asJavaClass}. */ public SimpleStatement(String query, Object... values) { this.query = query; this.values = convert(values); } private static ByteBuffer[] convert(Object[] values) { ByteBuffer[] serializedValues = new ByteBuffer[values.length]; for (int i = 0; i < values.length; i++) { try { serializedValues[i] = DataType.serializeValue(values[i]); } catch (IllegalArgumentException e) { // Catch and rethrow to provide a more helpful error message (one that include which value is bad) throw new IllegalArgumentException(String.format("Value %d of type %s does not correspond to any CQL3 type", i, values[i].getClass())); } } return serializedValues; } /** * Returns the query string. * * @return the query string; */ @Override public String getQueryString() { return query; } @Override public ByteBuffer[] getValues() { return values; } /** * Returns the routing key for the query. *

* Unless the routing key has been explicitly set through * {@link #setRoutingKey}, this method will return {@code null} to * avoid having to parse the query string to retrieve the partition key. * * @return the routing key set through {@link #setRoutingKey} if such a key * was set, {@code null} otherwise. * * @see Statement#getRoutingKey */ @Override public ByteBuffer getRoutingKey() { return routingKey; } /** * Sets the routing key for this query. *

* This method allows you to manually provide a routing key for this query. It * is thus optional since the routing key is only an hint for token aware * load balancing policy but is never mandatory. *

* If the partition key for the query is composite, use the * {@link #setRoutingKey(ByteBuffer...)} method instead to build the * routing key. * * @param routingKey the raw (binary) value to use as routing key. * @return this {@code SimpleStatement} object. * * @see Statement#getRoutingKey */ public SimpleStatement setRoutingKey(ByteBuffer routingKey) { this.routingKey = routingKey; return this; } /** * Returns the keyspace this query operates on. *

* Unless the keyspace has been explicitly set through {@link #setKeyspace}, * this method will return {@code null} to avoid having to parse the query * string. * * @return the keyspace set through {@link #setKeyspace} if such keyspace was * set, {@code null} otherwise. * * @see Statement#getKeyspace */ @Override public String getKeyspace() { return keyspace; } /** * Sets the keyspace this query operates on. *

* This method allows you to manually provide a keyspace for this query. It * is thus optional since the value returned by this method is only an hint * for token aware load balancing policy but is never mandatory. *

* Do note that if the query does not use a fully qualified keyspace, then * you do not need to set the keyspace through that method as the * currently logged in keyspace will be used. * * @param keyspace the name of the keyspace this query operates on. * @return this {@code SimpleStatement} object. * * @see Statement#getKeyspace */ public SimpleStatement setKeyspace(String keyspace) { this.keyspace = keyspace; return this; } /** * Sets the routing key for this query. *

* See {@link #setRoutingKey(ByteBuffer)} for more information. This * method is a variant for when the query partition key is composite and * thus the routing key must be built from multiple values. * * @param routingKeyComponents the raw (binary) values to compose to obtain * the routing key. * @return this {@code SimpleStatement} object. * * @see Statement#getRoutingKey */ public SimpleStatement setRoutingKey(ByteBuffer... routingKeyComponents) { this.routingKey = compose(routingKeyComponents); return this; } // TODO: we could find that a better place (but it's not expose so it doesn't matter too much) static ByteBuffer compose(ByteBuffer... buffers) { int totalLength = 0; for (ByteBuffer bb : buffers) totalLength += 2 + bb.remaining() + 1; ByteBuffer out = ByteBuffer.allocate(totalLength); for (ByteBuffer buffer : buffers) { ByteBuffer bb = buffer.duplicate(); putShortLength(out, bb.remaining()); out.put(bb); out.put((byte) 0); } out.flip(); return out; } private static void putShortLength(ByteBuffer bb, int length) { bb.put((byte) ((length >> 8) & 0xFF)); bb.put((byte) (length & 0xFF)); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy