lib/cequel/schema/column.rb
# -*- encoding : utf-8 -*-
module Cequel
module Schema
#
# Represents a column definition in a table schema.
#
# @abstract
#
class Column
# @return [Symbol] the name of the column
attr_reader :name
# @return [Type] the type of the column
attr_reader :type
#
# @param name [Symbol] the name of the column
# @param type [Type] the type of the column
#
def initialize(name, type)
@name, @type = name, type
end
# rubocop:disable LineLength
#
# @return [Boolean] true if this is a key column
#
# @see
# http://cassandra.apache.org/doc/cql3/CQL.html#createTablepartitionClustering
# CQL3 key documentation
#
def key?
partition_key? || clustering_column?
end
#
# @return [Boolean] true if this is a partition key column
#
# @see
# http://cassandra.apache.org/doc/cql3/CQL.html#createTablepartitionClustering
# CQL3 key documentation
#
def partition_key?
false
end
#
# @return [Boolean] true if this is a clustering column
#
# @see
# http://cassandra.apache.org/doc/cql3/CQL.html#createTablepartitionClustering
# CQL3 key documentation
#
def clustering_column?
false
end
# rubocop:enable LineLength
#
# @return [Boolean] true if this is a data column
#
def data_column?
!key?
end
#
# @return [Boolean] true if this is a collection column
#
def collection_column?
false
end
# Indicates if this column is indexed. Overridden by subclasses that
# support indexing.
#
# @return [Boolean] true if this column has a secondary index
#
def indexed?
false
end
#
# @param type_in [Symbol,Type] type to check against
# @return [Boolean] true if this column has the type given by `type_in`
#
def type?(type_in)
type == Type[type_in]
end
#
# @param value the value to cast
# @return the value cast to the appropriate type for this column
#
# @api private
#
def cast(value)
@type.cast(value)
end
#
# @return [String] a CQL fragment representing this column in a table
# definition
#
# @api private
#
def to_cql
%Q|"#{@name}" #{@type}|
end
#
# @param other [Column] a column object
# @return [Boolean] true if this column has the same CQL representation
# as `other` column
#
def ==(other)
to_cql == other.to_cql
end
alias_method :eql?, :==
#
# @return [String] the column's name
#
def to_s
name.to_s
end
#
# @return [String] human-readable representation of this column
#
def inspect
%Q(#<#{self.class.name}: #{to_cql}>)
end
end
#
# A partition key column
#
class PartitionKey < Column
#
# (see Column#partition_key?)
#
def partition_key?
true
end
end
#
# A clustering column
#
class ClusteringColumn < Column
#
# @return [:asc,:desc] whether rows are ordered by ascending or
# descending values in this column
#
attr_reader :clustering_order
#
# @param (see Column#initialize)
# @param clustering_order [:asc,:desc] ascending or descending order for
# this column
#
def initialize(name, type, clustering_order = nil)
super(name, type)
@clustering_order = (clustering_order || :asc).to_sym
end
#
# (see Column#clustering_column?)
#
def clustering_column?
true
end
# @private
def clustering_order_cql
"#{@name} #{@clustering_order}"
end
end
#
# A scalar data column
#
class DataColumn < Column
#
# @return [Symbol] name of the secondary index applied to this column, if
# any
#
attr_reader :index_name
#
# @param (see Column#initialize)
# @param index_name [Symbol] name this column's secondary index
#
def initialize(name, type, index_name = nil)
super(name, type)
@index_name = index_name
end
#
# @return [Boolean] true if this column has a secondary index
#
def indexed?
!!@index_name
end
end
#
# A collection column (list, set, or map)
#
# @abstract
#
class CollectionColumn < Column
# (see Column#collection_column?)
def collection_column?
true
end
# (see DataColumn#indexed?)
def indexed?
false
end
end
#
# A List column
#
# @see http://cassandra.apache.org/doc/cql3/CQL.html#list
# CQL documentation for the list type
#
class List < CollectionColumn
# (see Column#to_cql)
def to_cql
"#{@name} LIST <#{@type}>"
end
#
# @return [Array] array with elements cast to correct type for column
#
def cast(value)
value.map { |element| @type.cast(element) }
end
end
#
# A Set column
#
# @see http://cassandra.apache.org/doc/cql3/CQL.html#set
# CQL documentation for set columns
#
class Set < CollectionColumn
# (see Column#to_cql)
def to_cql
"#{@name} SET <#{@type}>"
end
#
# @param (see Column#cast)
# @return [::Set] set with elements cast to correct type for column
#
def cast(value)
value.to_set { |element| @type.cast(element) }
end
end
#
# A Map column
#
# @see
# http://cassandra.apache.org/doc/cql3/CQL.html#map
# CQL documentation for map columns
#
class Map < CollectionColumn
# @return [Type] the type of keys in this map
attr_reader :key_type
alias_method :value_type, :type
#
# @param name [Symbol] name of this column
# @param key_type [Type] type of the keys in the map
# @param value_type [Type] type of the values in the map
#
def initialize(name, key_type, value_type)
super(name, value_type)
@key_type = key_type
end
# (see Column#to_cql)
def to_cql
"#{@name} MAP <#{@key_type}, #{@type}>"
end
#
# @param (see Column#cast)
# @return [Hash] hash with keys and values cast to correct type for
# column
#
def cast(value)
value.each_with_object({}) do |(key, element), hash|
hash[@key_type.cast(key)] = @type.cast(element)
end
end
end
end
end