/*
 * 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 com.datastax.driver.core.schemabuilder;

import static com.datastax.driver.core.schemabuilder.SchemaBuilder.Caching;
import static com.datastax.driver.core.schemabuilder.SchemaBuilder.Direction;
import static com.datastax.driver.core.schemabuilder.SchemaBuilder.KeyCaching;
import static com.datastax.driver.core.schemabuilder.SchemaBuilder.allRows;
import static com.datastax.driver.core.schemabuilder.SchemaBuilder.always;
import static com.datastax.driver.core.schemabuilder.SchemaBuilder.createTable;
import static com.datastax.driver.core.schemabuilder.SchemaBuilder.frozen;
import static com.datastax.driver.core.schemabuilder.SchemaBuilder.leveledStrategy;
import static com.datastax.driver.core.schemabuilder.SchemaBuilder.lz4;
import static com.datastax.driver.core.schemabuilder.SchemaBuilder.millisecs;
import static com.datastax.driver.core.schemabuilder.SchemaBuilder.noSpeculativeRetry;
import static com.datastax.driver.core.schemabuilder.SchemaBuilder.percentile;
import static com.datastax.driver.core.schemabuilder.SchemaBuilder.rows;
import static org.assertj.core.api.Assertions.assertThat;

import com.datastax.driver.core.DataType;
import org.testng.annotations.Test;

/** Note: some addColumn variants are covered in {@link CreateTypeTest}. */
public class CreateTest {

  @Test(groups = "unit")
  public void should_create_simple_table() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id", DataType.bigint())
            .addColumn("name", DataType.text());

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id bigint,\n\t\t"
                + "name text,\n\t\t"
                + "PRIMARY KEY(id))");
  }

  @Test(groups = "unit")
  public void should_create_table_with_udt_partition_key() throws Exception {
    // When
    SchemaStatement statement = createTable("test").addUDTPartitionKey("u", frozen("user"));

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo("\n\tCREATE TABLE test(\n\t\t" + "u frozen<user>,\n\t\t" + "PRIMARY KEY(u))");
  }

  @Test(groups = "unit", expectedExceptions = IllegalStateException.class)
  public void should_fail_when_creating_table_without_partition_key() throws Exception {
    createTable("test").addColumn("name", DataType.text()).getQueryString();
  }

  @Test(groups = "unit")
  public void should_create_simple_table_if_not_exists() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .ifNotExists()
            .addPartitionKey("id", DataType.bigint())
            .addColumn("name", DataType.text());
    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE IF NOT EXISTS test(\n\t\t"
                + "id bigint,\n\t\t"
                + "name text,\n\t\t"
                + "PRIMARY KEY(id))");
  }

  @Test(groups = "unit")
  public void should_create_simple_table_with_keyspace() throws Exception {
    // When
    SchemaStatement statement =
        createTable("ks", "test")
            .addPartitionKey("id", DataType.bigint())
            .addColumn("name", DataType.text());
    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE ks.test(\n\t\t"
                + "id bigint,\n\t\t"
                + "name text,\n\t\t"
                + "PRIMARY KEY(id))");
  }

  @Test(groups = "unit")
  public void should_create_simple_table_with_list() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id", DataType.bigint())
            .addColumn("friends", DataType.list(DataType.text()));

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id bigint,\n\t\t"
                + "friends list<text>,\n\t\t"
                + "PRIMARY KEY(id))");
  }

  @Test(groups = "unit")
  public void should_create_simple_table_with_set() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id", DataType.bigint())
            .addColumn("friends", DataType.set(DataType.text()));

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id bigint,\n\t\t"
                + "friends set<text>,\n\t\t"
                + "PRIMARY KEY(id))");
  }

  @Test(groups = "unit")
  public void should_create_simple_table_with_map() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id", DataType.bigint())
            .addColumn("friends", DataType.map(DataType.cint(), DataType.text()));

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id bigint,\n\t\t"
                + "friends map<int, text>,\n\t\t"
                + "PRIMARY KEY(id))");
  }

  @Test(groups = "unit")
  public void should_create_table_with_clustering_keys() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id", DataType.bigint())
            .addClusteringColumn("col1", DataType.uuid())
            .addClusteringColumn("col2", DataType.uuid())
            .addColumn("name", DataType.text());

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id bigint,\n\t\t"
                + "col1 uuid,\n\t\t"
                + "col2 uuid,\n\t\t"
                + "name text,\n\t\t"
                + "PRIMARY KEY(id, col1, col2))");
  }

  @Test(groups = "unit")
  public void should_create_table_with_udt_clustering_keys() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id", DataType.bigint())
            .addClusteringColumn("col1", DataType.uuid())
            .addUDTClusteringColumn("col2", frozen("address"))
            .addColumn("name", DataType.text());

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id bigint,\n\t\t"
                + "col1 uuid,\n\t\t"
                + "col2 frozen<address>,\n\t\t"
                + "name text,\n\t\t"
                + "PRIMARY KEY(id, col1, col2))");
  }

  @Test(groups = "unit")
  public void should_create_table_with_composite_partition_key() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id1", DataType.bigint())
            .addPartitionKey("id2", DataType.text())
            .addColumn("name", DataType.text());

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id1 bigint,\n\t\t"
                + "id2 text,\n\t\t"
                + "name text,\n\t\t"
                + "PRIMARY KEY((id1, id2)))");
  }

  @Test(groups = "unit")
  public void should_create_table_with_composite_partition_key_and_clustering_keys()
      throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id1", DataType.bigint())
            .addPartitionKey("id2", DataType.text())
            .addClusteringColumn("col1", DataType.uuid())
            .addClusteringColumn("col2", DataType.uuid())
            .addColumn("name", DataType.text());

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id1 bigint,\n\t\t"
                + "id2 text,\n\t\t"
                + "col1 uuid,\n\t\t"
                + "col2 uuid,\n\t\t"
                + "name text,\n\t\t"
                + "PRIMARY KEY((id1, id2), col1, col2))");
  }

  @Test(groups = "unit")
  public void should_create_table_with_static_column() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id", DataType.bigint())
            .addClusteringColumn("col", DataType.uuid())
            .addStaticColumn("bucket", DataType.cint())
            .addColumn("name", DataType.text());

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id bigint,\n\t\t"
                + "col uuid,\n\t\t"
                + "bucket int static,\n\t\t"
                + "name text,\n\t\t"
                + "PRIMARY KEY(id, col))");
  }

  @Test(groups = "unit")
  public void should_create_table_with_udt_static_column() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id", DataType.bigint())
            .addClusteringColumn("col", DataType.uuid())
            .addUDTStaticColumn("bucket", frozen("address"))
            .addColumn("name", DataType.text());

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id bigint,\n\t\t"
                + "col uuid,\n\t\t"
                + "bucket frozen<address> static,\n\t\t"
                + "name text,\n\t\t"
                + "PRIMARY KEY(id, col))");
  }

  @Test(groups = "unit")
  public void should_create_table_with_clustering_order() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id", DataType.bigint())
            .addClusteringColumn("col1", DataType.uuid())
            .addClusteringColumn("col2", DataType.uuid())
            .addColumn("name", DataType.text())
            .withOptions()
            .clusteringOrder("col1", Direction.ASC)
            .clusteringOrder("col2", Direction.DESC);

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id bigint,\n\t\t"
                + "col1 uuid,\n\t\t"
                + "col2 uuid,\n\t\t"
                + "name text,\n\t\t"
                + "PRIMARY KEY(id, col1, col2))\n\t"
                + "WITH CLUSTERING ORDER BY(col1 ASC, col2 DESC)");
  }

  @Test(groups = "unit", expectedExceptions = IllegalArgumentException.class)
  public void should_fail_when_blank_clustering_order_column_provided() throws Exception {
    createTable("test")
        .addPartitionKey("id", DataType.bigint())
        .addClusteringColumn("col1", DataType.uuid())
        .addClusteringColumn("col2", DataType.uuid())
        .addColumn("name", DataType.text())
        .withOptions()
        .clusteringOrder("", Direction.DESC);
  }

  @Test(groups = "unit", expectedExceptions = IllegalArgumentException.class)
  public void should_fail_when_clustering_order_column_does_not_match_declared_clustering_keys()
      throws Exception {
    createTable("test")
        .addPartitionKey("id", DataType.bigint())
        .addClusteringColumn("col1", DataType.uuid())
        .addClusteringColumn("col2", DataType.uuid())
        .addColumn("name", DataType.text())
        .withOptions()
        .clusteringOrder("col3", Direction.ASC);
  }

  @Test(groups = "unit")
  public void should_create_table_with_compact_storage() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id", DataType.bigint())
            .addClusteringColumn("col1", DataType.uuid())
            .addClusteringColumn("col2", DataType.uuid())
            .addColumn("name", DataType.text())
            .withOptions()
            .compactStorage();

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id bigint,\n\t\t"
                + "col1 uuid,\n\t\t"
                + "col2 uuid,\n\t\t"
                + "name text,\n\t\t"
                + "PRIMARY KEY(id, col1, col2))\n\t"
                + "WITH COMPACT STORAGE");
  }

  @Test(groups = "unit")
  public void should_create_table_with_all_options() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id", DataType.bigint())
            .addClusteringColumn("col1", DataType.uuid())
            .addClusteringColumn("col2", DataType.uuid())
            .addColumn("name", DataType.text())
            .withOptions()
            .clusteringOrder("col1", Direction.ASC)
            .clusteringOrder("col2", Direction.DESC)
            .compactStorage()
            .bloomFilterFPChance(0.01)
            .caching(Caching.ROWS_ONLY)
            .comment("This is a comment")
            .compactionOptions(leveledStrategy().ssTableSizeInMB(160))
            .compressionOptions(lz4())
            .dcLocalReadRepairChance(0.21)
            .defaultTimeToLive(100)
            .gcGraceSeconds(9999)
            .minIndexInterval(64)
            .maxIndexInterval(512)
            .memtableFlushPeriodInMillis(12)
            .populateIOCacheOnFlush(true)
            .readRepairChance(0.05)
            .replicateOnWrite(true)
            .speculativeRetry(always())
            .cdc(true);

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id bigint,\n\t\t"
                + "col1 uuid,\n\t\t"
                + "col2 uuid,\n\t\t"
                + "name text,\n\t\tPRIMARY KEY(id, col1, col2))\n\t"
                + "WITH caching = 'rows_only' "
                + "AND bloom_filter_fp_chance = 0.01 "
                + "AND comment = 'This is a comment' "
                + "AND compression = {'sstable_compression' : 'LZ4Compressor'} "
                + "AND compaction = {'class' : 'LeveledCompactionStrategy', 'sstable_size_in_mb' : 160} "
                + "AND dclocal_read_repair_chance = 0.21 "
                + "AND default_time_to_live = 100 "
                + "AND gc_grace_seconds = 9999 "
                + "AND min_index_interval = 64 "
                + "AND max_index_interval = 512 "
                + "AND memtable_flush_period_in_ms = 12 "
                + "AND populate_io_cache_on_flush = true "
                + "AND read_repair_chance = 0.05 "
                + "AND replicate_on_write = true "
                + "AND speculative_retry = 'ALWAYS' "
                + "AND cdc = true AND CLUSTERING ORDER BY(col1 ASC, col2 DESC) AND COMPACT STORAGE");
  }

  @Test(groups = "unit")
  public void should_build_table_with_new_caching_options() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id", DataType.bigint())
            .addColumn("name", DataType.text())
            .withOptions()
            .caching(KeyCaching.ALL, rows(100));

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id bigint,\n\t\t"
                + "name text,\n\t\tPRIMARY KEY(id))\n\t"
                + "WITH caching = {'keys' : 'all', 'rows_per_partition' : 100}");

    // When
    statement =
        createTable("test")
            .addPartitionKey("id", DataType.bigint())
            .addColumn("name", DataType.text())
            .withOptions()
            .caching(KeyCaching.ALL, allRows());

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id bigint,\n\t\t"
                + "name text,\n\t\tPRIMARY KEY(id))\n\t"
                + "WITH caching = {'keys' : 'all', 'rows_per_partition' : 'all'}");
  }

  @Test(groups = "unit")
  public void should_build_table_with_custom_option() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id", DataType.bigint())
            .addColumn("name", DataType.text())
            .withOptions()
            .freeformOption("key1", "value1")
            .freeformOption("key2", 1.0);

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id bigint,\n\t\t"
                + "name text,\n\t\tPRIMARY KEY(id))\n\t"
                + "WITH key1 = 'value1' "
                + "AND key2 = 1.0");
  }

  @Test(groups = "unit", expectedExceptions = IllegalStateException.class)
  public void should_fail_when_both_caching_versions() throws Exception {
    createTable("test")
        .addPartitionKey("id", DataType.bigint())
        .addColumn("name", DataType.text())
        .withOptions()
        .caching(Caching.KEYS_ONLY)
        .caching(KeyCaching.ALL, allRows())
        .getQueryString();
  }

  @Test(groups = "unit", expectedExceptions = IllegalArgumentException.class)
  public void should_fail_when_negative_rows_per_partition() throws Exception {
    createTable("test")
        .addPartitionKey("id", DataType.bigint())
        .addColumn("name", DataType.text())
        .withOptions()
        .caching(KeyCaching.ALL, rows(-3));
  }

  @Test(groups = "unit", expectedExceptions = IllegalArgumentException.class)
  public void should_fail_when_read_repair_chance_out_of_bound() throws Exception {
    createTable("test")
        .addPartitionKey("id", DataType.bigint())
        .addColumn("name", DataType.text())
        .withOptions()
        .readRepairChance(1.3);
  }

  @Test(groups = "unit", expectedExceptions = IllegalArgumentException.class)
  public void should_fail_when_read_repair_chance_negative() throws Exception {
    createTable("test")
        .addPartitionKey("id", DataType.bigint())
        .addColumn("name", DataType.text())
        .withOptions()
        .readRepairChance(-1.3);
  }

  @Test(groups = "unit")
  public void should_create_table_with_speculative_retry_none() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id", DataType.bigint())
            .addColumn("name", DataType.text())
            .withOptions()
            .speculativeRetry(noSpeculativeRetry());

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id bigint,\n\t\t"
                + "name text,\n\t\t"
                + "PRIMARY KEY(id))\n\t"
                + "WITH speculative_retry = 'NONE'");
  }

  @Test(groups = "unit")
  public void should_create_table_with_speculative_retry_in_percentile() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id", DataType.bigint())
            .addColumn("name", DataType.text())
            .withOptions()
            .speculativeRetry(percentile(95));

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id bigint,\n\t\t"
                + "name text,\n\t\t"
                + "PRIMARY KEY(id))\n\t"
                + "WITH speculative_retry = '95percentile'");
  }

  @Test(groups = "unit")
  public void should_create_table_with_speculative_retry_in_milli_secs() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id", DataType.bigint())
            .addColumn("name", DataType.text())
            .withOptions()
            .speculativeRetry(millisecs(12));

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id bigint,\n\t\t"
                + "name text,\n\t\t"
                + "PRIMARY KEY(id))\n\t"
                + "WITH speculative_retry = '12ms'");
  }

  @Test(groups = "unit")
  public void should_create_table_with_cdc_true() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id", DataType.bigint())
            .addColumn("name", DataType.text())
            .withOptions()
            .cdc(true);

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id bigint,\n\t\t"
                + "name text,\n\t\t"
                + "PRIMARY KEY(id))\n\t"
                + "WITH cdc = true");
  }

  @Test(groups = "unit")
  public void should_create_table_with_cdc_false() throws Exception {
    // When
    SchemaStatement statement =
        createTable("test")
            .addPartitionKey("id", DataType.bigint())
            .addColumn("name", DataType.text())
            .withOptions()
            .cdc(false);

    // Then
    assertThat(statement.getQueryString())
        .isEqualTo(
            "\n\tCREATE TABLE test(\n\t\t"
                + "id bigint,\n\t\t"
                + "name text,\n\t\t"
                + "PRIMARY KEY(id))\n\t"
                + "WITH cdc = false");
  }

  @Test(
      groups = "unit",
      expectedExceptions = IllegalStateException.class,
      expectedExceptionsMessageRegExp =
          "The '\\[pk\\]' columns can not be declared as partition keys and clustering keys at the same time")
  public void should_fail_if_same_partition_and_clustering_column() throws Exception {
    createTable("test")
        .addPartitionKey("pk", DataType.bigint())
        .addClusteringColumn("pk", DataType.bigint())
        .getQueryString();
  }

  @Test(
      groups = "unit",
      expectedExceptions = IllegalStateException.class,
      expectedExceptionsMessageRegExp =
          "The '\\[pk\\]' columns can not be declared as partition keys and simple columns at the same time")
  public void should_fail_if_same_partition_and_simple_column() throws Exception {
    createTable("test")
        .addPartitionKey("pk", DataType.bigint())
        .addColumn("pk", DataType.text())
        .getQueryString();
  }

  @Test(
      groups = "unit",
      expectedExceptions = IllegalStateException.class,
      expectedExceptionsMessageRegExp =
          "The '\\[cluster\\]' columns can not be declared as clustering keys and simple columns at the same time")
  public void should_fail_if_same_clustering_and_simple_column() throws Exception {
    createTable("test")
        .addPartitionKey("pk", DataType.bigint())
        .addClusteringColumn("cluster", DataType.bigint())
        .addColumn("cluster", DataType.text())
        .getQueryString();
  }

  @Test(
      groups = "unit",
      expectedExceptions = IllegalStateException.class,
      expectedExceptionsMessageRegExp =
          "The '\\[pk\\]' columns can not be declared as partition keys and static columns at the same time")
  public void should_fail_if_same_partition_and_static_column() throws Exception {
    createTable("test")
        .addPartitionKey("pk", DataType.bigint())
        .addStaticColumn("pk", DataType.text())
        .getQueryString();
  }

  @Test(
      groups = "unit",
      expectedExceptions = IllegalStateException.class,
      expectedExceptionsMessageRegExp =
          "The '\\[cluster\\]' columns can not be declared as clustering keys and static columns at the same time")
  public void should_fail_if_same_clustering_and_static_column() throws Exception {
    createTable("test")
        .addPartitionKey("pk", DataType.bigint())
        .addClusteringColumn("cluster", DataType.bigint())
        .addStaticColumn("cluster", DataType.text())
        .getQueryString();
  }

  @Test(
      groups = "unit",
      expectedExceptions = IllegalStateException.class,
      expectedExceptionsMessageRegExp =
          "The '\\[col\\]' columns can not be declared as simple columns and static columns at the same time")
  public void should_fail_if_same_simple_and_static_column() throws Exception {
    createTable("test")
        .addPartitionKey("pk", DataType.bigint())
        .addClusteringColumn("cluster", DataType.uuid())
        .addColumn("col", DataType.bigint())
        .addStaticColumn("col", DataType.text())
        .getQueryString();
  }

  @Test(
      groups = "unit",
      expectedExceptions = IllegalStateException.class,
      expectedExceptionsMessageRegExp =
          "The table 'test' cannot declare static columns '\\[stat\\]' without clustering columns")
  public void should_fail_if_static_column_in_non_clustered_table() throws Exception {
    createTable("test")
        .addPartitionKey("pk", DataType.bigint())
        .addStaticColumn("stat", DataType.text())
        .getQueryString();
  }

  @Test(
      groups = "unit",
      expectedExceptions = IllegalArgumentException.class,
      expectedExceptionsMessageRegExp =
          "The keyspace name 'ADD' is not allowed because it is a reserved keyword")
  public void should_fail_if_keyspace_name_is_a_reserved_keyword() throws Exception {
    createTable("ADD", "test")
        .addPartitionKey("pk", DataType.bigint())
        .addColumn("col", DataType.text())
        .getQueryString();
  }

  @Test(
      groups = "unit",
      expectedExceptions = IllegalArgumentException.class,
      expectedExceptionsMessageRegExp =
          "The table name 'ADD' is not allowed because it is a reserved keyword")
  public void should_fail_if_table_name_is_a_reserved_keyword() throws Exception {
    createTable("ADD")
        .addPartitionKey("pk", DataType.bigint())
        .addColumn("col", DataType.text())
        .getQueryString();
  }

  @Test(
      groups = "unit",
      expectedExceptions = IllegalArgumentException.class,
      expectedExceptionsMessageRegExp =
          "The partition key name 'ADD' is not allowed because it is a reserved keyword")
  public void should_fail_if_partition_key_is_a_reserved_keyword() throws Exception {
    createTable("test")
        .addPartitionKey("ADD", DataType.bigint())
        .addColumn("col", DataType.text())
        .getQueryString();
  }

  @Test(
      groups = "unit",
      expectedExceptions = IllegalArgumentException.class,
      expectedExceptionsMessageRegExp =
          "The clustering column name 'ADD' is not allowed because it is a reserved keyword")
  public void should_fail_if_clustering_key_is_a_reserved_keyword() throws Exception {
    createTable("test")
        .addPartitionKey("pk", DataType.bigint())
        .addClusteringColumn("ADD", DataType.uuid())
        .addColumn("col", DataType.text())
        .getQueryString();
  }

  @Test(
      groups = "unit",
      expectedExceptions = IllegalArgumentException.class,
      expectedExceptionsMessageRegExp =
          "The column name 'ADD' is not allowed because it is a reserved keyword")
  public void should_fail_if_simple_column_is_a_reserved_keyword() throws Exception {
    createTable("test")
        .addPartitionKey("pk", DataType.bigint())
        .addClusteringColumn("cluster", DataType.uuid())
        .addColumn("ADD", DataType.text())
        .getQueryString();
  }

  @Test(
      groups = "unit",
      expectedExceptions = IllegalArgumentException.class,
      expectedExceptionsMessageRegExp =
          "The static column name 'ADD' is not allowed because it is a reserved keyword")
  public void should_fail_if_static_column_is_a_reserved_keyword() throws Exception {
    createTable("test")
        .addPartitionKey("pk", DataType.bigint())
        .addClusteringColumn("cluster", DataType.uuid())
        .addStaticColumn("ADD", DataType.text())
        .addColumn("col", DataType.text())
        .getQueryString();
  }

  @Test(
      groups = "unit",
      expectedExceptions = IllegalStateException.class,
      expectedExceptionsMessageRegExp =
          "Cannot create table 'test' with compact storage and static columns '\\[stat\\]'")
  public void should_fail_creating_table_with_static_columns_and_compact_storage()
      throws Exception {
    createTable("test")
        .addPartitionKey("pk", DataType.bigint())
        .addClusteringColumn("cluster", DataType.uuid())
        .addStaticColumn("stat", DataType.text())
        .withOptions()
        .compactStorage()
        .getQueryString();
  }
}
