Merge branch 'cassandra-3.11' into trunk

# Conflicts:
#	CHANGES.txt
#	src/java/org/apache/cassandra/db/DataRange.java
diff --git a/CHANGES.txt b/CHANGES.txt
index 3e7343c..e6acf40 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -24,6 +24,7 @@
  * Replace array iterators with get by index (CASSANDRA-15394)
  * Minimize BTree iterator allocations (CASSANDRA-15389)
 Merged from 3.11:
+ * Fix CQL formatting of read command restrictions for slow query log (CASSANDRA-15503)
 Merged from 3.0:
  * liveDiskSpaceUsed and totalDiskSpaceUsed get corrupted if IndexSummaryRedistribution gets interrupted (CASSANDRA-15674)
  * Fix Debian init start/stop (CASSANDRA-15770)
diff --git a/src/java/org/apache/cassandra/db/DataRange.java b/src/java/org/apache/cassandra/db/DataRange.java
index 420f3da..4db4198 100644
--- a/src/java/org/apache/cassandra/db/DataRange.java
+++ b/src/java/org/apache/cassandra/db/DataRange.java
@@ -67,7 +67,7 @@
      */
     public static DataRange allData(IPartitioner partitioner)
     {
-        return forTokenRange(new Range<Token>(partitioner.getMinimumToken(), partitioner.getMinimumToken()));
+        return forTokenRange(new Range<>(partitioner.getMinimumToken(), partitioner.getMinimumToken()));
     }
 
     /**
@@ -105,7 +105,7 @@
      */
     public static DataRange allData(IPartitioner partitioner, ClusteringIndexFilter filter)
     {
-        return new DataRange(Range.makeRowRange(new Range<Token>(partitioner.getMinimumToken(), partitioner.getMinimumToken())), filter);
+        return new DataRange(Range.makeRowRange(new Range<>(partitioner.getMinimumToken(), partitioner.getMinimumToken())), filter);
     }
 
     /**
@@ -278,16 +278,19 @@
     {
         sb.append("token(");
         sb.append(ColumnMetadata.toCQLString(metadata.partitionKeyColumns()));
-        sb.append(") ").append(getOperator(isStart, isInclusive)).append(" ");
+        sb.append(") ");
         if (pos instanceof DecoratedKey)
         {
+            sb.append(getOperator(isStart, isInclusive)).append(" ");
             sb.append("token(");
             appendKeyString(sb, metadata.partitionKeyType, ((DecoratedKey)pos).getKey());
             sb.append(")");
         }
         else
         {
-            sb.append(((Token.KeyBound)pos).getToken());
+            Token.KeyBound keyBound = (Token.KeyBound) pos;
+            sb.append(getOperator(isStart, isStart == keyBound.isMinimumBound)).append(" ");
+            sb.append(keyBound.getToken());
         }
     }
 
diff --git a/src/java/org/apache/cassandra/db/Slices.java b/src/java/org/apache/cassandra/db/Slices.java
index 9c7da79..3d19fe9 100644
--- a/src/java/org/apache/cassandra/db/Slices.java
+++ b/src/java/org/apache/cassandra/db/Slices.java
@@ -614,6 +614,8 @@
                 }
                 else
                 {
+                    boolean isReversed = column.isReversedType();
+
                     // As said above, we assume (without checking) that this means all ComponentOfSlice for this column
                     // are the same, so we only bother about the first.
                     if (first.startValue != null)
@@ -621,14 +623,24 @@
                         if (needAnd)
                             sb.append(" AND ");
                         needAnd = true;
-                        sb.append(column.name).append(first.startInclusive ? " >= " : " > ").append(column.type.getString(first.startValue));
+                        sb.append(column.name);
+                        if (isReversed)
+                            sb.append(first.startInclusive ? " <= " : " < ");
+                        else
+                            sb.append(first.startInclusive ? " >= " : " > ");
+                        sb.append(column.type.getString(first.startValue));
                     }
                     if (first.endValue != null)
                     {
                         if (needAnd)
                             sb.append(" AND ");
                         needAnd = true;
-                        sb.append(column.name).append(first.endInclusive ? " <= " : " < ").append(column.type.getString(first.endValue));
+                        sb.append(column.name);
+                        if (isReversed)
+                            sb.append(first.endInclusive ? " >= " : " > ");
+                        else
+                            sb.append(first.endInclusive ? " <= " : " < ");
+                        sb.append(column.type.getString(first.endValue));
                     }
                 }
             }
diff --git a/src/java/org/apache/cassandra/db/filter/ClusteringIndexNamesFilter.java b/src/java/org/apache/cassandra/db/filter/ClusteringIndexNamesFilter.java
index f25dc91..63815a1 100644
--- a/src/java/org/apache/cassandra/db/filter/ClusteringIndexNamesFilter.java
+++ b/src/java/org/apache/cassandra/db/filter/ClusteringIndexNamesFilter.java
@@ -191,7 +191,7 @@
 
     public String toCQLString(TableMetadata metadata)
     {
-        if (metadata.clusteringColumns().isEmpty() || clusterings.size() <= 1)
+        if (metadata.clusteringColumns().isEmpty() || clusterings.isEmpty())
             return "";
 
         StringBuilder sb = new StringBuilder();
@@ -199,7 +199,7 @@
         sb.append(clusterings.size() == 1 ? " = " : " IN (");
         int i = 0;
         for (Clustering clustering : clusterings)
-            sb.append(i++ == 0 ? "" : ", ").append("(").append(clustering.toCQLString(metadata)).append(")");
+            sb.append(i++ == 0 ? "" : ", ").append('(').append(clustering.toCQLString(metadata)).append(')');
         sb.append(clusterings.size() == 1 ? "" : ")");
 
         appendOrderByToCQLString(metadata, sb);