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

com.datastax.oss.driver.api.querybuilder.QueryBuilder Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 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.oss.driver.api.querybuilder;

import com.datastax.oss.driver.api.core.CqlIdentifier;
import com.datastax.oss.driver.api.core.context.DriverContext;
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.UserDefinedType;
import com.datastax.oss.driver.api.core.type.codec.CodecNotFoundException;
import com.datastax.oss.driver.api.core.type.codec.TypeCodec;
import com.datastax.oss.driver.api.core.type.codec.registry.CodecRegistry;
import com.datastax.oss.driver.api.querybuilder.delete.DeleteSelection;
import com.datastax.oss.driver.api.querybuilder.insert.InsertInto;
import com.datastax.oss.driver.api.querybuilder.relation.Relation;
import com.datastax.oss.driver.api.querybuilder.select.SelectFrom;
import com.datastax.oss.driver.api.querybuilder.select.Selector;
import com.datastax.oss.driver.api.querybuilder.term.Term;
import com.datastax.oss.driver.api.querybuilder.truncate.Truncate;
import com.datastax.oss.driver.api.querybuilder.update.UpdateStart;
import com.datastax.oss.driver.internal.core.metadata.schema.ShallowUserDefinedType;
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 com.datastax.oss.driver.internal.querybuilder.ArithmeticOperator;
import com.datastax.oss.driver.internal.querybuilder.DefaultLiteral;
import com.datastax.oss.driver.internal.querybuilder.DefaultRaw;
import com.datastax.oss.driver.internal.querybuilder.delete.DefaultDelete;
import com.datastax.oss.driver.internal.querybuilder.insert.DefaultInsert;
import com.datastax.oss.driver.internal.querybuilder.select.DefaultBindMarker;
import com.datastax.oss.driver.internal.querybuilder.select.DefaultSelect;
import com.datastax.oss.driver.internal.querybuilder.term.BinaryArithmeticTerm;
import com.datastax.oss.driver.internal.querybuilder.term.FunctionTerm;
import com.datastax.oss.driver.internal.querybuilder.term.OppositeTerm;
import com.datastax.oss.driver.internal.querybuilder.term.TupleTerm;
import com.datastax.oss.driver.internal.querybuilder.term.TypeHintTerm;
import com.datastax.oss.driver.internal.querybuilder.truncate.DefaultTruncate;
import com.datastax.oss.driver.internal.querybuilder.update.DefaultUpdate;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.util.Arrays;

/** A Domain-Specific Language to build CQL queries using Java code. */
public class QueryBuilder {

  /** Starts a SELECT query for a qualified table. */
  @NonNull
  public static SelectFrom selectFrom(
      @Nullable CqlIdentifier keyspace, @NonNull CqlIdentifier table) {
    return new DefaultSelect(keyspace, table);
  }

  /**
   * Shortcut for {@link #selectFrom(CqlIdentifier, CqlIdentifier)
   * selectFrom(CqlIdentifier.fromCql(keyspace), CqlIdentifier.fromCql(table))}
   */
  @NonNull
  public static SelectFrom selectFrom(@Nullable String keyspace, @NonNull String table) {
    return selectFrom(
        keyspace == null ? null : CqlIdentifier.fromCql(keyspace), CqlIdentifier.fromCql(table));
  }

  /** Starts a SELECT query for an unqualified table. */
  @NonNull
  public static SelectFrom selectFrom(@NonNull CqlIdentifier table) {
    return selectFrom(null, table);
  }

  /** Shortcut for {@link #selectFrom(CqlIdentifier) selectFrom(CqlIdentifier.fromCql(table))} */
  @NonNull
  public static SelectFrom selectFrom(@NonNull String table) {
    return selectFrom(CqlIdentifier.fromCql(table));
  }

  /** Starts an INSERT query for a qualified table. */
  @NonNull
  public static InsertInto insertInto(
      @Nullable CqlIdentifier keyspace, @NonNull CqlIdentifier table) {
    return new DefaultInsert(keyspace, table);
  }

  /**
   * Shortcut for {@link #insertInto(CqlIdentifier, CqlIdentifier)
   * insertInto(CqlIdentifier.fromCql(keyspace), CqlIdentifier.fromCql(table))}.
   */
  @NonNull
  public static InsertInto insertInto(@Nullable String keyspace, @NonNull String table) {
    return insertInto(
        keyspace == null ? null : CqlIdentifier.fromCql(keyspace), CqlIdentifier.fromCql(table));
  }

  /** Starts an INSERT query for an unqualified table. */
  @NonNull
  public static InsertInto insertInto(@NonNull CqlIdentifier table) {
    return insertInto(null, table);
  }

  /** Shortcut for {@link #insertInto(CqlIdentifier) insertInto(CqlIdentifier.fromCql(table))}. */
  @NonNull
  public static InsertInto insertInto(@NonNull String table) {
    return insertInto(CqlIdentifier.fromCql(table));
  }

  /** Starts an UPDATE query for a qualified table. */
  @NonNull
  public static UpdateStart update(@Nullable CqlIdentifier keyspace, @NonNull CqlIdentifier table) {
    return new DefaultUpdate(keyspace, table);
  }

  /**
   * Shortcut for {@link #update(CqlIdentifier, CqlIdentifier)
   * update(CqlIdentifier.fromCql(keyspace), CqlIdentifier.fromCql(table))}
   */
  @NonNull
  public static UpdateStart update(@Nullable String keyspace, @NonNull String table) {
    return update(
        keyspace == null ? null : CqlIdentifier.fromCql(keyspace), CqlIdentifier.fromCql(table));
  }

  /** Starts an UPDATE query for an unqualified table. */
  @NonNull
  public static UpdateStart update(@NonNull CqlIdentifier table) {
    return update(null, table);
  }

  /** Shortcut for {@link #update(CqlIdentifier) update(CqlIdentifier.fromCql(table))} */
  @NonNull
  public static UpdateStart update(@NonNull String table) {
    return update(CqlIdentifier.fromCql(table));
  }

  /** Starts a DELETE query for a qualified table. */
  @NonNull
  public static DeleteSelection deleteFrom(
      @Nullable CqlIdentifier keyspace, @NonNull CqlIdentifier table) {
    return new DefaultDelete(keyspace, table);
  }

  /**
   * Shortcut for {@link #deleteFrom(CqlIdentifier, CqlIdentifier)
   * deleteFrom(CqlIdentifier.fromCql(keyspace), CqlIdentifier.fromCql(table))}
   */
  @NonNull
  public static DeleteSelection deleteFrom(@Nullable String keyspace, @NonNull String table) {
    return deleteFrom(
        keyspace == null ? null : CqlIdentifier.fromCql(keyspace), CqlIdentifier.fromCql(table));
  }

  /** Starts a DELETE query for an unqualified table. */
  @NonNull
  public static DeleteSelection deleteFrom(@NonNull CqlIdentifier table) {
    return deleteFrom(null, table);
  }

  /** Shortcut for {@link #deleteFrom(CqlIdentifier) deleteFrom(CqlIdentifier.fromCql(table))} */
  @NonNull
  public static DeleteSelection deleteFrom(@NonNull String table) {
    return deleteFrom(CqlIdentifier.fromCql(table));
  }

  /**
   * An ordered set of anonymous terms, as in {@code WHERE (a, b) = (1, 2)} (on the right-hand
   * side).
   *
   * 

For example, this can be used as the right operand of {@link Relation#columns(String...)}. */ @NonNull public static Term tuple(@NonNull Iterable components) { return new TupleTerm(components); } /** Var-arg equivalent of {@link #tuple(Iterable)}. */ @NonNull public static Term tuple(@NonNull Term... components) { return tuple(Arrays.asList(components)); } /** The sum of two terms, as in {@code WHERE k = left + right}. */ @NonNull public static Term add(@NonNull Term left, @NonNull Term right) { return new BinaryArithmeticTerm(ArithmeticOperator.SUM, left, right); } /** The difference of two terms, as in {@code WHERE k = left - right}. */ @NonNull public static Term subtract(@NonNull Term left, @NonNull Term right) { return new BinaryArithmeticTerm(ArithmeticOperator.DIFFERENCE, left, right); } /** The product of two terms, as in {@code WHERE k = left * right}. */ @NonNull public static Term multiply(@NonNull Term left, @NonNull Term right) { return new BinaryArithmeticTerm(ArithmeticOperator.PRODUCT, left, right); } /** The quotient of two terms, as in {@code WHERE k = left / right}. */ @NonNull public static Term divide(@NonNull Term left, @NonNull Term right) { return new BinaryArithmeticTerm(ArithmeticOperator.QUOTIENT, left, right); } /** The remainder of two terms, as in {@code WHERE k = left % right}. */ @NonNull public static Term remainder(@NonNull Term left, @NonNull Term right) { return new BinaryArithmeticTerm(ArithmeticOperator.REMAINDER, left, right); } /** The opposite of a term, as in {@code WHERE k = -argument}. */ @NonNull public static Term negate(@NonNull Term argument) { return new OppositeTerm(argument); } /** A function call as a term, as in {@code WHERE k = f(arguments)}. */ @NonNull public static Term function( @NonNull CqlIdentifier functionId, @NonNull Iterable arguments) { return function(null, functionId, arguments); } /** Var-arg equivalent of {@link #function(CqlIdentifier, Iterable)}. */ @NonNull public static Term function(@NonNull CqlIdentifier functionId, @NonNull Term... arguments) { return function(functionId, Arrays.asList(arguments)); } /** * Shortcut for {@link #function(CqlIdentifier, Iterable) * function(CqlIdentifier.fromCql(functionName), arguments)}. */ @NonNull public static Term function(@NonNull String functionName, @NonNull Iterable arguments) { return function(CqlIdentifier.fromCql(functionName), arguments); } /** * Shortcut for {@link #function(CqlIdentifier, Term...) * function(CqlIdentifier.fromCql(functionName), arguments)}. */ @NonNull public static Term function(@NonNull String functionName, @NonNull Term... arguments) { return function(CqlIdentifier.fromCql(functionName), arguments); } /** A function call as a term, as in {@code WHERE k = ks.f(arguments)}. */ @NonNull public static Term function( @Nullable CqlIdentifier keyspaceId, @NonNull CqlIdentifier functionId, @NonNull Iterable arguments) { return new FunctionTerm(keyspaceId, functionId, arguments); } /** Var-arg equivalent of {@link #function(CqlIdentifier, CqlIdentifier, Iterable)}. */ @NonNull public static Term function( @Nullable CqlIdentifier keyspaceId, @NonNull CqlIdentifier functionId, @NonNull Term... arguments) { return function(keyspaceId, functionId, Arrays.asList(arguments)); } /** * Shortcut for {@link #function(CqlIdentifier, CqlIdentifier, Iterable) * function(CqlIdentifier.fromCql(keyspaceName), CqlIdentifier.fromCql(functionName), arguments)}. */ @NonNull public static Term function( @Nullable String keyspaceName, @NonNull String functionName, @NonNull Iterable arguments) { return function( keyspaceName == null ? null : CqlIdentifier.fromCql(keyspaceName), CqlIdentifier.fromCql(functionName), arguments); } /** * Shortcut for {@link #function(CqlIdentifier, CqlIdentifier, Term...) * function(CqlIdentifier.fromCql(keyspaceName), CqlIdentifier.fromCql(functionName), arguments)}. */ @NonNull public static Term function( @Nullable String keyspaceName, @NonNull String functionName, @NonNull Term... arguments) { return function( keyspaceName == null ? null : CqlIdentifier.fromCql(keyspaceName), CqlIdentifier.fromCql(functionName), arguments); } /** * Provides a type hint for an expression, as in {@code WHERE k = (double)1/3}. * *

To create the data type, use the constants and static methods in {@link DataTypes}, or * {@link #udt(CqlIdentifier)}. */ @NonNull public static Term typeHint(@NonNull Term term, @NonNull DataType targetType) { return new TypeHintTerm(term, targetType); } /** A call to the built-in {@code now} function as a term. */ @NonNull public static Term now() { return function("now"); } /** A call to the built-in {@code currentTimestamp} function as a term. */ @NonNull public static Term currentTimestamp() { return function("currenttimestamp"); } /** A call to the built-in {@code currentDate} function as a term. */ @NonNull public static Term currentDate() { return function("currentdate"); } /** A call to the built-in {@code currentTime} function as a term. */ @NonNull public static Term currentTime() { return function("currenttime"); } /** A call to the built-in {@code currentTimeUuid} function as a term. */ @NonNull public static Term currentTimeUuid() { return function("currenttimeuuid"); } /** A call to the built-in {@code minTimeUuid} function as a term. */ @NonNull public static Term minTimeUuid(@NonNull Term argument) { return function("mintimeuuid", argument); } /** A call to the built-in {@code maxTimeUuid} function as a term. */ @NonNull public static Term maxTimeUuid(@NonNull Term argument) { return function("maxtimeuuid", argument); } /** A call to the built-in {@code toDate} function as a term. */ @NonNull public static Term toDate(@NonNull Term argument) { return function("todate", argument); } /** A call to the built-in {@code toTimestamp} function as a term. */ @NonNull public static Term toTimestamp(@NonNull Term argument) { return function("totimestamp", argument); } /** A call to the built-in {@code toUnixTimestamp} function as a term. */ @NonNull public static Term toUnixTimestamp(@NonNull Term argument) { return function("tounixtimestamp", argument); } /** * A literal term, as in {@code WHERE k = 1}. * *

This method can process any type for which there is a default Java to CQL mapping, namely: * primitive types ({@code Integer=>int, Long=>bigint, String=>text, etc.}), and collections, * tuples, and user defined types thereof. * *

A null argument will be rendered as {@code NULL}. * *

For custom mappings, use {@link #literal(Object, CodecRegistry)} or {@link #literal(Object, * TypeCodec)}. * * @throws CodecNotFoundException if there is no default CQL mapping for the Java type of {@code * value}. */ @NonNull public static Literal literal(@Nullable Object value) { return literal(value, CodecRegistry.DEFAULT); } /** * A literal term, as in {@code WHERE k = 1}. * *

This is an alternative to {@link #literal(Object)} for custom type mappings. The provided * registry should contain a codec that can format the value. Typically, this will be your * session's registry, which is accessible via {@code session.getContext().getCodecRegistry()}. * * @see DriverContext#getCodecRegistry() * @throws CodecNotFoundException if {@code codecRegistry} does not contain any codec that can * handle {@code value}. */ @NonNull public static Literal literal(@Nullable Object value, @NonNull CodecRegistry codecRegistry) { if (value instanceof Murmur3Token) { value = ((Murmur3Token) value).getValue(); } else if (value instanceof ByteOrderedToken) { value = ((ByteOrderedToken) value).getValue(); } else if (value instanceof RandomToken) { value = ((RandomToken) value).getValue(); } else if (value instanceof Token) { throw new IllegalArgumentException("Unsupported token type: " + value.getClass().getName()); } try { return literal(value, (value == null) ? null : codecRegistry.codecFor(value)); } catch (CodecNotFoundException e) { assert value != null; throw new IllegalArgumentException( String.format( "Could not inline literal of type %s. " + "This happens because the driver doesn't know how to map it to a CQL type. " + "Try passing a TypeCodec or CodecRegistry to literal().", value.getClass().getName()), e); } } /** * A literal term, as in {@code WHERE k = 1}. * *

This is an alternative to {@link #literal(Object)} for custom type mappings. The value will * be turned into a string with {@link TypeCodec#format(Object)}, and inlined in the query. */ @NonNull public static Literal literal(@Nullable T value, @Nullable TypeCodec codec) { // Don't handle Token here, if the user calls this directly we assume they passed a codec that // can handle the value return new DefaultLiteral<>(value, codec); } /** * A raw CQL snippet. * *

The contents will be appended to the query as-is, without any syntax checking or escaping. * This method should be used with caution, as it's possible to generate invalid CQL that will * fail at execution time; on the other hand, it can be used as a workaround to handle new CQL * features that are not yet covered by the query builder. */ @NonNull public static Raw raw(@NonNull String raw) { return new DefaultRaw(raw); } /** Creates an anonymous bind marker, which appears as {@code ?} in the generated CQL. */ @NonNull public static BindMarker bindMarker() { return bindMarker((CqlIdentifier) null); } /** Creates a named bind marker, which appears as {@code :id} in the generated CQL. */ @NonNull public static BindMarker bindMarker(@Nullable CqlIdentifier id) { return new DefaultBindMarker(id); } /** Shortcut for {@link #bindMarker(CqlIdentifier) bindMarker(CqlIdentifier.fromCql(name))} */ @NonNull public static BindMarker bindMarker(@Nullable String name) { return bindMarker(name == null ? null : CqlIdentifier.fromCql(name)); } /** * Shortcut to reference a UDT in methods that use a {@link DataType}, such as {@link * #typeHint(Term, DataType)} and {@link Selector#cast(Selector, DataType)}. */ @NonNull public static UserDefinedType udt(@NonNull CqlIdentifier name) { return new ShallowUserDefinedType(null, name, false); } /** Shortcut for {@link #udt(CqlIdentifier) udt(CqlIdentifier.fromCql(name))}. */ @NonNull public static UserDefinedType udt(@NonNull String name) { return udt(CqlIdentifier.fromCql(name)); } /** * Creates a new {@code TRUNCATE} query. * * @param table the name of the table to truncate. * @return the truncation query. */ public static Truncate truncate(@NonNull CqlIdentifier table) { return truncate(null, table); } /** * Creates a new {@code TRUNCATE} query. * *

This is a shortcut for {@link #truncate(CqlIdentifier) * truncate(CqlIdentifier.fromCql(table))}. * * @param table the name of the table to truncate. * @return the truncation query. */ public static Truncate truncate(@NonNull String table) { return truncate(null, CqlIdentifier.fromCql(table)); } /** * Creates a new {@code TRUNCATE} query. * * @param keyspace the name of the keyspace to use. * @param table the name of the table to truncate. * @return the truncation query. */ public static Truncate truncate(@Nullable CqlIdentifier keyspace, @NonNull CqlIdentifier table) { return new DefaultTruncate(keyspace, table); } /** * Creates a new {@code TRUNCATE} query. * *

This is a shortcut for {@link #truncate(CqlIdentifier, CqlIdentifier) * truncate(CqlIdentifier.fromCql(keyspace), CqlIdentifier.fromCql(table))}. * * @param keyspace the name of the keyspace to use. * @param table the name of the table to truncate. * @return the truncation query. */ public static Truncate truncate(@Nullable String keyspace, @NonNull String table) { return truncate( keyspace == null ? null : CqlIdentifier.fromCql(keyspace), CqlIdentifier.fromCql(table)); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy