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/12/10 21:31:50 UTC

cassandra git commit: Fix type casting for counter columns

Repository: cassandra
Updated Branches:
  refs/heads/trunk 1299ec319 -> 485c23d29


Fix type casting for counter columns

patch by Benjamin Lerer; reviewed by Robert Stupp for CASSANDRA-10824


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/485c23d2
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/485c23d2
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/485c23d2

Branch: refs/heads/trunk
Commit: 485c23d29b558b1561df3dc219e4e8f887c09234
Parents: 1299ec3
Author: Benjamin Lerer <b....@gmail.com>
Authored: Thu Dec 10 21:28:16 2015 +0100
Committer: Benjamin Lerer <b....@gmail.com>
Committed: Thu Dec 10 21:30:50 2015 +0100

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../cassandra/cql3/functions/CastFcts.java      | 57 +++++++++++++++++---
 .../cassandra/cql3/functions/CastFctsTest.java  | 19 +++++++
 3 files changed, 70 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/485c23d2/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 9610181..dda12ba 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 3.2
+ * Fix type casting for counter columns (CASSANDRA-10824)
  * Prevent running Cassandra as root (CASSANDRA-8142)
  * bound maximum in-flight commit log replay mutation bytes to 64 megabytes (CASSANDRA-8639)
  * Normalize all scripts (CASSANDRA-10679)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/485c23d2/src/java/org/apache/cassandra/cql3/functions/CastFcts.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/functions/CastFcts.java b/src/java/org/apache/cassandra/cql3/functions/CastFcts.java
index 7349f0c..800ff65 100644
--- a/src/java/org/apache/cassandra/cql3/functions/CastFcts.java
+++ b/src/java/org/apache/cassandra/cql3/functions/CastFcts.java
@@ -146,7 +146,17 @@ public final class CastFcts
                                                    java.util.function.Function<I, O> converter)
     {
         if (!inputType.equals(outputType))
-            functions.add(JavaFunctionWrapper.create(inputType, outputType, converter));
+            functions.add(wrapJavaFunction(inputType, outputType, converter));
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <O, I> Function wrapJavaFunction(AbstractType<I> inputType,
+                                                    AbstractType<O> outputType,
+                                                    java.util.function.Function<I, O> converter)
+    {
+        return inputType.equals(CounterColumnType.instance)
+                ? JavaCounterFunctionWrapper.create(outputType, (java.util.function.Function<Long, O>) converter)
+                : JavaFunctionWrapper.create(inputType, outputType, converter);
     }
 
     private static String toLowerCaseString(CQL3Type type)
@@ -192,7 +202,7 @@ public final class CastFcts
      * @param <I> the input parameter
      * @param <O> the output parameter
      */
-    private static final class JavaFunctionWrapper<I, O> extends CastFunction<I, O>
+    private static class JavaFunctionWrapper<I, O> extends CastFunction<I, O>
     {
         /**
          * The java function used to convert the input type into the output one.
@@ -206,21 +216,54 @@ public final class CastFcts
             return new JavaFunctionWrapper<I, O>(inputType, outputType, converter);
         }
 
-        private JavaFunctionWrapper(AbstractType<I> inputType,
-                                    AbstractType<O> outputType,
-                                    java.util.function.Function<I, O> converter)
+        protected JavaFunctionWrapper(AbstractType<I> inputType,
+                                      AbstractType<O> outputType,
+                                      java.util.function.Function<I, O> converter)
         {
             super(inputType, outputType);
             this.converter = converter;
         }
 
-        public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
+        public final ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
         {
             ByteBuffer bb = parameters.get(0);
             if (bb == null)
                 return null;
 
-            return outputType().decompose(converter.apply(inputType().compose(bb)));
+            return outputType().decompose(converter.apply(compose(bb)));
+        }
+
+        protected I compose(ByteBuffer bb)
+        {
+            return inputType().compose(bb);
+        }
+    };
+
+    /**
+     * <code>JavaFunctionWrapper</code> for counter columns.
+     *
+     * <p>Counter columns need to be handled in a special way because their binary representation is converted into
+     * the one of a BIGINT before functions are applied.</p>
+     *
+     * @param <O> the output parameter
+     */
+    private static class JavaCounterFunctionWrapper<O> extends JavaFunctionWrapper<Long, O>
+    {
+        public static <O> JavaFunctionWrapper<Long, O> create(AbstractType<O> outputType,
+                                                              java.util.function.Function<Long, O> converter)
+        {
+            return new JavaCounterFunctionWrapper<O>(outputType, converter);
+        }
+
+        protected JavaCounterFunctionWrapper(AbstractType<O> outputType,
+                                            java.util.function.Function<Long, O> converter)
+        {
+            super(CounterColumnType.instance, outputType, converter);
+        }
+
+        protected Long compose(ByteBuffer bb)
+        {
+            return LongType.instance.compose(bb);
         }
     };
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/485c23d2/test/unit/org/apache/cassandra/cql3/functions/CastFctsTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/functions/CastFctsTest.java b/test/unit/org/apache/cassandra/cql3/functions/CastFctsTest.java
index ed30f03..9b4b570 100644
--- a/test/unit/org/apache/cassandra/cql3/functions/CastFctsTest.java
+++ b/test/unit/org/apache/cassandra/cql3/functions/CastFctsTest.java
@@ -292,4 +292,23 @@ public class CastFctsTest extends CQLTester
         assertRows(execute("SELECT CAST(" + f + "(CAST(b AS int)) AS text) FROM %s"),
                    row("2.0"));
     }
+
+    @Test
+    public void testCounterCastsInSelectionClause() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int primary key, b counter)");
+
+        execute("UPDATE %s SET b = b + 2 WHERE a = 1");
+
+        assertRows(execute("SELECT CAST(b AS tinyint), " +
+                "CAST(b AS smallint), " +
+                "CAST(b AS int), " +
+                "CAST(b AS bigint), " +
+                "CAST(b AS float), " +
+                "CAST(b AS double), " +
+                "CAST(b AS decimal), " +
+                "CAST(b AS ascii), " +
+                "CAST(b AS text) FROM %s"),
+                   row((byte) 2, (short) 2, 2, 2L, 2.0F, 2.0, BigDecimal.valueOf(2.0), "2", "2"));
+    }
 }