class CassandraMigrations::Migration::TableDefinition
Used to define a table in a migration of table creation or to add columns to an existing table.
An instance of this class is passed to the block of the method create_table
, available on every migration.
This class is also internally used in the method add_column
.
Constants
- PASSTHROUGH_TYPES
- PRECISION_MAP
- SPECIAL_OPTIONS_MAP
- TYPES_MAP
Public Class Methods
C* Data Types. See www.datastax.com/documentation/cql/3.0/cql/cql_reference/cql_data_types_c.html
Migration
| CQL Type | Ruby | Description Type | | Class |
string | varchar | String | UTF-8 encoded string text | text | String | UTF-8 encoded string ascii | ascii | String | US-ASCII character string
integer(4) | int | Integer | 32-bit signed integer integer(8) | bigint | Fixnum | 64-bit signed long varint | varint | Bignum | Arbitrary-precision integer
decimal | decimal | BigDecimal | Variable-precision decimal float(4) | float | | 32-bit IEEE-754 floating point double | double | | Float 64-bit IEEE-754 floating point float(8) | double | |
boolean | boolean | TrueClass | true or false
| | FalseClass |
uuid | uuid | Cql::Uuid | A UUID in standard UUID format timeuuid | timeuuid | Cql::TimeUuid | Type 1 UUID only (CQL 3)
inet | inet | IPAddr | IP address string in IPv4 or
| | | IPv6 format*
timestamp | timestamp | Time | Date plus time, encoded as 8
| | | bytes since epoch
datetime | timestamp | |
list | list | Array | A collection of one or more
| | | ordered elements
map | map | Hash | A JSON-style array of literals:
| | | { literal : literal, ... }
set | set | Set | A collection of one or more
| | | elements
binary | blob | | Arbitrary bytes (no validation),
| | | expressed as hexadecimal | counter | | Distributed counter value | | | (64-bit long)
# File lib/cassandra_migrations/migration/table_definition.rb, line 60 def initialize() @columns_name_type_hash = {} @primary_keys = [] @partition_keys = [] end
Public Instance Methods
# File lib/cassandra_migrations/migration/table_definition.rb, line 128 def ascii(column_name, options={}) @columns_name_type_hash[column_name.to_sym] = column_type_for(:ascii, options) define_primary_keys(column_name) if options[:primary_key] end
# File lib/cassandra_migrations/migration/table_definition.rb, line 153 def binary(column_name, options={}) @columns_name_type_hash[column_name.to_sym] = column_type_for(:binary, options) define_primary_keys(column_name) if options[:primary_key] end
# File lib/cassandra_migrations/migration/table_definition.rb, line 92 def boolean(column_name, options={}) @columns_name_type_hash[column_name.to_sym] = column_type_for(:boolean, options) define_primary_keys(column_name) if options[:primary_key] end
# File lib/cassandra_migrations/migration/table_definition.rb, line 158 def counter(column_name, options={}) @columns_name_type_hash[column_name.to_sym] = column_type_for(:counter, options) if options[:primary_key] raise Errors::MigrationDefinitionError, 'Counter columns cannot be primary keys' end end
# File lib/cassandra_migrations/migration/table_definition.rb, line 133 def datetime(column_name, options={}) @columns_name_type_hash[column_name.to_sym] = column_type_for(:datetime, options) define_primary_keys(column_name) if options[:primary_key] end
# File lib/cassandra_migrations/migration/table_definition.rb, line 102 def decimal(column_name, options={}) @columns_name_type_hash[column_name.to_sym] = column_type_for(:decimal, options) define_primary_keys(column_name) if options[:primary_key] end
# File lib/cassandra_migrations/migration/table_definition.rb, line 205 def define_options(hash) @options = hash end
# File lib/cassandra_migrations/migration/table_definition.rb, line 197 def define_partition_keys(*keys) if !@partition_keys.empty? raise Errors::MigrationDefinitionError, 'Partition key defined twice for the same table.' end @partition_keys = keys.flatten end
# File lib/cassandra_migrations/migration/table_definition.rb, line 189 def define_primary_keys(*keys) if !@primary_keys.empty? raise Errors::MigrationDefinitionError, 'Primary key defined twice for the same table.' end @primary_keys = keys.flatten end
# File lib/cassandra_migrations/migration/table_definition.rb, line 112 def double(column_name, options={}) options[:limit] = 8 @columns_name_type_hash[column_name.to_sym] = column_type_for(:float, options) define_primary_keys(column_name) if options[:primary_key] end
# File lib/cassandra_migrations/migration/table_definition.rb, line 107 def float(column_name, options={}) @columns_name_type_hash[column_name.to_sym] = column_type_for(:float, options) define_primary_keys(column_name) if options[:primary_key] end
# File lib/cassandra_migrations/migration/table_definition.rb, line 97 def integer(column_name, options={}) @columns_name_type_hash[column_name.to_sym] = column_type_for(:integer, options) define_primary_keys(column_name) if options[:primary_key] end
# File lib/cassandra_migrations/migration/table_definition.rb, line 165 def list(column_name, options={}) list_or_set(:list, column_name, options) end
# File lib/cassandra_migrations/migration/table_definition.rb, line 173 def map(column_name, options={}) key_type, value_type = options[:key_type], options[:value_type] [key_type, value_type].each_with_index do |type, index| if type.nil? raise Errors::MigrationDefinitionError, "A map must define a #{index = 0 ? 'key' : 'value'} type." elsif !self.respond_to?(type) raise Errors::MigrationDefinitionError, "Type '#{type}' is not valid for cassandra migration." end end if options[:primary_key] raise Errors::MigrationDefinitionError, 'A collection cannot be used as a primary key.' end @columns_name_type_hash[column_name.to_sym] = :"map<#{column_type_for(key_type)},#{column_type_for(value_type)}>" end
# File lib/cassandra_migrations/migration/table_definition.rb, line 88 def options @options ? " WITH %s" % (@options.map {|option| build_option(option)}.join(" AND ")) : '' end
# File lib/cassandra_migrations/migration/table_definition.rb, line 169 def set(column_name, options={}) list_or_set(:set, column_name, options) end
# File lib/cassandra_migrations/migration/table_definition.rb, line 118 def string(column_name, options={}) @columns_name_type_hash[column_name.to_sym] = column_type_for(:string, options) define_primary_keys(column_name) if options[:primary_key] end
# File lib/cassandra_migrations/migration/table_definition.rb, line 123 def text(column_name, options={}) @columns_name_type_hash[column_name.to_sym] = column_type_for(:text, options) define_primary_keys(column_name) if options[:primary_key] end
# File lib/cassandra_migrations/migration/table_definition.rb, line 138 def timestamp(column_name, options={}) @columns_name_type_hash[column_name.to_sym] = column_type_for(:timestamp, options) define_primary_keys(column_name) if options[:primary_key] end
# File lib/cassandra_migrations/migration/table_definition.rb, line 148 def timeuuid(column_name, options={}) @columns_name_type_hash[column_name.to_sym] = column_type_for(:timeuuid, options) define_primary_keys(column_name) if options[:primary_key] end
# File lib/cassandra_migrations/migration/table_definition.rb, line 74 def to_add_column_cql cql = "" if @columns_name_type_hash.size == 1 cql = "#{@columns_name_type_hash.keys.first} #{@columns_name_type_hash.values.first}" elsif @columns_name_type_hash.empty? raise Errors::MigrationDefinitionError, 'No column to add.' else raise Errors::MigrationDefinitionError, 'Only one column can be added at once.' end cql end
# File lib/cassandra_migrations/migration/table_definition.rb, line 66 def to_create_cql cql = [] build_name_type_cql(cql) check_for_non_key_fields_in_counter_table build_pk_clause(cql) cql.join(', ') end
# File lib/cassandra_migrations/migration/table_definition.rb, line 143 def uuid(column_name, options={}) @columns_name_type_hash[column_name.to_sym] = column_type_for(:uuid, options) define_primary_keys(column_name) if options[:primary_key] end
Private Instance Methods
# File lib/cassandra_migrations/migration/table_definition.rb, line 258 def build_name_type_cql(cql) if !@columns_name_type_hash.empty? @columns_name_type_hash.each do |column_name, type| cql << "#{column_name} #{type}" end else raise Errors::MigrationDefinitionError, 'No columns defined for table.' end end
# File lib/cassandra_migrations/migration/table_definition.rb, line 241 def build_option(option) name, value = option cql_name = SPECIAL_OPTIONS_MAP.fetch(name, name.to_s) case name when :clustering_order "#{cql_name} BY (#{value})" when :compact_storage cql_name else #if complex option with nested hash, convert keys and values to proper string value if value.is_a?(Hash) value = "{#{value.map {|k, v| "'#{k}':'#{v}'"}.join(',')}}" end "#{cql_name} = #{value}" end end
# File lib/cassandra_migrations/migration/table_definition.rb, line 278 def build_pk_clause(cql) key_info = (@primary_keys - @partition_keys) key_info = ["(#{@partition_keys.join(', ')})", *key_info] if @partition_keys.any? if key_info.any? cql << "PRIMARY KEY(#{key_info.join(', ')})" else raise Errors::MigrationDefinitionError, 'No primary key defined.' end end
# File lib/cassandra_migrations/migration/table_definition.rb, line 268 def check_for_non_key_fields_in_counter_table if (@columns_name_type_hash.values.include? :counter) non_key_columns = @columns_name_type_hash.keys - @primary_keys counter_columns = @columns_name_type_hash.select { |name, type| type == :counter }.keys if (non_key_columns - counter_columns).present? raise Errors::MigrationDefinitionError, 'Non key fields not allowed in tables with counter' end end end
# File lib/cassandra_migrations/migration/table_definition.rb, line 228 def column_type_for(type, options={}) cql_type = type if PASSTHROUGH_TYPES.include?(type) cql_type ||= TYPES_MAP[type] if PRECISION_MAP.keys.include?(type) limit = options[:limit] unless PRECISION_MAP[type].keys.include?(limit) raise Errors::MigrationDefinitionError, ":limit option should be #{PRECISION_MAP[type].keys.compact.join(' or ')} for #{type}." end cql_type ||= PRECISION_MAP[type][limit] end cql_type end
# File lib/cassandra_migrations/migration/table_definition.rb, line 289 def list_or_set(collection_type, column_name, options={}) type = options[:type] if type.nil? raise Errors::MigrationDefinitionError, "A #{collection_type} must define a collection type." elsif !self.respond_to?(type) raise Errors::MigrationDefinitionError, "Type '#{type}' is not valid for cassandra migration." end if options[:primary_key] raise Errors::MigrationDefinitionError, 'A collection cannot be used as a primary key.' end @columns_name_type_hash[column_name.to_sym] = :"#{collection_type}<#{column_type_for(type)}>" end