INSERT statement fails when Tuple type is used as clustering column with 
default DESC order

patch by Stavros Kontopoulos, reviewed by jasobrown for CASSANDRA-13717


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

Branch: refs/heads/trunk
Commit: a08a816a6a3497046ba75a38d76d5095347dfe95
Parents: a586f6c
Author: Stavros Kontopoulos <stavros.kontopou...@lightbend.com>
Authored: Thu Aug 10 04:23:26 2017 +0300
Committer: Jason Brown <jasedbr...@gmail.com>
Committed: Tue Sep 12 14:10:34 2017 -0700

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 src/java/org/apache/cassandra/cql3/Tuples.java  | 24 +++++++++++++++-----
 .../cql3/validation/entities/TupleTypeTest.java | 14 ++++++++++++
 3 files changed, 33 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/a08a816a/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 6053117..3d3903e 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 3.0.15
+ * INSERT statement fails when Tuple type is used as clustering column with 
default DESC order (CASSANDRA-13717)
  * Fix pending view mutations handling and cleanup batchlog when there are 
local and remote paired mutations (CASSANDRA-13069)
  * Improve config validation and documentation on overflow and NPE 
(CASSANDRA-13622)
  * Range deletes in a CAS batch are ignored (CASSANDRA-13655)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/a08a816a/src/java/org/apache/cassandra/cql3/Tuples.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Tuples.java 
b/src/java/org/apache/cassandra/cql3/Tuples.java
index ee08efe..c7564d3 100644
--- a/src/java/org/apache/cassandra/cql3/Tuples.java
+++ b/src/java/org/apache/cassandra/cql3/Tuples.java
@@ -47,7 +47,7 @@ public class Tuples
         return new ColumnSpecification(column.ksName,
                                        column.cfName,
                                        new 
ColumnIdentifier(String.format("%s[%d]", column.name, component), true),
-                                       
((TupleType)column.type).type(component));
+                                       
(getTupleType(column.type)).type(component));
     }
 
     /**
@@ -77,7 +77,7 @@ public class Tuples
 
                 values.add(value);
             }
-            DelayedValue value = new DelayedValue((TupleType)receiver.type, 
values);
+            DelayedValue value = new DelayedValue(getTupleType(receiver.type), 
values);
             return allTerminal ? value.bind(QueryOptions.DEFAULT) : value;
         }
 
@@ -104,10 +104,10 @@ public class Tuples
 
         private void validateAssignableTo(String keyspace, ColumnSpecification 
receiver) throws InvalidRequestException
         {
-            if (!(receiver.type instanceof TupleType))
+            if (!checkIfTupleType(receiver.type))
                 throw new InvalidRequestException(String.format("Invalid tuple 
type literal for %s of type %s", receiver.name, receiver.type.asCQL3Type()));
 
-            TupleType tt = (TupleType)receiver.type;
+            TupleType tt = getTupleType(receiver.type);
             for (int i = 0; i < elements.size(); i++)
             {
                 if (i >= tt.size())
@@ -256,7 +256,7 @@ public class Tuples
                 List<?> l = 
type.getSerializer().deserializeForNativeProtocol(value, 
options.getProtocolVersion());
 
                 assert type.getElementsType() instanceof TupleType;
-                TupleType tupleType = (TupleType) type.getElementsType();
+                TupleType tupleType = 
Tuples.getTupleType(type.getElementsType());
 
                 // type.split(bytes)
                 List<List<ByteBuffer>> elements = new ArrayList<>(l.size());
@@ -375,7 +375,7 @@ public class Tuples
             ByteBuffer value = options.getValues().get(bindIndex);
             if (value == ByteBufferUtil.UNSET_BYTE_BUFFER)
                 throw new InvalidRequestException(String.format("Invalid unset 
value for tuple %s", receiver.name));
-            return value == null ? null : Value.fromSerialized(value, 
(TupleType)receiver.type);
+            return value == null ? null : Value.fromSerialized(value, 
getTupleType(receiver.type));
         }
     }
 
@@ -412,4 +412,16 @@ public class Tuples
         sb.append(')');
         return sb.toString();
     }
+
+    public static boolean checkIfTupleType(AbstractType<?> tuple)
+    {
+        return (tuple instanceof TupleType) ||
+               (tuple instanceof ReversedType && ((ReversedType) 
tuple).baseType instanceof TupleType);
+
+    }
+
+    public static TupleType getTupleType(AbstractType<?> tuple)
+    {
+        return (tuple instanceof ReversedType ? ((TupleType) ((ReversedType) 
tuple).baseType) : (TupleType)tuple);
+    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/a08a816a/test/unit/org/apache/cassandra/cql3/validation/entities/TupleTypeTest.java
----------------------------------------------------------------------
diff --git 
a/test/unit/org/apache/cassandra/cql3/validation/entities/TupleTypeTest.java 
b/test/unit/org/apache/cassandra/cql3/validation/entities/TupleTypeTest.java
index cbe4a15..bace751 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/TupleTypeTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/TupleTypeTest.java
@@ -17,6 +17,10 @@
  */
 package org.apache.cassandra.cql3.validation.entities;
 
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+
 import org.junit.Test;
 
 import org.apache.cassandra.cql3.CQLTester;
@@ -211,4 +215,14 @@ public class TupleTypeTest extends CQLTester
         assertInvalidMessage("Not enough bytes to read 0th component",
                              "INSERT INTO %s (pk, t) VALUES (?, ?)", 1, 
Long.MAX_VALUE);
     }
+
+    @Test
+    public void testReversedTypeTuple() throws Throwable
+    {
+        // CASSANDRA-13717
+        createTable("CREATE TABLE %s (id int, tdemo frozen<tuple<timestamp, 
varchar>>, primary key (id, tdemo)) with clustering order by (tdemo desc)");
+        execute("INSERT INTO %s (id, tdemo) VALUES (1, ('2017-02-03 
03:05+0000','Europe'))");
+        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mmX", 
Locale.ENGLISH);
+        assertRows(execute("SELECT tdemo FROM %s"), row(tuple( 
df.parse("2017-02-03 03:05+0000"), "Europe")));
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to