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();