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.Delete 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;
/**
* A built DELETE statement.
*/
public class Delete extends BuiltStatement {
private final String table;
private final List columns;
private final Where where;
private final Options usings;
private final Conditions conditions;
private boolean ifExists;
Delete(String keyspace, String table, List columns) {
this(keyspace, table, null, null, columns);
}
Delete(TableMetadata table, List columns) {
this(escapeId(table.getKeyspace().getName()),
escapeId(table.getName()),
Arrays.asList(new Object[table.getPartitionKey().size()]),
table.getPartitionKey(),
columns);
}
Delete(String keyspace,
String table,
List routingKeyValues,
List partitionKey,
List columns) {
super(keyspace, partitionKey, routingKeyValues);
this.table = table;
this.columns = columns;
this.where = new Where(this);
this.usings = new Options(this);
this.conditions = new Conditions(this);
// This is for JAVA-1089, if the query deletes an element in a list, the statement should be non-idempotent.
if (!areIdempotent(columns)) {
setNonIdempotentOps();
}
}
@Override
StringBuilder buildQueryString(List variables, CodecRegistry codecRegistry) {
StringBuilder builder = new StringBuilder();
builder.append("DELETE");
if (!columns.isEmpty())
Utils.joinAndAppend(builder.append(" "), codecRegistry, ",", columns, variables);
builder.append(" FROM ");
if (keyspace != null)
Utils.appendName(keyspace, builder).append('.');
Utils.appendName(table, builder);
if (!usings.usings.isEmpty()) {
builder.append(" USING ");
Utils.joinAndAppend(builder, codecRegistry, " AND ", usings.usings, variables);
}
if (!where.clauses.isEmpty()) {
builder.append(" WHERE ");
Utils.joinAndAppend(builder, codecRegistry, " AND ", where.clauses, variables);
}
if (ifExists) {
builder.append(" IF EXISTS ");
}
if (!conditions.conditions.isEmpty()) {
builder.append(" IF ");
Utils.joinAndAppend(builder, codecRegistry, " AND ", conditions.conditions, variables);
}
return builder;
}
/**
* Adds a WHERE clause to this statement.
*
* This is a shorter/more readable version for {@code where().and(clause)}.
*
* @param clause the clause to add.
* @return the where clause of this query to which more clause can be added.
*/
public Where where(Clause clause) {
return where.and(clause);
}
/**
* Returns a Where statement for this query without adding clause.
*
* @return the where clause of this query to which more clause can be added.
*/
public Where where() {
return where;
}
/**
* Adds a conditions clause (IF) to this statement.
*
* This is a shorter/more readable version for {@code onlyIf().and(condition)}.
*
* This will configure the statement as non-idempotent, see {@link com.datastax.driver.core.Statement#isIdempotent()}
* for more information.
*
* @param condition the condition to add.
* @return the conditions of this query to which more conditions can be added.
*/
public Conditions onlyIf(Clause condition) {
return conditions.and(condition);
}
/**
* Adds a conditions clause (IF) to this statement.
*
* This will configure the statement as non-idempotent, see {@link com.datastax.driver.core.Statement#isIdempotent()}
* for more information.
*
* @return the conditions of this query to which more conditions can be added.
*/
public Conditions onlyIf() {
return conditions;
}
/**
* Adds a new options for this DELETE statement.
*
* @param using the option to add.
* @return the options of this DELETE statement.
*/
public Options using(Using using) {
return usings.and(using);
}
/**
* Returns the options for this DELETE statement.
*
* Chain this with {@link Options#and(Using)} to add options.
*
* @return the options of this DELETE statement.
*/
public Options using() {
return usings;
}
/**
* Sets the 'IF EXISTS' option for this DELETE statement.
*
*
* A delete with that option will report whether the statement actually
* resulted in data being deleted. The existence check and deletion are
* done transactionally in the sense that if multiple clients attempt to
* delete 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 DELETE statement.
*/
public Delete ifExists() {
this.ifExists = true;
setNonIdempotentOps();
return this;
}
/**
* The WHERE clause of a DELETE statement.
*/
public static class Where extends BuiltStatement.ForwardingStatement {
private final List clauses = new ArrayList();
Where(Delete statement) {
super(statement);
}
/**
* Adds the provided clause to this WHERE clause.
*
* @param clause the clause to add.
* @return this WHERE clause.
*/
public Where and(Clause clause) {
clauses.add(clause);
statement.maybeAddRoutingKey(clause.name(), clause.firstValue());
if (!hasNonIdempotentOps() && !Utils.isIdempotent(clause)) {
statement.setNonIdempotentOps();
}
checkForBindMarkers(clause);
return this;
}
/**
* Adds an option to the DELETE statement this WHERE clause is part of.
*
* @param using the using clause to add.
* @return the options of the DELETE statement this WHERE clause is part of.
*/
public Options using(Using using) {
return statement.using(using);
}
/**
* Sets the 'IF EXISTS' option for the DELETE statement this WHERE clause
* is part of.
*
*
* A delete with that option will report whether the statement actually
* resulted in data being deleted. The existence check and deletion are
* done transactionally in the sense that if multiple clients attempt to
* delete 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.
*
*
* @return the DELETE statement this WHERE clause is part of.
*/
public Delete ifExists() {
return statement.ifExists();
}
/**
* Adds a condition to the DELETE statement this WHERE clause is part of.
*
* @param condition the condition to add.
* @return the conditions for the DELETE statement this WHERE clause is part of.
*/
public Conditions onlyIf(Clause condition) {
return statement.onlyIf(condition);
}
}
/**
* The options of a DELETE statement.
*/
public static class Options extends BuiltStatement.ForwardingStatement {
private final List usings = new ArrayList();
Options(Delete statement) {
super(statement);
}
/**
* Adds the provided option.
*
* @param using a DELETE option.
* @return this {@code Options} object.
*/
public Options and(Using using) {
usings.add(using);
checkForBindMarkers(using);
return this;
}
/**
* Adds a where clause to the DELETE statement these options are part of.
*
* @param clause clause to add.
* @return the WHERE clause of the DELETE statement these options are part of.
*/
public Where where(Clause clause) {
return statement.where(clause);
}
}
/**
* An in-construction DELETE statement.
*/
public static class Builder {
List columns = new ArrayList();
Builder() {
}
Builder(String... columnNames) {
for (String columnName : columnNames) {
this.columns.add(new Selector(columnName));
}
}
/**
* Adds the table to delete from.
*
* @param table the name of the table to delete from.
* @return a newly built DELETE statement that deletes from {@code table}.
*/
public Delete from(String table) {
return from(null, table);
}
/**
* Adds the table to delete from.
*
* @param keyspace the name of the keyspace to delete from.
* @param table the name of the table to delete from.
* @return a newly built DELETE statement that deletes from {@code keyspace.table}.
*/
public Delete from(String keyspace, String table) {
return new Delete(keyspace, table, columns);
}
/**
* Adds the table to delete from.
*
* @param table the table to delete from.
* @return a newly built DELETE statement that deletes from {@code table}.
*/
public Delete from(TableMetadata table) {
return new Delete(table, columns);
}
}
/**
* An column selection clause for an in-construction DELETE statement.
*/
public static class Selection extends Builder {
/**
* Deletes all columns (i.e. "DELETE FROM ...")
*
* @return an in-build DELETE statement.
* @throws IllegalStateException if some columns had already been selected for this builder.
*/
public Builder all() {
if (!columns.isEmpty())
throw new IllegalStateException(String.format("Some columns (%s) have already been selected.", columns));
return this;
}
/**
* Deletes the provided column.
*
* @param columnName the column to select for deletion.
* @return this in-build DELETE Selection
*/
public Selection column(String columnName) {
columns.add(new Selector(columnName));
return this;
}
/**
* Deletes the provided list element.
*
* @param columnName the name of the list column.
* @param idx the index of the element to delete.
* @return this in-build DELETE Selection
*/
public Selection listElt(String columnName, int idx) {
columns.add(new ListElementSelector(columnName, idx));
return this;
}
/**
* Deletes the provided list element,
* specified as a bind marker.
*
* @param columnName the name of the list column.
* @param idx the index of the element to delete.
* @return this in-build DELETE Selection
*/
public Selection listElt(String columnName, BindMarker idx) {
columns.add(new ListElementSelector(columnName, idx));
return this;
}
/**
* Deletes the provided set element.
*
* @param columnName the name of the set column.
* @param element the element to delete.
* @return this in-build DELETE Selection
*/
public Selection setElt(String columnName, Object element) {
columns.add(new SetElementSelector(columnName, element));
return this;
}
/**
* Deletes the provided set element,
* specified as a bind marker.
*
* @param columnName the name of the set column.
* @param element the element to delete.
* @return this in-build DELETE Selection
*/
public Selection setElt(String columnName, BindMarker element) {
columns.add(new SetElementSelector(columnName, element));
return this;
}
/**
* Deletes a map element given a key.
*
* @param columnName the name of the map column.
* @param key the key for the element to delete.
* @return this in-build DELETE Selection
*/
public Selection mapElt(String columnName, Object key) {
columns.add(new MapElementSelector(columnName, key));
return this;
}
}
/**
* A selector in a DELETE selection clause.
* A selector can be either a column name,
* a list element, a set element or a map entry.
*/
private static class Selector extends Utils.Appendeable {
private final String columnName;
Selector(String columnName) {
this.columnName = columnName;
}
@Override
void appendTo(StringBuilder sb, List values, CodecRegistry codecRegistry) {
Utils.appendName(columnName, sb);
}
@Override
boolean containsBindMarker() {
return false;
}
@Override
public String toString() {
return columnName;
}
}
/**
* A selector representing a list index, a set element or a map key in a DELETE selection clause.
*/
private static class CollectionElementSelector extends Selector {
protected final Object key;
CollectionElementSelector(String columnName, Object key) {
super(columnName);
this.key = key;
}
@Override
void appendTo(StringBuilder sb, List values, CodecRegistry codecRegistry) {
super.appendTo(sb, values, codecRegistry);
sb.append('[');
Utils.appendValue(key, codecRegistry, sb, values);
sb.append(']');
}
@Override
boolean containsBindMarker() {
return Utils.containsBindMarker(key);
}
}
private static class ListElementSelector extends CollectionElementSelector {
ListElementSelector(String columnName, Object key) {
super(columnName, key);
}
}
private static class SetElementSelector extends CollectionElementSelector {
SetElementSelector(String columnName, Object key) {
super(columnName, key);
}
}
private static class MapElementSelector extends CollectionElementSelector {
MapElementSelector(String columnName, Object key) {
super(columnName, key);
}
}
private boolean areIdempotent(List selectors) {
for (Selector sel : selectors) {
if (sel instanceof ListElementSelector) {
return false;
}
}
return true;
}
/**
* Conditions for a DELETE statement.
*
* When provided some conditions, a deletion will not apply unless the
* provided conditions applies.
*
*
* Please keep in mind that provided conditions have a non negligible
* performance impact and should be avoided when possible.
*
*/
public static class Conditions extends BuiltStatement.ForwardingStatement {
private final List conditions = new ArrayList();
Conditions(Delete statement) {
super(statement);
}
/**
* Adds the provided condition for the deletion.
*
* Note that while the query builder accept any type of {@code Clause}
* as conditions, Cassandra currently only allows equality ones.
*
* @param condition the condition to add.
* @return this {@code Conditions} clause.
*/
public Conditions and(Clause condition) {
statement.setNonIdempotentOps();
conditions.add(condition);
checkForBindMarkers(condition);
return this;
}
/**
* Adds a where clause to the DELETE statement these conditions are part of.
*
* @param clause clause to add.
* @return the WHERE clause of the DELETE statement these conditions are part of.
*/
public Where where(Clause clause) {
return statement.where(clause);
}
/**
* Adds an option to the DELETE statement these conditions are part of.
*
* @param using the using clause to add.
* @return the options of the DELETE statement these conditions are part of.
*/
public Options using(Using using) {
return statement.using(using);
}
}
}