Ensure Relation#toRestriction() handles ReversedType properly

patch by Caleb Rackliffe; reviewed by David Capwell for CASSANDRA-19950
diff --git a/CHANGES.txt b/CHANGES.txt
index 1797b9f..ffd8e96 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 5.1
+ * Ensure Relation#toRestriction() handles ReversedType properly (CASSANDRA-19950)
  * Add JSON and YAML output option to nodetool gcstats (CASSANDRA-19771)
  * Introduce metadata serialization version V4 (CASSANDRA-19970)
  * Allow CMS reconfiguration to work around DOWN nodes (CASSANDRA-19943)
diff --git a/src/java/org/apache/cassandra/cql3/ColumnsExpression.java b/src/java/org/apache/cassandra/cql3/ColumnsExpression.java
index 8e52623..78b0b8e 100644
--- a/src/java/org/apache/cassandra/cql3/ColumnsExpression.java
+++ b/src/java/org/apache/cassandra/cql3/ColumnsExpression.java
@@ -368,7 +368,7 @@
      */
     public boolean isMapElementExpression()
     {
-        return kind == Kind.ELEMENT && element != null && element.kind() == ElementExpression.Kind.COLLECTION_ELEMENT && firstColumn().type instanceof MapType;
+        return kind == Kind.ELEMENT && element != null && element.kind() == ElementExpression.Kind.COLLECTION_ELEMENT && firstColumn().type.unwrap() instanceof MapType;
     }
 
     /**
diff --git a/src/java/org/apache/cassandra/cql3/ElementExpression.java b/src/java/org/apache/cassandra/cql3/ElementExpression.java
index 6a218fe..3665f71 100644
--- a/src/java/org/apache/cassandra/cql3/ElementExpression.java
+++ b/src/java/org/apache/cassandra/cql3/ElementExpression.java
@@ -214,11 +214,13 @@
         {
             if (kind == Kind.COLLECTION_ELEMENT)
             {
-                if (!(column.type.isCollection()))
+                AbstractType<?> baseType = column.type.unwrap();
+
+                if (!(baseType.isCollection()))
                     throw invalidRequest("Invalid element access syntax for non-collection column %s", column.name);
 
                 Term term = prepareCollectionElement(column);
-                CollectionType<?> collectionType = (CollectionType<?>) column.type;
+                CollectionType<?> collectionType = (CollectionType<?>) baseType;
                 AbstractType<?> elementType = collectionType.valueComparator();
                 AbstractType<?> keyOrIndexType = collectionType.isMap() ? ((MapType<?, ?>) collectionType).getKeysType() : Int32Type.instance;
                 return new ElementExpression(kind, elementType, keyOrIndexType, term);
@@ -238,7 +240,7 @@
         private Term prepareCollectionElement(ColumnMetadata receiver)
         {
             ColumnSpecification elementSpec;
-            switch ((((CollectionType<?>) receiver.type).kind))
+            switch ((((CollectionType<?>) receiver.type.unwrap()).kind))
             {
                 case LIST:
                     elementSpec = Lists.indexSpecOf(receiver);
diff --git a/src/java/org/apache/cassandra/cql3/Relation.java b/src/java/org/apache/cassandra/cql3/Relation.java
index 86d8db1..9fbd3ad 100644
--- a/src/java/org/apache/cassandra/cql3/Relation.java
+++ b/src/java/org/apache/cassandra/cql3/Relation.java
@@ -24,7 +24,9 @@
 
 import org.apache.cassandra.cql3.restrictions.SimpleRestriction;
 import org.apache.cassandra.cql3.restrictions.SingleRestriction;
-import org.apache.cassandra.cql3.terms.*;
+import org.apache.cassandra.cql3.terms.Term;
+import org.apache.cassandra.cql3.terms.Terms;
+import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.db.marshal.CollectionType;
 import org.apache.cassandra.db.marshal.ListType;
 import org.apache.cassandra.db.marshal.MapType;
@@ -198,9 +200,10 @@
         if (columnsExpression.isMapElementExpression())
         {
             ColumnMetadata column = columnsExpression.firstColumn();
-            checkFalse(column.type instanceof ListType, "Indexes on list entries (%s[index] = value) are not supported.", column.name);
-            checkTrue(column.type instanceof MapType, "Column %s cannot be used as a map", column.name);
-            checkTrue(column.type.isMultiCell(), "Map-entry predicates on frozen map column %s are not supported", column.name);
+            AbstractType<?> baseType = column.type.unwrap();
+            checkFalse(baseType instanceof ListType, "Indexes on list entries (%s[index] = value) are not supported.", column.name);
+            checkTrue(baseType instanceof MapType, "Column %s cannot be used as a map", column.name);
+            checkTrue(baseType.isMultiCell(), "Map-entry predicates on frozen map column %s are not supported", column.name);
             columnsExpression.collectMarkerSpecification(boundNames);
         }
 
diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectSingleColumnRelationTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectSingleColumnRelationTest.java
index 2cfd05c..5024eea 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectSingleColumnRelationTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectSingleColumnRelationTest.java
@@ -30,6 +30,14 @@
 public class SelectSingleColumnRelationTest extends CQLTester
 {
     @Test
+    public void textInvalidMapEntryPredicate()  throws Throwable
+    {
+        createTable("CREATE TABLE %s (pk int, ck frozen<map<int, int>>, v int, PRIMARY KEY(pk, ck)) WITH CLUSTERING ORDER BY (ck DESC)");
+        assertInvalidMessage("Map-entry predicates on frozen map column ck are not supported",
+                             "SELECT * FROM %s WHERE pk=? AND ck[0] = ?", 0, 0);
+    }
+
+    @Test
     public void testInvalidCollectionEqualityRelation() throws Throwable
     {
         createTable("CREATE TABLE %s (a int PRIMARY KEY, b set<int>, c list<int>, d map<int, int>)");