content: /*
   *
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied.  See the License for the
   * specific language governing permissions and limitations
   * under the License.
   *
   */
  package org.apache.cassandra.cql3.validation.operations;
  
  import java.util.Arrays;
  
  import org.junit.BeforeClass;
  import org.junit.Test;
  
  import org.apache.cassandra.Util;
  import org.apache.cassandra.config.DatabaseDescriptor;
  import org.apache.cassandra.cql3.CQLTester;
  import org.apache.cassandra.cql3.restrictions.StatementRestrictions;
  import org.apache.cassandra.dht.ByteOrderedPartitioner;
  
  import static org.junit.Assert.assertEquals;
  import static org.junit.Assert.assertNull;
  
  /**
   * SELECT statement tests that require a ByteOrderedPartitioner
   */
  public class SelectOrderedPartitionerTest extends CQLTester
  {
      @BeforeClass
      public static void setUp()
      {
          DatabaseDescriptor.setPartitionerUnsafe(ByteOrderedPartitioner.instance);
      }
  
      @Test
      public void testTokenAndIndex() throws Throwable
      {
          Util.assumeLegacySecondaryIndex();
          createTable("CREATE TABLE %s (a int, b int, c int, d int, PRIMARY KEY (a, b, c))");
          createIndex("CREATE INDEX ON %s(c)");
  
          for (int i = 0; i < 10; i++)
          {
              execute("INSERT INTO %s (a,b,c,d) VALUES (?, ?, ?, ?)", i, i, i, i);
              execute("INSERT INTO %s (a,b,c,d) VALUES (?, ?, ?, ?)", i, i + 10, i + 10, i + 10);
          }
  
          beforeAndAfterFlush(() -> {
              assertRows(execute("SELECT * FROM %s WHERE token(a) > token(8) AND a = 9 AND c = 9 ALLOW FILTERING"),
                         row(9, 9, 9, 9));
  
              assertRows(execute("SELECT * FROM %s WHERE token(a) > token(8) AND a > 8 AND c = 9 ALLOW FILTERING"),
                         row(9, 9, 9, 9));
          });
      }
  
      @Test
      public void testFilteringOnAllPartitionKeysWithTokenRestriction() throws Throwable
      {
          createTable("CREATE TABLE %s (a int, b int, c int, d int, PRIMARY KEY ((a, b), c))");
  
          for (int i = 0; i < 10; i++)
          {
              execute("INSERT INTO %s (a,b,c,d) VALUES (?, ?, ?, ?)", i, i, i, i);
              execute("INSERT INTO %s (a,b,c,d) VALUES (?, ?, ?, ?)", i, i + 10, i + 10, i + 10);
          }
  
          assertEmpty(execute("SELECT * FROM %s WHERE token(a, b) > token(10, 10)"));
          assertEmpty(execute("SELECT * FROM %s WHERE token(a, b) > token(10, 10) AND a < 8 AND b < 8 ALLOW FILTERING"));
          assertRows(execute("SELECT * FROM %s WHERE token(a, b) > token(5, 5) AND a < 8 AND b < 8 ALLOW FILTERING"),
                     row(6, 6, 6, 6),
                     row(7, 7, 7, 7));
      }
  
      @Test
      public void testFilteringOnPartitionKeyWithToken() throws Throwable
      {
          Util.assumeLegacySecondaryIndex();
          createTable("CREATE TABLE %s (a int, b int, c int, d int, PRIMARY KEY ((a, b), c))");
          createIndex("CREATE INDEX ON %s(d)");
  
          for (int i = 0; i < 10; i++)
          {
              execute("INSERT INTO %s (a,b,c,d) VALUES (?, ?, ?, ?)", i, i, i, i);
              execute("INSERT INTO %s (a,b,c,d) VALUES (?, ?, ?, ?)", i, i + 10, i + 10, i + 10);
          }
  
          beforeAndAfterFlush(() -> {
              assertRowsIgnoringOrder(execute("SELECT * FROM %s WHERE token(a, b) > token(5, 10) AND b < 8 ALLOW FILTERING"),
                                      row(6, 6, 6, 6),
                                      row(7, 7, 7, 7));
  
              assertRows(execute("SELECT * FROM %s WHERE token(a, b) > token(8, 10) AND a = 9 ALLOW FILTERING"),
                         row(9, 9, 9, 9),
                         row(9, 19, 19, 19));
  
              assertRows(execute("SELECT * FROM %s WHERE token(a, b) > token(8, 10) AND a = 9 AND d = 9 ALLOW FILTERING"),
                         row(9, 9, 9, 9));
  
              assertRows(execute("SELECT * FROM %s WHERE token(a, b) > token(8, 10) AND a > 8 AND b > 8 AND d = 9 ALLOW FILTERING"),
                         row(9, 9, 9, 9));
  
              assertRows(execute("SELECT * FROM %s WHERE a = 9 AND b = 9  AND token(a, b) > token(8, 10) AND d = 9 ALLOW FILTERING"),
                         row(9, 9, 9, 9));
  
              assertRows(execute("SELECT * FROM %s WHERE token(a, b) > token(8, 10) AND a = 9 AND c = 19 ALLOW FILTERING"),
                         row(9, 19, 19, 19));
  
              assertEmpty(execute("SELECT * FROM %s WHERE token(a, b) = token(8, 8) AND b = 9 ALLOW FILTERING"));
          });
      }
  
      @Test
      public void testTokenAndCollections() throws Throwable
      {
          createTable("CREATE TABLE %s (a frozen<map<int, int>>, b int, c int, PRIMARY KEY (a, b))");
  
          for (int i = 0; i < 10; i++)
          {
              execute("INSERT INTO %s (a,b,c) VALUES (?, ?, ?)", map(i, i), i, i);
              execute("INSERT INTO %s (a,b,c) VALUES (?, ?, ?)", map(i, i, 100, 200), i + 10, i + 10);
          }
  
          beforeAndAfterFlush(() -> {
              assertRows(execute("SELECT * FROM %s WHERE token(a) > token({0: 0}) AND a CONTAINS KEY 9 ALLOW FILTERING"),
                                      row(map(9, 9), 9, 9),
                                      row(map(9, 9, 100, 200), 19, 19));
  
              assertRows(execute("SELECT * FROM %s WHERE token(a) > token({0: 0}) AND a CONTAINS KEY 9 AND a CONTAINS 200 ALLOW FILTERING"),
                         row(map(9, 9, 100, 200), 19, 19));
  
              assertRows(execute("SELECT * FROM %s WHERE token(a) > token({0: 0}) AND a CONTAINS KEY 9 AND b = 19 ALLOW FILTERING"),
                         row(map(9, 9, 100, 200), 19, 19));
          });
      }
  
      @Test
      public void testTokenFunctionWithSingleColumnPartitionKey() throws Throwable
      {
          createTable("CREATE TABLE IF NOT EXISTS %s (a int PRIMARY KEY, b text)");
          execute("INSERT INTO %s (a, b) VALUES (0, 'a')");
  
          assertRows(execute("SELECT * FROM %s WHERE token(a) >= token(?)", 0), row(0, "a"));
          assertRows(execute("SELECT * FROM %s WHERE token(a) >= token(?) and token(a) < token(?)", 0, 1), row(0, "a"));
          assertRows(execute("SELECT * FROM %s WHERE token(a) BETWEEN token(?) and token(?)", 0, 1), row(0, "a"));
          assertInvalid("SELECT * FROM %s WHERE token(a) > token(?)", "a");
          assertInvalidMessage("The token() function must contains only partition key components",
                               "SELECT * FROM %s WHERE token(a, b) >= token(?, ?)", "b", 0);
          assertInvalidMessage("More than one restriction was found for the start bound on a",
                               "SELECT * FROM %s WHERE token(a) >= token(?) and token(a) >= token(?)", 0, 1);
          assertInvalidMessage("a cannot be restricted by more than one relation if it includes an Equal",
                               "SELECT * FROM %s WHERE token(a) >= token(?) and token(a) = token(?)", 0, 1);
          assertInvalidSyntax("SELECT * FROM %s WHERE token(a) = token(?) and token(a) IN (token(?))", 0, 1);
  
          assertInvalidMessage("More than one restriction was found for the start bound on a",
                               "SELECT * FROM %s WHERE token(a) > token(?) AND token(a) > token(?)", 1, 2);
          assertInvalidMessage("More than one restriction was found for the start bound on a",
                               "SELECT * FROM %s WHERE token(a) > token(?) AND token(a) BETWEEN token(?) AND token(?)", 1, 2, 3);
          assertInvalidMessage("More than one restriction was found for the end bound on a",
                               "SELECT * FROM %s WHERE token(a) <= token(?) AND token(a) < token(?)", 1, 2);
          assertInvalidMessage("More than one restriction was found for the end bound on a",
                               "SELECT * FROM %s WHERE token(a) <= token(?) AND token(a) BETWEEN token(?) AND token(?)", 1, 2, 3);
          assertInvalidMessage("a cannot be restricted by more than one relation if it includes an Equal",
                               "SELECT * FROM %s WHERE token(a) > token(?) AND token(a) = token(?)", 1, 2);
          assertInvalidMessage("a cannot be restricted by more than one relation if it includes an Equal",
                               "SELECT * FROM %s WHERE  token(a) = token(?) AND token(a) > token(?)", 1, 2);
          assertInvalidMessage("a cannot be restricted by more than one relation if it includes an Equal",
                               "SELECT * FROM %s WHERE  token(a) = token(?) AND token(a) BETWEEN token(?) AND token(?)", 1, 2, 3);
      }
  
      @Test
      public void testTokenFunctionWithPartitionKeyAndClusteringKeyArguments() throws Throwable
      {
          createTable("CREATE TABLE IF NOT EXISTS %s (a int, b text, PRIMARY KEY (a, b))");
          assertInvalidMessage("The token() function must contains only partition key components",
                               "SELECT * FROM %s WHERE token(a, b) > token(0, 'c')");
      }
  
      @Test
      public void testTokenFunctionWithMultiColumnPartitionKey() throws Throwable
      {
          createTable("CREATE TABLE IF NOT EXISTS %s (a int, b text, PRIMARY KEY ((a, b)))");
          execute("INSERT INTO %s (a, b) VALUES (0, 'a')");
          execute("INSERT INTO %s (a, b) VALUES (0, 'b')");
          execute("INSERT INTO %s (a, b) VALUES (0, 'c')");
  
          assertRows(execute("SELECT * FROM %s WHERE token(a, b) > token(?, ?)", 0, "a"),
                     row(0, "b"),
                     row(0, "c"));
          assertRows(execute("SELECT * FROM %s WHERE token(a, b) > token(?, ?) and token(a, b) < token(?, ?)", 0, "a", 0, "d"),
                     row(0, "b"),
                     row(0, "c"));
          assertRows(execute("SELECT * FROM %s WHERE token(a, b) between token(?, ?) and token(?, ?)", 0, "b", 0, "d"),
                     row(0, "b"),
                     row(0, "c"));
          assertInvalidMessage("The token() function must be applied to all partition key components or none of them",
                               "SELECT * FROM %s WHERE token(a) > token(?) and token(b) > token(?)", 0, "a");
          assertInvalidMessage("The token() function must be applied to all partition key components or none of them",
                               "SELECT * FROM %s WHERE token(a) > token(?, ?) and token(a) < token(?, ?) and token(b) > token(?, ?) ",
                               0, "a", 0, "d", 0, "a");
          assertInvalidMessage("The token() function must be applied to all partition key components or none of them",
                               "SELECT * FROM %s WHERE token(a) BETWEEN token(?, ?) AND token(?, ?) and token(b) > token(?, ?) ",
                               0, "a", 0, "d", 0, "a");
          assertInvalidMessage("The token function arguments must be in the partition key order: a, b",
                               "SELECT * FROM %s WHERE token(b, a) > token(0, 'c')");
          assertInvalidMessage("The token function arguments must be in the partition key order: a, b",
                               "SELECT * FROM %s WHERE token(b, a) BETWEEN token(0, 'c') AND token(0, 'f')");
          assertInvalidMessage("The token() function must be applied to all partition key components or none of them",
                               "SELECT * FROM %s WHERE token(a, b) > token(?, ?) and token(b) < token(?, ?)", 0, "a", 0, "a");
          assertInvalidMessage("The token() function must be applied to all partition key components or none of them",
                               "SELECT * FROM %s WHERE token(a) > token(?, ?) and token(b) > token(?, ?)", 0, "a", 0, "a");
          assertInvalidMessage("The token() function must be applied to all partition key components or none of them",
                               "SELECT * FROM %s WHERE token(a) > token(?, ?) and token(b) > token(?, ?)", 0, "a", 0, "a");
      }
  
      @Test
      public void testSingleColumnPartitionKeyWithTokenNonTokenRestrictionsMix() throws Throwable
      {
          createTable("CREATE TABLE %s (a int primary key, b int)");
  
          execute("INSERT INTO %s (a, b) VALUES (0, 0);");
          execute("INSERT INTO %s (a, b) VALUES (1, 1);");
          execute("INSERT INTO %s (a, b) VALUES (2, 2);");
          execute("INSERT INTO %s (a, b) VALUES (3, 3);");
          execute("INSERT INTO %s (a, b) VALUES (4, 4);");
  
          assertRows(execute("SELECT * FROM %s WHERE token(a) > token(?);", 1),
                     row(2, 2),
                     row(3, 3),
                     row(4, 4));
          assertRows(execute("SELECT * FROM %s WHERE token(a) < token(?);", 1),
                     row(0, 0));
          assertRows(execute("SELECT * FROM %s WHERE token(a) >= token(?) AND token(a) <= token(?);",1, 1),
                     row(1, 1));
          assertRows(execute("SELECT * FROM %s WHERE token(a) > token(?) AND token(a) < token(?);",1, 1));
  
          assertRows(execute("SELECT * FROM %s WHERE a IN (?, ?);", 1, 3),
                     row(1, 1),
                     row(3, 3));
          assertRows(execute("SELECT * FROM %s WHERE token(a)> token(?) and token(a) <= token(?);", 1, 3),
                     row(2, 2),
                     row(3, 3));
          assertRows(execute("SELECT * FROM %s WHERE token(a)= token(2);"),
                     row(2, 2));
          assertRows(execute("SELECT * FROM %s WHERE token(a) > token(?) AND token(a) <= token(?) AND a IN (?, ?);",
                             1, 3, 1, 3),
                     row(3, 3));
          assertRows(execute("SELECT * FROM %s WHERE token(a) < token(?) AND token(a) >= token(?);",
                             1, 3));
          assertRows(execute("SELECT * FROM %s WHERE token(a) < token(?) AND token(a) >= token(?) AND a IN (?, ?);",
                             1, 3, 1, 3));
          assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
                               "SELECT * FROM %s WHERE token(a) > token(?) AND token(a) <= token(?) AND a > ?;", 1, 3, 1);
  
          assertRows(execute("SELECT * FROM %s WHERE token(a) > token(?) AND token(a) <= token(?) AND a IN ?;",
                             1, 3, Arrays.asList(1, 3)),
                     row(3, 3));
          assertRows(execute("SELECT * FROM %s WHERE token(a) > token(?) AND a = ?;", 1, 3),
                     row(3, 3));
          assertRows(execute("SELECT * FROM %s WHERE a = ? AND token(a) > token(?);", 3, 1),
                     row(3, 3));
          assertEmpty(execute("SELECT * FROM %s WHERE token(a) > token(?) AND a = ?;", 3, 1));
          assertEmpty(execute("SELECT * FROM %s WHERE a = ? AND token(a) > token(?);", 1, 3));
          assertRows(execute("SELECT * FROM %s WHERE token(a) > token(?) AND a IN (?, ?);", 2, 1, 3),
                     row(3, 3));
          assertRows(execute("SELECT * FROM %s WHERE token(a) > token(?) AND token(a) < token(?) AND a IN (?, ?) ;", 2, 5, 1, 3),
                     row(3, 3));
          assertRows(execute("SELECT * FROM %s WHERE a IN (?, ?) AND token(a) > token(?) AND token(a) < token(?);", 1, 3, 2, 5),
                     row(3, 3));
          assertRows(execute("SELECT * FROM %s WHERE token(a) > token(?) AND a IN (?, ?) AND token(a) < token(?);", 2, 1, 3, 5),
                     row(3, 3));
          assertEmpty(execute("SELECT * FROM %s WHERE a IN (?, ?) AND token(a) > token(?);", 1, 3, 3));
          assertRows(execute("SELECT * FROM %s WHERE token(a) <= token(?) AND a = ?;", 2, 2),
                     row(2, 2));
          assertEmpty(execute("SELECT * FROM %s WHERE token(a) <= token(?) AND a = ?;", 2, 3));
          assertEmpty(execute("SELECT * FROM %s WHERE token(a) = token(?) AND a = ?;", 2, 3));
          assertRows(execute("SELECT * FROM %s WHERE token(a) >= token(?) AND token(a) <= token(?) AND a = ?;", 2, 2, 2),
                     row(2, 2));
          assertRows(execute("SELECT * FROM %s WHERE token(a) BETWEEN token(?) AND token(?) AND a = ?;", 2, 2, 2),
                     row(2, 2));
          assertEmpty(execute("SELECT * FROM %s WHERE token(a) >= token(?) AND token(a) < token(?) AND a = ?;", 2, 2, 2));
          assertEmpty(execute("SELECT * FROM %s WHERE token(a) > token(?) AND token(a) <= token(?) AND a = ?;", 2, 2, 2));
          assertEmpty(execute("SELECT * FROM %s WHERE token(a) > token(?) AND token(a) < token(?) AND a = ?;", 2, 2, 2));
      }
  
      @Test
      public void testMultiColumnPartitionKeyWithTokenNonTokenRestrictionsMix() throws Throwable
      {
          createTable("CREATE TABLE %s (a int, b int, c int, primary key((a, b)))");
  
          execute("INSERT INTO %s (a, b, c) VALUES (0, 0, 0);");
          execute("INSERT INTO %s (a, b, c) VALUES (0, 1, 1);");
          execute("INSERT INTO %s (a, b, c) VALUES (0, 2, 2);");
          execute("INSERT INTO %s (a, b, c) VALUES (1, 0, 3);");
          execute("INSERT INTO %s (a, b, c) VALUES (1, 1, 4);");
  
          assertRows(execute("SELECT * FROM %s WHERE token(a, b) > token(?, ?);", 0, 0),
                     row(0, 1, 1),
                     row(0, 2, 2),
                     row(1, 0, 3),
                     row(1, 1, 4));
  
          assertRows(execute("SELECT * FROM %s WHERE token(a, b) > token(?, ?) AND a = ? AND b IN (?, ?);",
                             0, 0, 1, 0, 1),
                     row(1, 0, 3),
                     row(1, 1, 4));
  
          assertRows(execute("SELECT * FROM %s WHERE a = ? AND token(a, b) > token(?, ?) AND b IN (?, ?);",
                             1, 0, 0, 0, 1),
                     row(1, 0, 3),
                     row(1, 1, 4));
  
          assertRows(execute("SELECT * FROM %s WHERE b IN (?, ?) AND token(a, b) > token(?, ?) AND a = ?;",
                             0, 1, 0, 0, 1),
                     row(1, 0, 3),
                     row(1, 1, 4));
  
          assertEmpty(execute("SELECT * FROM %s WHERE b IN (?, ?) AND token(a, b) > token(?, ?) AND token(a, b) < token(?, ?) AND a = ?;",
                              0, 1, 0, 0, 0, 0, 1));
  
          assertEmpty(execute("SELECT * FROM %s WHERE b IN (?, ?) AND token(a, b) > token(?, ?) AND token(a, b) <= token(?, ?) AND a = ?;",
                              0, 1, 0, 0, 0, 0, 1));
  
          assertEmpty(execute("SELECT * FROM %s WHERE b IN (?, ?) AND token(a, b) >= token(?, ?) AND token(a, b) < token(?, ?) AND a = ?;",
                              0, 1, 0, 0, 0, 0, 1));
  
          assertEmpty(execute("SELECT * FROM %s WHERE b IN (?, ?) AND token(a, b) = token(?, ?) AND a = ?;",
                              0, 1, 0, 0, 1));
  
          assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
                               "SELECT * FROM %s WHERE token(a, b) > token(?, ?) AND a = ?;", 0, 0, 1);
      }
  
      @Test
      public void testMultiColumnPartitionKeyWithIndexAndTokenNonTokenRestrictionsMix() throws Throwable
      {
          Util.assumeLegacySecondaryIndex();
          createTable("CREATE TABLE %s (a int, b int, c int, primary key((a, b)))");
          createIndex("CREATE INDEX ON %s(b)");
          createIndex("CREATE INDEX ON %s(c)");
  
          execute("INSERT INTO %s (a, b, c) VALUES (0, 0, 0);");
          execute("INSERT INTO %s (a, b, c) VALUES (0, 1, 1);");
          execute("INSERT INTO %s (a, b, c) VALUES (0, 2, 2);");
          execute("INSERT INTO %s (a, b, c) VALUES (1, 0, 3);");
          execute("INSERT INTO %s (a, b, c) VALUES (1, 1, 4);");
  
          assertRows(execute("SELECT * FROM %s WHERE b = ?;", 1),
                     row(0, 1, 1),
                     row(1, 1, 4));
  
          assertRows(execute("SELECT * FROM %s WHERE token(a, b) > token(?, ?) AND b = ?;", 0, 0, 1),
                     row(0, 1, 1),
                     row(1, 1, 4));
  
          assertRows(execute("SELECT * FROM %s WHERE b = ? AND token(a, b) > token(?, ?);", 1, 0, 0),
                     row(0, 1, 1),
                     row(1, 1, 4));
  
          assertRows(execute("SELECT * FROM %s WHERE b = ? AND token(a, b) > token(?, ?) and c = ? ALLOW FILTERING;", 1, 0, 0, 4),
                     row(1, 1, 4));
      }
  
      @Test
      public void testTokenFunctionWithCompoundPartitionAndClusteringCols() throws Throwable
      {
          createTable("CREATE TABLE IF NOT EXISTS %s (a int, b int, c int, d int, PRIMARY KEY ((a, b), c, d))");
          // just test that the queries don't error
          execute("SELECT * FROM %s WHERE token(a, b) > token(0, 0) AND c > 10 ALLOW FILTERING;");
          execute("SELECT * FROM %s WHERE c > 10 AND token(a, b) > token(0, 0) ALLOW FILTERING;");
          execute("SELECT * FROM %s WHERE token(a, b) > token(0, 0) AND (c, d) > (0, 0) ALLOW FILTERING;");
          execute("SELECT * FROM %s WHERE (c, d) > (0, 0) AND token(a, b) > token(0, 0) ALLOW FILTERING;");
      }
  
      /**
       * Test undefined columns
       * migrated from cql_tests.py:TestCQL.undefined_column_handling_test()
       */
      @Test
      public void testUndefinedColumns() throws Throwable
      {
          createTable("CREATE TABLE %s (k int PRIMARY KEY, v1 int, v2 int,)");
  
          execute("INSERT INTO %s (k, v1, v2) VALUES (0, 0, 0)");
          execute("INSERT INTO %s (k, v1) VALUES (1, 1)");
          execute("INSERT INTO %s (k, v1, v2) VALUES (2, 2, 2)");
  
          Object[][] rows = getRows(execute("SELECT v2 FROM %s"));
          assertEquals(0, rows[0][0]);
          assertNull(rows[1][0]);
          assertEquals(2, rows[2][0]);
  
          rows = getRows(execute("SELECT v2 FROM %s WHERE k = 1"));
          assertEquals(1, rows.length);
          assertNull(rows[0][0]);
      }
  
      /**
       * Check table with only a PK (#4361),
       * migrated from cql_tests.py:TestCQL.only_pk_test()
       */
      @Test
      public void testPrimaryKeyOnly() throws Throwable
      {
          createTable("CREATE TABLE %s (k int, c int, PRIMARY KEY (k, c))");
  
          for (int k = 0; k < 2; k++)
              for (int c = 0; c < 2; c++)
                  execute("INSERT INTO %s (k, c) VALUES (?, ?)", k, c);
  
          assertRows(execute("SELECT * FROM %s"),
                     row(0, 0),
                     row(0, 1),
                     row(1, 0),
                     row(1, 1));
      }
  
      /**
       * Migrated from cql_tests.py:TestCQL.composite_index_with_pk_test()
       */
      @Test
      public void testCompositeIndexWithPK() throws Throwable
      {
          Util.assumeLegacySecondaryIndex();
          createTable("CREATE TABLE %s (blog_id int, time1 int, time2 int, author text, content text, PRIMARY KEY (blog_id, time1, time2))");
  
          createIndex("CREATE INDEX ON %s(author)");
  
          execute("INSERT INTO %s (blog_id, time1, time2, author, content) VALUES (?, ?, ?, ?, ?)", 1, 0, 0, "foo", "bar1");
          execute("INSERT INTO %s (blog_id, time1, time2, author, content) VALUES (?, ?, ?, ?, ?)", 1, 0, 1, "foo", "bar2");
          execute("INSERT INTO %s (blog_id, time1, time2, author, content) VALUES (?, ?, ?, ?, ?)", 2, 1, 0, "foo", "baz");
          execute("INSERT INTO %s (blog_id, time1, time2, author, content) VALUES (?, ?, ?, ?, ?)", 3, 0, 1, "gux", "qux");
  
          assertRows(execute("SELECT blog_id, content FROM %s WHERE author='foo'"),
                     row(1, "bar1"),
                     row(1, "bar2"),
                     row(2, "baz"));
  
          assertRows(execute("SELECT blog_id, content FROM %s WHERE time1 > 0 AND author='foo' ALLOW FILTERING"),
                     row(2, "baz"));
  
          assertRows(execute("SELECT blog_id, content FROM %s WHERE time1 = 1 AND author='foo' ALLOW FILTERING"),
                     row(2, "baz"));
  
          assertRows(execute("SELECT blog_id, content FROM %s WHERE time1 = 1 AND time2 = 0 AND author='foo' ALLOW FILTERING"),
                     row(2, "baz"));
  
          assertEmpty(execute("SELECT content FROM %s WHERE time1 = 1 AND time2 = 1 AND author='foo' ALLOW FILTERING"));
  
          assertEmpty(execute("SELECT content FROM %s WHERE time1 = 1 AND time2 > 0 AND author='foo' ALLOW FILTERING"));
  
          assertInvalid("SELECT content FROM %s WHERE time2 >= 0 AND author='foo'");
  
          assertInvalid("SELECT blog_id, content FROM %s WHERE time1 > 0 AND author='foo'");
          assertInvalid("SELECT blog_id, content FROM %s WHERE time1 = 1 AND author='foo'");
          assertInvalid("SELECT blog_id, content FROM %s WHERE time1 = 1 AND time2 = 0 AND author='foo'");
          assertInvalid("SELECT content FROM %s WHERE time1 = 1 AND time2 = 1 AND author='foo'");
          assertInvalid("SELECT content FROM %s WHERE time1 = 1 AND time2 > 0 AND author='foo'");
      }
  
      /**
       * Test for LIMIT bugs from 4579,
       * migrated from cql_tests.py:TestCQL.limit_bugs_test()
       */
      @Test
      public void testLimitBug() throws Throwable
      {
          createTable("CREATE TABLE %s (a int, b int, c int, d int, e int, PRIMARY KEY (a, b))");
  
          execute("INSERT INTO %s (a, b, c, d, e) VALUES (1, 1, 1, 1, 1);");
          execute("INSERT INTO %s (a, b, c, d, e) VALUES (2, 2, 2, 2, 2);");
          execute("INSERT INTO %s (a, b, c, d, e) VALUES (3, 3, 3, 3, 3);");
          execute("INSERT INTO %s (a, b, c, d, e) VALUES (4, 4, 4, 4, 4);");
  
          assertRows(execute("SELECT * FROM %s"),
                     row(1, 1, 1, 1, 1),
                     row(2, 2, 2, 2, 2),
                     row(3, 3, 3, 3, 3),
                     row(4, 4, 4, 4, 4));
  
          assertRows(execute("SELECT * FROM %s LIMIT 1"),
                     row(1, 1, 1, 1, 1));
  
          assertRows(execute("SELECT * FROM %s LIMIT 2"),
                     row(1, 1, 1, 1, 1),
                     row(2, 2, 2, 2, 2));
  
          createTable("CREATE TABLE %s (a int primary key, b int, c int,)");
  
          execute("INSERT INTO %s (a, b, c) VALUES (1, 1, 1)");
          execute("INSERT INTO %s (a, b, c) VALUES (2, 2, 2)");
          execute("INSERT INTO %s (a, b, c) VALUES (3, 3, 3)");
          execute("INSERT INTO %s (a, b, c) VALUES (4, 4, 4)");
  
          assertRows(execute("SELECT * FROM %s"),
                     row(1, 1, 1),
                     row(2, 2, 2),
                     row(3, 3, 3),
                     row(4, 4, 4));
  
          assertRows(execute("SELECT * FROM %s LIMIT 1"),
                     row(1, 1, 1));
  
          assertRows(execute("SELECT * FROM %s LIMIT 2"),
                     row(1, 1, 1),
                     row(2, 2, 2));
  
          assertRows(execute("SELECT * FROM %s LIMIT 3"),
                     row(1, 1, 1),
                     row(2, 2, 2),
                     row(3, 3, 3));
  
          assertRows(execute("SELECT * FROM %s LIMIT 4"),
                     row(1, 1, 1),
                     row(2, 2, 2),
                     row(3, 3, 3),
                     row(4, 4, 4));
  
          assertRows(execute("SELECT * FROM %s LIMIT 5"),
                     row(1, 1, 1),
                     row(2, 2, 2),
                     row(3, 3, 3),
                     row(4, 4, 4));
      }
  
      /**
       * Test for #4612 bug and more generally order by when multiple C* rows are queried
       * migrated from cql_tests.py:TestCQL.order_by_multikey_test()
       */
      @Test
      public void testOrderByMultikey() throws Throwable
      {
          createTable("CREATE TABLE %s (my_id varchar, col1 int, col2 int, value varchar, PRIMARY KEY (my_id, col1, col2))");
  
          execute("INSERT INTO %s (my_id, col1, col2, value) VALUES ( 'key1', 1, 1, 'a');");
          execute("INSERT INTO %s (my_id, col1, col2, value) VALUES ( 'key2', 3, 3, 'a');");
          execute("INSERT INTO %s (my_id, col1, col2, value) VALUES ( 'key3', 2, 2, 'b');");
          execute("INSERT INTO %s (my_id, col1, col2, value) VALUES ( 'key4', 2, 1, 'b');");
  
          assertRows(execute("SELECT col1 FROM %s WHERE my_id in('key1', 'key2', 'key3') ORDER BY col1"),
                     row(1), row(2), row(3));
  
          assertRows(execute("SELECT col1, value, my_id, col2 FROM %s WHERE my_id in('key3', 'key4') ORDER BY col1, col2"),
                     row(2, "b", "key4", 1), row(2, "b", "key3", 2));
  
          assertInvalid("SELECT col1 FROM %s ORDER BY col1");
          assertInvalid("SELECT col1 FROM %s WHERE my_id > 'key1' ORDER BY col1");
      }
  
      /**
       * Migrated from cql_tests.py:TestCQL.composite_index_collections_test()
       */
      @Test
      public void testIndexOnCompositeWithCollections() throws Throwable
      {
          Util.assumeLegacySecondaryIndex();
          createTable("CREATE TABLE %s (blog_id int, time1 int, time2 int, author text, content set<text>, PRIMARY KEY (blog_id, time1, time2))");
  
          createIndex("CREATE INDEX ON %s (author)");
  
          execute("INSERT INTO %s (blog_id, time1, time2, author, content) VALUES (?, ?, ?, ?, { 'bar1', 'bar2' })", 1, 0, 0, "foo");
          execute("INSERT INTO %s (blog_id, time1, time2, author, content) VALUES (?, ?, ?, ?, { 'bar2', 'bar3' })", 1, 0, 1, "foo");
          execute("INSERT INTO %s (blog_id, time1, time2, author, content) VALUES (?, ?, ?, ?, { 'baz' })", 2, 1, 0, "foo");
          execute("INSERT INTO %s (blog_id, time1, time2, author, content) VALUES (?, ?, ?, ?, { 'qux' })", 3, 0, 1, "gux");
  
          assertRows(execute("SELECT blog_id, content FROM %s WHERE author='foo'"),
                     row(1, set("bar1", "bar2")),
                     row(1, set("bar2", "bar3")),
                     row(2, set("baz")));
      }
  
      /**
       * Migrated from cql_tests.py:TestCQL.truncate_clean_cache_test()
       */
      @Test
      public void testTruncateWithCaching() throws Throwable
      {
          createTable("CREATE TABLE %s (k int PRIMARY KEY, v1 int, v2 int) WITH CACHING = { 'keys': 'ALL', 'rows_per_partition': 'ALL' };");
  
          for (int i = 0; i < 3; i++)
              execute("INSERT INTO %s (k, v1, v2) VALUES (?, ?, ?)", i, i, i * 2);
  
          assertRows(execute("SELECT v1, v2 FROM %s WHERE k IN (0, 1, 2)"),
                     row(0, 0),
                     row(1, 2),
                     row(2, 4));
  
          execute("TRUNCATE %s");
  
          assertEmpty(execute("SELECT v1, v2 FROM %s WHERE k IN (0, 1, 2)"));
      }
  
      /**
       * Migrated from cql_tests.py:TestCQL.range_key_ordered_test()
       */
      @Test
      public void testRangeKey() throws Throwable
      {
          createTable("CREATE TABLE %s (k int PRIMARY KEY)");
  
          execute("INSERT INTO %s (k) VALUES (-1)");
          execute("INSERT INTO %s (k) VALUES ( 0)");
          execute("INSERT INTO %s (k) VALUES ( 1)");
  
          assertRows(execute("SELECT * FROM %s"),
                     row(0),
                     row(1),
                     row(-1));
  
          assertInvalid("SELECT * FROM %s WHERE k >= -1 AND k < 1");
      }
  
      @Test
      public void testTokenFunctionWithInvalidColumnNames() throws Throwable
      {
          createTable("CREATE TABLE %s (a int, b int, c int, d int, PRIMARY KEY ((a, b), c))");
          assertInvalidMessage("Undefined column name e", "SELECT * FROM %s WHERE token(a, e) = token(0, 0)");
          assertInvalidMessage("Undefined column name e", "SELECT * FROM %s WHERE token(a, e) > token(0, 1)");
          assertInvalidMessage("Undefined column name e", "SELECT b AS e FROM %s WHERE token(a, e) = token(0, 0)");
          assertInvalidMessage("Undefined column name e", "SELECT b AS e FROM %s WHERE token(a, e) > token(0, 1)");
      }
  }
  