com.github.helenusdriver.driver.StatementBuilder.java Source code

Java tutorial

Introduction

Here is the source code for com.github.helenusdriver.driver.StatementBuilder.java

Source

/*
 * Copyright (C) 2015-2015 The Helenus Driver Project Authors.
 *
 * 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.github.helenusdriver.driver;

import java.lang.reflect.Field;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;

import javax.json.JsonObject;

import com.github.helenusdriver.driver.info.ClassInfo;
import com.github.helenusdriver.persistence.Column;

/**
 * The <code>StatementBuilder</code> class extends the functionality of Cassandra's
 * {@link com.datastax.driver.core.querybuilder.QueryBuilder} class in order to
 * provide support for POJOs.
 *
 * @copyright 2015-2015 The Helenus Driver Project Authors
 *
 * @author  The Helenus Driver Project Authors
 * @version 1 - Jan 15, 2015 - paouelle - Creation
 *
 * @since 1.0
 */
public final class StatementBuilder {
    /**
     * Prevents instantiation
     *
     * @author paouelle
     */
    private StatementBuilder() {
    }

    /**
     * Gets a class info structure that defines the specified POJO class.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO associated with this statement
     *
     * @param  clazz the class of POJO for which to get a class info object for
     * @return the non-<code>null</code> class info object representing the given
     *         POJO class
     * @throws NullPointerException if <code>clazz</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>clazz</code> doesn't represent
     *         a valid POJO class
     */
    public static <T> ClassInfo<T> getClassInfo(Class<T> clazz) {
        org.apache.commons.lang3.Validate.notNull(clazz, "invalid null POJO class");
        return StatementManager.getManager().getClassInfo(clazz);
    }

    /**
     * Start building a new SELECT statement that selects the provided names.
     * <p>
     * <i>Note:</i> that {@code select(clazz, c1, c2)} is just a shortcut for
     * {@code select(clazz).column(c1).column(c2)}.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO associated with the statement.
     *
     * @param  clazz the class of POJO associated with this statement
     * @param  columns the columns names that should be selected by the statement.
     * @return an in-construction SELECT statement (you will need to provide at
     *         least a FROM clause to complete the statement).
     * @throws NullPointerException if <code>clazz</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>clazz</code> doesn't represent a
     *         valid POJO class or any of the specified columns are not defined
     *         by the POJO
     */
    public static <T> Select.Builder<T> select(Class<T> clazz, CharSequence... columns) {
        return StatementManager.getManager().select(clazz, columns);
    }

    /**
     * Starts building a new SELECT statement.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO associated with the statement.
     *
     * @param  clazz the class of POJO associated with this statement
     * @return an in-construction SELECT statement (you will need to provide a column
     *         selection and at least a FROM clause to complete the statement).
     * @throws NullPointerException if <code>clazz</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>clazz</code> doesn't represent a
     *         valid POJO class
     */
    public static <T> Select.Selection<T> select(Class<T> clazz) {
        return StatementManager.getManager().select(clazz);
    }

    /**
     * Starts building a new INSERT statement for the following POJO object.
     * <p>
     * <i>Note:</i> If no columns are added as part of the INSERT statement then
     * all columns and values from the POJO are automatically added.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO associated with the statement.
     *
     * @param  object the POJO object to be inserted
     * @return an in-construction INSERT statement
     * @throws NullPointerException if <code>object</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>object</code> is not a valid POJO
     */
    public static <T> Insert<T> insert(T object) {
        return StatementManager.getManager().insert(object);
    }

    /**
     * Starts building a new UPDATE statement for the following POJO object to update
     * all the required tables defined by the POJO based on the assignment clauses
     * specified.
     * <p>
     * <i>Note:</i> The primary key columns are automatically added to the
     * "WHERE" part of the UPDATE statement if no clauses are added to the "WHERE"
     * part. In addition, if no assignments are specified via the "WITH" part of
     * the UPDATE statement, all non-primary columns will be automatically added.
     * <p>
     * If it is discovered that a primary key is part of the set of assignments,
     * the "update" will be translated into a full "insert" of the POJO object
     * without regards to the assignments specified with the "update. This is to
     * ensure that the whole POJO is persisted to the DB into a new row. If a
     * primary key is assigned using the {@link #set(CharSequence, Object, Object)}
     * then a "delete" statement will also be generated for each tables affected
     * by the primary key column before a full "insert" is generated.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO associated with the statement.
     *
     * @param  object the POJO object to be updated
     * @return an in-construction UPDATE statement
     * @throws NullPointerException if <code>object</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>object</code> is not a valid POJO
     */
    public static <T> Update<T> update(T object) {
        org.apache.commons.lang3.Validate.notNull(object, "invalid null object");
        return StatementManager.getManager().update(object);
    }

    /**
     * Starts building a new UPDATE statement for the following POJO object to update
     * all the specified tables defined by the POJO based on the assignment clauses
     * specified.
     * <p>
     * <i>Note:</i> The primary key columns are automatically added to the
     * "WHERE" part of the UPDATE statement if no clauses are added to the "WHERE"
     * part. In addition, if no assignments are specified via the "WITH" part of
     * the UPDATE statement, all non-primary columns will be automatically added.
     * <p>
     * If it is discovered that a primary key is part of the set of assignments,
     * the "update" will be translated into a full "insert" of the POJO object
     * without regards to the assignments specified with the "update. This is to
     * ensure that the whole POJO is persisted to the DB into a new row. If a
     * primary key is assigned using the {@link #set(CharSequence, Object, Object)}
     * then a "delete" statement will also be generated for each tables affected
     * by the primary key column before a full "insert" is generated.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO associated with the statement.
     *
     * @param  object the POJO object to be updated
     * @param  tables the tables to update
     * @return an in-construction UPDATE statement
     * @throws NullPointerException if <code>object</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>object</code> is not a valid POJO
     *         or if any of the specified tables are not defined in the POJO
     */
    public static <T> Update<T> update(T object, String... tables) {
        return StatementManager.getManager().update(object, tables);
    }

    // TODO: implement Update with only POJO class
    // this one will support statements like this:
    // UPDATE(class, [table...]).with(setAllFrom(obj))
    //                          .with(setFrom(obj, cname))
    //                          .with(set(cname, val))
    //                          .isPartionnedLike(obj)) or any other clauses
    //  /**
    //   * Starts building a new UPDATE statement for the following POJO class to update
    //   * all the required tables defined by the POJO class based on the assignment
    //   * clauses specified.
    //   * <p>
    //   * <i>Note:</i> At least a SET and a WHERE clause needs to be provided to
    //   * complete the statement.
    //   *
    //   * @author paouelle
    //   *
    //   * @param <T> The type of POJO associated with the statement.
    //   *
    //   * @param  clazz the class of POJO associated with the statement
    //   * @return an in-construction UPDATE statement
    //   * @throws NullPointerException if <code>clazz</code> is <code>null</code>
    //   * @throws IllegalArgumentException if <code>clazz</code> doesn't represent a
    //   *         valid POJO class
    //   */
    //  public static <T> Update<T> update(Class<T> clazz) {
    //    return new Update<>(
    //      GenericStatement.getClassInfo((Class<T>)object.getClass()).newContext(object)
    //    );
    //  }

    /**
     * Start building a new DELETE statement that deletes the provided columns from
     * the specified POJO.
     *
     * @param <T> The type of POJO associated with the statement.
     *
     * @param  object the POJO object to delete columns from
     * @param  columns the columns names that should be deleted by the statement
     * @return an in-construction DELETE statement (At least a FROM and a WHERE
     *         clause needs to be provided to complete the statement).
     * @throws NullPointerException if <code>object</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>object</code> is not a valid POJO
     *         or if any of the specified columns are not defined in the POJO
     */
    public static <T> Delete.Builder<T> delete(T object, String... columns) {
        return StatementManager.getManager().delete(object, columns);
    }

    /**
     * Start building a new DELETE statement for the specified POJO.
     *
     * @param <T> The type of POJO associated with the statement.
     *
     * @param  object the POJO object to delete columns from
     * @return an in-construction SELECT statement (you will need to provide a
     *         column selection and at least a FROM and a WHERE clause to complete
     *         the statement).
     * @throws NullPointerException if <code>object</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>object</code> is not a valid POJO
     */
    public static <T> Delete.Selection<T> delete(T object) {
        return StatementManager.getManager().delete(object);
    }

    /**
     * Start building a new DELETE statement that deletes the provided columns from
     * the specified POJO.
     *
     * @param <T> The type of POJO associated with the statement.
     *
     * @param  clazz the class of POJO to delete columns for
     * @param  columns the columns names that should be deleted by the statement
     * @return an in-construction DELETE statement (At least a FROM and a WHERE
     *         clause needs to be provided to complete the statement).
     * @throws NullPointerException if <code>clazz</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>clazz</code> doesn't represent a
     *         valid POJO class or any of the specified columns are not defined
     *         by the POJO
     */
    public static <T> Delete.Builder<T> delete(Class<T> clazz, String... columns) {
        return StatementManager.getManager().delete(clazz, columns);
    }

    /**
     * Start building a new DELETE statement for the specified POJO.
     *
     * @param <T> The type of POJO associated with the statement.
     *
     * @param  clazz the class of POJO to delete columns for
     * @return an in-construction SELECT statement (you will need to provide a
     *         column selection and at least a FROM and a WHERE clause to complete
     *         the statement).
     * @throws NullPointerException if <code>clazz</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>clazz</code> doesn't represent a
     *         valid POJO class
     */
    public static <T> Delete.Selection<T> delete(Class<T> clazz) {
        return StatementManager.getManager().delete(clazz);
    }

    /**
     * Starts building a new BATCH statement on the provided statements.
     * <p>
     * This method will build a logged batch (this is the default in CQL3). To
     * create unlogged batches, use {@link #unloggedBatch}. Also note that
     * for convenience, if the provided statements are counter statements, this
     * method will create a COUNTER batch even though COUNTER batches are never
     * logged (so for counters, using this method is effectively equivalent to
     * using {@link #unloggedBatch}).
     *
     * @param  statements the statements to batch
     * @return a new {@code BatchableStatement} that batch {@code statements}
     * @throws NullPointerException if <code>statement</code> or any of the
     *         statements are <code>null</code>
     * @throws IllegalArgumentException if counter and non-counter operations
     *         are mixed or if any statement represents a "select" statement or a
     *         "batch" statement
     */
    public static Batch batch(BatchableStatement<?, ?>... statements) {
        return StatementManager.getManager().batch(statements);
    }

    /**
     * Starts building a new BATCH statement on the provided statements.
     * <p>
     * This method will build a logged batch (this is the default in CQL3). To
     * create unlogged batches, use {@link #unloggedBatch}. Also note that
     * for convenience, if the provided statements are counter statements, this
     * method will create a COUNTER batch even though COUNTER batches are never
     * logged (so for counters, using this method is effectively equivalent to
     * using {@link #unloggedBatch}).
     *
     * @param  statements the statements to batch
     * @return a new {@code BatchableStatement} that batch {@code statements}
     * @throws NullPointerException if <code>statement</code> or any of the
     *         statements are <code>null</code>
     * @throws IllegalArgumentException if counter and non-counter operations
     *         are mixed or if any statement represents a "select" statement or a
     *         "batch" statement
     */
    public static Batch batch(Iterable<BatchableStatement<?, ?>> statements) {
        return StatementManager.getManager().batch(statements);
    }

    /**
     * Built a new UNLOGGED BATCH statement on the provided statements.
     * <p>
     * Compared to logged batches (the default), unlogged batch don't
     * use the distributed batch log server side and as such are not
     * guaranteed to be atomic. In other words, if an unlogged batch
     * timeout, some of the batched statements may have been persisted
     * while some have not. Unlogged batch will however be slightly
     * faster than logged batch.
     * <p>
     * If the statements added to the batch are counter statements, the
     * resulting batch will be a COUNTER one.
     *
     * @param  statements the statements to batch
     * @return a new {@code BatchableStatement} that batch {@code statements}
     *         without using the batch log
     * @throws NullPointerException if <code>statement</code> or any of the
     *         statements are <code>null</code>
     * @throws IllegalArgumentException if counter and non-counter operations
     *         are mixed or if any statement represents a "select" statement or a
     *         "batch" statement
     */
    public static Batch unloggedBatch(BatchableStatement<?, ?>... statements) {
        return StatementManager.getManager().unloggedBatch(statements);
    }

    /**
     * Built a new UNLOGGED BATCH statement on the provided statements.
     * <p>
     * Compared to logged batches (the default), unlogged batch don't
     * use the distributed batch log server side and as such are not
     * guaranteed to be atomic. In other words, if an unlogged batch
     * timeout, some of the batched statements may have been persisted
     * while some have not. Unlogged batch will however be slightly
     * faster than logged batch.
     * <p>
     * If the statements added to the batch are counter statements, the
     * resulting batch will be a COUNTER one.
     *
     * @param  statements the statements to batch
     * @return a new {@code BatchableStatement} that batch {@code statements}
     *         without using the batch log
     * @throws NullPointerException if <code>statement</code> or any of the
     *         statements are <code>null</code>
     * @throws IllegalArgumentException if counter and non-counter operations
     *         are mixed or if any statement represents a "select" statement or a
     *         "batch" statement
     */
    public static Batch unloggedBatch(Iterable<BatchableStatement<?, ?>> statements) {
        return StatementManager.getManager().unloggedBatch(statements);
    }

    /**
     * Wraps a Cassandra regular statement into a statement that can be executed
     * or batched using this API.
     *
     * @author paouelle
     *
     * @param  statement the raw statement to be wrapped
     * @return a new {@code RegularStatement} that corresponds to the specified
     *         raw statement
     * @throws NullPointerException if <code>statement</code> is <code>null</code>
     */
    public static RegularStatement regular(com.datastax.driver.core.RegularStatement statement) {
        return StatementManager.getManager().regular(statement);
    }

    /**
     * Starts building a new CREATE KEYSPACE statement for the given POJO class.
     * <p>
     * <i>Note:</i> By default, it will create the keyspace defined as part of
     * the POJO along with the options set in the POJO @keyspace annotation.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO associated with the statement.
     *
     * @param  clazz the class of POJO associated with this statement
     * @return a new CREATE KEYSPACE statement
     * @throws NullPointerException if <code>clazz</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>clazz</code> doesn't represent a
     *         valid POJO class
     */
    public static <T> CreateKeyspace<T> createKeyspace(Class<T> clazz) {
        return StatementManager.getManager().createKeyspace(clazz);
    }

    /**
     * Starts building a new CREATE TYPE statement for the given POJO class.
     * <p>
     * The column schema is automatically extracted from the POJO class definition.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO associated with the statement.
     *
     * @param  clazz the class of POJO associated with this statement
     * @return a new CREATE TYPE statement
     * @throws NullPointerException if <code>clazz</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>clazz</code> doesn't represent a
     *         valid user-defined type POJO class
     */
    public static <T> CreateType<T> createType(Class<T> clazz) {
        return StatementManager.getManager().createType(clazz);
    }

    /**
     * Starts building a new CREATE TABLE statement for the given POJO class. This
     * might actually results in multiple CREATE TABLE statements.
     * <p>
     * <i>Note:</i> If the POJO defines multiple tables, executing this
     * statement with default values will actually create all tables. Since table creation
     * cannot be batched with Cassandra, this will result in a non-atomic creation
     * of all tables. The process will stop at first failure and will not revert back
     * the created tables if any.
     * <p>
     * The column schema is automatically extracted from the POJO class definition.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO associated with the statement.
     *
     * @param  clazz the class of POJO associated with this statement
     * @return a new CREATE TABLE statement
     * @throws NullPointerException if <code>clazz</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>clazz</code> doesn't represent a
     *         valid POJO class
     */
    public static <T> CreateTable<T> createTable(Class<T> clazz) {
        return StatementManager.getManager().createTable(clazz);
    }

    /**
     * Starts building a new CREATE TABLE statement for the given POJO class. This
     * might actually results in multiple CREATE TABLE statements.
     * <p>
     * <i>Note:</i> If multiple tables are specified, executing this statement
     * will actually create all these tables. Since table creation cannot be
     * batched with Cassandra, this will result in a non-atomic creation of all
     * tables. The process will stop at first failure and will not revert back
     * the created tables if any.
     * <p>
     * The column schema is automatically extracted from the POJO class definition.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO associated with the statement.
     *
     * @param  clazz the class of POJO associated with this statement
     * @param  tables the tables to create
     * @return a new CREATE TABLE statement
     * @throws NullPointerException if <code>clazz</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>clazz</code> doesn't represent a
     *         valid POJO class or if any of the specified tables are not defined
     *         in the POJO
     */
    public static <T> CreateTable<T> createTable(Class<T> clazz, String... tables) {
        return StatementManager.getManager().createTable(clazz, tables);
    }

    /**
     * Starts building a new CREATE INDEX statement for the given POJO class.
     * This might actually results in multiple CREATE INDEX statements.
     * <p>
     * <i>Note:</i> If the POJO defines multiple tables and indexes, executing this
     * statement will potentially create all indexes for all tables. Since index
     * creation cannot be batched with Cassandra, this will result in a non-atomic
     * creation of all indexes. The process will stop at first failure and will
     * not revert back the created indexes if any.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO associated with the statement.
     *
     * @param  clazz the class of POJO associated with this statement
     * @return an in-build construct for the CREATE INDEX statement
     * @throws NullPointerException if <code>clazz</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>clazz</code> doesn't represent a
     *         valid POJO class
     */
    public static <T> CreateIndex.Builder<T> createIndex(Class<T> clazz) {
        return StatementManager.getManager().createIndex(clazz);
    }

    /**
     * Starts building a new CREATE SCHEMA statement for the given POJO class.
     * This will create all the required elements to support the schema for a given
     * POJO. It will take care of creating the required keyspace, user-defined types,
     * tables, and indexes.
     * <p>
     * <i>Note:</i> If the POJO defines multiple tables and indexes, executing this
     * statement will potentially create the keyspace, all tables and all indexes
     * for all tables. Since keyspace, table, and index creation cannot be batched
     * with Cassandra, this will result in a non-atomic creation of everything.
     * The process will stop at first failure and will not revert back the created
     * keyspace, tables, or indexes if any.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO associated with the statement.
     *
     * @param  clazz the class of POJO associated with this statement
     * @return an in-build construct for the CREATE SCHEMA statement
     * @throws NullPointerException if <code>clazz</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>clazz</code> doesn't represent a
     *         valid POJO class
     */
    public static <T> CreateSchema<T> createSchema(Class<T> clazz) {
        return StatementManager.getManager().createSchema(clazz);
    }

    /**
     * Starts building a new CREATE SCHEMAS statement for all POJO classes defined
     * in a given package. This will create all the required elements to support
     * the schema for each POJO. It will take care of creating the required
     * keyspaces, user-defined types, tables, and indexes.
     * <p>
     * <i>Note:</i> This statement will create the schemas for all POJOs for which
     * the defined keyspace can be computed with any of the specified suffixes via
     * the WHERE clauses.
     * <p>
     * <i>Note:</i> Executing this statement will potentially create the keyspaces,
     * all user-defined types, all tables and all indexes for all tables. Since
     * keyspace, user-defined type, table, and index creation cannot be batched
     * with Cassandra, this will result in a non-atomic creation of everything.
     * The process will stop at first failure and will not revert back the created
     * keyspaces, user-defined types, tables, or indexes if any.
     *
     * @author paouelle
     *
     * @param  pkg the package where the POJOs for which to create schemas are
     *         defined
     * @return a new CREATE SCHEMAS statement
     * @throws NullPointerException if <code>pkg</code> is <code>null</code>
     * @throws IllegalArgumentException if two entities defines the same keyspace
     *         with different options or an entity class doesn't represent
     *         a valid POJO class or if no entities are found
     */
    public static CreateSchemas createSchemas(String pkg) {
        return StatementManager.getManager().createSchemas(pkg);
    }

    /**
     * Starts building a new CREATE SCHEMAS statement for all POJO classes defined
     * in a given package. This will create all the required elements to support
     * the schema for each POJO. It will take care of creating the required
     * keyspaces, user-defined types, tables, and indexes.
     * <p>
     * <i>Note:</i> This statement will create the schemas for only the POJOs for
     * which the defined keyspace can be computed with exactly all of the specified
     * suffixes via the WHERE clauses.
     * <p>
     * <i>Note:</i> Executing this statement will potentially create the keyspaces,
     * all user-defined types, all tables and all indexes for all tables. Since
     * keyspace, user-defined type, table, and index creation cannot be batched
     * with Cassandra, this will result in a non-atomic creation of everything.
     * The process will stop at first failure and will not revert back the created
     * keyspaces, user-defined types, tables, or indexes if any.
     *
     * @author paouelle
     *
     * @param  pkg the package where the POJOs for which to create schemas are
     *         defined
     * @return a new CREATE SCHEMAS statement
     * @throws NullPointerException if <code>pkg</code> is <code>null</code>
     * @throws IllegalArgumentException if two entities defines the same keyspace
     *         with different options or an @Entitiy annotated class doesn't represent
     *         a valid POJO class or if no entities are found
     */
    public static CreateSchemas createMatchingSchemas(String pkg) {
        return StatementManager.getManager().createMatchingSchemas(pkg);
    }

    /**
     * Starts building a new TRUNCATE statement for the given POJO class. This
     * might actually results in multiple TRUNCATE statements.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO associated with the statement.
     *
     * @param  clazz the class of POJO associated with this statement
     * @return a new TRUNCATE statement
     * @throws NullPointerException if <code>clazz</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>clazz</code> doesn't represent a
     *         valid POJO class
     */
    public static <T> Truncate<T> truncate(Class<T> clazz) {
        return StatementManager.getManager().truncate(clazz);
    }

    /**
     * Starts building a new TRUNCATE statement for the given POJO class. This
     * might actually results in multiple TRUNCATE statements.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO associated with the statement.
     *
     * @param  clazz the class of POJO associated with this statement
     * @param  tables the tables to truncate
     * @return a new TRUNCATE statement
     * @throws NullPointerException if <code>clazz</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>clazz</code> doesn't represent a
     *         valid POJO class or if any of the specified tables are not defined
     *         in the POJO
     */
    public static <T> Truncate<T> truncate(Class<T> clazz, String... tables) {
        return StatementManager.getManager().truncate(clazz, tables);
    }

    /**
     * Starts building a new set of statements that will execute all of them in
     * sequence one after the other.
     * <p>
     * <i>Note:</i> Executing this statement will actually execute all contained
     * statements one after the other in the given order, this will result
     * in a non-atomic execution of the statements. The process will stop
     * at first failure and will not revert back any of the previously executed
     * statements.
     *
     * @param  statements the statements to sequence
     * @return a new {@code SequenceableStatement} that sequence {@code statements}
     * @throws NullPointerException if <code>statement</code> or any of the
     *         statements are <code>null</code>
     */
    public static Sequence sequence(SequenceableStatement<?, ?>... statements) {
        return StatementManager.getManager().sequence(statements);
    }

    /**
     * Starts building a new set of statements that will execute all of them in
     * sequence one after the other.
     * <p>
     * <i>Note:</i> Executing this statement will actually execute all contained
     * statements one after the other in the given order, this will result
     * in a non-atomic execution of the statements. The process will stop
     * at first failure and will not revert back any of the previously executed
     * statements.
     *
     * @param  statements the statements to sequence
     * @return a new {@code SequenceableStatement} that sequence {@code statements}
     * @throws NullPointerException if <code>statement</code> or any of the
     *         statements are <code>null</code>
     */
    public static Sequence sequence(Iterable<SequenceableStatement<?, ?>> statements) {
        return StatementManager.getManager().sequence(statements);
    }

    /**
     * Quotes a column name to make it case sensitive.
     *
     * @author paouelle
     *
     * @param  columnName the column name to quote.
     * @return the quoted column name.
     * @throws NullPointerException if <code>columnName</code> is <code>null</code>
     */
    public static CharSequence quote(String columnName) {
        return StatementManager.getManager().quote(columnName);
    }

    /**
     * The token of a column name.
     *
     * @author paouelle
     *
     * @param  columnName the column name to take the token of.
     * @return {@code "token(" + columnName + ")"}.
     * @throws NullPointerException if <code>columnName</code> is <code>null</code>
     */
    public static CharSequence token(String columnName) {
        return StatementManager.getManager().token(columnName);
    }

    /**
     * The token of column names.
     * <p>
     * This variant is most useful when the partition key is composite.
     *
     * @author paouelle
     *
     * @param  columnNames the column names to take the token of.
     * @return a string representing the token of the provided column names.
     * @throws NullPointerException if any of the column names are <code>null</code>
     */
    public static CharSequence token(String... columnNames) {
        return StatementManager.getManager().token(columnNames);
    }

    /**
     * Creates a set of "equal" where clause stating all suffix keys must be
     * equal to the POJO's used when the statement was initialized.
     *
     * @author paouelle
     *
     * @return the corresponding where clause
     */
    public static Clause isSuffixedLikeObject() {
        return StatementManager.getManager().isSuffixedLikeObject();
    }

    /**
     * Creates a set of "equal" where clause stating all suffix keys must be
     * equal to the provided POJO's.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO.
     *
     * @param  object the POJO from which to get the suffix keys
     * @return the corresponding where clause
     * @throws NullPointerException if <code>object</code> is <code>null</code>
     */
    public static <T> Clause isSuffixedLike(T object) {
        return StatementManager.getManager().isSuffixedLike(object);
    }

    /**
     * Creates a set of "equal" where clause stating all partition primary key
     * columns and suffix keys must be equal to the POJO's used when the statement
     * was initialized.
     *
     * @author paouelle
     *
     * @return the corresponding where clause
     */
    public static Clause isPartitionedLikeObject() {
        return StatementManager.getManager().isPartitionedLikeObject();
    }

    /**
     * Creates a set of "equal" where clause stating all partition primary key
     * columns and suffix keys must be equal to the provided POJO's.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO.
     *
     * @param  object the POJO from which to get the primary and suffix keys
     * @return the corresponding where clause
     * @throws NullPointerException if <code>object</code> is <code>null</code>
     */
    public static <T> Clause isPartitionedLike(T object) {
        return StatementManager.getManager().isPartitionedLike(object);
    }

    /**
     * Creates a set of "equal" where clause stating all primary key columns
     * and suffix keys must be equal to the POJO's used when the statement was
     * initialized.
     *
     * @author paouelle
     *
     * @return the corresponding where clause
     */
    public static Clause isObject() {
        return StatementManager.getManager().isObject();
    }

    /**
     * Creates a set of "equal" where clause stating all primary key columns
     * and suffix keys must be equal to the provided POJO's.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO.
     *
     * @param  object the PJO from which to get the primary and suffix keys
     * @return the corresponding where clause
     * @throws NullPointerException if <code>object</code> is <code>null</code>
     */
    public static <T> Clause is(T object) {
        return StatementManager.getManager().is(object);
    }

    /**
     * Creates an "equal" where clause stating the provided column must be equal
     * to the provided value.
     * <p>
     * This clause can also be used to identify a suffix key to use as part of
     * the statement.
     *
     * @author paouelle
     *
     * @param  name the column name
     * @param  value the value
     * @return the corresponding where equality clause.
     * @throws NullPointerException if <code>columnName</code> is <code>null</code>
     */
    public static Clause.Equality eq(CharSequence name, Object value) {
        return StatementManager.getManager().eq(name, value);
    }

    /**
     * Create an "in" where clause stating the provided column must be equal to
     * one of the provided values.
     *
     * @author paouelle
     *
     * @param  name the column name
     * @param  values the values
     * @return the corresponding where clause.
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>values</code> is empty
     */
    public static Clause in(CharSequence name, Object... values) {
        return StatementManager.getManager().in(name, values);
    }

    /**
     * Create an "in" where clause stating the provided column must be equal to
     * one of the provided values.
     *
     * @author paouelle
     *
     * @param  name the column name
     * @param  values the values
     * @return the corresponding where clause.
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>values</code> is empty
     */
    public static Clause in(CharSequence name, Collection<?> values) {
        return StatementManager.getManager().in(name, values);
    }

    /**
     * Create an "in" where clause stating the provided column must be equal to
     * one of the provided values.
     *
     * @author paouelle
     *
     * @param  name the column name
     * @param  values the values
     * @return the corresponding where clause.
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>values</code> is empty
     */
    public static Clause in(CharSequence name, Stream<?> values) {
        return StatementManager.getManager().in(name, values);
    }

    /**
     * Create an "in" where clause stating the provided column must be equal to
     * a value in the provided range.
     *
     * @author paouelle
     *
     * @param  name the column name
     * @param  from the starting value to include in the "in" clause
     * @param  to the ending value (inclusive) to include in the "in" clause
     * @return the corresponding where clause.
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     * @throws IllegalArgumentException if the specified range is empty
     */
    public static Clause in(CharSequence name, int from, int to) {
        return StatementManager.getManager().in(name, from, to);
    }

    /**
     * Creates a "lesser than" where clause stating the provided column must be
     * less than the provided value.
     *
     * @author paouelle
     *
     * @param  name the column name
     * @param  value the value
     * @return the corresponding where clause.
     * @throws NullPointerException if <code>columnName</code> is <code>null</code>
     */
    public static Clause lt(CharSequence name, Object value) {
        return StatementManager.getManager().lt(name, value);
    }

    /**
     * Creates a "lesser than or equal" where clause stating the provided column
     * must be lesser than or equal to the provided value.
     *
     * @author paouelle
     *
     * @param  name the column name
     * @param  value the value
     * @return the corresponding where clause.
     * @throws NullPointerException if <code>columnName</code> is <code>null</code>
     */
    public static Clause lte(CharSequence name, Object value) {
        return StatementManager.getManager().lte(name, value);
    }

    /**
     * Creates a "greater than" where clause stating the provided column must be
     * greater to the provided value.
     *
     * @author paouelle
     *
     * @param  name the column name
     * @param  value the value
     * @return the corresponding where clause.
     * @throws NullPointerException if <code>columnName</code> is <code>null</code>
     */
    public static Clause gt(CharSequence name, Object value) {
        return StatementManager.getManager().gt(name, value);
    }

    /**
     * Creates a "greater than or equal" where clause stating the provided column
     * must be greater than or equal to the provided value.
     *
     * @author paouelle
     *
     * @param  name the column name
     * @param  value the value
     * @return the corresponding where clause.
     * @throws NullPointerException if <code>columnName</code> is <code>null</code>
     */
    public static Clause gte(CharSequence name, Object value) {
        return StatementManager.getManager().gte(name, value);
    }

    /**
     * Ascending ordering for the provided column.
     *
     * @author paouelle
     *
     * @param  columnName the column name
     * @return the corresponding ordering
     * @throws NullPointerException if <code>columnName</code> is <code>null</code>
     */
    public static Ordering asc(CharSequence columnName) {
        return StatementManager.getManager().asc(columnName);
    }

    /**
     * Descending ordering for the provided column.
     *
     * @author paouelle
     *
     * @param  columnName the column name
     * @return the corresponding ordering
     * @throws NullPointerException if <code>columnName</code> is <code>null</code>
     */
    public static Ordering desc(CharSequence columnName) {
        return StatementManager.getManager().desc(columnName);
    }

    /**
     * Option to set the timestamp for a modification statement (insert, update or
     * delete).
     *
     * @author paouelle
     *
     * @param  timestamp the timestamp (in microseconds) to use.
     * @return the corresponding option
     * @throws IllegalArgumentException if <code>timestamp</code> is negative
     */
    public static Using timestamp(long timestamp) {
        return StatementManager.getManager().timestamp(timestamp);
    }

    /**
     * Option to set the timestamp for a modification statement (insert, update or
     * delete).
     *
     * @author paouelle
     *
     * @param  timestamp the timestamp (in milliseconds) to use.
     * @return the corresponding option
     * @throws IllegalArgumentException if <code>timestamp</code> is negative
     */
    public static Using timestampInMS(long timestamp) {
        return StatementManager.getManager().timestamp(timestamp * 1000L);
    }

    /**
     * Option to set the ttl for a modification statement (insert, update or delete).
     *
     * @author paouelle
     *
     * @param  ttl the ttl (in seconds) to use.
     * @return the corresponding option
     * @throws IllegalArgumentException if <code>ttl</code> is negative
     */
    public static Using ttl(int ttl) {
        return StatementManager.getManager().ttl(ttl);
    }

    /**
     * An object representing a bind marker (a question mark).
     * <p>
     * This can be used wherever a value is expected. For instance, one can do:
     *
     * <pre>
     * {
     *   &#064;code Insert i = StatementBuilder.insertInto(&quot;test&quot;).value(&quot;k&quot;, 0)
     *     .value(&quot;c&quot;, StatementBuilder.bindMarker());
     *   PreparedState p = session.prepare(i.toString());
     * }
     * </pre>
     *
     * @author paouelle
     *
     * @return an object representing a bind marker.
     */
    public static Object bindMarker() {
        return StatementManager.getManager().bindMarker();
    }

    /**
     * Simple "set" assignment of a value to a column. The value is extracted
     * directly from the POJO in play at the time the assignment is added to a
     * statement.
     * <p>
     * <code>Note:</code> This form of the <code>set()</code> cannot be used
     * with an UPDATE statement if this one was not initialized with the POJO to
     * start with.
     * <p>
     * This will generate: {@code name = value}.
     *
     * @author paouelle
     *
     * @param  name the column name
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     */
    public static Assignment setFromObject(CharSequence name) {
        return StatementManager.getManager().setFromObject(name);
    }

    /**
     * Simple "set" assignment of a value to a column. The value is extracted
     * directly from the POJO in play at the time the assignment is added to a
     * statement.
     * <p>
     * <code>Note:</code> This form of the <code>set()</code> cannot be used
     * with an UPDATE statement if this one was not initialized with the POJO to
     * start with.
     * <p>
     * This will generate: {@code name = value}.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO.
     *
     * @param  object the POJO from which to extract all non primary key values
     * @param  name the column name
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>object</code> or <code>name</code>
     *         is <code>null</code>
     */
    public static <T> Assignment setFrom(T object, CharSequence name) {
        return StatementManager.getManager().setFrom(object, name);
    }

    /**
     * Simple "set" assignment of a value to a column.
     * <p>
     * This will generate: {@code name = value}.
     *
     * @author paouelle
     *
     * @param  name the column name
     * @param  value the value to set for the column
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     */
    public static Assignment set(CharSequence name, Object value) {
        return StatementManager.getManager().set(name, value);
    }

    /**
     * Simple "set" assignment of a value to a column.
     * <p>
     * This will generate: {@code name = value}.
     * <p>
     * <i>Note:</i> This version can be useful when assigning a new value to
     * a primary key column. By specifying the old value, the statement can
     * properly generate a corresponding "delete" statement for the old record
     * using the old value before generating an "insert" statement for the new
     * record using the new primary key value.
     *
     * @author paouelle
     *
     * @param  name the column name
     * @param  value the value to set for the column
     * @param  old the old value to replace for the column
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     */
    public static Assignment set(CharSequence name, Object value, Object old) {
        return StatementManager.getManager().set(name, value, old);
    }

    /**
     * "set" assignment of all non primary key values to columns. The values are
     * extracted directly from the POJO in play at the time the assignment is
     * added to a statement.
     * <p>
     * <code>Note:</code> This form of the <code>setAll()</code> cannot be used
     * with an UPDATE statement if this one was not initialized with the POJO to
     * start with.
     * <p>
     * This will generate: {@code name = value} for all non primary keys.
     *
     * @author paouelle
     *
     * @return the correspond assignment (to use in an update statement)
     */
    public static Assignment setAllFromObject() {
        return StatementManager.getManager().setAllFromObject();
    }

    /**
     * "set" assignment of all non primary key values of the specified POJO to
     * columns.
     * <p>
     * This will generate: {@code name = value} for all non primary keys.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO.
     *
     * @param  object the POJO from which to extract all non primary key values
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>object</code> is <code>null</code>
     */
    public static <T> Assignment setAllFrom(T object) {
        return StatementManager.getManager().setAllFrom(object);
    }

    /**
     * Incrementation of a counter column.
     * <p>
     * This will generate: {@code name = name + 1}.
     *
     * @author paouelle
     *
     * @param  name the column name to increment
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     */
    public static Assignment incr(CharSequence name) {
        return StatementBuilder.incr(name, 1L);
    }

    /**
     * Incrementation of a counter column by a provided value.
     * <p>
     * This will generate: {@code name = name + value}.
     *
     * @author paouelle
     *
     * @param  name the column name to increment
     * @param  value the value by which to increment
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     */
    public static Assignment incr(CharSequence name, long value) {
        return StatementManager.getManager().incr(name, value);
    }

    /**
     * Decrementation of a counter column.
     * <p>
     * This will generate: {@code name = name - 1}.
     *
     * @author paouelle
     *
     * @param  name the column name to decrement
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     */
    public static Assignment decr(CharSequence name) {
        return StatementBuilder.decr(name, 1L);
    }

    /**
     * Decrementation of a counter column by a provided value.
     * <p>
     * This will generate: {@code name = name - value}.
     *
     * @author paouelle
     *
     * @param  name the column name to decrement
     * @param  value the value by which to decrement
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     */
    public static Assignment decr(CharSequence name, long value) {
        return StatementManager.getManager().decr(name, value);
    }

    /**
     * Prepend a value to a list column.
     * <p>
     * This will generate: {@code name = [ value ] + name}.
     *
     * @author paouelle
     *
     * @param  name the column name (must be of type list).
     * @param  value the value to prepend
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     */
    public static Assignment prepend(CharSequence name, Object value) {
        return StatementManager.getManager().prepend(name, value);
    }

    /**
     * Prepend a list of values to a list column.
     * <p>
     * This will generate: {@code name = list + name}.
     *
     * @author paouelle
     *
     * @param  name the column name (must be of type list).
     * @param  values the list of values to prepend
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> or <code>values</code> is
     *         <code>null</code>
     */
    public static Assignment prependAll(CharSequence name, List<?> values) {
        return StatementManager.getManager().prependAll(name, values);
    }

    /**
     * Append a value to a list column.
     * <p>
     * This will generate: {@code name = name + [value]}.
     *
     * @author paouelle
     *
     * @param  name the column name (must be of type list).
     * @param  value the value to append
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     */
    public static Assignment append(CharSequence name, Object value) {
        return StatementManager.getManager().append(name, value);
    }

    /**
     * Append a list of values to a list column.
     * <p>
     * This will generate: {@code name = name + list}.
     *
     * @author paouelle
     *
     * @param  name the column name (must be of type list).
     * @param  values the list of values to append
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> or <code>values</code> is
     *         <code>null</code>
     */
    public static Assignment appendAll(CharSequence name, List<?> values) {
        return StatementManager.getManager().appendAll(name, values);
    }

    /**
     * Discard a value from a list column.
     * <p>
     * This will generate: {@code name = name - [value]}.
     *
     * @author paouelle
     *
     * @param  name the column name (must be of type list).
     * @param  value the value to discard
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     */
    public static Assignment discard(CharSequence name, Object value) {
        return StatementManager.getManager().discard(name, value);
    }

    /**
     * Discard a list of values to a list column.
     * <p>
     * This will generate: {@code name = name - list}.
     *
     * @author paouelle
     *
     * @param  name the column name (must be of type list).
     * @param  values the list of values to append
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> or <code>values</code> is
     *         <code>null</code>
     */
    public static Assignment discardAll(CharSequence name, List<?> values) {
        return StatementManager.getManager().discardAll(name, values);
    }

    /**
     * Sets a list column value by index.
     * <p>
     * This will generate: {@code name[idx] = value}.
     *
     * @author paouelle
     *
     * @param  name the column name (must be of type list).
     * @param  idx the index to set
     * @param  value the value to set
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     * @throws IndexOutOfBoundsException if <code>idx</code> is less than 0
     */
    public static Assignment setIdx(CharSequence name, int idx, Object value) {
        return StatementManager.getManager().setIdx(name, idx, value);
    }

    /**
     * Adds a value to a set column.
     * <p>
     * This will generate: {@code name = name + value}}.
     *
     * @author paouelle
     *
     * @param  name the column name (must be of type set).
     * @param  value the value to add
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     */
    public static Assignment add(CharSequence name, Object value) {
        return StatementManager.getManager().add(name, value);
    }

    /**
     * Adds a set of values to a set column.
     * <p>
     * This will generate: {@code name = name + set}.
     *
     * @author paouelle
     *
     * @param  name the column name (must be of type set).
     * @param  values the set of values to add
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> or <code>values</code> is
     *         <code>null</code>
     */
    public static Assignment addAll(CharSequence name, Set<?> values) {
        return StatementManager.getManager().addAll(name, values);
    }

    /**
     * Remove a value from a set column.
     * <p>
     * This will generate: {@code name = name - value}}.
     *
     * @author paouelle
     *
     * @param  name the column name (must be of type set).
     * @param  value the value to remove
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     */
    public static Assignment remove(CharSequence name, Object value) {
        return StatementManager.getManager().remove(name, value);
    }

    /**
     * Remove a set of values from a set column.
     * <p>
     * This will generate: {@code name = name - set}.
     *
     * @author paouelle
     *
     * @param  name the column name (must be of type set).
     * @param  values the set of values to remove
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> or <code>values</code> is
     *         <code>null</code>
     */
    public static Assignment removeAll(CharSequence name, Set<?> values) {
        return StatementManager.getManager().removeAll(name, values);
    }

    /**
     * Puts a new key/value pair to a map column.
     * <p>
     * This will generate: {@code name[key] = value}.
     *
     * @author paouelle
     *
     * @param  name the column name (must be of type map).
     * @param  key the key to put
     * @param  value the value to put
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     */
    public static Assignment put(CharSequence name, Object key, Object value) {
        return StatementManager.getManager().put(name, key, value);
    }

    /**
     * Puts a map of new key/value pairs to a map column.
     * <p>
     * This will generate: {@code name = name + map}.
     *
     * @author paouelle
     *
     * @param  name the column name (must be of type map).
     * @param  mappings the map of key/value pairs to put
     * @return the correspond assignment (to use in an update statement)
     * @throws NullPointerException if <code>name</code> or <code>mappings</code> is
     *         <code>null</code>
     */
    public static Assignment putAll(CharSequence name, Map<?, ?> mappings) {
        return StatementManager.getManager().putAll(name, mappings);
    }

    /**
     * Puts a replication set of properties together for keyspace creation. This
     * will generate: {@code REPLICATION = map}.
     *
     * @author paouelle
     *
     * @param  map the map of replication properties in json format
     * @return the corresponding option (to use in a create keyspace statement)
     * @throws NullPointerException if <code>map</code> is <code>null</code>
     */
    public static KeyspaceWith replication(JsonObject map) {
        return StatementManager.getManager().replication(map);
    }

    /**
     * Sets the durable write option for a keyspace. This will generate:
     * {@code DURABLE_WRITES = true}.
     *
     * @author paouelle
     *
     * @return the corresponding option (to use in a create keyspace statement)
     */
    public static KeyspaceWith durableWrites() {
        return StatementBuilder.durableWrites(true);
    }

    /**
     * Sets the durable write option for a keyspace. This will generate:
     * {@code DURABLE_WRITES = value}.
     *
     * @author paouelle
     *
     * @param  value the keyspace durable writes option value
     * @return the corresponding option (to use in a create keyspace statement)
     */
    public static KeyspaceWith durableWrites(boolean value) {
        return StatementManager.getManager().durableWrites(value);
    }

    /**
     * Protects a value from any interpretation by the query builder.
     * <p>
     * The following table exemplify the behavior of this function:
     * <table border=1 summary="Behavior">
     * <tr>
     * <th>Code</th>
     * <th>Resulting query string</th>
     * </tr>
     * <tr>
     * <td>{@code select().from("t").where(eq("c", "C'est la vie!")); }</td>
     * <td>{@code "SELECT * FROM t WHERE c='C''est la vie!';"}</td>
     * </tr>
     * <tr>
     * <td>{@code select().from("t").where(eq("c", raw("C'est la vie!"))); }</td>
     * <td>{@code "SELECT * FROM t WHERE c=C'est la vie!;"}</td>
     * </tr>
     * <tr>
     * <td>{@code select().from("t").where(eq("c", raw("'C'est la vie!'"))); }</td>
     * <td>{@code "SELECT * FROM t WHERE c='C'est la vie!';"}</td>
     * </tr>
     * <tr>
     * <td>{@code select().from("t").where(eq("c", "now()")); }</td>
     * <td>{@code "SELECT * FROM t WHERE c='now()';"}</td>
     * </tr>
     * <tr>
     * <td>{@code select().from("t").where(eq("c", raw("now()"))); }</td>
     * <td>{@code "SELECT * FROM t WHERE c=now();"}</td>
     * </tr>
     * </table>
     * <i>Note: the 2nd and 3rd examples in this table are not a valid CQL3
     * queries.</i>
     * <p>
     * The use of that method is generally discouraged since it lead to security
     * risks. However, if you know what you are doing, it allows to escape the
     * interpretations done by the StatementBuilder.
     *
     * @author paouelle
     *
     * @param  str the raw value to use as a string
     * @return the value but protected from being interpreted/escaped by the query
     *         builder.
     */
    public static Object raw(String str) {
        return StatementManager.getManager().raw(str);
    }

    /**
     * Creates a function call.
     *
     * @author paouelle
     *
     * @param  name the name of the function to call.
     * @param  parameters the parameters for the function.
     * @return the function call.
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     */
    public static Object fcall(String name, Object... parameters) {
        return StatementManager.getManager().fcall(name, parameters);
    }

    /**
     * Declares that the name in argument should be treated as a column name.
     * <p>
     * This mainly meant for use with {@link Select.Selection#fcall} when a
     * function should apply to a column name, not a string value.
     *
     * @author paouelle
     *
     * @param  name the name of the column.
     * @return the name as a column name.
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     */
    public static Object column(String name) {
        return StatementManager.getManager().column(name);
    }

    /**
     * Gets all the column names defined for a given field based on the specified
     * POJO class. The field must be annotated with {@link Column} and be part of
     * a class hierarchy annotated as an entity.
     *
     * @author paouelle
     *
     * @param <T> The type of POJO associated with the request.
     *
     * @param  clazz the POJO class to get all the column names for
     * @param  field the field to get all the column names for
     * @return a non-<code>null</code> set of all the column names the specified
     *         field is annotated with
     * @throws NullPointerException if <code>clazz</code> or <code>name</code>
     *         is <code>null</code>
     * @throws IllegalArgumentException if the field or its class are not properly
     *         annotated or the field is not in a class that is the same or a base
     *         class of the specified class
     */
    public static <T> Set<String> getColumnNamesFor(Class<T> clazz, Field field) {
        org.apache.commons.lang3.Validate.notNull(clazz, "invalid null class");
        org.apache.commons.lang3.Validate.notNull(field, "invalid null field name");
        org.apache.commons.lang3.Validate.isTrue(field.getDeclaringClass().isAssignableFrom(clazz),
                "field '%s.%s' is not defined in the class hieriarchy of: %s", field.getDeclaringClass().getName(),
                field.getName(), clazz.getClass().getName());
        return StatementManager.getManager().getColumnNamesFor(clazz, field);
    }
}