Class BuiltStatement

  • Direct Known Subclasses:
    Batch, Batch.Options, Delete, Delete.Conditions, Delete.Options, Delete.Where, Insert, Insert.Options, Select, Select.Options, Select.Where, Truncate, Update, Update.Assignments, Update.Conditions, Update.IfExists, Update.Options, Update.Where

    public abstract class BuiltStatement
    extends RegularStatement
    Common ancestor to statements generated with the QueryBuilder.

    The actual query string will be generated and cached the first time it is requested, which is either when the driver tries to execute the query, or when you call certain public methods (for example RegularStatement.getQueryString(CodecRegistry), getObject(int, CodecRegistry)).

    Whenever possible (and unless you call setForceNoValues(boolean), the builder will try to handle values passed to its methods as standalone values bound to the query string with placeholders. For instance:

         select().all().from("foo").where(eq("k", "the key"));
         // Is equivalent to:
         new SimpleStatement("SELECT * FROM foo WHERE k=?", "the key");
     
    There are a few exceptions to this rule:
    • for fixed-size number types, the builder can't guess what the actual CQL type is. Standalone values are sent to Cassandra in their serialized form, and number types aren't all serialized in the same way, so picking the wrong type could lead to a query error;
    • if the value is a "special" element like a function call, it can't be serialized. This also applies to collections mixing special elements and regular objects.
    In these cases, the builder will inline the value in the query string:
         select().all().from("foo").where(eq("k", 1));
         // Is equivalent to:
         new SimpleStatement("SELECT * FROM foo WHERE k=1");
     
    One final thing to consider is custom codecs. If you've registered codecs to handle your own Java types against the cluster, then you can pass instances of those types to query builder methods. But should the builder have to inline those values, it needs your codecs to convert them to string form. That is why some of the public methods of this class take a CodecRegistry as a parameter:
         BuiltStatement s = select().all().from("foo").where(eq("k", myCustomObject));
         // if we do this codecs will definitely be needed:
         s.forceNoValues(true);
         s.getQueryString(myCodecRegistry);
     
    For convenience, there are no-arg versions of those methods that use CodecRegistry.DEFAULT_INSTANCE. But you should only use them if you are sure that no custom values will need to be inlined while building the statement, or if you have registered your custom codecs with the default registry instance. Otherwise, you will get a CodecNotFoundException.
    • Method Detail

      • getQueryString

        public String getQueryString​(CodecRegistry codecRegistry)
        Description copied from class: 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 Statement objects.

        For example, Statement objects carry numerous protocol-level settings, such as the consistency level to use, or the 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.

        Specified by:
        getQueryString in class RegularStatement
        Parameters:
        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 RegularStatement.getQueryString() depending on the type of statement this is called on.
        Returns:
        a valid CQL query string.
        See Also:
        RegularStatement.getQueryString()
      • getObject

        public Object getObject​(int i,
                                CodecRegistry codecRegistry)
        Returns the ith value as the Java type matching its CQL type.
        Parameters:
        i - the index to retrieve.
        codecRegistry - the codec registry that will be used if the statement must be rebuilt in order to determine if it has values, and Java objects must be inlined in the process (see BuiltStatement for more explanations on why this is so).
        Returns:
        the value of the ith value of this statement.
        Throws:
        IllegalStateException - if this statement does not have values.
        IndexOutOfBoundsException - if i is not a valid index for this object.
        See Also:
        getObject(int)
      • getObject

        public Object getObject​(int i)
        Returns the ith value as the Java type matching its CQL type.

        This method calls getObject(int, CodecRegistry) with CodecRegistry.DEFAULT_INSTANCE. It's safe to use if you don't use any custom codecs, or if your custom codecs are in the default registry; otherwise, use the other method and provide the registry that contains your codecs.

        Parameters:
        i - the index to retrieve.
        Returns:
        the value of the ith value of this statement.
        Throws:
        IllegalStateException - if this statement does not have values.
        IndexOutOfBoundsException - if i is not a valid index for this object.
      • getRoutingKey

        public ByteBuffer getRoutingKey​(ProtocolVersion protocolVersion,
                                        CodecRegistry codecRegistry)
        Description copied from class: Statement
        Returns the routing key (in binary raw form) to use for token aware routing of this query.

        The routing key is optional in that implementers are free to return null. The routing key is an hint used for token-aware routing (see TokenAwarePolicy), and if provided should correspond to the binary value for the query partition key. However, not providing a routing key never causes a query to fail and if the load balancing policy used is not token aware, then the routing key can be safely ignored.

        Specified by:
        getRoutingKey in class Statement
        Parameters:
        protocolVersion - the protocol version that will be used if the actual implementation needs to serialize something to compute the key.
        codecRegistry - the codec registry that will be used if the actual implementation needs to serialize something to compute this key.
        Returns:
        the routing key for this query or null.
      • getKeyspace

        public String getKeyspace()
        Description copied from class: Statement
        Returns the keyspace this query operates on.

        Note that not all query specify on which keyspace they operate on, and so this method can always return null. Firstly, some queries do not operate inside a keyspace: keyspace creation, USE queries, user creation, etc. Secondly, even query that operate within a keyspace do not have to specify said keyspace directly, in which case the currently logged in keyspace (the one set through a USE query (or through the use of Cluster.connect(String))). Lastly, as for the routing key, this keyspace information is only a hint for token-aware routing (since replica placement depend on the replication strategy in use which is a per-keyspace property) and having this method return null (or even a bogus keyspace name) will never cause the query to fail.

        Specified by:
        getKeyspace in class Statement
        Returns:
        the keyspace this query operate on if relevant or null.
      • isIdempotent

        public Boolean isIdempotent()
        Description copied from class: Statement
        Whether this statement is idempotent, i.e. whether it can be applied multiple times without changing the result beyond the initial application.

        If a statement is not idempotent, the driver will ensure that it never gets executed more than once, which means:

        (this behavior is implemented in the driver internals, the corresponding policies will not even be invoked).

        Note that this method can return null, in which case the driver will default to QueryOptions.getDefaultIdempotence().

        By default, this method returns null for all statements, except for

        • BuiltStatement - value will be inferred from the query: if it updates counters, prepends/appends to a list, or uses a function call or QueryBuilder.raw(String) anywhere in an inserted value, the result will be false; otherwise it will be true.
        • Batch and BatchStatement:
          1. If any statement in batch has isIdempotent() false - return false
          2. If no statements with isIdempotent() false, but some have isIdempotent() null - return null
          3. Otherwise - return true
        In all cases, calling Statement.setIdempotent(boolean) forces a value that overrides calculated value.

        Note that when a statement is prepared (Session.prepare(String)), its idempotence flag will be propagated to all PreparedStatements created from it.

        Overrides:
        isIdempotent in class Statement
        Returns:
        whether this statement is idempotent, or null to use QueryOptions.getDefaultIdempotence().
      • setForceNoValues

        public RegularStatement setForceNoValues​(boolean forceNoValues)
        Allows to force this builder to not generate values (through its getValues() method).

        By default (and unless the protocol version 1 is in use, see below) and for performance reasons, the query builder will not serialize all values provided to strings. This means that getQueryString(CodecRegistry) may return a query string with bind markers (where and when is at the discretion of the builder) and getValues(com.datastax.driver.core.ProtocolVersion, com.datastax.driver.core.CodecRegistry) will return the binary values for those markers. This method allows to force the builder to not generate binary values but rather to inline them all in the query string. In practice, this means that if you call setForceNoValues(true), you are guaranteed that getValues() will return null and that the string returned by getQueryString() will contain no other bind markers than the ones specified by the user.

        If the native protocol version 1 is in use, the driver will default to not generating values since those are not supported by that version of the protocol. In practice, the driver will automatically call this method with true as argument prior to execution. Hence, calling this method when the protocol version 1 is in use is basically a no-op.

        Note that this method is mainly useful for debugging purpose. In general, the default behavior should be the correct and most efficient one.

        Parameters:
        forceNoValues - whether or not this builder may generate values.
        Returns:
        this statement.