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 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 static com.datastax.driver.$internal.com.google.common.base.Preconditions.checkState;
import com.datastax.driver.core.CodecRegistry;
import com.datastax.driver.core.ColumnMetadata;
import com.datastax.driver.core.Metadata;
import com.datastax.driver.core.TableMetadata;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/** A built {@code INSERT} statement. */
public class Insert extends BuiltStatement {
private enum JsonDefault {
NULL,
UNSET
}
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;
private JsonDefault jsonDefault;
Insert(String keyspace, String table) {
this(keyspace, table, null, null);
}
Insert(TableMetadata table) {
this(
Metadata.quoteIfNecessary(table.getKeyspace().getName()),
Metadata.quoteIfNecessary(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);
if (jsonDefault == JsonDefault.UNSET) builder.append(" DEFAULT UNSET");
else if (jsonDefault == JsonDefault.NULL) builder.append(" DEFAULT NULL");
} 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 {@code INSERT} statement.
*
* @param name the name of the column to insert/update.
* @param value the value to insert/update for {@code name}.
* @return this {@code 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 && jsonDefault == 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 && jsonDefault == 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;
}
/**
* Appends a {@code DEFAULT UNSET} clause to this {@code INSERT INTO ... JSON} statement.
*
* Support for {@code DEFAULT UNSET} has been introduced in Cassandra 3.10.
*
* @return this {@code 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.
*/
public Insert defaultUnset() {
checkState(
values.isEmpty() && names.isEmpty(),
"Cannot mix INSERT JSON syntax with regular INSERT syntax");
this.jsonDefault = JsonDefault.UNSET;
return this;
}
/**
* Appends a {@code DEFAULT NULL} clause to this {@code INSERT INTO ... JSON} statement.
*
*
Support for {@code DEFAULT NULL} has been introduced in Cassandra 3.10.
*
* @return this {@code 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.
*/
public Insert defaultNull() {
checkState(
values.isEmpty() && names.isEmpty(),
"Cannot mix INSERT JSON syntax with regular INSERT syntax");
this.jsonDefault = JsonDefault.NULL;
return this;
}
/**
* Adds a new options for this {@code INSERT} statement.
*
* @param using the option to add.
* @return the options of this {@code INSERT} statement.
*/
public Options using(Using using) {
return usings.and(using);
}
/**
* Returns the options for this {@code INSERT} statement.
*
*
Chain this with {@link Options#and(Using)} to add options.
*
* @return the options of this {@code INSERT} statement.
*/
public Options using() {
return usings;
}
/**
* Sets the 'IF NOT EXISTS' option for this {@code 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 {@code INSERT} statement.
*/
public Insert ifNotExists() {
this.setNonIdempotentOps();
this.ifNotExists = true;
return this;
}
/** The options of an {@code 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 {@code 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 {@code INSERT} statement.
*
* @param name the name of the column to insert/update.
* @param value the value to insert/update for {@code name}.
* @return the {@code 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 {@code 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 {@code 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);
}
}
}