Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.datastax.driver.core.querybuilder.Insert Maven / Gradle / Ivy
Go to download
Shaded version of DataStax Java Driver for Apache Cassandra
/*
* Copyright (C) 2012-2015 DataStax Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.datastax.driver.core.querybuilder;
import com.datastax.driver.core.CodecRegistry;
import com.datastax.driver.core.ColumnMetadata;
import com.datastax.driver.core.TableMetadata;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.datastax.driver.$internal.com.google.common.base.Preconditions.checkState;
/**
* A built INSERT statement.
*/
public class Insert extends BuiltStatement {
private final String table;
private final List names = new ArrayList();
private final List values = new ArrayList();
private final Options usings;
private boolean ifNotExists;
private Object json;
Insert(String keyspace, String table) {
this(keyspace, table, null, null);
}
Insert(TableMetadata table) {
this(escapeId(table.getKeyspace().getName()),
escapeId(table.getName()),
Arrays.asList(new Object[table.getPartitionKey().size()]),
table.getPartitionKey());
}
Insert(String keyspace,
String table,
List routingKeyValues,
List partitionKey) {
super(keyspace, partitionKey, routingKeyValues);
this.table = table;
this.usings = new Options(this);
}
@Override
StringBuilder buildQueryString(List variables, CodecRegistry codecRegistry) {
StringBuilder builder = new StringBuilder();
builder.append("INSERT INTO ");
if (keyspace != null)
Utils.appendName(keyspace, builder).append('.');
Utils.appendName(table, builder);
builder.append(" ");
if (json != null) {
builder.append("JSON ");
Utils.appendValue(json, codecRegistry, builder, variables);
} else {
builder.append("(");
Utils.joinAndAppendNames(builder, codecRegistry, ",", names);
builder.append(") VALUES (");
Utils.joinAndAppendValues(builder, codecRegistry, ",", values, variables);
builder.append(')');
}
if (ifNotExists)
builder.append(" IF NOT EXISTS");
if (!usings.usings.isEmpty()) {
builder.append(" USING ");
Utils.joinAndAppend(builder, codecRegistry, " AND ", usings.usings, variables);
}
return builder;
}
/**
* Adds a column/value pair to the values inserted by this INSERT statement.
*
* @param name the name of the column to insert/update.
* @param value the value to insert/update for {@code name}.
* @return this INSERT statement.
* @throws IllegalStateException if this method is called and the {@link #json(Object)}
* method has been called before, because it's not possible
* to mix {@code INSERT JSON} syntax with regular {@code INSERT} syntax.
*/
public Insert value(String name, Object value) {
checkState(json == null, "Cannot mix INSERT JSON syntax with regular INSERT syntax");
names.add(name);
values.add(value);
checkForBindMarkers(value);
if (!hasNonIdempotentOps() && !Utils.isIdempotent(value))
this.setNonIdempotentOps();
maybeAddRoutingKey(name, value);
return this;
}
/**
* Adds multiple column/value pairs to the values inserted by this INSERT statement.
*
* @param names a list of column names to insert/update.
* @param values a list of values to insert/update. The {@code i}th
* value in {@code values} will be inserted for the {@code i}th column
* in {@code names}.
* @return this INSERT statement.
* @throws IllegalArgumentException if {@code names.length != values.length}.
* @throws IllegalStateException if this method is called and the {@link #json(Object)}
* method has been called before, because it's not possible
* to mix {@code INSERT JSON} syntax with regular {@code INSERT} syntax.
*/
public Insert values(String[] names, Object[] values) {
return values(Arrays.asList(names), Arrays.asList(values));
}
/**
* Adds multiple column/value pairs to the values inserted by this INSERT statement.
*
* @param names a list of column names to insert/update.
* @param values a list of values to insert/update. The {@code i}th
* value in {@code values} will be inserted for the {@code i}th column
* in {@code names}.
* @return this INSERT statement.
* @throws IllegalArgumentException if {@code names.size() != values.size()}.
* @throws IllegalStateException if this method is called and the {@link #json(Object)}
* method has been called before, because it's not possible
* to mix {@code INSERT JSON} syntax with regular {@code INSERT} syntax.
*/
public Insert values(List names, List values) {
if (names.size() != values.size())
throw new IllegalArgumentException(String.format("Got %d names but %d values", names.size(), values.size()));
checkState(json == null, "Cannot mix INSERT JSON syntax with regular INSERT syntax");
this.names.addAll(names);
this.values.addAll(values);
for (int i = 0; i < names.size(); i++) {
Object value = values.get(i);
checkForBindMarkers(value);
maybeAddRoutingKey(names.get(i), value);
if (!hasNonIdempotentOps() && !Utils.isIdempotent(value))
this.setNonIdempotentOps();
}
return this;
}
/**
* Inserts the provided object, using the {@code INSERT INTO ... JSON} syntax introduced
* in Cassandra 2.2.
*
* With INSERT statements, the new {@code JSON} keyword can be used to enable inserting a JSON
* structure as a single row.
*
* The provided object can be of the following types:
*
* A raw string. In this case, it will be appended to the query string as is.
* It should NOT be surrounded by single quotes.
* Its format should generally match that returned by a
* {@code SELECT JSON} statement on the same table.
* Note that it is not possible to insert function calls nor bind markers in a JSON string.
* A {@link QueryBuilder#bindMarker() bind marker}. In this case, the statement is meant to be prepared
* and no JSON string will be appended to the query string, only a bind marker for the whole JSON parameter.
* Any object that can be serialized to JSON. Such objects can be used provided that
* a matching {@link com.datastax.driver.core.TypeCodec codec} is registered with the
* {@link CodecRegistry} in use. This allows the usage of JSON libraries, such
* as the Java API for JSON processing ,
* the popular Jackson library, or
* Google's Gson library, for instance.
*
* Case-sensitive column names
* When passing raw strings to this method, users are required to handle case-sensitive column names
* by surrounding them with double quotes.
*
* For example, to insert into a table with two columns named “myKey” and “value”,
* you would do the following:
*
* insertInto("mytable").json("{\"\\\"myKey\\\"\": 0, \"value\": 0}");
*
* This will produce the following CQL:
*
* INSERT INTO mytable JSON '{"\"myKey\"": 0, "value": 0}';
*
* Escaping quotes in column values
* When passing raw strings to this method, double quotes should be escaped with a backslash,
* but single quotes should be escaped in
* the CQL manner, i.e. by another single quote. For example, the column value
* {@code foo"'bar} should be inserted in the JSON string
* as {@code "foo\"''bar"}.
*
* Null values and tombstones
* Any columns which are omitted from the JSON string will be defaulted to a {@code NULL} value
* (which will result in a tombstone being created).
*
* @param json the JSON string, or a bind marker, or a JSON object handled by a specific {@link com.datastax.driver.core.TypeCodec codec}.
* @return this INSERT statement.
* @throws IllegalStateException if this method is called and any of the {@code value} or {@code values}
* methods have been called before, because it's not possible
* to mix {@code INSERT JSON} syntax with regular {@code INSERT} syntax.
* @see JSON Support for CQL
* @see JSON Support in Cassandra 2.2
* @see Inserting JSON data
*/
public Insert json(Object json) {
checkState(values.isEmpty() && names.isEmpty(), "Cannot mix INSERT JSON syntax with regular INSERT syntax");
this.json = json;
return this;
}
/**
* Adds a new options for this INSERT statement.
*
* @param using the option to add.
* @return the options of this INSERT statement.
*/
public Options using(Using using) {
return usings.and(using);
}
/**
* Returns the options for this INSERT statement.
*
* Chain this with {@link Options#and(Using)} to add options.
*
* @return the options of this INSERT statement.
*/
public Options using() {
return usings;
}
/**
* Sets the 'IF NOT EXISTS' option for this INSERT statement.
*
* An insert with that option will not succeed unless the row does not
* exist at the time the insertion is executed. The existence check and
* insertions are done transactionally in the sense that if multiple
* clients attempt to create a given row with this option, then at most one
* may succeed.
*
* Please keep in mind that using this option has a non negligible
* performance impact and should be avoided when possible.
*
* This will configure the statement as non-idempotent, see {@link com.datastax.driver.core.Statement#isIdempotent()}
* for more information.
*
* @return this INSERT statement.
*/
public Insert ifNotExists() {
this.setNonIdempotentOps();
this.ifNotExists = true;
return this;
}
/**
* The options of an INSERT statement.
*/
public static class Options extends BuiltStatement.ForwardingStatement {
private final List usings = new ArrayList();
Options(Insert st) {
super(st);
}
/**
* Adds the provided option.
*
* @param using an INSERT option.
* @return this {@code Options} object.
*/
public Options and(Using using) {
usings.add(using);
checkForBindMarkers(using);
return this;
}
/**
* Adds a column/value pair to the values inserted by this INSERT statement.
*
* @param name the name of the column to insert/update.
* @param value the value to insert/update for {@code name}.
* @return the INSERT statement those options are part of.
*/
public Insert value(String name, Object value) {
return statement.value(name, value);
}
/**
* Adds multiple column/value pairs to the values inserted by this INSERT statement.
*
* @param names a list of column names to insert/update.
* @param values a list of values to insert/update. The {@code i}th
* value in {@code values} will be inserted for the {@code i}th column
* in {@code names}.
* @return the INSERT statement those options are part of.
* @throws IllegalArgumentException if {@code names.length != values.length}.
*/
public Insert values(String[] names, Object[] values) {
return statement.values(names, values);
}
}
}