This is an automated email from the ASF dual-hosted git repository.

maedhroz pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git


The following commit(s) were added to refs/heads/trunk by this push:
     new c7e9048d4d Fix BETWEEN filtering for reversed clustering columns
c7e9048d4d is described below

commit c7e9048d4df9c0a5bb178c8388a13ad44f1cc0d2
Author: Benjamin Lerer <[email protected]>
AuthorDate: Tue Aug 27 09:11:41 2024 +0200

    Fix BETWEEN filtering for reversed clustering columns
    
    patch by Benjamin Lerer; reviewed by Caleb Rackliffe for CASSANDRA-19878
---
 CHANGES.txt                                        |  1 +
 src/java/org/apache/cassandra/cql3/Operator.java   |  4 +--
 .../cql3/restrictions/SimpleRestriction.java       |  3 ++
 .../operations/SelectSingleColumnRelationTest.java | 38 ++++++++++++++++++++++
 4 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index f3d40ad3c7..e170fd9487 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 5.1
+ * Fix BETWEEN filtering for reversed clustering columns (CASSANDRA-19878)
  * Retry if node leaves CMS while committing a transformation (CASSANDRA-19872)
  * Add support for NOT operators in WHERE clauses. Fixed Three Valued Logic 
(CASSANDRA-18584)
  * Allow getendpoints for system tables and make sure getNaturalReplicas work 
for MetaStrategy (CASSANDRA-19846)
diff --git a/src/java/org/apache/cassandra/cql3/Operator.java 
b/src/java/org/apache/cassandra/cql3/Operator.java
index 18c7a9f3f9..64658b4322 100644
--- a/src/java/org/apache/cassandra/cql3/Operator.java
+++ b/src/java/org/apache/cassandra/cql3/Operator.java
@@ -788,8 +788,8 @@ public enum Operator
         public boolean isSatisfiedBy(AbstractType<?> type, ByteBuffer 
leftOperand, ByteBuffer rightOperand)
         {
             List<ByteBuffer> buffers = ListType.getInstance(type, 
false).unpack(rightOperand);
-            buffers.sort(type);
-            return type.compareForCQL(leftOperand, buffers.get(0)) >= 0 && 
type.compareForCQL(leftOperand, buffers.get(1)) <= 0;
+            // We use compare instead of compareForCQL to deal properly with 
reversed clustering columns
+            return type.compare(leftOperand, buffers.get(0)) >= 0 && 
type.compare(leftOperand, buffers.get(1)) <= 0;
         }
 
         @Override
diff --git 
a/src/java/org/apache/cassandra/cql3/restrictions/SimpleRestriction.java 
b/src/java/org/apache/cassandra/cql3/restrictions/SimpleRestriction.java
index d8b6e7aec8..8592fbbb7b 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/SimpleRestriction.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/SimpleRestriction.java
@@ -333,6 +333,9 @@ public final class SimpleRestriction implements 
SingleRestriction
                 List<ByteBuffer> buffers = bindAndGet(options);
                 if (operator.kind() != Operator.Kind.BINARY)
                 {
+                    // For BETWEEN we support like in SQL reversed bounds
+                    if (operator.kind() == Operator.Kind.TERNARY)
+                        buffers.sort(column.type);
                     filter.add(column, operator, 
multiInputOperatorValues(column, buffers));
                 }
                 else if (operator == Operator.LIKE)
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 2f683c4e59..2cfd05cb4b 100644
--- 
a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectSingleColumnRelationTest.java
+++ 
b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectSingleColumnRelationTest.java
@@ -1328,4 +1328,42 @@ public class SelectSingleColumnRelationTest extends 
CQLTester
                    row(0, 3)
         );
     }
+
+    @Test
+    public void testBetweenFilteringWithReversedOrdering() throws Throwable
+    {
+        createTable("CREATE TABLE %s(p int, c int, c2 int, abbreviation ascii, 
PRIMARY KEY (p, c, c2))");
+
+        beforeAndAfterFlush(() -> {
+            execute("INSERT INTO %s(p, c, c2, abbreviation) VALUES (0, 1, 1, 
'CA')");
+            execute("INSERT INTO %s(p, c, c2, abbreviation) VALUES (0, 2, 2, 
'MA')");
+            execute("INSERT INTO %s(p, c, c2, abbreviation) VALUES (0, 3, 3, 
'MA')");
+            execute("INSERT INTO %s(p, c, c2, abbreviation) VALUES (0, 4, 4, 
'TX')");
+
+            assertRows(execute("SELECT * FROM %s WHERE c2 BETWEEN 2 AND 3 
ALLOW FILTERING"),
+                       row (0, 2, 2, "MA"),
+                       row (0, 3, 3, "MA"));
+
+            assertRows(execute("SELECT * FROM %s WHERE c2 BETWEEN 3 AND 2 
ALLOW FILTERING"),
+                       row (0, 2, 2, "MA"),
+                       row (0, 3, 3, "MA"));
+        });
+
+        createTable("CREATE TABLE %s(p int, c int, c2 int, abbreviation ascii, 
PRIMARY KEY (p, c, c2)) WITH CLUSTERING ORDER BY (c DESC, c2 DESC)");
+
+        beforeAndAfterFlush(() -> {
+            execute("INSERT INTO %s(p, c, c2, abbreviation) VALUES (0, 1, 1, 
'CA')");
+            execute("INSERT INTO %s(p, c, c2, abbreviation) VALUES (0, 2, 2, 
'MA')");
+            execute("INSERT INTO %s(p, c, c2, abbreviation) VALUES (0, 3, 3, 
'MA')");
+            execute("INSERT INTO %s(p, c, c2, abbreviation) VALUES (0, 4, 4, 
'TX')");
+
+            assertRows(execute("SELECT * FROM %s WHERE c2 BETWEEN 2 AND 3 
ALLOW FILTERING"),
+                       row(0, 3, 3, "MA"),
+                       row(0, 2, 2, "MA"));
+
+            assertRows(execute("SELECT * FROM %s WHERE c2 BETWEEN 3 AND 2 
ALLOW FILTERING"),
+                       row(0, 3, 3, "MA"),
+                       row(0, 2, 2, "MA"));
+        });
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to