cequel 2.0.3 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/Gemfile +1 -2
- data/Gemfile.lock +5 -8
- data/README.md +27 -29
- data/Rakefile +2 -1
- data/lib/cequel/instrumentation.rb +1 -1
- data/lib/cequel/metal/data_set.rb +20 -1
- data/lib/cequel/metal/policy/cassandra_error.rb +1 -1
- data/lib/cequel/record/data_set_builder.rb +9 -1
- data/lib/cequel/record/properties.rb +37 -0
- data/lib/cequel/record/record_set.rb +20 -3
- data/lib/cequel/schema/keyspace.rb +6 -4
- data/lib/cequel/schema/table.rb +3 -0
- data/lib/cequel/version.rb +1 -1
- data/spec/examples/metal/keyspace_spec.rb +54 -40
- data/spec/examples/record/properties_spec.rb +13 -1
- data/spec/examples/record/record_set_spec.rb +6 -0
- data/spec/examples/spec_helper.rb +12 -4
- data/spec/examples/spec_support/preparation_spec.rb +1 -1
- metadata +18 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31fac6cdfcc42c42c1cd03489d11aa97e4791193
|
4
|
+
data.tar.gz: 5d86e45f0dac711e70936c61ff7a4879095b28d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4a4696642f07aed6bf5e777b57fd48a9f570eb7ae370e31f8b37d92770874b9d25b0b72d0159dc3501d2d94671e0845f33119895cadc4bbe3498c668ee38fe7
|
7
|
+
data.tar.gz: 7600517db78e87916d1f40584d21f181388ee91b2c21a73d26db17a598ce5c4bbee627ed26cfab4c33f0a84908bd568ab3e0cd9df67df76eec1eaa4242c5969c
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## 2.1.0
|
2
|
+
|
3
|
+
* Add ActiveRecord::Enum like support `column :status, :enum, values: { open: 1, closed: 2 }` ([PR 354](https://github.com/cequel/cequel/pull/354))
|
4
|
+
* Fix bug CQL statement execution error handling ([PR 357](https://github.com/cequel/cequel/pull/357)
|
5
|
+
* Documentation fixes ([PR 355](https://github.com/cequel/cequel/pull/355))
|
6
|
+
* Add support for `ALLOW FILTERING` queries ([PR 353](https://github.com/cequel/cequel/pull/353))
|
7
|
+
* Add support for `IF EXISTS` to schema modifications ([PR 349](https://github.com/cequel/cequel/pull/349))
|
8
|
+
* Make `test` the default rake tast ([PR 348](https://github.com/cequel/cequel/pull/348))
|
9
|
+
|
1
10
|
## 2.0.3
|
2
11
|
|
3
12
|
* Add synchronization around use of @cluster and other variables Fix ([PR 333](https://github.com/cequel/cequel/pull/333))
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
cequel (2.0
|
4
|
+
cequel (2.1.0)
|
5
5
|
activemodel (>= 4.0)
|
6
6
|
cassandra-driver (~> 3.0)
|
7
7
|
|
@@ -30,12 +30,7 @@ GEM
|
|
30
30
|
coderay (1.1.1)
|
31
31
|
columnize (0.9.0)
|
32
32
|
concurrent-ruby (1.0.2)
|
33
|
-
debugger (1.6.8)
|
34
|
-
columnize (>= 0.3.1)
|
35
|
-
debugger-linecache (~> 1.2.0)
|
36
|
-
debugger-ruby_core_source (~> 1.3.5)
|
37
33
|
debugger-linecache (1.2.0)
|
38
|
-
debugger-ruby_core_source (1.3.8)
|
39
34
|
diff-lcs (1.2.5)
|
40
35
|
ethon (0.9.1)
|
41
36
|
ffi (>= 1.3.0)
|
@@ -103,6 +98,8 @@ GEM
|
|
103
98
|
rspec-mocks (3.5.0)
|
104
99
|
diff-lcs (>= 1.2.0, < 2.0)
|
105
100
|
rspec-support (~> 3.5.0)
|
101
|
+
rspec-retry (0.5.3)
|
102
|
+
rspec-core (> 3.3, < 3.6)
|
106
103
|
rspec-support (3.5.0)
|
107
104
|
rubocop (0.43.0)
|
108
105
|
parser (>= 2.3.1.1, < 3.0)
|
@@ -345,13 +342,13 @@ DEPENDENCIES
|
|
345
342
|
appraisal (~> 1.0)
|
346
343
|
byebug (~> 2.7)
|
347
344
|
cequel!
|
348
|
-
debugger (~> 1.6)
|
349
345
|
pry (~> 0.9)
|
350
346
|
psych (~> 2.0)
|
351
347
|
racc (~> 1.4)
|
352
348
|
rake (~> 10.1)
|
353
|
-
rspec (~> 3.
|
349
|
+
rspec (~> 3.5)
|
354
350
|
rspec-its (~> 1.0)
|
351
|
+
rspec-retry (~> 0.5)
|
355
352
|
rubocop
|
356
353
|
rubysl (~> 2.0)
|
357
354
|
timecop (~> 0.7)
|
data/README.md
CHANGED
@@ -159,6 +159,8 @@ To add timestamp columns, simply use the `timestamps` class macro:
|
|
159
159
|
|
160
160
|
```ruby
|
161
161
|
class Blog
|
162
|
+
include Cequel::Record
|
163
|
+
|
162
164
|
key :subdomain, :text
|
163
165
|
column :name, :text
|
164
166
|
timestamps
|
@@ -171,6 +173,29 @@ populate them appropriately on save.
|
|
171
173
|
If the creation time can be extracted from the primary key as outlined above,
|
172
174
|
this method will be preferred and no `created_at` column will be defined.
|
173
175
|
|
176
|
+
### Enums ###
|
177
|
+
|
178
|
+
If your a column should behave like an `ActiveRecord::Enum` you can use the
|
179
|
+
column type `:enum`. It will be handled by the data-type `:int` and expose some
|
180
|
+
helper methods on the model:
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
class Blog
|
184
|
+
include Cequel::Record
|
185
|
+
|
186
|
+
key :subdomain, :text
|
187
|
+
column :name, :text
|
188
|
+
column :status, :enum, values: { open: 1, closed: 2 }
|
189
|
+
end
|
190
|
+
|
191
|
+
blog = Blog.new(status: :open)
|
192
|
+
blog.open? # true
|
193
|
+
blog.closed? # false
|
194
|
+
blog.status # :open
|
195
|
+
|
196
|
+
Blog.status # { open: 1, closed: 2 }
|
197
|
+
```
|
198
|
+
|
174
199
|
### Schema synchronization ###
|
175
200
|
|
176
201
|
Cequel will automatically synchronize the schema stored in Cassandra to match
|
@@ -608,35 +633,8 @@ See
|
|
608
633
|
|
609
634
|
## Credits ##
|
610
635
|
|
611
|
-
Cequel was written by
|
612
|
-
|
613
|
-
* Mat Brown
|
614
|
-
* Aubrey Holland
|
615
|
-
* Keenan Brock
|
616
|
-
* Insoo Buzz Jung
|
617
|
-
* Louis Simoneau
|
618
|
-
* Peter Williams
|
619
|
-
* Kenneth Hoffman
|
620
|
-
* Antti Tapio
|
621
|
-
* Ilya Bazylchuk
|
622
|
-
* Dan Cardamore
|
623
|
-
* Kei Kusakari
|
624
|
-
* Oleh Novosad
|
625
|
-
* John Smart
|
626
|
-
* Angelo Lakra
|
627
|
-
* Olivier Lance
|
628
|
-
* Tomohiro Nishimura
|
629
|
-
* Masaki Takahashi
|
630
|
-
* G Gordon Worley III
|
631
|
-
* Clark Bremer
|
632
|
-
* Tamara Temple
|
633
|
-
* Long On
|
634
|
-
* Lucas Mundim
|
635
|
-
* Luke Duncalfe
|
636
|
-
* Eric Betts
|
637
|
-
* Maxim Dobryakov
|
638
|
-
* Yi-Cyuan Chen
|
639
|
-
* Justin Hannus
|
636
|
+
Cequel was written by an [awesome lot](https://github.com/cequel/cequel/graphs/contributors). Thanks to you all.
|
637
|
+
|
640
638
|
|
641
639
|
Special thanks to [Brewster](http://www.brewster.com), which supported the 0.x
|
642
640
|
releases of Cequel.
|
data/Rakefile
CHANGED
@@ -8,7 +8,8 @@ require File.expand_path('../lib/cequel/version', __FILE__)
|
|
8
8
|
|
9
9
|
RUBY_VERSIONS = YAML.load_file(File.expand_path('../.travis.yml', __FILE__))['rvm']
|
10
10
|
|
11
|
-
task :
|
11
|
+
task default: :test
|
12
|
+
|
12
13
|
task :release => [
|
13
14
|
:verify_changelog,
|
14
15
|
:"test:all",
|
@@ -14,7 +14,7 @@ module Cequel
|
|
14
14
|
# Example:
|
15
15
|
#
|
16
16
|
# extend Instrumentation
|
17
|
-
# instrument :create, "create.cequel",
|
17
|
+
# instrument :create, data: {topic: "create.cequel", table_name: table_name}
|
18
18
|
#
|
19
19
|
# @param method_name [Symbol,String] The method to instrument
|
20
20
|
#
|
@@ -50,6 +50,7 @@ module Cequel
|
|
50
50
|
attr_reader :query_consistency
|
51
51
|
attr_reader :query_page_size
|
52
52
|
attr_reader :query_paging_state
|
53
|
+
attr_reader :allow_filtering
|
53
54
|
|
54
55
|
def_delegator :keyspace, :write_with_options
|
55
56
|
|
@@ -573,6 +574,15 @@ module Cequel
|
|
573
574
|
end
|
574
575
|
end
|
575
576
|
|
577
|
+
#
|
578
|
+
# @see RecordSet#allow_filtering!
|
579
|
+
#
|
580
|
+
def allow_filtering!
|
581
|
+
clone.tap do |data_set|
|
582
|
+
data_set.allow_filtering = true
|
583
|
+
end
|
584
|
+
end
|
585
|
+
|
576
586
|
def paging_state(paging_state)
|
577
587
|
clone.tap do |data_set|
|
578
588
|
data_set.query_paging_state = paging_state
|
@@ -645,6 +655,7 @@ module Cequel
|
|
645
655
|
.append(*row_specifications_cql)
|
646
656
|
.append(sort_order_cql)
|
647
657
|
.append(limit_cql)
|
658
|
+
.append(allow_filtering_cql)
|
648
659
|
end
|
649
660
|
|
650
661
|
#
|
@@ -675,9 +686,17 @@ module Cequel
|
|
675
686
|
end
|
676
687
|
end
|
677
688
|
|
689
|
+
# @private
|
690
|
+
def allow_filtering_cql
|
691
|
+
if allow_filtering
|
692
|
+
' ALLOW FILTERING'
|
693
|
+
else ''
|
694
|
+
end
|
695
|
+
end
|
696
|
+
|
678
697
|
protected
|
679
698
|
|
680
|
-
attr_writer :row_limit, :query_consistency, :query_page_size, :query_paging_state
|
699
|
+
attr_writer :row_limit, :query_consistency, :query_page_size, :query_paging_state, :allow_filtering
|
681
700
|
|
682
701
|
private
|
683
702
|
|
@@ -47,7 +47,7 @@ module Cequel
|
|
47
47
|
yield
|
48
48
|
rescue Cassandra::Errors::NoHostsAvailable,
|
49
49
|
Cassandra::Errors::ExecutionError,
|
50
|
-
Cassandra::Errors::TimeoutError =>
|
50
|
+
Cassandra::Errors::TimeoutError => error
|
51
51
|
raise error if retries_remaining == 0
|
52
52
|
sleep(retry_delay)
|
53
53
|
keyspace.clear_active_connections! if clear_before_retry
|
@@ -40,6 +40,7 @@ module Cequel
|
|
40
40
|
add_bounds
|
41
41
|
add_order
|
42
42
|
set_consistency
|
43
|
+
set_allow_filtering
|
43
44
|
set_page_size
|
44
45
|
set_paging_state
|
45
46
|
data_set
|
@@ -53,7 +54,8 @@ module Cequel
|
|
53
54
|
:scoped_key_names, :scoped_key_values,
|
54
55
|
:scoped_indexed_column, :lower_bound,
|
55
56
|
:upper_bound, :reversed?, :order_by_column,
|
56
|
-
:query_consistency, :query_page_size, :query_paging_state,
|
57
|
+
:query_consistency, :query_page_size, :query_paging_state,
|
58
|
+
:ascends_by?, :allow_filtering
|
57
59
|
|
58
60
|
private
|
59
61
|
|
@@ -99,6 +101,12 @@ module Cequel
|
|
99
101
|
end
|
100
102
|
end
|
101
103
|
|
104
|
+
def set_allow_filtering
|
105
|
+
if allow_filtering
|
106
|
+
self.data_set = data_set.allow_filtering!
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
102
110
|
def set_page_size
|
103
111
|
if query_page_size
|
104
112
|
self.data_set = data_set.page_size(query_page_size)
|
@@ -123,6 +123,14 @@ module Cequel
|
|
123
123
|
# this column
|
124
124
|
# @return [void]
|
125
125
|
#
|
126
|
+
# @note Using type :enum will behave similar to an ActiveRecord enum:
|
127
|
+
# example: `column :status, :enum, values: { open: 1, closed: 2 }`
|
128
|
+
# will be handled as type Int
|
129
|
+
# calling model.status will return the symbol ie. :open or :closed
|
130
|
+
# expects setter to be called with symbol ie. model.status(:open)
|
131
|
+
# exposes helpers ie. model.open?
|
132
|
+
# exposes values-mapping on a class-level ModelClass.status
|
133
|
+
#
|
126
134
|
# @note Secondary indexes are not nearly as flexible as primary keys:
|
127
135
|
# you cannot query for multiple values or for ranges of values. You
|
128
136
|
# also cannot combine a secondary index restriction with a primary
|
@@ -131,6 +139,7 @@ module Cequel
|
|
131
139
|
#
|
132
140
|
def column(name, type, options = {})
|
133
141
|
def_accessors(name)
|
142
|
+
def_enum(name, options[:values]) if type == :enum
|
134
143
|
set_attribute_default(name, options[:default])
|
135
144
|
end
|
136
145
|
|
@@ -193,6 +202,34 @@ module Cequel
|
|
193
202
|
|
194
203
|
private
|
195
204
|
|
205
|
+
def def_enum(name, values)
|
206
|
+
name = name.to_sym
|
207
|
+
def_enum_values(name, values)
|
208
|
+
def_enum_reader(name, values)
|
209
|
+
def_enum_writer(name, values)
|
210
|
+
end
|
211
|
+
|
212
|
+
def def_enum_values(name, values)
|
213
|
+
define_singleton_method(name) { values }
|
214
|
+
end
|
215
|
+
|
216
|
+
def def_enum_reader(name, values)
|
217
|
+
module_eval <<-RUBY, __FILE__, __LINE__+1
|
218
|
+
def #{name}; #{values.invert}[read_attribute(#{name.inspect})]; end
|
219
|
+
RUBY
|
220
|
+
values.each do |key, value|
|
221
|
+
module_eval <<-RUBY, __FILE__, __LINE__+1
|
222
|
+
def #{key}?; read_attribute(#{name.inspect}) == #{value}; end
|
223
|
+
RUBY
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def def_enum_writer(name, values)
|
228
|
+
module_eval <<-RUBY, __FILE__, __LINE__+1
|
229
|
+
def #{name}=(value); write_attribute(#{name.inspect}, #{values}[value]); end
|
230
|
+
RUBY
|
231
|
+
end
|
232
|
+
|
196
233
|
def def_accessors(name)
|
197
234
|
name = name.to_sym
|
198
235
|
def_reader(name)
|
@@ -464,6 +464,22 @@ module Cequel
|
|
464
464
|
scoped(query_consistency: consistency)
|
465
465
|
end
|
466
466
|
|
467
|
+
#
|
468
|
+
# Add `ALLOW FILTERING` to select-queries for filtering of none-indexed fields.
|
469
|
+
#
|
470
|
+
# `Post.allow_filtering!.where(title: 'Cequel 0')`
|
471
|
+
#
|
472
|
+
# Available as of Cassandra 3.6
|
473
|
+
#
|
474
|
+
# @return [RecordSet] record set tuned to given consistency
|
475
|
+
|
476
|
+
# @see https://docs.datastax.com/en/cql/3.3/cql/cql_reference/cqlSelect.html#cqlSelect__filtering-on-clustering-column
|
477
|
+
# @note Filtering can incurr a significant performance overhead or even timeout on a large data-set.
|
478
|
+
#
|
479
|
+
def allow_filtering!
|
480
|
+
scoped(allow_filtering: true)
|
481
|
+
end
|
482
|
+
|
467
483
|
#
|
468
484
|
# Set the page_size at which to read records into the record set.
|
469
485
|
#
|
@@ -695,10 +711,11 @@ module Cequel
|
|
695
711
|
hattr_reader :attributes, :select_columns, :scoped_key_values,
|
696
712
|
:row_limit, :lower_bound, :upper_bound,
|
697
713
|
:scoped_indexed_column, :query_consistency,
|
698
|
-
:query_page_size, :query_paging_state
|
714
|
+
:query_page_size, :query_paging_state,
|
715
|
+
:allow_filtering
|
699
716
|
protected :select_columns, :scoped_key_values, :row_limit, :lower_bound,
|
700
717
|
:upper_bound, :scoped_indexed_column, :query_consistency,
|
701
|
-
:query_page_size, :query_paging_state
|
718
|
+
:query_page_size, :query_paging_state, :allow_filtering
|
702
719
|
hattr_inquirer :attributes, :reversed
|
703
720
|
protected :reversed?
|
704
721
|
|
@@ -812,7 +829,7 @@ module Cequel
|
|
812
829
|
fail IllegalQuery,
|
813
830
|
"Can't scope by more than one indexed column in the same query"
|
814
831
|
end
|
815
|
-
unless column.indexed?
|
832
|
+
unless column.indexed? || allow_filtering
|
816
833
|
fail ArgumentError,
|
817
834
|
"Can't scope by non-indexed column #{column_name}"
|
818
835
|
end
|
@@ -192,20 +192,22 @@ module Cequel
|
|
192
192
|
# Drop this table from the keyspace
|
193
193
|
#
|
194
194
|
# @param name [Symbol] name of the table to drop
|
195
|
+
# @param exists [Boolean] if set to true, will drop only if exists (Cassandra 3.x)
|
195
196
|
# @return [void]
|
196
197
|
#
|
197
|
-
def drop_table(name)
|
198
|
-
keyspace.execute("DROP TABLE #{name}")
|
198
|
+
def drop_table(name, exists: false)
|
199
|
+
keyspace.execute("DROP TABLE #{'IF EXISTS ' if exists}#{name}")
|
199
200
|
end
|
200
201
|
|
201
202
|
#
|
202
203
|
# Drop this materialized view from the keyspace
|
203
204
|
#
|
204
205
|
# @param name [Symbol] name of the materialized view to drop
|
206
|
+
# @param exists [Boolean] if set to true, will drop only if exists (Cassandra 3.x)
|
205
207
|
# @return [void]
|
206
208
|
#
|
207
|
-
def drop_materialized_view(name)
|
208
|
-
keyspace.execute("DROP MATERIALIZED VIEW #{name}")
|
209
|
+
def drop_materialized_view(name, exists: false)
|
210
|
+
keyspace.execute("DROP MATERIALIZED VIEW #{'IF EXISTS ' if exists}#{name}")
|
209
211
|
end
|
210
212
|
|
211
213
|
#
|
data/lib/cequel/schema/table.rb
CHANGED
@@ -104,6 +104,9 @@ module Cequel
|
|
104
104
|
options = {index: options} unless options.is_a?(Hash)
|
105
105
|
index_name = options[:index]
|
106
106
|
index_name = :"#{@name}_#{name}_idx" if index_name == true
|
107
|
+
if type == :enum
|
108
|
+
type = :int
|
109
|
+
end
|
107
110
|
DataColumn.new(name, type(type), index_name)
|
108
111
|
.tap { |column| @data_columns << add_column(column) }
|
109
112
|
end
|
data/lib/cequel/version.rb
CHANGED
@@ -73,7 +73,7 @@ describe Cequel::Metal::Keyspace do
|
|
73
73
|
end
|
74
74
|
|
75
75
|
describe "#exists?" do
|
76
|
-
it "is true for existent keyspaces" do
|
76
|
+
it "is true for existent keyspaces", :retry => 1, :retry_wait => 1 do
|
77
77
|
expect(cequel.exists?).to eq true
|
78
78
|
end
|
79
79
|
|
@@ -86,6 +86,20 @@ describe Cequel::Metal::Keyspace do
|
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
|
+
describe "#drop_table", cassandra: '~> 3.x' do
|
90
|
+
it "allows IF EXISTS" do
|
91
|
+
expect { cequel.schema.drop_table(:unknown) }.to raise_error(Cassandra::Errors::InvalidError)
|
92
|
+
expect { cequel.schema.drop_table(:unknown, exists: true) }.not_to raise_error(Cassandra::Errors::InvalidError)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "#drop_materialized_view", cassandra: '~> 3.x' do
|
97
|
+
it "allows IF EXISTS" do
|
98
|
+
expect { cequel.schema.drop_materialized_view(:unknown) }.to raise_error(Cassandra::Errors::ConfigurationError)
|
99
|
+
expect { cequel.schema.drop_materialized_view(:unknown, exists: true) }.not_to raise_error(Cassandra::Errors::ConfigurationError)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
89
103
|
describe "#ssl_config" do
|
90
104
|
it "ssl configuration settings get extracted correctly for sending to cluster" do
|
91
105
|
connect = Cequel.connect host: Cequel::SpecSupport::Helpers.host,
|
@@ -115,99 +129,99 @@ describe Cequel::Metal::Keyspace do
|
|
115
129
|
expect(connect.client_compression).to eq client_compression
|
116
130
|
end
|
117
131
|
end
|
118
|
-
|
119
|
-
describe '#cassandra_options' do
|
132
|
+
|
133
|
+
describe '#cassandra_options' do
|
120
134
|
let(:cassandra_options) { {foo: :bar} }
|
121
135
|
let(:connect) do
|
122
136
|
Cequel.connect host: Cequel::SpecSupport::Helpers.host,
|
123
137
|
port: Cequel::SpecSupport::Helpers.port,
|
124
138
|
cassandra_options: cassandra_options
|
125
139
|
end
|
126
|
-
it 'passes the cassandra options as part of the client options' do
|
140
|
+
it 'passes the cassandra options as part of the client options' do
|
127
141
|
expect(connect.send(:client_options)).to have_key(:foo)
|
128
142
|
end
|
129
143
|
end
|
130
|
-
|
144
|
+
|
131
145
|
describe 'cassandra error handling' do
|
132
|
-
let(:connect_options) do
|
146
|
+
let(:connect_options) do
|
133
147
|
{
|
134
148
|
host: Cequel::SpecSupport::Helpers.host,
|
135
149
|
port: Cequel::SpecSupport::Helpers.port
|
136
|
-
}
|
137
|
-
end
|
138
|
-
|
139
|
-
let(:default_connect) do
|
150
|
+
}
|
151
|
+
end
|
152
|
+
|
153
|
+
let(:default_connect) do
|
140
154
|
Cequel.connect(connect_options)
|
141
|
-
end
|
142
|
-
|
155
|
+
end
|
156
|
+
|
143
157
|
class SpecCassandraErrorHandler
|
144
158
|
def initialize(options = {})
|
145
159
|
end
|
146
|
-
|
160
|
+
|
147
161
|
def execute_stmt(keyspace)
|
148
162
|
yield
|
149
|
-
end
|
163
|
+
end
|
150
164
|
end
|
151
|
-
|
152
|
-
it 'uses the error handler passed in as a string' do
|
165
|
+
|
166
|
+
it 'uses the error handler passed in as a string' do
|
153
167
|
obj = Cequel.connect connect_options.merge(
|
154
168
|
cassandra_error_policy: 'SpecCassandraErrorHandler')
|
155
|
-
|
169
|
+
|
156
170
|
expect(obj.error_policy.class).to equal(SpecCassandraErrorHandler)
|
157
|
-
end
|
158
|
-
|
159
|
-
it 'uses the error handler passed in as a module' do
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'uses the error handler passed in as a module' do
|
160
174
|
obj = Cequel.connect connect_options.merge(
|
161
175
|
cassandra_error_policy: SpecCassandraErrorHandler)
|
162
|
-
|
176
|
+
|
163
177
|
expect(obj.error_policy.class).to equal(SpecCassandraErrorHandler)
|
164
178
|
end
|
165
|
-
|
179
|
+
|
166
180
|
it 'uses the instance of an error handler passed in' do
|
167
|
-
policy = SpecCassandraErrorHandler.new
|
168
|
-
|
181
|
+
policy = SpecCassandraErrorHandler.new
|
182
|
+
|
169
183
|
obj = Cequel.connect connect_options.merge(
|
170
184
|
cassandra_error_policy: policy)
|
171
|
-
|
185
|
+
|
172
186
|
expect(obj.error_policy).to equal(policy)
|
173
187
|
end
|
174
|
-
|
188
|
+
|
175
189
|
it 'responds to error policy' do
|
176
|
-
# Always defined, even if config does not specify it
|
190
|
+
# Always defined, even if config does not specify it
|
177
191
|
expect(default_connect).to respond_to(:error_policy)
|
178
192
|
end
|
179
|
-
|
180
|
-
it 'calls execute_stmt on the error policy' do
|
181
|
-
policy = ::Cequel::Metal::Policy::CassandraError::RetryPolicy.new
|
182
|
-
|
193
|
+
|
194
|
+
it 'calls execute_stmt on the error policy' do
|
195
|
+
policy = ::Cequel::Metal::Policy::CassandraError::RetryPolicy.new
|
196
|
+
|
183
197
|
obj = Cequel.connect connect_options.merge(
|
184
198
|
cassandra_error_policy: policy)
|
185
199
|
expect(policy).to receive(:execute_stmt).at_least(:once)
|
186
200
|
obj.execute_with_options(Cequel::Metal::Statement.new('select * from system.peers;'))
|
187
|
-
end
|
188
|
-
|
189
|
-
it 'rejects a negative value for retry delay' do
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'rejects a negative value for retry delay' do
|
190
204
|
expect { Cequel.connect connect_options.merge(
|
191
205
|
retry_delay: -1.0)
|
192
206
|
}.to raise_error(ArgumentError)
|
193
207
|
end
|
194
|
-
|
208
|
+
|
195
209
|
it 'accepts a configured value for retry delay' do
|
196
210
|
obj = Cequel.connect connect_options.merge(
|
197
211
|
retry_delay: 1337.0)
|
198
|
-
|
212
|
+
|
199
213
|
# do not compare floats exactly, it is error prone
|
200
214
|
# the value is passed to the error policy
|
201
|
-
expect(obj.error_policy.retry_delay).to be_within(0.1).of(1337.0)
|
215
|
+
expect(obj.error_policy.retry_delay).to be_within(0.1).of(1337.0)
|
202
216
|
end
|
203
|
-
|
204
|
-
it 'can clear active connections' do
|
217
|
+
|
218
|
+
it 'can clear active connections' do
|
205
219
|
expect {
|
206
220
|
default_connect.clear_active_connections!
|
207
221
|
}.to change {
|
208
222
|
default_connect.client
|
209
223
|
}
|
210
|
-
end
|
224
|
+
end
|
211
225
|
end
|
212
226
|
|
213
227
|
describe "#execute" do
|
@@ -7,6 +7,7 @@ describe Cequel::Record::Properties do
|
|
7
7
|
model :Post do
|
8
8
|
key :permalink, :text
|
9
9
|
column :title, :text
|
10
|
+
column :status, :enum, values: { open: 1, closed: 2 }
|
10
11
|
list :tags, :text
|
11
12
|
set :categories, :text
|
12
13
|
map :shares, :text, :int
|
@@ -30,6 +31,17 @@ describe Cequel::Record::Properties do
|
|
30
31
|
expect(Post.new.permalink).to be_nil
|
31
32
|
end
|
32
33
|
|
34
|
+
it 'should have enums' do
|
35
|
+
expect(Post.new.status).to be_nil
|
36
|
+
expect(Post.status).to eql({ open: 1, closed: 2 })
|
37
|
+
expect(Post.new { |post| post.status = :open }.status).to eq(:open)
|
38
|
+
expect(Post.new { |post| post.status = :open }).to be_open
|
39
|
+
expect(Post.new { |post| post.status = :closed }.status).to eq(:closed)
|
40
|
+
expect(Post.new { |post| post.status = :closed }).to be_closed
|
41
|
+
expect(Post.new { |post| post.status = :closed }.attributes['status']).to eq(2)
|
42
|
+
expect(Post.new { |post| post.status = :unknown }.status).to eq(nil)
|
43
|
+
end
|
44
|
+
|
33
45
|
it 'should provide accessor for data column' do
|
34
46
|
expect(Post.new { |post| post.title = 'Big Data' }.title).to eq('Big Data')
|
35
47
|
end
|
@@ -197,7 +209,7 @@ describe Cequel::Record::Properties do
|
|
197
209
|
end
|
198
210
|
|
199
211
|
it 'should run default proc on keys' do
|
200
|
-
expect(Post.new.subid).to eq("subid #{1+1}")
|
212
|
+
expect(Post.new.subid).to eq("subid #{1+1}")
|
201
213
|
end
|
202
214
|
|
203
215
|
it 'should run default proc' do
|
@@ -805,6 +805,12 @@ describe Cequel::Record::RecordSet do
|
|
805
805
|
to raise_error(ArgumentError)
|
806
806
|
end
|
807
807
|
end
|
808
|
+
|
809
|
+
context 'allow_filtering!', cassandra: '~> 3.x' do
|
810
|
+
it 'should allow filtering for none indexed columns' do
|
811
|
+
expect(Post.allow_filtering!.where(title: 'Cequel 0').entries.length).to be(1)
|
812
|
+
end
|
813
|
+
end
|
808
814
|
end
|
809
815
|
|
810
816
|
describe '#consistency' do
|
@@ -15,10 +15,15 @@ RSpec.configure do |config|
|
|
15
15
|
config.include(Cequel::SpecSupport::Helpers)
|
16
16
|
config.extend(Cequel::SpecSupport::Macros)
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
}
|
18
|
+
{
|
19
|
+
rails: ActiveSupport::VERSION::STRING,
|
20
|
+
cassandra: ENV.fetch('CASSANDRA_VERSION', '3.0'),
|
21
|
+
}.each do |tag, version|
|
22
|
+
config.filter_run_excluding tag => ->(requirement) {
|
23
|
+
!Gem::Requirement.new(requirement).
|
24
|
+
satisfied_by?(Gem::Version.new(version))
|
25
|
+
}
|
26
|
+
end
|
22
27
|
|
23
28
|
unless defined? CassandraCQL
|
24
29
|
config.filter_run_excluding thrift: true
|
@@ -41,6 +46,9 @@ RSpec.configure do |config|
|
|
41
46
|
config.filter_run :focus => true
|
42
47
|
config.run_all_when_everything_filtered = true
|
43
48
|
config.order = "random"
|
49
|
+
|
50
|
+
config.verbose_retry = true
|
51
|
+
config.default_retry_count = 0
|
44
52
|
end
|
45
53
|
|
46
54
|
if defined? byebug
|
@@ -10,7 +10,7 @@ describe Cequel::SpecSupport::Preparation do
|
|
10
10
|
expect(prep.drop_keyspace).to eq prep
|
11
11
|
end
|
12
12
|
|
13
|
-
it "returns itself from #create_keyspace" do
|
13
|
+
it "returns itself from #create_keyspace", :retry => 1, :retry_wait => 1 do
|
14
14
|
expect(prep.create_keyspace).to eq prep
|
15
15
|
end
|
16
16
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cequel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mat Brown
|
@@ -29,7 +29,7 @@ authors:
|
|
29
29
|
autorequire:
|
30
30
|
bindir: bin
|
31
31
|
cert_chain: []
|
32
|
-
date: 2017-01-
|
32
|
+
date: 2017-01-26 00:00:00.000000000 Z
|
33
33
|
dependencies:
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
35
|
name: activemodel
|
@@ -107,14 +107,14 @@ dependencies:
|
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '3.
|
110
|
+
version: '3.5'
|
111
111
|
type: :development
|
112
112
|
prerelease: false
|
113
113
|
version_requirements: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '3.
|
117
|
+
version: '3.5'
|
118
118
|
- !ruby/object:Gem::Dependency
|
119
119
|
name: rspec-its
|
120
120
|
requirement: !ruby/object:Gem::Requirement
|
@@ -129,6 +129,20 @@ dependencies:
|
|
129
129
|
- - "~>"
|
130
130
|
- !ruby/object:Gem::Version
|
131
131
|
version: '1.0'
|
132
|
+
- !ruby/object:Gem::Dependency
|
133
|
+
name: rspec-retry
|
134
|
+
requirement: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0.5'
|
139
|
+
type: :development
|
140
|
+
prerelease: false
|
141
|
+
version_requirements: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0.5'
|
132
146
|
- !ruby/object:Gem::Dependency
|
133
147
|
name: rubocop
|
134
148
|
requirement: !ruby/object:Gem::Requirement
|