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

com.datastax.driver.core.AbstractTableMetadata Maven / Gradle / Ivy

Go to download

A driver for DataStax Enterprise (DSE) and Apache Cassandra 1.2+ clusters that works exclusively with the Cassandra Query Language version 3 (CQL3) and Cassandra's binary protocol, supporting DSE-specific features such as geospatial types, DSE Graph and DSE authentication.

There is a newer version: 2.4.0
Show newest version
/*
 * Copyright DataStax, Inc.
 *
 * This software can be used solely with DataStax Enterprise. Please consult the license at
 * http://www.datastax.com/terms/datastax-dse-driver-license-terms
 */
package com.datastax.driver.core;

import com.datastax.driver.core.utils.Bytes;
import com.google.common.base.Charsets;
import com.google.common.base.Predicate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/** Base class for Tables and Materialized Views metadata. */
public abstract class AbstractTableMetadata {

  static final Comparator columnMetadataComparator =
      new Comparator() {
        @Override
        public int compare(ColumnMetadata c1, ColumnMetadata c2) {
          return c1.getName().compareTo(c2.getName());
        }
      };

  // comparator for ordering tables and views by name.
  static final Comparator byNameComparator =
      new Comparator() {
        @Override
        public int compare(AbstractTableMetadata o1, AbstractTableMetadata o2) {
          return o1.getName().compareTo(o2.getName());
        }
      };

  static final Predicate isAscending =
      new Predicate() {
        @Override
        public boolean apply(ClusteringOrder o) {
          return o == ClusteringOrder.ASC;
        }
      };

  private static final String DSE_RLACA = "DSE_RLACA";

  protected final KeyspaceMetadata keyspace;
  protected final String name;
  protected final UUID id;
  protected final List partitionKey;
  protected final List clusteringColumns;
  protected final Map columns;
  protected final TableOptionsMetadata options;
  protected final List clusteringOrder;
  protected final VersionNumber cassandraVersion;

  protected AbstractTableMetadata(
      KeyspaceMetadata keyspace,
      String name,
      UUID id,
      List partitionKey,
      List clusteringColumns,
      Map columns,
      TableOptionsMetadata options,
      List clusteringOrder,
      VersionNumber cassandraVersion) {
    this.keyspace = keyspace;
    this.name = name;
    this.id = id;
    this.partitionKey = partitionKey;
    this.clusteringColumns = clusteringColumns;
    this.columns = columns;
    this.options = options;
    this.clusteringOrder = clusteringOrder;
    this.cassandraVersion = cassandraVersion;
  }

  /**
   * Returns the name of this table.
   *
   * @return the name of this CQL table.
   */
  public String getName() {
    return name;
  }

  /**
   * Returns the unique id of this table.
   *
   * 

Note: this id is available in Cassandra 2.1 and above. It will be {@code null} for earlier * versions. * * @return the unique id of the table. */ public UUID getId() { return id; } /** * Returns the keyspace this table belong to. * * @return the keyspace metadata of the keyspace this table belong to. */ public KeyspaceMetadata getKeyspace() { return keyspace; } /** * Returns metadata on a column of this table. * * @param name the name of the column to retrieve ({@code name} will be interpreted as a * case-insensitive identifier unless enclosed in double-quotes, see {@link Metadata#quote}). * @return the metadata for the column if it exists, or {@code null} otherwise. */ public ColumnMetadata getColumn(String name) { return columns.get(Metadata.handleId(name)); } /** * Returns a list containing all the columns of this table. * *

The order of the columns in the list is consistent with the order of the columns returned by * a {@code SELECT * FROM thisTable}: the first column is the partition key, next are the * clustering columns in their defined order, and then the rest of the columns follow in * alphabetic order. * * @return a list containing the metadata for the columns of this table. */ public List getColumns() { return new ArrayList(columns.values()); } /** * Returns the list of columns composing the primary key for this table. * *

A table will always at least have a partition key (that may itself be one or more columns), * so the returned list at least has one element. * * @return the list of columns composing the primary key for this table. */ public List getPrimaryKey() { List pk = new ArrayList(partitionKey.size() + clusteringColumns.size()); pk.addAll(partitionKey); pk.addAll(clusteringColumns); return pk; } /** * Returns the list of columns composing the partition key for this table. * *

A table always has a partition key so the returned list has at least one element. * * @return the list of columns composing the partition key for this table. */ public List getPartitionKey() { return Collections.unmodifiableList(partitionKey); } /** * Returns the list of clustering columns for this table. * * @return the list of clustering columns for this table. If there is no clustering columns, an * empty list is returned. */ public List getClusteringColumns() { return Collections.unmodifiableList(clusteringColumns); } /** * Returns the clustering order for this table. * *

The returned contains the clustering order of each clustering column. The {@code i}th * element of the result correspond to the order (ascending or descending) of the {@code i}th * clustering column (see {@link #getClusteringColumns}). Note that a table defined without any * particular clustering order is equivalent to one for which all the clustering keys are in * ascending order. * * @return a list with the clustering order for each clustering column. */ public List getClusteringOrder() { return clusteringOrder; } /** * Returns the options for this table. * *

This value will be null for virtual tables. * * @return the options for this table. */ public TableOptionsMetadata getOptions() { return options; } /** * Returns whether or not this table is a virtual table * * @return {@code true} if virtual keyspace, {@code false} otherwise. */ public boolean isVirtual() { return getKeyspace().isVirtual(); } void add(ColumnMetadata column) { columns.put(column.getName(), column); } /** * Returns a {@code String} containing CQL statements representing this table or materialized view * and all of its derived resources, such as secondary indexes or – in the case of a table – its * own materialized views. * *

In other words, this method returns the statements that would allow you to recreate the * complete schema of this table or view, along with the secondary indexes and materialized views * defined on it, if any. * *

Note that the returned String is formatted to be human readable (for some definition of * human readable at least). * * @return the CQL statements representing this table or view as a {@code String}. * @see #asCQLQuery */ public String exportAsString() { StringBuilder sb = new StringBuilder(); sb.append(asCQLQuery(true)); maybeAppendRLAC(sb); return sb.toString(); } /** * Returns a single CQL statement representing this table or materialized view. * *

This method returns a single {@code CREATE TABLE} or {@code CREATE MATERIALIZED VIEW} * statement with the options corresponding to this table or view definition. * *

Note that the returned string is a single line; the returned statement is not formatted in * any way. * * @return the {@code CREATE TABLE} or {@code CREATE MATERIALIZED VIEW} statement corresponding to * this table or view. * @see #exportAsString */ public String asCQLQuery() { return asCQLQuery(false); } protected abstract String asCQLQuery(boolean formatted); protected StringBuilder appendOptions(StringBuilder sb, boolean formatted) { // Options if (options == null) { return sb; } sb.append("WITH "); if (options.isCompactStorage()) and(sb.append("COMPACT STORAGE"), formatted); if (!clusteringOrder.isEmpty()) and(appendClusteringOrder(sb), formatted); sb.append("read_repair_chance = ").append(options.getReadRepairChance()); and(sb, formatted) .append("dclocal_read_repair_chance = ") .append(options.getLocalReadRepairChance()); if (cassandraVersion.getMajor() < 2 || (cassandraVersion.getMajor() == 2 && cassandraVersion.getMinor() == 0)) and(sb, formatted).append("replicate_on_write = ").append(options.getReplicateOnWrite()); and(sb, formatted).append("gc_grace_seconds = ").append(options.getGcGraceInSeconds()); and(sb, formatted) .append("bloom_filter_fp_chance = ") .append(options.getBloomFilterFalsePositiveChance()); if (cassandraVersion.getMajor() < 2 || cassandraVersion.getMajor() == 2 && cassandraVersion.getMinor() < 1) and(sb, formatted) .append("caching = '") .append(options.getCaching().get("keys")) .append('\''); else and(sb, formatted).append("caching = ").append(formatOptionMap(options.getCaching())); if (options.getComment() != null) and(sb, formatted) .append("comment = '") .append(options.getComment().replace("'", "''")) .append('\''); and(sb, formatted).append("compaction = ").append(formatOptionMap(options.getCompaction())); and(sb, formatted).append("compression = ").append(formatOptionMap(options.getCompression())); if (cassandraVersion.getMajor() >= 2) { and(sb, formatted).append("default_time_to_live = ").append(options.getDefaultTimeToLive()); and(sb, formatted) .append("speculative_retry = '") .append(options.getSpeculativeRetry()) .append('\''); if (options.getIndexInterval() != null) and(sb, formatted).append("index_interval = ").append(options.getIndexInterval()); } if (cassandraVersion.getMajor() > 2 || (cassandraVersion.getMajor() == 2 && cassandraVersion.getMinor() >= 1)) { and(sb, formatted).append("min_index_interval = ").append(options.getMinIndexInterval()); and(sb, formatted).append("max_index_interval = ").append(options.getMaxIndexInterval()); } if (cassandraVersion.getMajor() > 2) { and(sb, formatted).append("crc_check_chance = ").append(options.getCrcCheckChance()); } if (cassandraVersion.getMajor() > 3 || (cassandraVersion.getMajor() == 3 && cassandraVersion.getMinor() >= 8)) { and(sb, formatted).append("cdc = ").append(options.isCDC()); } if (cassandraVersion.getMajor() > 1) { and(sb, formatted) .append("memtable_flush_period_in_ms = ") .append(options.getMemtableFlushPeriodInMs()); } if (cassandraVersion.getMajor() >= 4 && !options.getNodeSync().isEmpty()) { and(sb, formatted).append("nodesync = ").append(formatOptionMap(options.getNodeSync())); } sb.append(';'); return sb; } @Override public String toString() { if (keyspace.isVirtual()) { return name; } return asCQLQuery(); } private StringBuilder appendClusteringOrder(StringBuilder sb) { sb.append("CLUSTERING ORDER BY ("); for (int i = 0; i < clusteringColumns.size(); i++) { if (i > 0) sb.append(", "); sb.append(Metadata.quoteIfNecessary(clusteringColumns.get(i).getName())) .append(' ') .append(clusteringOrder.get(i)); } return sb.append(')'); } /** * Append a row-level access control (RLAC) statement, if applicable. * *

See JAVA-1335. */ private void maybeAppendRLAC(StringBuilder sb) { if (!isVirtual() && getOptions().getExtensions().containsKey(DSE_RLACA)) { newLine(sb, true); sb.append("RESTRICT ROWS ON ") .append(Metadata.quoteIfNecessary(keyspace.getName())) .append('.') .append(Metadata.quoteIfNecessary(name)) .append(" USING ") .append( new String( Bytes.getArray(getOptions().getExtensions().get(DSE_RLACA)), Charsets.UTF_8)) .append(';'); } } private static String formatOptionMap(Map m) { StringBuilder sb = new StringBuilder(); sb.append("{ "); boolean first = true; for (Map.Entry entry : m.entrySet()) { if (first) first = false; else sb.append(", "); sb.append('\'').append(entry.getKey()).append('\''); sb.append(" : "); try { sb.append(Integer.parseInt(entry.getValue())); } catch (NumberFormatException e) { sb.append('\'').append(entry.getValue()).append('\''); } } sb.append(" }"); return sb.toString(); } private StringBuilder and(StringBuilder sb, boolean formatted) { return spaceOrNewLine(sb, formatted).append("AND "); } static StringBuilder newLine(StringBuilder sb, boolean formatted) { if (formatted) sb.append('\n'); return sb; } static StringBuilder spaceOrNewLine(StringBuilder sb, boolean formatted) { sb.append(formatted ? "\n " : ' '); return sb; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy