You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by bl...@apache.org on 2015/09/17 21:09:11 UTC
[1/2] cassandra git commit: Fix IndexOutOfBoundsException when using
empty BATCH statements
Repository: cassandra
Updated Branches:
refs/heads/cassandra-2.2 b62fde1bb -> 416ba6e8b
Fix IndexOutOfBoundsException when using empty BATCH statements
patch by Vovodroid; reviewed by Benjamin Lerer for CASSANDRA-10277
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/1a2a1d2c
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/1a2a1d2c
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/1a2a1d2c
Branch: refs/heads/cassandra-2.2
Commit: 1a2a1d2c24b777d4c9ea9106e0e7199c7b91fa29
Parents: b62fde1
Author: Vovodroid <vo...@gmail.com>
Authored: Thu Sep 17 20:57:51 2015 +0200
Committer: blerer <be...@datastax.com>
Committed: Thu Sep 17 20:57:51 2015 +0200
----------------------------------------------------------------------
.../org/apache/cassandra/cql3/statements/BatchStatement.java | 2 +-
.../apache/cassandra/cql3/validation/operations/BatchTest.java | 6 ++++++
2 files changed, 7 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/1a2a1d2c/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 0661b56..46dfda5 100644
--- a/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java
@@ -510,7 +510,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/1a2a1d2c/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 1447845..07117fd 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/BatchTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/BatchTest.java
@@ -103,4 +103,10 @@ public class BatchTest extends CQLTester
row(111, "batchtext", null)
);
}
+
+ @Test
+ public void testBatchEmpty() throws Throwable
+ {
+ execute("BEGIN BATCH APPLY BATCH;");
+ }
}
[2/2] cassandra git commit: Preserve the names of query parameters in
QueryOptions
Posted by bl...@apache.org.
Preserve the names of query parameters in QueryOptions
patch by Benjamin Lerer; reviewed by Sam Tunnicliffe for CASSANDRA-9632
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/416ba6e8
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/416ba6e8
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/416ba6e8
Branch: refs/heads/cassandra-2.2
Commit: 416ba6e8b2729c671d66be43cbcbc7c76d1c8a91
Parents: 1a2a1d2
Author: blerer <be...@datastax.com>
Authored: Thu Sep 17 21:06:21 2015 +0200
Committer: blerer <be...@datastax.com>
Committed: Thu Sep 17 21:06:21 2015 +0200
----------------------------------------------------------------------
NEWS.txt | 6 ++
.../cassandra/cql3/BatchQueryOptions.java | 28 ++++++++
.../cassandra/cql3/ColumnSpecification.java | 10 +++
.../org/apache/cassandra/cql3/QueryOptions.java | 70 +++++++++++++++++++-
.../transport/messages/BatchMessage.java | 2 +-
.../transport/messages/ExecuteMessage.java | 5 +-
6 files changed, 117 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/416ba6e8/NEWS.txt
----------------------------------------------------------------------
diff --git a/NEWS.txt b/NEWS.txt
index 198e8e9..49744cf 100644
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -33,6 +33,12 @@ Changed Defaults
- Parallel repairs are the default since 2.2.0, run sequential repairs
by providing the '-seq' parameter to nodetool repair.
+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/416ba6e8/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/416ba6e8/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/416ba6e8/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 fb46b9b..7fc0997 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;
@@ -82,10 +83,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()
{
@@ -169,7 +203,7 @@ public abstract class QueryOptions
}
}
- static abstract class QueryOptionsWrapper extends QueryOptions
+ static class QueryOptionsWrapper extends QueryOptions
{
protected final QueryOptions wrapped;
@@ -178,6 +212,11 @@ public abstract class QueryOptions
this.wrapped = wrapped;
}
+ public List<ByteBuffer> getValues()
+ {
+ return this.wrapped.getValues();
+ }
+
public ConsistencyLevel getConsistency()
{
return wrapped.getConsistency();
@@ -206,6 +245,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;
@@ -238,6 +303,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/416ba6e8/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 2db380b..d86bb1a 100644
--- a/src/java/org/apache/cassandra/transport/messages/BatchMessage.java
+++ b/src/java/org/apache/cassandra/transport/messages/BatchMessage.java
@@ -208,7 +208,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/416ba6e8/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 718595c..11a227c 100644
--- a/src/java/org/apache/cassandra/transport/messages/ExecuteMessage.java
+++ b/src/java/org/apache/cassandra/transport/messages/ExecuteMessage.java
@@ -136,7 +136,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();