cequel 2.1.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +2 -2
- data/README.md +8 -0
- data/lib/cequel/errors.rb +2 -0
- data/lib/cequel/metal/new_relic_instrumentation.rb +2 -1
- data/lib/cequel/record.rb +8 -0
- data/lib/cequel/record/schema.rb +30 -23
- data/lib/cequel/schema.rb +3 -2
- data/lib/cequel/schema/column.rb +11 -1
- data/lib/cequel/schema/keyspace.rb +18 -7
- data/lib/cequel/schema/patch.rb +152 -0
- data/lib/cequel/schema/table.rb +55 -137
- data/lib/cequel/schema/table_desc_dsl.rb +196 -0
- data/lib/cequel/schema/table_differ.rb +112 -0
- data/lib/cequel/schema/table_property.rb +14 -0
- data/lib/cequel/schema/table_reader.rb +81 -85
- data/lib/cequel/schema/table_updater.rb +0 -17
- data/lib/cequel/schema/table_writer.rb +10 -9
- data/lib/cequel/version.rb +1 -1
- data/spec/examples/metal/data_set_spec.rb +156 -153
- data/spec/examples/metal/keyspace_spec.rb +4 -4
- data/spec/examples/record/associations_spec.rb +6 -0
- data/spec/examples/record/mass_assignment_spec.rb +2 -2
- data/spec/examples/record/properties_spec.rb +1 -0
- data/spec/examples/record/record_set_spec.rb +1 -1
- data/spec/examples/schema/patch_spec.rb +190 -0
- data/spec/examples/schema/table_differ_spec.rb +280 -0
- data/spec/examples/schema/table_reader_spec.rb +379 -354
- data/spec/examples/schema/table_updater_spec.rb +0 -12
- data/spec/examples/spec_helper.rb +5 -5
- data/spec/examples/spec_support/preparation_spec.rb +4 -0
- data/spec/support/helpers.rb +23 -0
- metadata +9 -6
- data/lib/cequel/schema/create_table_dsl.rb +0 -88
- data/lib/cequel/schema/table_synchronizer.rb +0 -180
- data/spec/examples/schema/table_synchronizer_spec.rb +0 -200
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c970b068b50a1215dc4bf58af07dfc5b1b936214
|
4
|
+
data.tar.gz: c7470426d1cac668b2bd698d7f35608835b2bf0a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ce7dfd8aa2d73dc6d6748a789b4cd84ab137fb7c3d98bc70df830c6f64d8fb86a0e4e3fb26de6ce0d0c8167db8fcb8a0a2e3c57799f6847cf239db0ae73e4e0
|
7
|
+
data.tar.gz: 886e98099ef58ee431a76f4560e89ad10e3146a0850293671aa8bef45b852fa1bcdab41d2968639ec24dd7bfcba45c516ac88bf1de0f119f3fecf8b15a0eda95
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## 3.0.0
|
2
|
+
* Drop support for changing the type of cluster keys as it is no longer support by Cassandra.
|
3
|
+
* Drop support for non-option based index specification in table schema DSL. For example, `column :author_name, :text, true` must be rewritten as `column :author_name, :text, index: true`.
|
4
|
+
* Fix Relic instrumentation for batch statements [PR 361](https://github.com/cequel/cequel/pull/361)
|
5
|
+
* Don't set table name when it is already present [PR 364](https://github.com/cequel/cequel/pull/364)
|
6
|
+
|
1
7
|
## 2.1.0
|
2
8
|
|
3
9
|
* Add ActiveRecord::Enum like support `column :status, :enum, values: { open: 1, closed: 2 }` ([PR 354](https://github.com/cequel/cequel/pull/354))
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -612,6 +612,14 @@ you require this functionality.
|
|
612
612
|
|
613
613
|
## Breaking API changes
|
614
614
|
|
615
|
+
### 3.0
|
616
|
+
|
617
|
+
* Dropped support for changing the type of cluster keys because the ability has
|
618
|
+
been removed from Cassandra. Calls to `#change_column` must be removed.
|
619
|
+
* Dropped support for previously deprecated signature of the `#column` method
|
620
|
+
of schema DSL. Uses like `column :my_column, :text, true` must be rewritten
|
621
|
+
as `#column :my_column, :text, indexed: true`
|
622
|
+
|
615
623
|
### 2.0
|
616
624
|
|
617
625
|
* dropped support for jruby (Due to difficult to work around bugs in jruby. PRs welcome to restore jruby compatibility.)
|
data/lib/cequel/errors.rb
CHANGED
@@ -16,7 +16,7 @@ module Cequel
|
|
16
16
|
define_method :execute_with_options_with_newrelic do |statement, options|
|
17
17
|
|
18
18
|
operation = nil
|
19
|
-
statement_txt = nil
|
19
|
+
statement_txt = nil
|
20
20
|
statement_words = nil
|
21
21
|
|
22
22
|
if statement.is_a?(::Cequel::Metal::Statement)
|
@@ -25,6 +25,7 @@ module Cequel
|
|
25
25
|
operation = statement_words.first.downcase
|
26
26
|
elsif statement.is_a?(::Cassandra::Statements::Batch)
|
27
27
|
operation = "batch"
|
28
|
+
statement_txt = 'BEGIN BATCH'
|
28
29
|
end
|
29
30
|
|
30
31
|
callback = Proc.new do |result, scoped_metric, elapsed|
|
data/lib/cequel/record.rb
CHANGED
@@ -136,6 +136,14 @@ module Cequel
|
|
136
136
|
weak_descendants << WeakRef.new(base)
|
137
137
|
end
|
138
138
|
|
139
|
+
# This is probably not the method you are looking for.
|
140
|
+
#
|
141
|
+
# Clear descendants list. Useful in tests to ensure bogus record classes
|
142
|
+
# are not synced.
|
143
|
+
def forget_all_descendants!
|
144
|
+
weak_descendants.clear
|
145
|
+
end
|
146
|
+
|
139
147
|
private
|
140
148
|
|
141
149
|
def weak_descendants
|
data/lib/cequel/record/schema.rb
CHANGED
@@ -20,7 +20,7 @@ module Cequel
|
|
20
20
|
|
21
21
|
included do
|
22
22
|
class_attribute :table_name, instance_writer: false
|
23
|
-
self.table_name = name.demodulize.tableize.to_sym unless name.nil?
|
23
|
+
self.table_name = name.demodulize.tableize.to_sym unless name.nil? || self.table_name.present?
|
24
24
|
end
|
25
25
|
|
26
26
|
#
|
@@ -80,21 +80,24 @@ module Cequel
|
|
80
80
|
# @return [void]
|
81
81
|
#
|
82
82
|
def synchronize_schema
|
83
|
-
reader = get_table_reader
|
84
|
-
return if reader.materialized_view?
|
85
|
-
Cequel::Schema::TableSynchronizer
|
86
|
-
.apply(connection, reader.read, table_schema)
|
87
|
-
end
|
88
|
-
|
89
|
-
#
|
90
|
-
# Return a {TableReader} instance
|
91
|
-
#
|
92
|
-
# @return [Schema::TableReader] object
|
93
|
-
#
|
94
|
-
def get_table_reader
|
95
83
|
fail MissingTableNameError unless table_name
|
96
84
|
|
97
|
-
|
85
|
+
patch =
|
86
|
+
begin
|
87
|
+
existing_table_descriptor = Cequel::Schema::TableReader.read(connection,
|
88
|
+
table_name)
|
89
|
+
|
90
|
+
return if existing_table_descriptor.materialized_view?
|
91
|
+
|
92
|
+
Cequel::Schema::TableDiffer.new(existing_table_descriptor,
|
93
|
+
table_schema)
|
94
|
+
.call
|
95
|
+
|
96
|
+
rescue NoSuchTableError
|
97
|
+
Cequel::Schema::TableWriter.new(table_schema)
|
98
|
+
end
|
99
|
+
|
100
|
+
patch.statements.each { |stmt| connection.execute(stmt) }
|
98
101
|
end
|
99
102
|
|
100
103
|
#
|
@@ -113,46 +116,50 @@ module Cequel
|
|
113
116
|
# specified in the class definition
|
114
117
|
#
|
115
118
|
def table_schema
|
116
|
-
|
119
|
+
dsl.table
|
117
120
|
end
|
118
121
|
|
119
122
|
protected
|
120
123
|
|
124
|
+
def dsl
|
125
|
+
@dsl ||= Cequel::Schema::TableDescDsl.new(table_name)
|
126
|
+
end
|
127
|
+
|
121
128
|
def key(name, type, options = {})
|
122
129
|
super
|
123
130
|
if options[:partition]
|
124
|
-
|
131
|
+
dsl.partition_key(name, type)
|
125
132
|
else
|
126
|
-
|
133
|
+
dsl.key(name, type, options[:order])
|
127
134
|
end
|
128
135
|
end
|
129
136
|
|
130
137
|
def column(name, type, options = {})
|
131
138
|
super
|
132
|
-
|
139
|
+
dsl.column(name, type, options)
|
133
140
|
end
|
134
141
|
|
135
142
|
def list(name, type, options = {})
|
136
143
|
super
|
137
|
-
|
144
|
+
dsl.list(name, type)
|
138
145
|
end
|
139
146
|
|
140
147
|
def set(name, type, options = {})
|
141
148
|
super
|
142
|
-
|
149
|
+
dsl.set(name, type)
|
143
150
|
end
|
144
151
|
|
145
152
|
def map(name, key_type, value_type, options = {})
|
146
153
|
super
|
147
|
-
|
154
|
+
dsl.map(name, key_type, value_type)
|
148
155
|
end
|
149
156
|
|
150
157
|
def table_property(name, value)
|
151
|
-
|
158
|
+
dsl.with(name, value)
|
152
159
|
end
|
153
160
|
|
154
161
|
def compact_storage
|
155
|
-
|
162
|
+
dsl.compact_storage
|
156
163
|
end
|
157
164
|
end
|
158
165
|
|
data/lib/cequel/schema.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
require 'cequel/schema/column'
|
3
|
-
require 'cequel/schema/
|
3
|
+
require 'cequel/schema/table_desc_dsl'
|
4
4
|
require 'cequel/schema/keyspace'
|
5
5
|
require 'cequel/schema/migration_validator'
|
6
6
|
require 'cequel/schema/table'
|
7
7
|
require 'cequel/schema/table_property'
|
8
8
|
require 'cequel/schema/table_reader'
|
9
|
-
require 'cequel/schema/
|
9
|
+
require 'cequel/schema/table_differ'
|
10
|
+
require 'cequel/schema/patch'
|
10
11
|
require 'cequel/schema/table_updater'
|
11
12
|
require 'cequel/schema/table_writer'
|
12
13
|
require 'cequel/schema/update_table_dsl'
|
data/lib/cequel/schema/column.rb
CHANGED
@@ -71,6 +71,15 @@ module Cequel
|
|
71
71
|
false
|
72
72
|
end
|
73
73
|
|
74
|
+
# Indicates if this column is indexed. Overridden by subclasses that
|
75
|
+
# support indexing.
|
76
|
+
#
|
77
|
+
# @return [Boolean] true if this column has a secondary index
|
78
|
+
#
|
79
|
+
def indexed?
|
80
|
+
false
|
81
|
+
end
|
82
|
+
|
74
83
|
#
|
75
84
|
# @param type_in [Symbol,Type] type to check against
|
76
85
|
# @return [Boolean] true if this column has the type given by `type_in`
|
@@ -96,7 +105,7 @@ module Cequel
|
|
96
105
|
# @api private
|
97
106
|
#
|
98
107
|
def to_cql
|
99
|
-
"#{@name} #{@type}
|
108
|
+
%Q|"#{@name}" #{@type}|
|
100
109
|
end
|
101
110
|
|
102
111
|
#
|
@@ -107,6 +116,7 @@ module Cequel
|
|
107
116
|
def ==(other)
|
108
117
|
to_cql == other.to_cql
|
109
118
|
end
|
119
|
+
alias_method :eql?, :==
|
110
120
|
|
111
121
|
#
|
112
122
|
# @return [String] the column's name
|
@@ -52,7 +52,7 @@ module Cequel
|
|
52
52
|
}
|
53
53
|
|
54
54
|
options = options.symbolize_keys
|
55
|
-
options.reverse_merge!(keyspace.configuration)
|
55
|
+
options.reverse_merge!(keyspace.configuration.symbolize_keys)
|
56
56
|
options.reverse_merge!(default_options)
|
57
57
|
|
58
58
|
if options.key?(:class)
|
@@ -148,8 +148,7 @@ module Cequel
|
|
148
148
|
# @see CreateTableDSL
|
149
149
|
#
|
150
150
|
def create_table(name, &block)
|
151
|
-
table =
|
152
|
-
CreateTableDSL.apply(table, &block)
|
151
|
+
table = TableDescDsl.new(name).eval(&block)
|
153
152
|
TableWriter.apply(keyspace, table)
|
154
153
|
end
|
155
154
|
|
@@ -224,13 +223,25 @@ module Cequel
|
|
224
223
|
# @see #create_table Example of DSL usage
|
225
224
|
#
|
226
225
|
def sync_table(name, &block)
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
226
|
+
new_table_desc = TableDescDsl.new(name).eval(&block)
|
227
|
+
patch = if has_table?(name)
|
228
|
+
existing_table_desc = read_table(name)
|
229
|
+
TableDiffer.new(existing_table_desc, new_table_desc).call
|
230
|
+
else
|
231
|
+
TableWriter.new(new_table_desc) # close enough to a patch
|
232
|
+
end
|
233
|
+
|
234
|
+
patch.statements.each{|stmt| keyspace.execute(stmt) }
|
231
235
|
end
|
232
236
|
alias_method :synchronize_table, :sync_table
|
233
237
|
|
238
|
+
|
239
|
+
# Returns true iff the specified table name exists in the keyspace.
|
240
|
+
#
|
241
|
+
def has_table?(table_name)
|
242
|
+
!!read_table(table_name)
|
243
|
+
end
|
244
|
+
|
234
245
|
protected
|
235
246
|
|
236
247
|
attr_reader :keyspace
|
@@ -0,0 +1,152 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Cequel
|
3
|
+
module Schema
|
4
|
+
#
|
5
|
+
# The set of changes needed to transform a table from its current form to a
|
6
|
+
# desired form. `Patch`es are immutable.
|
7
|
+
#
|
8
|
+
class Patch
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
protected def initialize(changes)
|
12
|
+
@changes = changes
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :changes
|
16
|
+
|
17
|
+
def_delegator :changes, :empty?
|
18
|
+
|
19
|
+
def statements
|
20
|
+
changes.map(&:to_cql)
|
21
|
+
end
|
22
|
+
|
23
|
+
class AbstractChange
|
24
|
+
protected def initialize(table, *post_init_args)
|
25
|
+
@table = table
|
26
|
+
|
27
|
+
post_init(*post_init_args)
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_reader :table
|
31
|
+
|
32
|
+
def to_cql
|
33
|
+
fail NotImplementedError
|
34
|
+
end
|
35
|
+
|
36
|
+
def inspect
|
37
|
+
"#<#{self.class.name} #{to_cql}>"
|
38
|
+
end
|
39
|
+
|
40
|
+
def ==(other)
|
41
|
+
other.class == self.class &&
|
42
|
+
other.table == self.table &&
|
43
|
+
subclass_eql?(other)
|
44
|
+
end
|
45
|
+
|
46
|
+
def eql?(other)
|
47
|
+
self == other
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
def subclass_eql?(other)
|
53
|
+
fail NotImplementedError
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class SetTableProperties < AbstractChange
|
58
|
+
protected def post_init()
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_cql
|
62
|
+
%Q|ALTER TABLE "#{table.name}" WITH #{properties.map(&:to_cql).join(' AND ')}|
|
63
|
+
end
|
64
|
+
|
65
|
+
def properties
|
66
|
+
table.properties.values
|
67
|
+
end
|
68
|
+
|
69
|
+
protected
|
70
|
+
|
71
|
+
def subclass_eql?(other)
|
72
|
+
other.properties == propreties
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class DropIndex < AbstractChange
|
77
|
+
protected def post_init(column_with_obsolete_idx)
|
78
|
+
@index_name = column_with_obsolete_idx.index_name
|
79
|
+
end
|
80
|
+
|
81
|
+
attr_reader :index_name
|
82
|
+
|
83
|
+
def to_cql
|
84
|
+
%Q|DROP INDEX IF EXISTS "#{index_name}"|
|
85
|
+
end
|
86
|
+
|
87
|
+
protected
|
88
|
+
|
89
|
+
def subclass_eql?(other)
|
90
|
+
other.index_name == index_name
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class AddIndex < AbstractChange
|
95
|
+
protected def post_init(column)
|
96
|
+
@column = column
|
97
|
+
@index_name = column.index_name
|
98
|
+
end
|
99
|
+
|
100
|
+
attr_reader :column, :index_name
|
101
|
+
|
102
|
+
def to_cql
|
103
|
+
%Q|CREATE INDEX "#{index_name}" ON "#{table.name}" ("#{column.name}")|
|
104
|
+
end
|
105
|
+
|
106
|
+
protected
|
107
|
+
|
108
|
+
def subclass_eql?(other)
|
109
|
+
other.column == column &&
|
110
|
+
other.index_name == index_name
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
class AddColumn < AbstractChange
|
115
|
+
protected def post_init(column)
|
116
|
+
@column = column
|
117
|
+
end
|
118
|
+
|
119
|
+
attr_reader :column
|
120
|
+
|
121
|
+
def to_cql
|
122
|
+
%Q|ALTER TABLE "#{table.name}" ADD #{column.to_cql}|
|
123
|
+
end
|
124
|
+
|
125
|
+
protected
|
126
|
+
|
127
|
+
def subclass_eql?(other)
|
128
|
+
other.column == column
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
class RenameColumn < AbstractChange
|
133
|
+
protected def post_init(old_column, new_column)
|
134
|
+
@old_name, @new_name = old_column.name, new_column.name
|
135
|
+
end
|
136
|
+
|
137
|
+
attr_reader :old_name, :new_name
|
138
|
+
|
139
|
+
def to_cql
|
140
|
+
%Q|ALTER TABLE "#{table.name}" RENAME "#{old_name}" TO "#{new_name}"|
|
141
|
+
end
|
142
|
+
|
143
|
+
protected
|
144
|
+
|
145
|
+
def subclass_eql?(other)
|
146
|
+
other.old_name == old_name &&
|
147
|
+
other.new_name == new_name
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|