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.constraints;
  
  
  import java.util.Arrays;
  import java.util.Collection;
  
  import org.junit.Test;
  import org.junit.runner.RunWith;
  import org.junit.runners.Parameterized;
  
  import org.apache.cassandra.cql3.constraints.InvalidConstraintDefinitionException;
  import org.apache.cassandra.exceptions.InvalidRequestException;
  import org.apache.cassandra.utils.Generators;
  
  import static org.assertj.core.api.Assertions.assertThatThrownBy;
  import static org.junit.Assert.assertTrue;
  import static org.junit.Assert.fail;
  import static accord.utils.Property.qt;
  import static org.quicktheories.generators.SourceDSL.doubles;
  import static org.quicktheories.generators.SourceDSL.integers;
  
  @RunWith(Parameterized.class)
  public class CreateTableWithColumnCqlConstraintValidationTest extends CqlConstraintValidationTester
  {
  
      @Parameterized.Parameter
      public String order;
  
      @Parameterized.Parameters()
      public static Collection<Object[]> generateData()
      {
          return Arrays.asList(new Object[][]{
          { "ASC" },
          { "DESC" }
          });
      }
  
      @Test
      public void testCreateTableWithColumnNotNamedConstraintDescribeTableNonFunction() throws Throwable
      {
          String table = createTable(KEYSPACE_PER_TEST, "CREATE TABLE %s (pk int, ck1 int CHECK ck1 < 100, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 ASC);");
  
          String tableCreateStatement = "CREATE TABLE " + KEYSPACE_PER_TEST + "." + table + " (\n" +
                                        "    pk int,\n" +
                                        "    ck1 int CHECK ck1 < 100,\n" +
                                        "    ck2 int,\n" +
                                        "    v int,\n" +
                                        "    PRIMARY KEY (pk, ck1, ck2)\n" +
                                        ") WITH CLUSTERING ORDER BY (ck1 ASC, ck2 ASC)\n" +
                                        "    AND " + tableParametersCql();
  
          assertRowsNet(executeDescribeNet("DESCRIBE TABLE " + KEYSPACE_PER_TEST + "." + table),
                        row(KEYSPACE_PER_TEST,
                            "table",
                            table,
                            tableCreateStatement));
      }
  
      @Test
      public void testCreateTableWithColumnMultipleConstraintsDescribeTableNonFunction() throws Throwable
      {
          String table = createTable(KEYSPACE_PER_TEST, "CREATE TABLE %s (pk int, ck1 int CHECK ck1 < 100 AND ck1 > 10, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 ASC);");
  
          String tableCreateStatement = "CREATE TABLE " + KEYSPACE_PER_TEST + "." + table + " (\n" +
                                        "    pk int,\n" +
                                        "    ck1 int CHECK ck1 < 100 AND ck1 > 10,\n" +
                                        "    ck2 int,\n" +
                                        "    v int,\n" +
                                        "    PRIMARY KEY (pk, ck1, ck2)\n" +
                                        ") WITH CLUSTERING ORDER BY (ck1 ASC, ck2 ASC)\n" +
                                        "    AND " + tableParametersCql();
  
          assertRowsNet(executeDescribeNet("DESCRIBE TABLE " + KEYSPACE_PER_TEST + "." + table),
                        row(KEYSPACE_PER_TEST,
                            "table",
                            table,
                            tableCreateStatement));
      }
  
      @Test
      public void testCreateTableWithColumnNotNamedConstraintDescribeTableFunction() throws Throwable
      {
          String table = createTable(KEYSPACE_PER_TEST, "CREATE TABLE %s (pk int, ck1 text CHECK LENGTH() = 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 ASC);");
  
          String tableCreateStatement = "CREATE TABLE " + KEYSPACE_PER_TEST + "." + table + " (\n" +
                                        "    pk int,\n" +
                                        "    ck1 text CHECK LENGTH() = 4,\n" +
                                        "    ck2 int,\n" +
                                        "    v int,\n" +
                                        "    PRIMARY KEY (pk, ck1, ck2)\n" +
                                        ") WITH CLUSTERING ORDER BY (ck1 ASC, ck2 ASC)\n" +
                                        "    AND " + tableParametersCql();
  
          assertRowsNet(executeDescribeNet("DESCRIBE TABLE " + KEYSPACE_PER_TEST + "." + table),
                        row(KEYSPACE_PER_TEST,
                            "table",
                            table,
                            tableCreateStatement));
      }
  
      @Test
      public void testCreateTableWithColumnNotNullConstraintDescribe() throws Throwable
      {
          String table = createTable(KEYSPACE_PER_TEST, "CREATE TABLE %s (pk int, ck1 int, ck2 int, v int CHECK NOT NULL, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 ASC);");
  
          String tableCreateStatement = "CREATE TABLE " + KEYSPACE_PER_TEST + "." + table + " (\n" +
                                        "    pk int,\n" +
                                        "    ck1 int,\n" +
                                        "    ck2 int,\n" +
                                        "    v int CHECK NOT NULL,\n" +
                                        "    PRIMARY KEY (pk, ck1, ck2)\n" +
                                        ") WITH CLUSTERING ORDER BY (ck1 ASC, ck2 ASC)\n" +
                                        "    AND " + tableParametersCql();
  
          assertRowsNet(executeDescribeNet("DESCRIBE TABLE " + KEYSPACE_PER_TEST + "." + table),
                        row(KEYSPACE_PER_TEST,
                            "table",
                            table,
                            tableCreateStatement));
      }
  
      // SCALAR
      @Test
      public void testCreateTableWithColumnWithClusteringColumnLessThanScalarConstraintInteger() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int CHECK ck1 < 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(integers().between(0, 3)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 < 4";
          // Invalid
          qt().forAll(Generators.toGen(integers().between(4, 100)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnBiggerThanScalarConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int CHECK ck1 > 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(integers().between(5, 100)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 > 4";
          // Invalid
          qt().forAll(Generators.toGen(integers().between(0, 4)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnBiggerOrEqualThanScalarConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int CHECK ck1 >= 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(integers().between(4, 100)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 >= 4";
          // Invalid
          qt().forAll(Generators.toGen(integers().between(0, 3)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnLessOrEqualThanScalarConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int CHECK ck1 <= 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(integers().between(0, 4)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 <= 4";
          // Invalid
          qt().forAll(Generators.toGen(integers().between(5, 100)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnDifferentThanScalarConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int CHECK ck1 != 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(integers().between(0, 3)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
          qt().forAll(Generators.toGen(integers().between(5, 100)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 != 4";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 4, 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnMultipleScalarConstraints() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int CHECK ck1 < 4 AND ck1 >= 2, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(integers().between(2, 3)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 >= 2";
          // Invalid
          qt().forAll(Generators.toGen(integers().between(-100, 1)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
  
          final String expectedErrorMessage2 = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 < 4";
          qt().forAll(Generators.toGen(integers().between(4, 100)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage2, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnLessThanScalarSmallIntConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 smallint CHECK ck1 < 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(integers().between(0, 3)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 < 4";
          // Invalid
          qt().forAll(Generators.toGen(integers().between(4, 100)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnBiggerThanScalarSmallIntConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 smallint CHECK ck1 > 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(integers().between(5, 100)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 > 4";
          // Invalid
          qt().forAll(Generators.toGen(integers().between(0, 4)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnBiggerOrEqualThanScalarSmallIntConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 smallint CHECK ck1 >= 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(integers().between(4, 100)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 >= 4";
          // Invalid
          qt().forAll(Generators.toGen(integers().between(0, 3)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnLessOrEqualThanScalarSmallIntConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 smallint CHECK ck1 <= 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(integers().between(0, 4)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 <= 4";
          // Invalid
          qt().forAll(Generators.toGen(integers().between(5, 100)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnDifferentThanScalarSmallIntConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 smallint CHECK ck1 != 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(integers().between(0, 3)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
          qt().forAll(Generators.toGen(integers().between(5, 100)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 != 4";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 4, 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnMultipleScalarSmallIntConstraints() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 smallint CHECK ck1 < 4 AND ck1 >= 2, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(integers().between(2, 3)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 >= 2";
          // Invalid
          qt().forAll(Generators.toGen(integers().between(-100, 1)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
  
          final String expectedErrorMessage2 = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 < 4";
          qt().forAll(Generators.toGen(integers().between(4, 100)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage2, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnLessThanScalarDecimalConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 decimal CHECK ck1 < 4.2, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 2, 3)");
          qt().forAll(Generators.toGen(doubles().between(0, 4.1)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 < 4.2";
          // Invalid
          qt().forAll(Generators.toGen(doubles().between(4.3, 100)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnBiggerThanScalarDecimalConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 decimal CHECK ck1 > 4.2, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(doubles().between(4.3, 100)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 > 4.2";
          // Invalid
          qt().forAll(Generators.toGen(doubles().between(0, 4.2)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnBiggerOrEqualThanScalarDecimalConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 decimal CHECK ck1 >= 4.2, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(doubles().between(4.2, 100)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 >= 4.2";
          // Invalid
          qt().forAll(Generators.toGen(doubles().between(0, 4.1)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnLessOrEqualThanScalarDecimalConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 decimal CHECK ck1 <= 4.2, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(doubles().between(0, 4.2)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 <= 4.2";
          // Invalid
          qt().forAll(Generators.toGen(doubles().between(4.3, 100)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnDifferentThanScalarDecimalConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 decimal CHECK ck1 != 4.2, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(doubles().between(0, 4.1)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
          qt().forAll(Generators.toGen(doubles().between(4.3, 100)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 != 4.2";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 4.2, 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnMultipleScalarDecimalConstraints() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 decimal CHECK ck1 < 4.2 AND ck1 >= 2.1, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(doubles().between(2.1, 4.1)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 >= 2.1";
          // Invalid
          qt().forAll(Generators.toGen(doubles().between(-100, 2)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
  
          final String expectedErrorMessage2 = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 < 4.2";
          qt().forAll(Generators.toGen(doubles().between(4.2, 100)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage2, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnLessThanScalarDoubleConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 double CHECK ck1 < 4.2, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 2, 3)");
          qt().forAll(Generators.toGen(doubles().between(0, 4.1)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 < 4.2";
          // Invalid
          qt().forAll(Generators.toGen(doubles().between(4.3, 100)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnBiggerThanScalarDoubleConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 double CHECK ck1 > 4.2, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(doubles().between(4.3, 100)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 > 4.2";
          // Invalid
          qt().forAll(Generators.toGen(doubles().between(0, 4.2)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnBiggerOrEqualThanScalarDoubleConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 double CHECK ck1 >= 4.2, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(doubles().between(4.2, 100)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 >= 4.2";
          // Invalid
          qt().forAll(Generators.toGen(doubles().between(0, 4.1)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnLessOrEqualThanScalarDoubleConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 double CHECK ck1 <= 4.2, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(doubles().between(0, 4.2)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 <= 4.2";
          // Invalid
          qt().forAll(Generators.toGen(doubles().between(4.3, 100)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnDifferentThanScalarDoubleConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 double CHECK ck1 != 4.2, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(doubles().between(0, 4.1)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
          qt().forAll(Generators.toGen(doubles().between(4.3, 100)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 != 4.2";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 4.2, 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnMultipleScalarDoubleConstraints() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 double CHECK ck1 < 4.2 AND ck1 >= 2.1, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(doubles().between(2.1, 4.1)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 >= 2.1";
          // Invalid
          qt().forAll(Generators.toGen(doubles().between(-100, 2)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
  
          final String expectedErrorMessage2 = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 < 4.2";
          qt().forAll(Generators.toGen(doubles().between(4.2, 100)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage2, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnLessThanScalarFloatConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 float CHECK ck1 < 4.2, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 2, 3)");
          qt().forAll(Generators.toGen(doubles().between(0, 4.1)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 < 4.2";
          // Invalid
          qt().forAll(Generators.toGen(doubles().between(4.3, 100)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnBiggerThanScalarFloatConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 float CHECK ck1 > 4.2, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(doubles().between(4.3, 100)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 > 4.2";
          // Invalid
          qt().forAll(Generators.toGen(doubles().between(0, 4.2)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnBiggerOrEqualThanScalarFloatConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 float CHECK ck1 >= 4.2, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(doubles().between(4.2, 100)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 >= 4.2";
          // Invalid
          qt().forAll(Generators.toGen(doubles().between(0, 4.1)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnLessOrEqualThanScalarFloatConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 float CHECK ck1 <= 4.2, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(doubles().between(0, 4.2)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 <= 4.2";
          // Invalid
          qt().forAll(Generators.toGen(doubles().between(4.3, 100)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnDifferentThanScalarFloatConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 float CHECK ck1 != 4.2, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(doubles().between(0, 4.1)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
          qt().forAll(Generators.toGen(doubles().between(4.3, 100)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 != 4.2";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 4.2, 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnMultipleScalarFloatConstraints() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 float CHECK ck1 < 4.2 AND ck1 >= 2.1, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          qt().forAll(Generators.toGen(doubles().between(2.1, 4.1)))
              .check(d -> execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 >= 2.1";
          // Invalid
          qt().forAll(Generators.toGen(doubles().between(-100, 2)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
  
          final String expectedErrorMessage2 = "Column value does not satisfy value constraint for column 'ck1'. It should be ck1 < 4.2";
          qt().forAll(Generators.toGen(doubles().between(4.2, 100)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrowMessage(expectedErrorMessage2, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableWithColumnWithNotNullCheckScalarIntConstraints() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int, ck2 int, v int CHECK v < 4 AND v >= 2, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'v' as it is null.";
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, null)");
      }
  
      @Test
      public void testCreateTableWithColumnWithNotNullCheckScalarSmallintConstraints() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int, ck2 int, v smallint CHECK v < 4 AND v >= 2, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'v' as it is null.";
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, null)");
      }
  
      @Test
      public void testCreateTableWithColumnWithNotNullCheckScalarDecimalConstraints() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int, ck2 int, v decimal CHECK v < 4 AND v >= 2, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'v' as it is null.";
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, null)");
      }
  
      @Test
      public void testCreateTableWithColumnWithNotNullCheckScalarDoubleConstraints() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int, ck2 int, v double CHECK v < 4 AND v >= 2, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'v' as it is null.";
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, null)");
      }
  
      @Test
      public void testCreateTableWithColumnWithNotNullCheckScalarFloatConstraints() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int, ck2 int, v float CHECK v < 4 AND v >= 2, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'v' as it is null.";
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, null)");
      }
  
      // FUNCTION
      @Test
      public void testCreateTableWithColumnWithClusteringColumnLengthEqualToConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 text CHECK LENGTH() = 4, ck2 int, v int, PRIMARY KEY ((pk), ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 ASC);");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 'fooo', 2, 3)");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 'foo', 2, 3)");
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 'foooo', 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnLengthDifferentThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 text CHECK LENGTH() != 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 ASC);");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It has a length of";
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 'foo', 2, 3)");
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 'foooo', 2, 3)");
  
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 'fooo', 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnLengthBiggerThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 text CHECK LENGTH() > 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 ASC);");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 'foooo', 2, 3)");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 'foo', 2, 3)");
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 'fooo', 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnLengthBiggerOrEqualThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 text CHECK LENGTH() >= 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 ASC);");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 'foooo', 2, 3)");
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 'fooo', 2, 3)");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 'foo', 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnLengthSmallerThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 text CHECK LENGTH() < 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 ASC);");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 'foo', 2, 3)");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 'fooo', 2, 3)");
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 'foooo', 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnLengthSmallerOrEqualThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 text CHECK LENGTH() <= 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 ASC);");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 'foo', 2, 3)");
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 'fooo', 2, 3)");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 'foooo', 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringBlobColumnLengthEqualToConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 blob CHECK LENGTH() = 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 ASC);");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, textAsBlob('fooo'), 2, 3)");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, textAsBlob('foo'), 2, 3)");
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, textAsBlob('foooo'), 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringBlobColumnLengthDifferentThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 blob CHECK LENGTH() != 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 ASC);");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, textAsBlob('foo'), 2, 3)");
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, textAsBlob('foooo'), 2, 3)");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, textAsBlob('fooo'), 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringBlobColumnLengthBiggerThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 blob CHECK LENGTH() > 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 ASC);");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, textAsBlob('foooo'), 2, 3)");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, textAsBlob('foo'), 2, 3)");
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, textAsBlob('fooo'), 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringBlobColumnLengthBiggerOrEqualThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 blob CHECK LENGTH() >= 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 ASC);");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, textAsBlob('foooo'), 2, 3)");
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, textAsBlob('fooo'), 2, 3)");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, textAsBlob('foo'), 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringBlobColumnLengthSmallerThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 blob CHECK LENGTH() < 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 ASC);");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, textAsBlob('foo'), 2, 3)");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, textAsBlob('fooo'), 2, 3)");
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, textAsBlob('foooo'), 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringBlobColumnLengthSmallerOrEqualThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 blob CHECK LENGTH() <= 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 ASC);");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, textAsBlob('foo'), 2, 3)");
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, textAsBlob('fooo'), 2, 3)");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'ck1'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, textAsBlob('foooo'), 2, 3)");
      }
  
  
      @Test
      public void testCreateTableWithColumnWithPkColumnLengthEqualToConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk text CHECK LENGTH() = 4, ck1 int, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES ('fooo', 1, 2, 3)");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'pk'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES ('foo', 1, 2, 3)");
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES ('foooo', 1, 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithPkColumnLengthDifferentThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk text CHECK LENGTH() != 4, ck1 int, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES ('foo', 1, 2, 3)");
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES ('foooo', 1, 2, 3)");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'pk'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES ('fooo', 1, 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithPkColumnLengthBiggerThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk text CHECK LENGTH() > 4, ck1 int, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES ('foooo', 1, 2, 3)");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'pk'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES ('foo', 1, 2, 3)");
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES ('fooo', 1, 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithPkColumnLengthBiggerOrEqualThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk text CHECK LENGTH() >= 4, ck1 int, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES ('foooo', 1, 2, 3)");
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES ('fooo', 1, 2, 3)");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'pk'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES ('foo', 1, 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithPkColumnLengthSmallerThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk text CHECK LENGTH() < 4, ck1 int, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES ('foo', 1, 2, 3)");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'pk'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES ('fooo', 1, 2, 3)");
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES ('foooo', 1, 2, 3)");
      }
  
      @Test
      public void testCreateTableWithColumnWithPkColumnLengthSmallerOrEqualThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk text CHECK LENGTH() <= 4, ck1 int, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES ('foo', 1, 2, 3)");
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES ('fooo', 1, 2, 3)");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'pk'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES ('foooo', 1, 2, 3)");
      }
  
  
      @Test
      public void testCreateTableWithColumnWithRegularColumnLengthEqualToConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int, ck2 int, v text CHECK LENGTH() = 4, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, 'fooo')");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'v'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, 'foo')");
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, 'foooo')");
      }
  
      @Test
      public void testCreateTableWithColumnWithRegularColumnLengthDifferentThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int, ck2 int, v text CHECK LENGTH() != 4, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, 'foo')");
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, 'foooo')");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'v'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, 'fooo')");
      }
  
      @Test
      public void testCreateTableWithColumnWithRegularColumnLengthBiggerThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int, ck2 int, v text CHECK LENGTH() > 4, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, 'foooo')");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'v'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, 'foo')");
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, 'fooo')");
      }
  
      @Test
      public void testCreateTableWithColumnWithRegularColumnLengthBiggerOrEqualThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int, ck2 int, v text CHECK LENGTH() >= 4, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, 'foooo')");
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, 'fooo')");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'v'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, 'foo')");
      }
  
      @Test
      public void testCreateTableWithColumnWithRegularColumnLengthSmallerThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int, ck2 int, v text CHECK LENGTH() < 4, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, 'foo')");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'v'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, 'fooo')");
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, 'foooo')");
      }
  
      @Test
      public void testCreateTableWithColumnWithRegularColumnLengthSmallerOrEqualThanConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int, ck2 int, v text CHECK LENGTH() <= 4, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, 'foo')");
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, 'fooo')");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'v'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, 'foooo')");
      }
  
      @Test
      public void testCreateTableWithColumnWithRegularColumnLengthCheckNullTextConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int, ck2 int, v text CHECK LENGTH() <= 4, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'v' as it is null.";
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, null)");
      }
  
      @Test
      public void testCreateTableWithColumnWithRegularColumnLengthCheckNullVarcharConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int, ck2 int, v varchar CHECK LENGTH() <= 4, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'v' as it is null.";
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, null)");
      }
  
      @Test
      public void testCreateTableWithColumnWithRegularColumnLengthCheckNullAsciiConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int, ck2 int, v ascii CHECK LENGTH() <= 4, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'v' as it is null.";
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, null)");
      }
  
      @Test
      public void testCreateTableWithColumnWithRegularColumnLengthCheckNullBlobConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck1 int, ck2 int, v blob CHECK LENGTH() <= 4, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'v' as it is null.";
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES (1, 2, 3, null)");
      }
  
      @Test
      public void testCreateTableWithColumnMixedColumnsLengthConstraint() throws Throwable
      {
          createTable("CREATE TABLE %s (pk text CHECK LENGTH() = 4, ck1 int, ck2 int, v text CHECK LENGTH() = 4, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
  
          // Valid
          execute("INSERT INTO %s (pk, ck1, ck2, v) VALUES ('fooo', 2, 3, 'fooo')");
  
          final String expectedErrorMessage = "Column value does not satisfy value constraint for column 'pk'. It has a length of";
          final String expectedErrorMessage2 = "Column value does not satisfy value constraint for column 'v'. It has a length of";
          // Invalid
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES ('foo', 2, 3, 'foo')");
          assertInvalidThrowMessage(expectedErrorMessage2, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES ('fooo', 2, 3, 'foo')");
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES ('foo', 2, 3, 'fooo')");
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES ('foooo', 2, 3, 'fooo')");
          assertInvalidThrowMessage(expectedErrorMessage2, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES ('fooo', 2, 3, 'foooo')");
          assertInvalidThrowMessage(expectedErrorMessage, InvalidRequestException.class, "INSERT INTO %s (pk, ck1, ck2, v) VALUES ('foooo', 2, 3, 'foooo')");
      }
  
      @Test
      public void testCreateTableWithWrongColumnConstraint() throws Throwable
      {
          try
          {
              createTable("CREATE TABLE %s (pk text, ck1 int CHECK LENGTH() = 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
              fail();
          }
          catch (InvalidRequestException e)
          {
              assertTrue(e.getCause() instanceof InvalidRequestException);
              assertTrue(e.getMessage().contains("Error setting schema for test"));
          }
      }
  
      @Test
      public void testCreateTableWithWrongColumnMultipleConstraint() throws Throwable
      {
          try
          {
              createTable("CREATE TABLE %s (pk text, ck1 int CHECK LENGTH() = 4 AND ck1 < 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
              fail();
          }
          catch (InvalidRequestException e)
          {
              assertTrue(e.getCause() instanceof InvalidRequestException);
              assertTrue(e.getMessage().contains("Error setting schema for test"));
          }
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnInvalidTypeConstraint() throws Throwable
      {
          try
          {
              createTable("CREATE TABLE %s (pk int, ck1 int CHECK LENGTH() = 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
              fail();
          }
          catch (InvalidRequestException e)
          {
              assertTrue(e.getCause() instanceof InvalidRequestException);
              assertTrue(e.getMessage().contains("Error setting schema for test"));
          }
      }
  
      @Test
      public void testCreateTableWithColumnWithClusteringColumnInvalidScalarTypeConstraint() throws Throwable
      {
          try
          {
              createTable("CREATE TABLE %s (pk text CHECK pk = 4, ck1 int, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
              fail();
          }
          catch (InvalidRequestException e)
          {
              assertTrue(e.getCause() instanceof InvalidRequestException);
              assertTrue(e.getCause().getMessage().contains("can be used only for columns of type"));
              assertTrue(e.getMessage().contains("Error setting schema for test"));
          }
      }
  
      @Test
      public void testCreateTableInvalidFunction() throws Throwable
      {
          try
          {
              createTable("CREATE TABLE %s (pk text CHECK not_a_function() = 4, ck1 int, ck2 int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");");
              fail();
          }
          catch (InvalidRequestException e)
          {
              assertTrue(e.getCause() instanceof InvalidRequestException);
              assertTrue(e.getMessage().contains("Error setting schema for test"));
          }
      }
  
      @Test
      public void testCreateTableWithPKConstraintsAndCDCEnabled() throws Throwable
      {
          // It works
          createTable("CREATE TABLE %s (pk text CHECK length() = 4, ck1 int, ck2 int, PRIMARY KEY ((pk), ck1, ck2)) WITH cdc = true;");
      }
  
      @Test
      public void testCreateTableWithClusteringConstraintsAndCDCEnabled() throws Throwable
      {
          // It works
          createTable("CREATE TABLE %s (pk text, ck1 int CHECK ck1 < 100, ck2 int, PRIMARY KEY ((pk), ck1, ck2)) WITH cdc = true;");
      }
  
      @Test
      public void testCreateTableWithRegularConstraintsAndCDCEnabled() throws Throwable
      {
          // It works
          createTable("CREATE TABLE %s (pk text, ck1 int CHECK ck1 < 100, ck2 int, PRIMARY KEY (pk)) WITH cdc = true;");
      }
  
      // Copy table with like
      @Test
      public void testCreateTableWithColumnWithClusteringColumnLessThanScalarConstraintIntegerOnLikeTable() throws Throwable
      {
          createTable(KEYSPACE, "CREATE TABLE %s (pk int, ck1 int CHECK ck1 < 4, ck2 int, v int, PRIMARY KEY ((pk),ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 " + order + ");", "liketabletame");
  
          execute("create table " + KEYSPACE + ".tb_copy like %s");
  
          // Valid
          qt().forAll(Generators.toGen(integers().between(0, 3)))
              .check(d -> execute("INSERT INTO " + KEYSPACE + ".tb_copy (pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)"));
  
          // Invalid
          qt().forAll(Generators.toGen(integers().between(4, 100)))
              .check(d -> {
                  try
                  {
                      assertInvalidThrow(InvalidRequestException.class, "INSERT INTO " + KEYSPACE + ".tb_copy(pk, ck1, ck2, v) VALUES (1, " + d + ", 3, 4)");
                  }
                  catch (Throwable e)
                  {
                      throw new RuntimeException(e);
                  }
              });
      }
  
      @Test
      public void testCreateTableAddConstraintWithCheckOnNonExistingColumn() throws Throwable
      {
          assertThatThrownBy(() -> createTable("CREATE TABLE %s (pk int, ck1 int CHECK ck3 > 5, ck2 text, v int, PRIMARY KEY ((pk),ck1, ck2));"))
          .hasRootCauseMessage("Constraint ck3 > 5 was not specified on a column it operates on: ck1 but on: ck3")
          .rootCause().isInstanceOf(InvalidConstraintDefinitionException.class);
      }
  }
  