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,56 +1,87 @@
|
|
1
1
|
module Cequel
|
2
|
-
|
3
2
|
module Schema
|
4
|
-
|
3
|
+
#
|
4
|
+
# Implements a DSL that can be used to define a table schema
|
5
|
+
#
|
6
|
+
# @see Keyspace#create_table
|
7
|
+
#
|
5
8
|
class CreateTableDSL < BasicObject
|
6
|
-
|
9
|
+
extend ::Forwardable
|
10
|
+
#
|
11
|
+
# Evaluate `block` in the context of this DSL, and apply directives to
|
12
|
+
# `table`
|
13
|
+
#
|
14
|
+
# @param table [Table] a table
|
15
|
+
# @yield block evaluated in the context of the create table DSL
|
16
|
+
# @return [void]
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
#
|
7
20
|
def self.apply(table, &block)
|
8
21
|
dsl = new(table)
|
9
22
|
dsl.instance_eval(&block)
|
10
23
|
end
|
11
24
|
|
25
|
+
#
|
26
|
+
# @param table [Table] table to apply directives to
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
#
|
12
30
|
def initialize(table)
|
13
31
|
@table = table
|
14
32
|
end
|
15
33
|
|
16
|
-
|
17
|
-
|
18
|
-
|
34
|
+
#
|
35
|
+
# @!method partition_key(name, type)
|
36
|
+
# (see Cequel::Schema::Table#add_partition_key)
|
37
|
+
#
|
38
|
+
def_delegator :@table, :add_partition_key, :partition_key
|
19
39
|
|
20
|
-
|
21
|
-
|
22
|
-
|
40
|
+
#
|
41
|
+
# @!method key(name, type, clustering_order = nil)
|
42
|
+
# (see Cequel::Schema::Table#add_key)
|
43
|
+
#
|
44
|
+
def_delegator :@table, :add_key, :key
|
23
45
|
|
24
|
-
|
25
|
-
|
26
|
-
|
46
|
+
#
|
47
|
+
# @!method column(name, type, options = {})
|
48
|
+
# (see Cequel::Schema::Table#add_data_column)
|
49
|
+
#
|
50
|
+
def_delegator :@table, :add_data_column, :column
|
27
51
|
|
28
|
-
|
29
|
-
|
30
|
-
|
52
|
+
#
|
53
|
+
# @!method list(name, type)
|
54
|
+
# (see Cequel::Schema::Table#add_list)
|
55
|
+
#
|
56
|
+
def_delegator :@table, :add_list, :list
|
31
57
|
|
32
|
-
|
33
|
-
|
34
|
-
|
58
|
+
#
|
59
|
+
# @!method set(name, type)
|
60
|
+
# (see Cequel::Schema::Table#add_set)
|
61
|
+
#
|
62
|
+
def_delegator :@table, :add_set, :set
|
35
63
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
)
|
42
|
-
end
|
64
|
+
#
|
65
|
+
# @!method map(name, key_type, value_type)
|
66
|
+
# (see Cequel::Schema::Table#add_map)
|
67
|
+
#
|
68
|
+
def_delegator :@table, :add_map, :map
|
43
69
|
|
44
|
-
|
45
|
-
|
46
|
-
|
70
|
+
#
|
71
|
+
# @!method with(name, value)
|
72
|
+
# (see Cequel::Schema::Table#add_property)
|
73
|
+
#
|
74
|
+
def_delegator :@table, :add_property, :with
|
47
75
|
|
76
|
+
#
|
77
|
+
# Direct that this table use "compact storage". This is primarily useful
|
78
|
+
# for backwards compatibility with legacy CQL2 table schemas.
|
79
|
+
#
|
80
|
+
# @return [void]
|
81
|
+
#
|
48
82
|
def compact_storage
|
49
83
|
@table.compact_storage = true
|
50
84
|
end
|
51
|
-
|
52
85
|
end
|
53
|
-
|
54
86
|
end
|
55
|
-
|
56
87
|
end
|
@@ -1,20 +1,44 @@
|
|
1
1
|
module Cequel
|
2
|
-
|
3
2
|
module Schema
|
4
|
-
|
3
|
+
#
|
4
|
+
# Provides read/write access to the schema for a keyspace and the tables it
|
5
|
+
# contains
|
6
|
+
#
|
7
|
+
# @deprecated These methods will be exposed directly on
|
8
|
+
# {Cequel::Metal::Keyspace} in a future version of Cequel
|
9
|
+
#
|
5
10
|
class Keyspace
|
6
|
-
|
11
|
+
#
|
12
|
+
# @param keyspace [Keyspace] the keyspace whose schema this object
|
13
|
+
# manipulates
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
#
|
7
17
|
def initialize(keyspace)
|
8
18
|
@keyspace = keyspace
|
9
19
|
end
|
10
20
|
|
21
|
+
#
|
22
|
+
# Create this keyspace in the database
|
23
|
+
#
|
24
|
+
# @param options [Options] persistence options for this keyspace.
|
25
|
+
# @option options [String] :class ("SimpleStrategy") the replication
|
26
|
+
# strategy to use for this keyspace
|
27
|
+
# @option options [Integer] :replication_factor (1) the number of
|
28
|
+
# replicas that should exist for each piece of data
|
29
|
+
# @return [void]
|
30
|
+
#
|
31
|
+
# @see TK CQL3 CREATE KEYSPACE documentation
|
32
|
+
#
|
11
33
|
def create!(options = {})
|
12
34
|
bare_connection =
|
13
35
|
Metal::Keyspace.new(keyspace.configuration.except(:keyspace))
|
14
36
|
|
15
37
|
options = options.symbolize_keys
|
16
38
|
options[:class] ||= 'SimpleStrategy'
|
17
|
-
|
39
|
+
if options[:class] == 'SimpleStrategy'
|
40
|
+
options[:replication_factor] ||= 1
|
41
|
+
end
|
18
42
|
options_strs = options.map do |name, value|
|
19
43
|
"'#{name}': #{CassandraCQL::Statement.quote(value)}"
|
20
44
|
end
|
@@ -25,34 +49,111 @@ module Cequel
|
|
25
49
|
CQL
|
26
50
|
end
|
27
51
|
|
52
|
+
#
|
53
|
+
# Drop this keyspace from the database
|
54
|
+
#
|
55
|
+
# @return [void]
|
56
|
+
#
|
57
|
+
# @see TK CQL3 DROP KEYSPACE documentation
|
58
|
+
#
|
28
59
|
def drop!
|
29
60
|
keyspace.execute("DROP KEYSPACE #{keyspace.name}")
|
30
61
|
end
|
31
62
|
|
63
|
+
#
|
64
|
+
# @param name [Symbol] name of the table to read
|
65
|
+
# @return [Table] object representation of the table schema as it
|
66
|
+
# currently exists in the database
|
67
|
+
#
|
32
68
|
def read_table(name)
|
33
69
|
TableReader.read(keyspace, name)
|
34
70
|
end
|
35
71
|
|
72
|
+
#
|
73
|
+
# Create a table in the keyspace
|
74
|
+
#
|
75
|
+
# @param name [Symbol] name of the new table to create
|
76
|
+
# @yield block evaluated in the context of a {CreateTableDSL}
|
77
|
+
# @return [void]
|
78
|
+
#
|
79
|
+
# @example
|
80
|
+
# schema.create_table :posts do
|
81
|
+
# partition_key :blog_subdomain, :text
|
82
|
+
# key :id, :timeuuid
|
83
|
+
#
|
84
|
+
# column :title, :text
|
85
|
+
# column :body, :text
|
86
|
+
# column :author_id, :uuid, :index => true
|
87
|
+
#
|
88
|
+
# with :caching, :all
|
89
|
+
# end
|
90
|
+
#
|
91
|
+
# @see CreateTableDSL
|
92
|
+
#
|
36
93
|
def create_table(name, &block)
|
37
94
|
table = Table.new(name)
|
38
95
|
CreateTableDSL.apply(table, &block)
|
39
96
|
TableWriter.apply(keyspace, table)
|
40
97
|
end
|
41
98
|
|
99
|
+
#
|
100
|
+
# Make changes to an existing table in the keyspace
|
101
|
+
#
|
102
|
+
# @param name [Symbol] the name of the table to alter
|
103
|
+
# @yield block evaluated in the context of an {UpdateTableDSL}
|
104
|
+
# @return [void]
|
105
|
+
#
|
106
|
+
# @example
|
107
|
+
# schema.alter_table :posts do
|
108
|
+
# add_set :categories, :text
|
109
|
+
# rename_column :author_id, :author_uuid
|
110
|
+
# create_index :title
|
111
|
+
# end
|
112
|
+
#
|
113
|
+
# @see UpdateTableDSL
|
114
|
+
#
|
42
115
|
def alter_table(name, &block)
|
43
116
|
updater = TableUpdater.apply(keyspace, name) do |updater|
|
44
117
|
UpdateTableDSL.apply(updater, &block)
|
45
118
|
end
|
46
119
|
end
|
47
120
|
|
121
|
+
#
|
122
|
+
# Remove all data from this table. Truncating a table can be much slower
|
123
|
+
# than simply iterating over its keys and issuing `DELETE` statements,
|
124
|
+
# particularly if the table does not have many rows. Truncating is
|
125
|
+
# equivalent to dropping a table and then recreating it
|
126
|
+
#
|
127
|
+
# @param name [Symbol] name of the table to truncate.
|
128
|
+
# @return [void]
|
129
|
+
#
|
48
130
|
def truncate_table(name)
|
49
131
|
keyspace.execute("TRUNCATE #{name}")
|
50
132
|
end
|
51
133
|
|
134
|
+
#
|
135
|
+
# Drop this table from the keyspace
|
136
|
+
#
|
137
|
+
# @param name [Symbol] name of the table to drop
|
138
|
+
# @return [void]
|
139
|
+
#
|
52
140
|
def drop_table(name)
|
53
141
|
keyspace.execute("DROP TABLE #{name}")
|
54
142
|
end
|
55
143
|
|
144
|
+
#
|
145
|
+
# Create or update a table to match a given schema structure. The desired
|
146
|
+
# schema structure is defined by the directives given in the block; this
|
147
|
+
# is then compared to the existing table in the database (if it is
|
148
|
+
# defined at all), and then the table is created or altered accordingly.
|
149
|
+
#
|
150
|
+
# @param name [Symbol] name of the table to synchronize
|
151
|
+
# @yield (see #create_table)
|
152
|
+
# @return [void]
|
153
|
+
# @raise (see TableSynchronizer#apply)
|
154
|
+
#
|
155
|
+
# @see #create_table Example of DSL usage
|
156
|
+
#
|
56
157
|
def sync_table(name, &block)
|
57
158
|
existing = read_table(name)
|
58
159
|
updated = Table.new(name)
|
@@ -62,10 +163,8 @@ module Cequel
|
|
62
163
|
alias_method :synchronize_table, :sync_table
|
63
164
|
|
64
165
|
protected
|
65
|
-
attr_reader :keyspace
|
66
166
|
|
167
|
+
attr_reader :keyspace
|
67
168
|
end
|
68
|
-
|
69
169
|
end
|
70
|
-
|
71
170
|
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
module Cequel
|
2
|
+
module Schema
|
3
|
+
#
|
4
|
+
# This is a utility class to test that it is possible to perform a given
|
5
|
+
# table schema migration
|
6
|
+
#
|
7
|
+
# @api private
|
8
|
+
#
|
9
|
+
class MigrationValidator
|
10
|
+
extend Forwardable
|
11
|
+
#
|
12
|
+
# Check for various impossible schema changes and raise if any are found
|
13
|
+
#
|
14
|
+
# @param (see #initialize)
|
15
|
+
# @return [void]
|
16
|
+
# @raise (see #validate)
|
17
|
+
#
|
18
|
+
def self.validate!(synchronizer)
|
19
|
+
new(synchronizer).validate!
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# @param synchronizer [TableSynchronizer] the synchronizer to validate
|
24
|
+
#
|
25
|
+
def initialize(synchronizer)
|
26
|
+
@synchronizer = synchronizer
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# Check for various impossible schema changes and raise if any are found
|
31
|
+
#
|
32
|
+
# @raise [InvalidSchemaMigration] if it is impossible to modify existing
|
33
|
+
# table to match desired schema
|
34
|
+
#
|
35
|
+
def validate!
|
36
|
+
assert_keys_match!
|
37
|
+
assert_data_columns_match!
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
attr_reader :synchronizer
|
43
|
+
def_delegators :synchronizer, :each_key_pair,
|
44
|
+
:each_clustering_column_pair, :each_data_column_pair,
|
45
|
+
:existing, :updated
|
46
|
+
|
47
|
+
def assert_keys_match!
|
48
|
+
assert_partition_keys_match!
|
49
|
+
assert_clustering_columns_match!
|
50
|
+
assert_same_key_types!
|
51
|
+
assert_same_clustering_order!
|
52
|
+
end
|
53
|
+
|
54
|
+
def assert_same_key_types!
|
55
|
+
each_key_pair do |old_key, new_key|
|
56
|
+
if old_key.type != new_key.type
|
57
|
+
fail InvalidSchemaMigration,
|
58
|
+
"Can't change type of key column #{old_key.name} from " \
|
59
|
+
"#{old_key.type} to #{new_key.type}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def assert_same_clustering_order!
|
65
|
+
each_clustering_column_pair do |old_key, new_key|
|
66
|
+
if old_key.clustering_order != new_key.clustering_order
|
67
|
+
fail InvalidSchemaMigration,
|
68
|
+
"Can't change the clustering order of #{old_key.name} from " \
|
69
|
+
"#{old_key.clustering_order} to #{new_key.clustering_order}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def assert_partition_keys_match!
|
75
|
+
if existing.partition_key_column_count !=
|
76
|
+
updated.partition_key_column_count
|
77
|
+
|
78
|
+
fail InvalidSchemaMigration,
|
79
|
+
"Existing partition keys " \
|
80
|
+
"#{existing.partition_key_column_names.join(',')} " \
|
81
|
+
"differ from specified partition keys " \
|
82
|
+
"#{updated.partition_key_column_names.join(',')}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def assert_clustering_columns_match!
|
87
|
+
if existing.clustering_column_count != updated.clustering_column_count
|
88
|
+
fail InvalidSchemaMigration,
|
89
|
+
"Existing clustering columns " \
|
90
|
+
"#{existing.clustering_column_names.join(',')} " \
|
91
|
+
"differ from specified clustering keys " \
|
92
|
+
"#{updated.clustering_column_names.join(',')}"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def assert_data_columns_match!
|
97
|
+
each_data_column_pair do |old_column, new_column|
|
98
|
+
if old_column && new_column
|
99
|
+
assert_valid_type_transition!(old_column, new_column)
|
100
|
+
assert_same_column_structure!(old_column, new_column)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def assert_valid_type_transition!(old_column, new_column)
|
106
|
+
if old_column.type != new_column.type
|
107
|
+
valid_new_types = old_column.type.compatible_types
|
108
|
+
unless valid_new_types.include?(new_column.type)
|
109
|
+
fail InvalidSchemaMigration,
|
110
|
+
"Can't change #{old_column.name} from " \
|
111
|
+
"#{old_column.type} to #{new_column.type}. " \
|
112
|
+
"#{old_column.type} columns may only be altered to " \
|
113
|
+
"#{valid_new_types.to_sentence}."
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def assert_same_column_structure!(old_column, new_column)
|
119
|
+
if old_column.class != new_column.class
|
120
|
+
fail InvalidSchemaMigration,
|
121
|
+
"Can't change #{old_column.name} from " \
|
122
|
+
"#{old_column.class.name.demodulize} to " \
|
123
|
+
"#{new_column.class.name.demodulize}"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/lib/cequel/schema/table.rb
CHANGED
@@ -1,19 +1,42 @@
|
|
1
1
|
require 'stringio'
|
2
2
|
|
3
3
|
module Cequel
|
4
|
-
|
5
4
|
module Schema
|
6
|
-
|
5
|
+
#
|
6
|
+
# An object representation of a CQL3 table schema.
|
7
|
+
#
|
8
|
+
# @see Keyspace#read_table
|
9
|
+
#
|
7
10
|
class Table
|
11
|
+
STORAGE_PROPERTIES = %w[
|
12
|
+
bloom_filter_fp_chance caching comment compaction compression
|
13
|
+
dclocal_read_repair_chance gc_grace_seconds read_repair_chance
|
14
|
+
replicate_on_write
|
15
|
+
]
|
8
16
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
# @return [Symbol] the name of the table
|
18
|
+
attr_reader :name
|
19
|
+
# @return [Array<Column>] all columns defined on the table
|
20
|
+
attr_reader :columns
|
21
|
+
# @return [Array<PartitionKey>] partition key columns defined on the
|
22
|
+
# table
|
23
|
+
attr_reader :partition_key_columns
|
24
|
+
# @return [Array<ClusteringColumn>] clustering columns defined on the
|
25
|
+
# table
|
26
|
+
attr_reader :clustering_columns
|
27
|
+
# @return [Array<DataColumn,CollectionColumn>] data columns and
|
28
|
+
# collection columns defined on the table
|
29
|
+
attr_reader :data_columns
|
30
|
+
# @return [Hash] storage properties defined on the table
|
31
|
+
attr_reader :properties
|
32
|
+
# @return [Boolean] `true` if this table is configured with compact
|
33
|
+
# storage
|
15
34
|
attr_writer :compact_storage
|
16
35
|
|
36
|
+
#
|
37
|
+
# @param name [Symbol] the name of the table
|
38
|
+
# @api private
|
39
|
+
#
|
17
40
|
def initialize(name)
|
18
41
|
@name = name
|
19
42
|
@partition_key_columns, @clustering_columns, @data_columns = [], [], []
|
@@ -21,11 +44,24 @@ module Cequel
|
|
21
44
|
@properties = ActiveSupport::HashWithIndifferentAccess.new
|
22
45
|
end
|
23
46
|
|
47
|
+
#
|
48
|
+
# Define a key column. If this is the first key column defined, it will
|
49
|
+
# be a partition key; otherwise, it will be a clustering column.
|
50
|
+
#
|
51
|
+
# @param name [Symbol] the name of the column
|
52
|
+
# @param type [Symbol,Type] the type for the column
|
53
|
+
# @param clustering_order [:asc,:desc] whether rows should be in
|
54
|
+
# ascending or descending order by this column. Only meaningful for
|
55
|
+
# clustering columns.
|
56
|
+
# @return [void]
|
57
|
+
#
|
58
|
+
# @see #add_partition_key
|
59
|
+
#
|
24
60
|
def add_key(name, type, clustering_order = nil)
|
25
61
|
if @partition_key_columns.empty?
|
26
62
|
unless clustering_order.nil?
|
27
|
-
|
28
|
-
|
63
|
+
fail ArgumentError,
|
64
|
+
"Can't set clustering order for partition key #{name}"
|
29
65
|
end
|
30
66
|
add_partition_key(name, type)
|
31
67
|
else
|
@@ -33,82 +69,212 @@ module Cequel
|
|
33
69
|
end
|
34
70
|
end
|
35
71
|
|
72
|
+
#
|
73
|
+
# Define a partition key for the table
|
74
|
+
#
|
75
|
+
# @param name [Symbol] the name of the column
|
76
|
+
# @param type [Symbol,Type] the type for the column
|
77
|
+
# @return [void]
|
78
|
+
#
|
36
79
|
def add_partition_key(name, type)
|
37
80
|
PartitionKey.new(name, type(type)).tap do |column|
|
38
81
|
@partition_key_columns << add_column(column)
|
39
82
|
end
|
40
83
|
end
|
41
84
|
|
85
|
+
#
|
86
|
+
# Define a clustering column for the table
|
87
|
+
#
|
88
|
+
# @param (see #add_key)
|
89
|
+
# @return [void]
|
90
|
+
#
|
42
91
|
def add_clustering_column(name, type, clustering_order = nil)
|
43
|
-
ClusteringColumn.new(name, type(type), clustering_order)
|
44
|
-
@clustering_columns << add_column(column)
|
45
|
-
end
|
92
|
+
ClusteringColumn.new(name, type(type), clustering_order)
|
93
|
+
.tap { |column| @clustering_columns << add_column(column) }
|
46
94
|
end
|
47
95
|
|
48
|
-
|
96
|
+
#
|
97
|
+
# Define a data column on the table
|
98
|
+
#
|
99
|
+
# @param name [Symbol] name of the column
|
100
|
+
# @param type [Type] type for the column
|
101
|
+
# @param options [Options] options for the column
|
102
|
+
# @option options [Boolean,Symbol] :index (nil) name of a secondary index
|
103
|
+
# to apply to the column, or `true` to infer an index name by
|
104
|
+
# convention
|
105
|
+
# @return [void]
|
106
|
+
#
|
107
|
+
def add_data_column(name, type, options = {})
|
108
|
+
options = {index: options} unless options.is_a?(Hash)
|
109
|
+
index_name = options[:index]
|
49
110
|
index_name = :"#{@name}_#{name}_idx" if index_name == true
|
50
|
-
DataColumn.new(name, type(type), index_name)
|
51
|
-
tap { |column| @data_columns << add_column(column) }
|
111
|
+
DataColumn.new(name, type(type), index_name)
|
112
|
+
.tap { |column| @data_columns << add_column(column) }
|
52
113
|
end
|
53
114
|
|
115
|
+
#
|
116
|
+
# Define a list column on the table
|
117
|
+
#
|
118
|
+
# @param name [Symbol] name of the list
|
119
|
+
# @param type [Symbol,Type] type of the list's elements
|
120
|
+
# @return [void]
|
121
|
+
#
|
122
|
+
# @see List
|
123
|
+
#
|
54
124
|
def add_list(name, type)
|
55
125
|
List.new(name, type(type)).tap do |column|
|
56
126
|
@data_columns << add_column(column)
|
57
127
|
end
|
58
128
|
end
|
59
129
|
|
130
|
+
#
|
131
|
+
# Define a set column on the table
|
132
|
+
#
|
133
|
+
# @param name [Symbol] name of the set
|
134
|
+
# @param type [Symbol,Type] type of the set's elements
|
135
|
+
# @return [void]
|
136
|
+
#
|
137
|
+
# @see Set
|
138
|
+
#
|
60
139
|
def add_set(name, type)
|
61
140
|
Set.new(name, type(type)).tap do |column|
|
62
141
|
@data_columns << add_column(column)
|
63
142
|
end
|
64
143
|
end
|
65
144
|
|
145
|
+
#
|
146
|
+
# Define a map column on the table
|
147
|
+
#
|
148
|
+
# @param name [Symbol] name of the set
|
149
|
+
# @param key_type [Symbol,Type] type of the map's keys
|
150
|
+
# @param value_type [Symbol,Type] type of the map's values
|
151
|
+
# @return [void]
|
152
|
+
#
|
153
|
+
# @see Map
|
154
|
+
#
|
66
155
|
def add_map(name, key_type, value_type)
|
67
156
|
Map.new(name, type(key_type), type(value_type)).tap do |column|
|
68
157
|
@data_columns << add_column(column)
|
69
158
|
end
|
70
159
|
end
|
71
160
|
|
161
|
+
#
|
162
|
+
# Define a storage property for the table
|
163
|
+
#
|
164
|
+
# @param name [Symbol] name of the property
|
165
|
+
# @param value value for the property
|
166
|
+
# @return [void]
|
167
|
+
#
|
168
|
+
# @see STORAGE_PROPERTIES List of storage property names
|
169
|
+
# @see TK list of CQL3 table storage properties
|
170
|
+
#
|
72
171
|
def add_property(name, value)
|
73
|
-
TableProperty.
|
172
|
+
TableProperty.build(name, value).tap do |property|
|
74
173
|
@properties[name] = property
|
75
174
|
end
|
76
175
|
end
|
77
176
|
|
177
|
+
#
|
178
|
+
# @param name [Symbol] name of column to look up
|
179
|
+
# @return [Column] column defined on table with given name
|
180
|
+
#
|
78
181
|
def column(name)
|
79
182
|
columns_by_name[name.to_sym]
|
80
183
|
end
|
81
184
|
|
185
|
+
#
|
186
|
+
# @return [Array<Column>] all key columns (partition + clustering)
|
187
|
+
#
|
82
188
|
def key_columns
|
83
189
|
@partition_key_columns + @clustering_columns
|
84
190
|
end
|
85
191
|
|
192
|
+
#
|
193
|
+
# @return [Array<Symbol>] names of all key columns (partition +
|
194
|
+
# clustering)
|
195
|
+
#
|
86
196
|
def key_column_names
|
87
197
|
key_columns.map { |key| key.name }
|
88
198
|
end
|
89
199
|
|
200
|
+
#
|
201
|
+
# @return [Integer] total number of key columns
|
202
|
+
#
|
203
|
+
def key_column_count
|
204
|
+
key_columns.length
|
205
|
+
end
|
206
|
+
|
207
|
+
#
|
208
|
+
# @return [Array<Symbol>] names of partition key columns
|
209
|
+
#
|
210
|
+
def partition_key_column_names
|
211
|
+
partition_key_columns.map { |key| key.name }
|
212
|
+
end
|
213
|
+
|
214
|
+
#
|
215
|
+
# @return [Integer] number of partition key columns
|
216
|
+
#
|
217
|
+
def partition_key_column_count
|
218
|
+
partition_key_columns.length
|
219
|
+
end
|
220
|
+
|
221
|
+
#
|
222
|
+
# @return [Array<Symbol>] names of clustering columns
|
223
|
+
#
|
224
|
+
def clustering_column_names
|
225
|
+
clustering_columns.map { |key| key.name }
|
226
|
+
end
|
227
|
+
|
228
|
+
#
|
229
|
+
# @return [Integer] number of clustering columns
|
230
|
+
#
|
231
|
+
def clustering_column_count
|
232
|
+
clustering_columns.length
|
233
|
+
end
|
234
|
+
|
235
|
+
#
|
236
|
+
# @param name [Symbol] name of partition key column to look up
|
237
|
+
# @return [PartitionKey] partition key column with given name
|
238
|
+
#
|
90
239
|
def partition_key(name)
|
91
240
|
@partition_key_columns.find { |column| column.name == name }
|
92
241
|
end
|
93
242
|
|
243
|
+
#
|
244
|
+
# @param name [Symbol] name of clustering column to look up
|
245
|
+
# @return [ClusteringColumn] clustering column with given name
|
246
|
+
#
|
94
247
|
def clustering_column(name)
|
95
248
|
@clustering_columns.find { |column| column.name == name }
|
96
249
|
end
|
97
250
|
|
251
|
+
#
|
252
|
+
# @param name [Symbol] name of data column to look up
|
253
|
+
# @return [DataColumn,CollectionColumn] data column or collection column
|
254
|
+
# with given name
|
255
|
+
#
|
98
256
|
def data_column(name)
|
99
257
|
name = name.to_sym
|
100
258
|
@data_columns.find { |column| column.name == name }
|
101
259
|
end
|
102
260
|
|
261
|
+
#
|
262
|
+
# @param name [Symbol] name of property to look up
|
263
|
+
# @return [TableProperty] property as defined on table
|
264
|
+
#
|
103
265
|
def property(name)
|
104
266
|
@properties[name].try(:value)
|
105
267
|
end
|
106
268
|
|
269
|
+
#
|
270
|
+
# @return [Boolean] `true` if this table uses compact storage
|
271
|
+
#
|
107
272
|
def compact_storage?
|
108
273
|
!!@compact_storage
|
109
274
|
end
|
110
275
|
|
111
276
|
protected
|
277
|
+
|
112
278
|
attr_reader :columns_by_name
|
113
279
|
|
114
280
|
private
|
@@ -121,9 +287,6 @@ module Cequel
|
|
121
287
|
def type(type)
|
122
288
|
::Cequel::Type[type]
|
123
289
|
end
|
124
|
-
|
125
290
|
end
|
126
|
-
|
127
291
|
end
|
128
|
-
|
129
292
|
end
|