Repository: cassandra Updated Branches: refs/heads/trunk 0bae8034d -> d6d5698b8
Merge cassandra-2.2 into cassandra-3.0 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/a90de7c6 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/a90de7c6 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/a90de7c6 Branch: refs/heads/trunk Commit: a90de7c61df62adba6af753b28653c241ddd27fb Parents: 2db8370 Author: blerer <[email protected]> Authored: Thu Sep 17 21:38:42 2015 +0200 Committer: blerer <[email protected]> Committed: Thu Sep 17 21:40:52 2015 +0200 ---------------------------------------------------------------------- NEWS.txt | 6 ++ .../cassandra/cql3/BatchQueryOptions.java | 28 ++++++++ .../cassandra/cql3/ColumnSpecification.java | 10 +++ .../org/apache/cassandra/cql3/QueryOptions.java | 70 +++++++++++++++++++- .../cql3/statements/BatchStatement.java | 2 +- .../transport/messages/BatchMessage.java | 2 +- .../transport/messages/ExecuteMessage.java | 5 +- .../cql3/validation/operations/BatchTest.java | 10 +-- 8 files changed, 124 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/a90de7c6/NEWS.txt ---------------------------------------------------------------------- diff --git a/NEWS.txt b/NEWS.txt index 4b35f71..b6730a1 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -118,6 +118,12 @@ Changed Defaults of the total space of the commitlog volume. (Before: always used 8192) +New features +------------ + - Custom QueryHandlers can retrieve the column specifications for the bound + variables from QueryOptions by using the hasColumnSpecifications() + and getColumnSpecifications() methods. + 2.2.1 ===== http://git-wip-us.apache.org/repos/asf/cassandra/blob/a90de7c6/src/java/org/apache/cassandra/cql3/BatchQueryOptions.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/BatchQueryOptions.java b/src/java/org/apache/cassandra/cql3/BatchQueryOptions.java index 2fcee5b..db7fa39 100644 --- a/src/java/org/apache/cassandra/cql3/BatchQueryOptions.java +++ b/src/java/org/apache/cassandra/cql3/BatchQueryOptions.java @@ -22,6 +22,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import org.apache.cassandra.utils.MD5Digest; + import org.apache.cassandra.db.ConsistencyLevel; import org.apache.cassandra.service.QueryState; @@ -50,6 +52,11 @@ public abstract class BatchQueryOptions public abstract QueryOptions forStatement(int i); + public void prepareStatement(int i, List<ColumnSpecification> boundNames) + { + forStatement(i).prepare(boundNames); + } + public ConsistencyLevel getConsistency() { return wrapped.getConsistency(); @@ -107,5 +114,26 @@ public abstract class BatchQueryOptions { return perStatementOptions.get(i); } + + @Override + public void prepareStatement(int i, List<ColumnSpecification> boundNames) + { + if (isPreparedStatement(i)) + { + QueryOptions options = perStatementOptions.get(i); + options.prepare(boundNames); + options = QueryOptions.addColumnSpecifications(options, boundNames); + perStatementOptions.set(i, options); + } + else + { + super.prepareStatement(i, boundNames); + } + } + + private boolean isPreparedStatement(int i) + { + return getQueryOrIdList().get(i) instanceof MD5Digest; + } } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/a90de7c6/src/java/org/apache/cassandra/cql3/ColumnSpecification.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/ColumnSpecification.java b/src/java/org/apache/cassandra/cql3/ColumnSpecification.java index e12a57e..e64f5f9 100644 --- a/src/java/org/apache/cassandra/cql3/ColumnSpecification.java +++ b/src/java/org/apache/cassandra/cql3/ColumnSpecification.java @@ -18,6 +18,7 @@ package org.apache.cassandra.cql3; import com.google.common.base.Objects; + import org.apache.cassandra.db.marshal.AbstractType; import org.apache.cassandra.db.marshal.ReversedType; @@ -91,4 +92,13 @@ public class ColumnSpecification { return Objects.hashCode(ksName, cfName, name, type); } + + @Override + public String toString() + { + return Objects.toStringHelper(this) + .add("name", name) + .add("type", type) + .toString(); + } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/a90de7c6/src/java/org/apache/cassandra/cql3/QueryOptions.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/QueryOptions.java b/src/java/org/apache/cassandra/cql3/QueryOptions.java index 672f8ea..ad554ed 100644 --- a/src/java/org/apache/cassandra/cql3/QueryOptions.java +++ b/src/java/org/apache/cassandra/cql3/QueryOptions.java @@ -23,8 +23,9 @@ import java.util.Collections; import java.util.EnumSet; import java.util.List; -import io.netty.buffer.ByteBuf; +import com.google.common.collect.ImmutableList; +import io.netty.buffer.ByteBuf; import org.apache.cassandra.db.ConsistencyLevel; import org.apache.cassandra.service.QueryState; import org.apache.cassandra.service.pager.PagingState; @@ -72,10 +73,43 @@ public abstract class QueryOptions return new DefaultQueryOptions(consistency, values, skipMetadata, new SpecificOptions(pageSize, pagingState, serialConsistency, -1L), 0); } + public static QueryOptions addColumnSpecifications(QueryOptions options, List<ColumnSpecification> columnSpecs) + { + return new OptionsWithColumnSpecifications(options, columnSpecs); + } + public abstract ConsistencyLevel getConsistency(); public abstract List<ByteBuffer> getValues(); public abstract boolean skipMetadata(); + /** + * Tells whether or not this <code>QueryOptions</code> contains the column specifications for the bound variables. + * <p>The column specifications will be present only for prepared statements.</p> + * @return <code>true</code> this <code>QueryOptions</code> contains the column specifications for the bound + * variables, <code>false</code> otherwise. + */ + public boolean hasColumnSpecifications() + { + return false; + } + + /** + * Returns the column specifications for the bound variables (<i>optional operation</i>). + * + * <p>The column specifications will be present only for prepared statements.</p> + * + * <p>Invoke the {@link hasColumnSpecifications} method before invoking this method in order to ensure that this + * <code>QueryOptions</code> contains the column specifications.</p> + * + * @return the option names + * @throws UnsupportedOperationException If this <code>QueryOptions</code> does not contains the column + * specifications. + */ + public ImmutableList<ColumnSpecification> getColumnSpecifications() + { + throw new UnsupportedOperationException(); + } + /** The pageSize for this query. Will be <= 0 if not relevant for the query. */ public int getPageSize() { @@ -159,7 +193,7 @@ public abstract class QueryOptions } } - static abstract class QueryOptionsWrapper extends QueryOptions + static class QueryOptionsWrapper extends QueryOptions { protected final QueryOptions wrapped; @@ -168,6 +202,11 @@ public abstract class QueryOptions this.wrapped = wrapped; } + public List<ByteBuffer> getValues() + { + return this.wrapped.getValues(); + } + public ConsistencyLevel getConsistency() { return wrapped.getConsistency(); @@ -196,6 +235,32 @@ public abstract class QueryOptions } } + /** + * <code>QueryOptions</code> decorator that provides access to the column specifications. + */ + static class OptionsWithColumnSpecifications extends QueryOptionsWrapper + { + private final ImmutableList<ColumnSpecification> columnSpecs; + + OptionsWithColumnSpecifications(QueryOptions wrapped, List<ColumnSpecification> columnSpecs) + { + super(wrapped); + this.columnSpecs = ImmutableList.copyOf(columnSpecs); + } + + @Override + public boolean hasColumnSpecifications() + { + return true; + } + + @Override + public ImmutableList<ColumnSpecification> getColumnSpecifications() + { + return columnSpecs; + } + } + static class OptionsWithNames extends QueryOptionsWrapper { private final List<String> names; @@ -228,6 +293,7 @@ public abstract class QueryOptions return this; } + @Override public List<ByteBuffer> getValues() { assert orderedValues != null; // We should have called prepare first! http://git-wip-us.apache.org/repos/asf/cassandra/blob/a90de7c6/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java b/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java index 4a92ec1..0b3e1ba 100644 --- a/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java @@ -519,7 +519,7 @@ public class BatchStatement implements CQLStatement // Use the CFMetadata of the first statement for partition key bind indexes. If the statements affect // multiple tables, we won't send partition key bind indexes. - Short[] partitionKeyBindIndexes = haveMultipleCFs ? null + Short[] partitionKeyBindIndexes = (haveMultipleCFs || batchStatement.statements.isEmpty())? null : boundNames.getPartitionKeyBindIndexes(batchStatement.statements.get(0).cfm); return new ParsedStatement.Prepared(batchStatement, boundNames, partitionKeyBindIndexes); http://git-wip-us.apache.org/repos/asf/cassandra/blob/a90de7c6/src/java/org/apache/cassandra/transport/messages/BatchMessage.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/transport/messages/BatchMessage.java b/src/java/org/apache/cassandra/transport/messages/BatchMessage.java index 5baf1a6..bd2423e 100644 --- a/src/java/org/apache/cassandra/transport/messages/BatchMessage.java +++ b/src/java/org/apache/cassandra/transport/messages/BatchMessage.java @@ -203,7 +203,7 @@ public class BatchMessage extends Message.Request for (int i = 0; i < prepared.size(); i++) { ParsedStatement.Prepared p = prepared.get(i); - batchOptions.forStatement(i).prepare(p.boundNames); + batchOptions.prepareStatement(i, p.boundNames); if (!(p.statement instanceof ModificationStatement)) throw new InvalidRequestException("Invalid statement in batch: only UPDATE, INSERT and DELETE statements are allowed."); http://git-wip-us.apache.org/repos/asf/cassandra/blob/a90de7c6/src/java/org/apache/cassandra/transport/messages/ExecuteMessage.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/transport/messages/ExecuteMessage.java b/src/java/org/apache/cassandra/transport/messages/ExecuteMessage.java index 940a0fc..e9923b4 100644 --- a/src/java/org/apache/cassandra/transport/messages/ExecuteMessage.java +++ b/src/java/org/apache/cassandra/transport/messages/ExecuteMessage.java @@ -124,7 +124,10 @@ public class ExecuteMessage extends Message.Request Tracing.instance.begin("Execute CQL3 prepared query", state.getClientAddress(), builder.build()); } - Message.Response response = handler.processPrepared(statement, state, options, getCustomPayload()); + // Some custom QueryHandlers are interested by the bound names. We provide them this information + // by wrapping the QueryOptions. + QueryOptions queryOptions = QueryOptions.addColumnSpecifications(options, prepared.boundNames); + Message.Response response = handler.processPrepared(statement, state, queryOptions, getCustomPayload()); if (options.skipMetadata() && response instanceof ResultMessage.Rows) ((ResultMessage.Rows)response).result.metadata.setSkipMetadata(); http://git-wip-us.apache.org/repos/asf/cassandra/blob/a90de7c6/test/unit/org/apache/cassandra/cql3/validation/operations/BatchTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/BatchTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/BatchTest.java index c0d1df5..43e3a30 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/operations/BatchTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/operations/BatchTest.java @@ -18,12 +18,8 @@ package org.apache.cassandra.cql3.validation.operations; -import java.util.Arrays; - import org.junit.Test; -import static org.apache.commons.lang3.StringUtils.isEmpty; - import org.apache.cassandra.cql3.CQLTester; public class BatchTest extends CQLTester @@ -172,4 +168,10 @@ public class BatchTest extends CQLTester row(0, 5, 20), row(0, 6, 20)); } + + @Test + public void testBatchEmpty() throws Throwable + { + assertEmpty(execute("BEGIN BATCH APPLY BATCH;")); + } }
