cequel 1.0.0.rc1 → 1.0.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/cequel.rb +18 -0
- data/lib/cequel/errors.rb +8 -4
- data/lib/cequel/metal.rb +14 -0
- data/lib/cequel/metal/batch.rb +21 -11
- data/lib/cequel/metal/batch_manager.rb +74 -0
- data/lib/cequel/metal/cql_row_specification.rb +19 -6
- data/lib/cequel/metal/data_set.rb +400 -163
- data/lib/cequel/metal/deleter.rb +45 -11
- data/lib/cequel/metal/incrementer.rb +23 -10
- data/lib/cequel/metal/inserter.rb +19 -6
- data/lib/cequel/metal/keyspace.rb +82 -159
- data/lib/cequel/metal/logger.rb +71 -0
- data/lib/cequel/metal/logging.rb +47 -0
- data/lib/cequel/metal/new_relic_instrumentation.rb +26 -0
- data/lib/cequel/metal/row.rb +36 -10
- data/lib/cequel/metal/row_specification.rb +21 -8
- data/lib/cequel/metal/statement.rb +30 -6
- data/lib/cequel/metal/updater.rb +89 -12
- data/lib/cequel/metal/writer.rb +23 -14
- data/lib/cequel/record.rb +52 -6
- data/lib/cequel/record/association_collection.rb +13 -6
- data/lib/cequel/record/associations.rb +146 -54
- data/lib/cequel/record/belongs_to_association.rb +34 -7
- data/lib/cequel/record/bound.rb +69 -12
- data/lib/cequel/record/bulk_writes.rb +29 -1
- data/lib/cequel/record/callbacks.rb +22 -6
- data/lib/cequel/record/collection.rb +273 -36
- data/lib/cequel/record/configuration_generator.rb +5 -0
- data/lib/cequel/record/data_set_builder.rb +86 -0
- data/lib/cequel/record/dirty.rb +11 -8
- data/lib/cequel/record/errors.rb +38 -4
- data/lib/cequel/record/has_many_association.rb +42 -9
- data/lib/cequel/record/lazy_record_collection.rb +39 -10
- data/lib/cequel/record/mass_assignment.rb +14 -6
- data/lib/cequel/record/persistence.rb +157 -20
- data/lib/cequel/record/properties.rb +147 -24
- data/lib/cequel/record/railtie.rb +15 -2
- data/lib/cequel/record/record_set.rb +504 -75
- data/lib/cequel/record/schema.rb +77 -13
- data/lib/cequel/record/scoped.rb +16 -11
- data/lib/cequel/record/secondary_indexes.rb +42 -6
- data/lib/cequel/record/tasks.rb +2 -1
- data/lib/cequel/record/validations.rb +51 -11
- data/lib/cequel/schema.rb +9 -0
- data/lib/cequel/schema/column.rb +172 -33
- data/lib/cequel/schema/create_table_dsl.rb +62 -31
- data/lib/cequel/schema/keyspace.rb +106 -7
- data/lib/cequel/schema/migration_validator.rb +128 -0
- data/lib/cequel/schema/table.rb +183 -20
- data/lib/cequel/schema/table_property.rb +92 -34
- data/lib/cequel/schema/table_reader.rb +45 -15
- data/lib/cequel/schema/table_synchronizer.rb +101 -43
- data/lib/cequel/schema/table_updater.rb +114 -19
- data/lib/cequel/schema/table_writer.rb +31 -13
- data/lib/cequel/schema/update_table_dsl.rb +71 -40
- data/lib/cequel/type.rb +214 -53
- data/lib/cequel/util.rb +6 -9
- data/lib/cequel/version.rb +2 -1
- data/spec/examples/record/associations_spec.rb +12 -12
- data/spec/examples/record/persistence_spec.rb +5 -5
- data/spec/examples/record/record_set_spec.rb +62 -50
- data/spec/examples/schema/table_synchronizer_spec.rb +37 -11
- data/spec/examples/schema/table_updater_spec.rb +3 -3
- data/spec/examples/spec_helper.rb +2 -11
- data/spec/examples/type_spec.rb +3 -3
- metadata +23 -4
- data/lib/cequel/new_relic_instrumentation.rb +0 -22
@@ -1,69 +1,163 @@
|
|
1
1
|
module Cequel
|
2
|
-
|
3
2
|
module Schema
|
4
|
-
|
3
|
+
#
|
4
|
+
# Encapsulates a series of schema modification statements that can be
|
5
|
+
# applied to an existing table
|
6
|
+
#
|
5
7
|
class TableUpdater
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
#
|
9
|
+
# Construct a table updater and apply the schema modifications to the
|
10
|
+
# given table.
|
11
|
+
#
|
12
|
+
# @param (see #initialize)
|
13
|
+
# @yieldparam updater [TableUpdater] instance of updater whose
|
14
|
+
# modifications will be applied to the named table
|
15
|
+
# @return [void]
|
16
|
+
#
|
17
|
+
def self.apply(keyspace, table_name, &block)
|
18
|
+
new(keyspace, table_name).tap(&block).apply
|
11
19
|
end
|
12
20
|
|
21
|
+
#
|
22
|
+
# @param keyspace [Metal::Keyspace] keyspace containing the table
|
23
|
+
# @param table_name [Symbol] name of the table to modify
|
24
|
+
# @private
|
25
|
+
#
|
13
26
|
def initialize(keyspace, table_name)
|
14
27
|
@keyspace, @table_name = keyspace, table_name
|
15
28
|
@statements = []
|
16
29
|
end
|
17
30
|
private_class_method :new
|
18
31
|
|
32
|
+
#
|
33
|
+
# Apply the schema modifications to the table schema in the database
|
34
|
+
#
|
35
|
+
# @return [void]
|
36
|
+
#
|
37
|
+
# @api private
|
38
|
+
#
|
19
39
|
def apply
|
20
40
|
statements.each { |statement| keyspace.execute(statement) }
|
21
41
|
end
|
22
42
|
|
43
|
+
#
|
44
|
+
# Add a column to the table
|
45
|
+
#
|
46
|
+
# @param name [Symbol] the name of the column
|
47
|
+
# @param type [Symbol,Type] the type of the column
|
48
|
+
# @return [void]
|
49
|
+
#
|
23
50
|
def add_column(name, type)
|
24
|
-
add_data_column(Column.new(name, type))
|
51
|
+
add_data_column(Column.new(name, type(type)))
|
25
52
|
end
|
26
53
|
|
54
|
+
#
|
55
|
+
# Add a list to the table
|
56
|
+
#
|
57
|
+
# @param name [Symbol] the name of the list
|
58
|
+
# @param type [Symbol,Type] the type of the list elements
|
59
|
+
# @return [void]
|
60
|
+
#
|
27
61
|
def add_list(name, type)
|
28
|
-
add_data_column(List.new(name, type))
|
62
|
+
add_data_column(List.new(name, type(type)))
|
29
63
|
end
|
30
64
|
|
65
|
+
#
|
66
|
+
# Add a set to the table
|
67
|
+
#
|
68
|
+
# @param name [Symbol] the name of the set
|
69
|
+
# @param type [Symbol,Type] the type of the set elements
|
70
|
+
# @return [void]
|
71
|
+
#
|
31
72
|
def add_set(name, type)
|
32
|
-
add_data_column(Set.new(name, type))
|
73
|
+
add_data_column(Set.new(name, type(type)))
|
33
74
|
end
|
34
75
|
|
76
|
+
#
|
77
|
+
# Add a map to the table
|
78
|
+
#
|
79
|
+
# @param name [Symbol] the name of the map
|
80
|
+
# @param key_type [Symbol,Type] the type of the map's keys
|
81
|
+
# @param value_type [Symbol,Type] the type of the map's values
|
82
|
+
# @return [void]
|
83
|
+
#
|
35
84
|
def add_map(name, key_type, value_type)
|
36
|
-
add_data_column(Map.new(name, key_type, value_type))
|
85
|
+
add_data_column(Map.new(name, type(key_type), type(value_type)))
|
37
86
|
end
|
38
87
|
|
88
|
+
#
|
89
|
+
# Change an existing column's type
|
90
|
+
#
|
91
|
+
# @param name [Symbol] the name of the column
|
92
|
+
# @param type [Symbol,Type] the new type of the column
|
93
|
+
# @return [void]
|
94
|
+
#
|
95
|
+
# @note Changing the type of a CQL column does not modify the data
|
96
|
+
# currently stored in the column. Thus, client-side handling is needed
|
97
|
+
# to convert old values to the new type at read time. Cequel does not
|
98
|
+
# currently support this functionality, although it may in the future.
|
99
|
+
# Altering column types is not recommended.
|
100
|
+
#
|
39
101
|
def change_column(name, type)
|
40
|
-
alter_table("ALTER #{name} TYPE #{type.cql_name}")
|
102
|
+
alter_table("ALTER #{name} TYPE #{type(type).cql_name}")
|
41
103
|
end
|
42
104
|
|
105
|
+
#
|
106
|
+
# Rename a column
|
107
|
+
#
|
108
|
+
# @param old_name [Symbol] the current name of the column
|
109
|
+
# @param new_name [Symbol] the new name of the column
|
110
|
+
# @return [void]
|
111
|
+
#
|
43
112
|
def rename_column(old_name, new_name)
|
44
113
|
alter_table(%(RENAME "#{old_name}" TO "#{new_name}"))
|
45
114
|
end
|
46
115
|
|
116
|
+
#
|
117
|
+
# Change one or more table storage properties
|
118
|
+
#
|
119
|
+
# @param options [Hash] map of property names to new values
|
120
|
+
# @return [void]
|
121
|
+
#
|
122
|
+
# @see Table#add_property
|
123
|
+
#
|
47
124
|
def change_properties(options)
|
48
|
-
properties = options
|
49
|
-
map { |name, value| TableProperty.
|
125
|
+
properties = options
|
126
|
+
.map { |name, value| TableProperty.build(name, value).to_cql }
|
50
127
|
alter_table("WITH #{properties.join(' AND ')}")
|
51
128
|
end
|
52
129
|
|
53
|
-
|
54
|
-
|
55
|
-
|
130
|
+
#
|
131
|
+
# Create a secondary index
|
132
|
+
#
|
133
|
+
# @param column_name [Symbol] name of the column to add an index on
|
134
|
+
# @param index_name [Symbol] name of the index; will be inferred from
|
135
|
+
# convention if nil
|
136
|
+
# @return [void]
|
137
|
+
#
|
138
|
+
def create_index(column_name, index_name = nil)
|
139
|
+
index_name ||= "#{table_name}_#{column_name}_idx"
|
140
|
+
statements <<
|
141
|
+
"CREATE INDEX #{index_name} ON #{table_name} (#{column_name})"
|
56
142
|
end
|
57
143
|
|
144
|
+
#
|
145
|
+
# Remove a secondary index
|
146
|
+
#
|
147
|
+
# @param index_name [Symbol] the name of the index to remove
|
148
|
+
# @return [void]
|
149
|
+
#
|
58
150
|
def drop_index(index_name)
|
59
151
|
statements << "DROP INDEX #{index_name}"
|
60
152
|
end
|
61
153
|
|
154
|
+
# @!visibility protected
|
62
155
|
def add_data_column(column)
|
63
156
|
add_column_statement(column)
|
64
157
|
end
|
65
158
|
|
66
159
|
protected
|
160
|
+
|
67
161
|
attr_reader :keyspace, :table_name, :statements
|
68
162
|
|
69
163
|
private
|
@@ -76,8 +170,9 @@ module Cequel
|
|
76
170
|
alter_table("ADD #{column.to_cql}")
|
77
171
|
end
|
78
172
|
|
173
|
+
def type(type)
|
174
|
+
::Cequel::Type[type]
|
175
|
+
end
|
79
176
|
end
|
80
|
-
|
81
177
|
end
|
82
|
-
|
83
178
|
end
|
@@ -1,25 +1,44 @@
|
|
1
1
|
module Cequel
|
2
|
-
|
3
2
|
module Schema
|
4
|
-
|
5
|
-
|
3
|
+
#
|
4
|
+
# Creates a new table schema in the database
|
5
|
+
#
|
6
6
|
class TableWriter
|
7
|
-
|
7
|
+
#
|
8
|
+
# Creates a new table schema in the database given an object
|
9
|
+
# representation of the schema to create
|
10
|
+
#
|
11
|
+
# @param (see #initialize)
|
12
|
+
# @return (see #apply)
|
13
|
+
#
|
8
14
|
def self.apply(keyspace, table)
|
9
15
|
new(keyspace, table).apply
|
10
16
|
end
|
11
17
|
|
18
|
+
#
|
19
|
+
# @param keyspace [Keyspace] keyspace in which to create the table
|
20
|
+
# @param table [Table] object representation of table schema
|
21
|
+
# @private
|
22
|
+
#
|
12
23
|
def initialize(keyspace, table)
|
13
24
|
@keyspace, @table = keyspace, table
|
14
25
|
end
|
15
26
|
private_class_method :new
|
16
27
|
|
28
|
+
#
|
29
|
+
# Create the table in the keyspace
|
30
|
+
#
|
31
|
+
# @return [void]
|
32
|
+
#
|
33
|
+
# @api private
|
34
|
+
#
|
17
35
|
def apply
|
18
36
|
keyspace.execute(create_statement)
|
19
37
|
index_statements.each { |statement| keyspace.execute(statement) }
|
20
38
|
end
|
21
39
|
|
22
40
|
protected
|
41
|
+
|
23
42
|
attr_reader :keyspace, :table
|
24
43
|
|
25
44
|
private
|
@@ -36,7 +55,8 @@ module Cequel
|
|
36
55
|
table.data_columns.each do |column|
|
37
56
|
if column.indexed?
|
38
57
|
statements <<
|
39
|
-
"CREATE INDEX #{column.index_name}
|
58
|
+
"CREATE INDEX #{column.index_name} " \
|
59
|
+
"ON #{table.name} (#{column.name})"
|
40
60
|
end
|
41
61
|
end
|
42
62
|
end
|
@@ -51,8 +71,8 @@ module Cequel
|
|
51
71
|
end
|
52
72
|
|
53
73
|
def keys_cql
|
54
|
-
partition_cql = table.partition_key_columns
|
55
|
-
map { |key| key.name }.join(', ')
|
74
|
+
partition_cql = table.partition_key_columns
|
75
|
+
.map { |key| key.name }.join(', ')
|
56
76
|
if table.clustering_columns.any?
|
57
77
|
nonpartition_cql =
|
58
78
|
table.clustering_columns.map { |key| key.name }.join(', ')
|
@@ -63,19 +83,17 @@ module Cequel
|
|
63
83
|
end
|
64
84
|
|
65
85
|
def properties_cql
|
66
|
-
properties_fragments = table.properties
|
67
|
-
map { |_, property| property.to_cql }
|
86
|
+
properties_fragments = table.properties
|
87
|
+
.map { |_, property| property.to_cql }
|
68
88
|
properties_fragments << 'COMPACT STORAGE' if table.compact_storage?
|
69
89
|
if table.clustering_columns.any?
|
70
90
|
clustering_fragment =
|
71
91
|
table.clustering_columns.map(&:clustering_order_cql).join(',')
|
72
|
-
properties_fragments <<
|
92
|
+
properties_fragments <<
|
93
|
+
"CLUSTERING ORDER BY (#{clustering_fragment})"
|
73
94
|
end
|
74
95
|
properties_fragments.join(' AND ') if properties_fragments.any?
|
75
96
|
end
|
76
|
-
|
77
97
|
end
|
78
|
-
|
79
98
|
end
|
80
|
-
|
81
99
|
end
|
@@ -1,60 +1,91 @@
|
|
1
1
|
module Cequel
|
2
|
-
|
3
2
|
module Schema
|
4
|
-
|
3
|
+
#
|
4
|
+
# DSL for describing a series of schema modification statements
|
5
|
+
#
|
5
6
|
class UpdateTableDSL < BasicObject
|
6
|
-
|
7
|
+
extend ::Forwardable
|
8
|
+
#
|
9
|
+
# Describe a series of schema modifications and build a {TableUpdater}
|
10
|
+
# to encapsulate them
|
11
|
+
#
|
12
|
+
# @param (see #initialize)
|
13
|
+
# @yield a block evaluated in the context of an {UpdateTableDSL} instance
|
14
|
+
# @return [void]
|
15
|
+
#
|
16
|
+
# @api private
|
17
|
+
# @see Keyspace#update_table
|
18
|
+
#
|
7
19
|
def self.apply(updater, &block)
|
8
20
|
dsl = new(updater)
|
9
21
|
dsl.instance_eval(&block)
|
10
22
|
end
|
11
23
|
|
24
|
+
#
|
25
|
+
# @param updater [TableUpdater]
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
#
|
12
29
|
def initialize(updater)
|
13
30
|
@updater = updater
|
14
31
|
end
|
15
32
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
33
|
+
#
|
34
|
+
# @!method add_column(name, type)
|
35
|
+
# (see Cequel::Schema::TableUpdater#add_column)
|
36
|
+
#
|
37
|
+
def_delegator :@updater, :add_column
|
38
|
+
|
39
|
+
#
|
40
|
+
# @!method add_list(name, type)
|
41
|
+
# (see Cequel::Schema::TableUpdater#add_list)
|
42
|
+
#
|
43
|
+
def_delegator :@updater, :add_list
|
44
|
+
|
45
|
+
#
|
46
|
+
# @!method add_set(name, type)
|
47
|
+
# (see Cequel::Schema::TableUpdater#add_set)
|
48
|
+
#
|
49
|
+
def_delegator :@updater, :add_set
|
50
|
+
|
51
|
+
#
|
52
|
+
# @!method add_map(name, key_type, value_type)
|
53
|
+
# (see Cequel::Schema::TableUpdater#add_map)
|
54
|
+
#
|
55
|
+
def_delegator :@updater, :add_map
|
56
|
+
|
57
|
+
#
|
58
|
+
# @!method change_column(name, type)
|
59
|
+
# (see Cequel::Schema::TableUpdater#change_column)
|
60
|
+
#
|
61
|
+
def_delegator :@updater, :change_column
|
62
|
+
|
63
|
+
#
|
64
|
+
# @!method rename_column(old_name, new_name)
|
65
|
+
# (see Cequel::Schema::TableUpdater#rename_column)
|
66
|
+
#
|
67
|
+
def_delegator :@updater, :rename_column
|
68
|
+
|
69
|
+
#
|
70
|
+
# @!method change_properties(options)
|
71
|
+
# (see Cequel::Schema::TableUpdater#change_properties)
|
72
|
+
#
|
73
|
+
def_delegator :@updater, :change_properties
|
44
74
|
alias_method :change_options, :change_properties
|
45
75
|
|
46
|
-
|
47
|
-
|
48
|
-
|
76
|
+
#
|
77
|
+
# @!method create_index(column_name, index_name = nil)
|
78
|
+
# (see Cequel::Schema::TableUpdater#create_index
|
79
|
+
#
|
80
|
+
def_delegator :@updater, :create_index
|
49
81
|
alias_method :add_index, :create_index
|
50
82
|
|
51
|
-
|
52
|
-
|
53
|
-
|
83
|
+
#
|
84
|
+
# @!method drop_index(index_name)
|
85
|
+
# (see Cequel::Schema::TableUpdater#drop_index)
|
86
|
+
#
|
87
|
+
def_delegator :@updater, :drop_index
|
54
88
|
alias_method :remove_index, :drop_index
|
55
|
-
|
56
89
|
end
|
57
|
-
|
58
90
|
end
|
59
|
-
|
60
91
|
end
|
data/lib/cequel/type.rb
CHANGED
@@ -1,71 +1,172 @@
|
|
1
1
|
require 'singleton'
|
2
2
|
|
3
3
|
module Cequel
|
4
|
-
|
4
|
+
#
|
5
|
+
# The Type module encapsulates information about the CQL3 type system. Each
|
6
|
+
# type has a `cql_name`, which is the name of the type as defined in CQL, and
|
7
|
+
# an `internal_name`, which is the name of the type in the lower-level
|
8
|
+
# interface that is exposed when introspecting table information in the
|
9
|
+
# database.
|
10
|
+
#
|
11
|
+
# As well as knowing their respective names, types also know how to cast Ruby
|
12
|
+
# objects to the correct canonical class corresponding to the type. These
|
13
|
+
# implicit types are used by the underlying `cassandra-cql` library to
|
14
|
+
# determine how to represent values when passing them to Cassandra.
|
15
|
+
#
|
16
|
+
# @since 1.0.0
|
17
|
+
#
|
5
18
|
module Type
|
6
|
-
|
19
|
+
# Raised if an unknown type is looked up
|
7
20
|
UnknownType = Class.new(ArgumentError)
|
8
21
|
|
9
22
|
BY_CQL_NAME = {}
|
10
23
|
BY_INTERNAL_NAME = {}
|
11
24
|
|
25
|
+
#
|
26
|
+
# Register a type for lookup
|
27
|
+
#
|
28
|
+
# @param type [Type] a new type
|
29
|
+
# @return [void]
|
30
|
+
#
|
12
31
|
def self.register(type)
|
13
32
|
BY_CQL_NAME[type.cql_name] = type
|
14
33
|
type.cql_aliases.each { |aliaz| BY_CQL_NAME[aliaz] = type }
|
15
|
-
|
34
|
+
type.internal_names.each do |internal_name|
|
35
|
+
BY_INTERNAL_NAME[internal_name] = type
|
36
|
+
end
|
16
37
|
end
|
17
38
|
|
39
|
+
#
|
40
|
+
# Return a type corresponding to the given input
|
41
|
+
#
|
42
|
+
# @param cql_name [Symbol,Base] CQL name of a type, or a type
|
43
|
+
# @return [Base] type with the given CQL name
|
44
|
+
#
|
18
45
|
def self.[](cql_name)
|
19
46
|
cql_name.is_a?(Base) ? cql_name : lookup_cql(cql_name)
|
20
47
|
end
|
21
48
|
|
49
|
+
#
|
50
|
+
# Look up a type by CQL name
|
51
|
+
#
|
52
|
+
# @param cql_name [Symbol] CQL name of a type
|
53
|
+
# @return [Base] type with the given CQL name
|
54
|
+
# @raise [UnknownType] if no type by that name is registered
|
55
|
+
#
|
22
56
|
def self.lookup_cql(cql_name)
|
23
57
|
BY_CQL_NAME.fetch(cql_name.to_sym)
|
24
58
|
rescue KeyError
|
25
59
|
raise UnknownType, "Unrecognized CQL type #{cql_name.inspect}"
|
26
60
|
end
|
27
61
|
|
62
|
+
#
|
63
|
+
# Look up a type by internal name
|
64
|
+
#
|
65
|
+
# @param internal_name [String] internal name of a type
|
66
|
+
# @return [Base] type with the given internal name
|
67
|
+
# @raise [UnknownType] if no type by that name is registered
|
68
|
+
#
|
28
69
|
def self.lookup_internal(internal_name)
|
29
70
|
BY_INTERNAL_NAME.fetch(internal_name)
|
30
71
|
rescue KeyError
|
31
72
|
raise UnknownType, "Unrecognized internal type #{internal_name.inspect}"
|
32
73
|
end
|
33
74
|
|
75
|
+
#
|
76
|
+
# The base class for all type objects. Types are singletons.
|
77
|
+
#
|
78
|
+
# @abstract Subclasses should implement {#cast}, and may implement
|
79
|
+
# {#internal_names} if it cannot be inferred from the class name. The
|
80
|
+
# name of the type class should be the camel-cased CQL name of the type
|
81
|
+
#
|
34
82
|
class Base
|
35
83
|
include Singleton
|
36
84
|
|
85
|
+
#
|
86
|
+
# @return the name of the type used in CQL. This is also the name that is
|
87
|
+
# used in all of Cequel's public interfaces
|
88
|
+
#
|
37
89
|
def cql_name
|
38
90
|
self.class.name.demodulize.underscore.to_sym
|
39
91
|
end
|
40
92
|
|
93
|
+
#
|
94
|
+
# @return [Array<Symbol>] other names used in CQL for this type
|
95
|
+
#
|
41
96
|
def cql_aliases
|
42
97
|
[]
|
43
98
|
end
|
44
99
|
|
100
|
+
#
|
101
|
+
# @return [Array<String>] full class name of this type used in
|
102
|
+
# Cassandra's underlying representation
|
103
|
+
#
|
104
|
+
# @deprecated use {internal_names}
|
105
|
+
#
|
45
106
|
def internal_name
|
46
|
-
|
107
|
+
internal_names.first
|
47
108
|
end
|
48
109
|
|
110
|
+
#
|
111
|
+
# @return [Array<String>] full class name(s) of this type used in
|
112
|
+
# Cassandra's underlying representation (allows for multiple values for
|
113
|
+
# types that have different names between different versions)
|
114
|
+
#
|
115
|
+
def internal_names
|
116
|
+
["org.apache.cassandra.db.marshal.#{self.class.name.demodulize}Type"]
|
117
|
+
end
|
118
|
+
|
119
|
+
#
|
120
|
+
# @param value the value to cast
|
121
|
+
# @return the value cast to the correct Ruby class for this type
|
122
|
+
#
|
49
123
|
def cast(value)
|
50
124
|
value
|
51
125
|
end
|
52
126
|
|
127
|
+
#
|
128
|
+
# CQL only allows changing column types when the old type's binary
|
129
|
+
# representation is compatible with the new type.
|
130
|
+
#
|
131
|
+
# @return [Array<Type>] new types that columns of this type may be
|
132
|
+
# altered to
|
133
|
+
#
|
134
|
+
def compatible_types
|
135
|
+
[Type[:blob]]
|
136
|
+
end
|
137
|
+
|
138
|
+
#
|
139
|
+
# A string representation of this type
|
140
|
+
#
|
53
141
|
def to_s
|
54
142
|
cql_name.to_s
|
55
143
|
end
|
56
|
-
|
57
144
|
end
|
58
145
|
|
146
|
+
#
|
147
|
+
# Abstract superclass for types that represent character data
|
148
|
+
#
|
149
|
+
# @abstract Subclasses must implement `#encoding`, which returns the name
|
150
|
+
# of the Ruby encoding corresponding to the character encoding used for
|
151
|
+
# values of this type
|
152
|
+
#
|
59
153
|
class String < Base
|
60
|
-
|
61
154
|
def cast(value)
|
62
155
|
str = String(value)
|
63
156
|
str.encoding.name == encoding ? str : str.dup.force_encoding(encoding)
|
64
157
|
end
|
65
|
-
|
66
158
|
end
|
67
159
|
|
160
|
+
#
|
161
|
+
# `ascii` columns store 7-bit ASCII character data
|
162
|
+
#
|
163
|
+
# @see TK CQL3 documentation for ascii type
|
164
|
+
#
|
68
165
|
class Ascii < String
|
166
|
+
def compatible_types
|
167
|
+
super + [Type[:text]]
|
168
|
+
end
|
169
|
+
|
69
170
|
private
|
70
171
|
|
71
172
|
def encoding
|
@@ -74,14 +175,19 @@ module Cequel
|
|
74
175
|
end
|
75
176
|
register Ascii.instance
|
76
177
|
|
178
|
+
#
|
179
|
+
# `blob` columns store arbitrary bytes of data, represented as 8-bit ASCII
|
180
|
+
# strings of hex digits
|
181
|
+
#
|
182
|
+
# @see TK CQL3 documentation for blob type
|
183
|
+
#
|
77
184
|
class Blob < String
|
78
|
-
|
79
|
-
|
80
|
-
'org.apache.cassandra.db.marshal.BytesType'
|
185
|
+
def internal_names
|
186
|
+
['org.apache.cassandra.db.marshal.BytesType']
|
81
187
|
end
|
82
188
|
|
83
189
|
def cast(value)
|
84
|
-
value = value.to_s(16) if Integer
|
190
|
+
value = value.to_s(16) if value.is_a?(Integer)
|
85
191
|
super
|
86
192
|
end
|
87
193
|
|
@@ -90,10 +196,14 @@ module Cequel
|
|
90
196
|
def encoding
|
91
197
|
'ASCII-8BIT'
|
92
198
|
end
|
93
|
-
|
94
199
|
end
|
95
200
|
register Blob.instance
|
96
201
|
|
202
|
+
#
|
203
|
+
# `boolean` types store boolean values
|
204
|
+
#
|
205
|
+
# @see TK CQL3 documentation for boolean type
|
206
|
+
#
|
97
207
|
class Boolean < Base
|
98
208
|
def cast(value)
|
99
209
|
!!value
|
@@ -101,26 +211,47 @@ module Cequel
|
|
101
211
|
end
|
102
212
|
register Boolean.instance
|
103
213
|
|
214
|
+
#
|
215
|
+
# Counter columns are a special type of column in Cassandra that can be
|
216
|
+
# incremented and decremented atomically. Counter columns cannot comingle
|
217
|
+
# with regular data columns in the same table. Unlike other columns,
|
218
|
+
# counter columns cannot be updated without Cassandra internally reading
|
219
|
+
# the existing state of the column
|
220
|
+
#
|
221
|
+
# @see TK CQL3 documentation for counter columns
|
222
|
+
#
|
104
223
|
class Counter < Base
|
224
|
+
def internal_names
|
225
|
+
['org.apache.cassandra.db.marshal.CounterColumnType']
|
226
|
+
end
|
105
227
|
|
106
|
-
def
|
107
|
-
|
228
|
+
def compatible_types
|
229
|
+
[]
|
108
230
|
end
|
109
231
|
|
110
232
|
def cast(value)
|
111
233
|
Integer(value)
|
112
234
|
end
|
113
|
-
|
114
235
|
end
|
115
236
|
register Counter.instance
|
116
237
|
|
238
|
+
#
|
239
|
+
# `decimal` columns store decimal numeric values
|
240
|
+
#
|
241
|
+
# @see TK CQL3 documentation for decimal columns
|
242
|
+
#
|
117
243
|
class Decimal < Base
|
118
244
|
def cast(value)
|
119
|
-
BigDecimal
|
245
|
+
value.is_a?(BigDecimal) ? value : BigDecimal.new(value, 0)
|
120
246
|
end
|
121
247
|
end
|
122
248
|
register Decimal.instance
|
123
249
|
|
250
|
+
#
|
251
|
+
# `double` columns store 64-bit floating-point numeric values
|
252
|
+
#
|
253
|
+
# @see TK CQL3 documentation for double columns
|
254
|
+
#
|
124
255
|
class Double < Base
|
125
256
|
def cast(value)
|
126
257
|
Float(value)
|
@@ -128,44 +259,64 @@ module Cequel
|
|
128
259
|
end
|
129
260
|
register Double.instance
|
130
261
|
|
262
|
+
#
|
263
|
+
# TK
|
264
|
+
#
|
265
|
+
# @see TK CQL3 documentation for inet columns
|
266
|
+
#
|
131
267
|
class Inet < Base
|
132
|
-
|
133
|
-
|
134
|
-
'org.apache.cassandra.db.marshal.InetAddressType'
|
268
|
+
def internal_names
|
269
|
+
['org.apache.cassandra.db.marshal.InetAddressType']
|
135
270
|
end
|
136
|
-
|
137
271
|
end
|
138
272
|
register Inet.instance
|
139
273
|
|
274
|
+
#
|
275
|
+
# `int` columns store 32-bit integer values
|
276
|
+
#
|
277
|
+
# @see TK CQL3 documentation for int columns
|
278
|
+
#
|
140
279
|
class Int < Base
|
141
|
-
|
142
|
-
|
143
|
-
'org.apache.cassandra.db.marshal.Int32Type'
|
280
|
+
def internal_names
|
281
|
+
['org.apache.cassandra.db.marshal.Int32Type']
|
144
282
|
end
|
145
283
|
|
146
284
|
def cast(value)
|
147
285
|
Integer(value)
|
148
286
|
end
|
149
|
-
|
150
287
|
end
|
151
288
|
register Int.instance
|
152
289
|
|
290
|
+
#
|
291
|
+
# `float` columns store 32-bit floating-point numeric values
|
292
|
+
#
|
293
|
+
# @see TK CQL3 documentation for float columns
|
294
|
+
#
|
153
295
|
class Float < Double; end
|
154
296
|
register Float.instance
|
155
297
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
298
|
+
#
|
299
|
+
# `bigint` columns store 64-bit integer values
|
300
|
+
#
|
301
|
+
# @see TK CQL3 documentation for bigint columns
|
302
|
+
#
|
303
|
+
class Bigint < Int
|
304
|
+
def internal_names
|
305
|
+
['org.apache.cassandra.db.marshal.LongType']
|
160
306
|
end
|
161
|
-
|
162
307
|
end
|
163
|
-
register
|
164
|
-
|
308
|
+
register Bigint.instance
|
309
|
+
|
310
|
+
#
|
311
|
+
# `text` columns store UTF-8 character data. They are also known as
|
312
|
+
# `varchar` columns; the names can be used interchangeably. Text columns do
|
313
|
+
# not have a length limit
|
314
|
+
#
|
315
|
+
# @see TK CQL3 documentation for text columns
|
316
|
+
#
|
165
317
|
class Text < String
|
166
|
-
|
167
|
-
|
168
|
-
'org.apache.cassandra.db.marshal.UTF8Type'
|
318
|
+
def internal_names
|
319
|
+
['org.apache.cassandra.db.marshal.UTF8Type']
|
169
320
|
end
|
170
321
|
|
171
322
|
def cql_aliases
|
@@ -177,31 +328,38 @@ module Cequel
|
|
177
328
|
def encoding
|
178
329
|
'UTF-8'
|
179
330
|
end
|
180
|
-
|
181
331
|
end
|
182
332
|
register Text.instance
|
183
333
|
|
334
|
+
#
|
335
|
+
# `timestamp` columns store timestamps. Timestamps do not include time zone
|
336
|
+
# data, and all input times are cast to UTC before being stored.
|
337
|
+
#
|
184
338
|
class Timestamp < Base
|
185
|
-
|
186
|
-
|
187
|
-
|
339
|
+
def internal_names
|
340
|
+
['org.apache.cassandra.db.marshal.DateType',
|
341
|
+
'org.apache.cassandra.db.marshal.TimestampType']
|
188
342
|
end
|
189
343
|
|
190
344
|
def cast(value)
|
191
|
-
if ::String
|
345
|
+
if value.is_a?(::String) then Time.parse(value)
|
192
346
|
elsif value.respond_to?(:to_time) then value.to_time
|
193
|
-
elsif Numeric
|
347
|
+
elsif value.is_a?(Numeric) then Time.at(value)
|
194
348
|
else Time.parse(value.to_s)
|
195
349
|
end.utc
|
196
350
|
end
|
197
|
-
|
198
351
|
end
|
199
352
|
register Timestamp.instance
|
200
353
|
|
354
|
+
#
|
355
|
+
# `uuid` columns store type 1 and type 4 UUIDs. Cequel uses the
|
356
|
+
# `CassandraCQL::UUID` type to represent UUIDs in Ruby, since this is what
|
357
|
+
# the underlying `cassandra-cql` library expects. Other UUID formats are
|
358
|
+
# supported as inputs.
|
359
|
+
#
|
201
360
|
class Uuid < Base
|
202
|
-
|
203
|
-
|
204
|
-
'org.apache.cassandra.db.marshal.UUIDType'
|
361
|
+
def internal_names
|
362
|
+
['org.apache.cassandra.db.marshal.UUIDType']
|
205
363
|
end
|
206
364
|
|
207
365
|
def cast(value)
|
@@ -211,28 +369,31 @@ module Cequel
|
|
211
369
|
else CassandraCQL::UUID.new(value)
|
212
370
|
end
|
213
371
|
end
|
214
|
-
|
215
372
|
end
|
216
373
|
register Uuid.instance
|
217
374
|
|
375
|
+
#
|
376
|
+
# `timeuuid` columns are a special type of UUID column that support
|
377
|
+
# time-based queries. For instance, a `timeuuid` clustering column can be
|
378
|
+
# filtered by ranges of times into which the UUIDs must fall. This
|
379
|
+
# functionality presumes the use of type 1 UUIDs, which encode the
|
380
|
+
# timestamp of their creation.
|
381
|
+
#
|
218
382
|
class Timeuuid < Uuid
|
219
|
-
|
220
|
-
|
221
|
-
'org.apache.cassandra.db.marshal.TimeUUIDType'
|
383
|
+
def internal_names
|
384
|
+
['org.apache.cassandra.db.marshal.TimeUUIDType']
|
222
385
|
end
|
223
|
-
|
224
386
|
end
|
225
387
|
register Timeuuid.instance
|
226
388
|
|
389
|
+
#
|
390
|
+
# `varint` columns store arbitrary-length integer data
|
391
|
+
#
|
227
392
|
class Varint < Int
|
228
|
-
|
229
393
|
def internal_name
|
230
394
|
'org.apache.cassandra.db.marshal.IntegerType'
|
231
395
|
end
|
232
|
-
|
233
396
|
end
|
234
397
|
register Varint.instance
|
235
|
-
|
236
398
|
end
|
237
|
-
|
238
399
|
end
|