All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.scalar.db.schemaloader.TableSchema Maven / Gradle / Ivy

package com.scalar.db.schemaloader;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.scalar.db.api.Scan.Ordering.Order;
import com.scalar.db.api.TableMetadata;
import com.scalar.db.io.DataType;
import com.scalar.db.storage.cassandra.CassandraAdmin;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.concurrent.Immutable;

@SuppressFBWarnings("JCIP_FIELD_ISNT_FINAL_IN_IMMUTABLE_CLASS")
@Immutable
public class TableSchema {

  private static final String COLUMNS = "columns";
  private static final String TRANSACTION = "transaction";
  private static final String PARTITION_KEY = "partition-key";
  private static final String CLUSTERING_KEY = "clustering-key";
  private static final String SECONDARY_INDEX = "secondary-index";
  private static final ImmutableMap DATA_MAP_TYPE =
      ImmutableMap.builder()
          .put("BOOLEAN", DataType.BOOLEAN)
          .put("INT", DataType.INT)
          .put("BIGINT", DataType.BIGINT)
          .put("FLOAT", DataType.FLOAT)
          .put("DOUBLE", DataType.DOUBLE)
          .put("TEXT", DataType.TEXT)
          .put("BLOB", DataType.BLOB)
          .build();
  private static final ImmutableMap ORDER_MAP =
      ImmutableMap.builder().put("ASC", Order.ASC).put("DESC", Order.DESC).build();

  private String namespace;
  private String tableName;
  private TableMetadata tableMetadata;
  private ImmutableMap options;
  private boolean isTransactionTable = true;
  private Set traveledKeys;

  @VisibleForTesting
  TableSchema() {}

  @VisibleForTesting
  TableSchema(Set traveledKeys) {
    this.traveledKeys = traveledKeys;
  }

  public TableSchema(String tableFullName, JsonObject tableDefinition, Map options)
      throws SchemaLoaderException {
    traveledKeys = new HashSet<>();

    String[] fullName = tableFullName.split("\\.", -1);
    if (fullName.length < 2) {
      throw new SchemaLoaderException(
          "Parsing the schema JSON failed. Table full name must contains table name and namespace");
    }
    namespace = fullName[0];
    tableName = fullName[1];
    tableMetadata = buildTableMetadata(tableDefinition);
    this.options = buildOptions(tableDefinition, options);
  }

  protected TableMetadata buildTableMetadata(JsonObject tableDefinition)
      throws SchemaLoaderException {
    TableMetadata.Builder tableBuilder = TableMetadata.newBuilder();

    // Add partition keys
    if (!tableDefinition.keySet().contains(PARTITION_KEY)) {
      throw new SchemaLoaderException(
          "Parsing the schema JSON failed. Table must contains partition key");
    }
    JsonArray partitionKeys = tableDefinition.get(PARTITION_KEY).getAsJsonArray();
    traveledKeys.add(PARTITION_KEY);
    for (JsonElement partitionKey : partitionKeys) {
      tableBuilder.addPartitionKey(partitionKey.getAsString());
    }

    // Add clustering keys
    if (tableDefinition.keySet().contains(CLUSTERING_KEY)) {
      JsonArray clusteringKeys = tableDefinition.get(CLUSTERING_KEY).getAsJsonArray();
      traveledKeys.add(CLUSTERING_KEY);
      for (JsonElement clusteringKeyRaw : clusteringKeys) {
        String clusteringKey;
        String order;
        String[] clusteringKeyFull = clusteringKeyRaw.getAsString().split(" ", -1);
        if (clusteringKeyFull.length < 2) {
          clusteringKey = clusteringKeyFull[0];
          tableBuilder.addClusteringKey(clusteringKey);
        } else if (clusteringKeyFull.length == 2
            && (clusteringKeyFull[1].equalsIgnoreCase("ASC")
                || clusteringKeyFull[1].equalsIgnoreCase("DESC"))) {
          clusteringKey = clusteringKeyFull[0];
          order = clusteringKeyFull[1];
          tableBuilder.addClusteringKey(clusteringKey, ORDER_MAP.get(order.toUpperCase()));
        } else {
          throw new SchemaLoaderException(
              "Parsing the schema JSON failed. Invalid clustering keys");
        }
      }
    }

    if (tableDefinition.keySet().contains(TRANSACTION)) {
      isTransactionTable = tableDefinition.get(TRANSACTION).getAsBoolean();
      traveledKeys.add(TRANSACTION);
    }

    // Add columns
    if (!tableDefinition.keySet().contains(COLUMNS)) {
      throw new SchemaLoaderException(
          "Parsing the schema JSON failed. Table must contains columns");
    }
    JsonObject columns = tableDefinition.get(COLUMNS).getAsJsonObject();
    traveledKeys.add(COLUMNS);
    for (Entry column : columns.entrySet()) {
      String columnName = column.getKey();
      DataType columnDataType = DATA_MAP_TYPE.get(column.getValue().getAsString().toUpperCase());
      if (columnDataType == null) {
        throw new SchemaLoaderException(
            "Parsing the schema JSON failed. Invalid column type for column " + columnName);
      }
      tableBuilder.addColumn(columnName, columnDataType);
    }

    // Add secondary indexes
    if (tableDefinition.keySet().contains(SECONDARY_INDEX)) {
      JsonArray secondaryIndexes = tableDefinition.get(SECONDARY_INDEX).getAsJsonArray();
      traveledKeys.add(SECONDARY_INDEX);
      for (JsonElement sIdx : secondaryIndexes) {
        tableBuilder.addSecondaryIndex(sIdx.getAsString());
      }
    }

    return tableBuilder.build();
  }

  protected ImmutableMap buildOptions(
      JsonObject tableDefinition, Map options) {
    ImmutableMap.Builder builder = ImmutableMap.builder();
    builder.putAll(options);

    for (Map.Entry option : tableDefinition.entrySet()) {
      if (!traveledKeys.contains(option.getKey())) {
        // For backward compatibility
        if (option.getKey().equals("network-strategy")) {
          builder.put(CassandraAdmin.REPLICATION_STRATEGY, option.getValue().getAsString());
        } else {
          builder.put(option.getKey(), option.getValue().getAsString());
        }
      }
    }
    return builder.build();
  }

  public String getNamespace() {
    return namespace;
  }

  public String getTable() {
    return tableName;
  }

  public TableMetadata getTableMetadata() {
    return tableMetadata;
  }

  public Map getOptions() {
    return options;
  }

  public boolean isTransactionTable() {
    return isTransactionTable;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy