cequel 1.7.0 → 1.8.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 +8 -0
- data/Gemfile.lock +64 -75
- data/README.md +32 -4
- data/Rakefile +8 -7
- data/lib/cequel/metal/data_set.rb +29 -4
- data/lib/cequel/metal/keyspace.rb +18 -14
- data/lib/cequel/metal/request_logger.rb +7 -0
- data/lib/cequel/record/data_set_builder.rb +15 -1
- data/lib/cequel/record/properties.rb +2 -0
- data/lib/cequel/record/record_set.rb +28 -2
- data/lib/cequel/schema/table_reader.rb +1 -1
- data/lib/cequel/version.rb +1 -1
- data/spec/examples/metal/data_set_spec.rb +24 -0
- data/spec/examples/record/dirty_spec.rb +0 -8
- data/spec/examples/record/persistence_spec.rb +2 -2
- data/spec/examples/record/properties_spec.rb +5 -0
- data/spec/examples/record/record_set_spec.rb +35 -0
- data/spec/examples/record/schema_spec.rb +42 -0
- data/spec/examples/schema/table_reader_spec.rb +16 -15
- data/spec/examples/schema/table_synchronizer_spec.rb +14 -13
- data/spec/examples/schema/table_updater_spec.rb +23 -20
- data/spec/examples/schema/table_writer_spec.rb +13 -12
- data/spec/examples/spec_support/preparation_spec.rb +8 -0
- data/spec/support/helpers.rb +8 -0
- metadata +3 -6
- data/DRIVER_TODO +0 -5
- data/cequel.gemspec +0 -42
- data/tags +0 -836
@@ -187,23 +187,13 @@ module Cequel
|
|
187
187
|
execute_with_consistency(statement, bind_vars, default_consistency)
|
188
188
|
end
|
189
189
|
|
190
|
-
|
191
|
-
|
192
|
-
#
|
193
|
-
# @param statement [String] CQL string
|
194
|
-
# @param bind_vars [Array] array of values for bind variables
|
195
|
-
# @param consistency [Symbol] consistency at which to execute query
|
196
|
-
# @return [Enumerable] the results of the query
|
197
|
-
#
|
198
|
-
# @since 1.1.0
|
199
|
-
#
|
200
|
-
def execute_with_consistency(statement, bind_vars, consistency)
|
201
|
-
retries = max_retries
|
190
|
+
def execute_with_options(statement, bind_vars, options={})
|
191
|
+
options[:consistency] ||= default_consistency
|
202
192
|
|
193
|
+
retries = max_retries
|
203
194
|
log('CQL', statement, *bind_vars) do
|
204
195
|
begin
|
205
|
-
client.execute(sanitize(statement, bind_vars),
|
206
|
-
consistency: consistency || default_consistency)
|
196
|
+
client.execute(sanitize(statement, bind_vars), options)
|
207
197
|
rescue Cassandra::Errors::NoHostsAvailable,
|
208
198
|
Ione::Io::ConnectionError => e
|
209
199
|
clear_active_connections!
|
@@ -213,6 +203,20 @@ module Cequel
|
|
213
203
|
retry
|
214
204
|
end
|
215
205
|
end
|
206
|
+
|
207
|
+
end
|
208
|
+
#
|
209
|
+
# Execute a CQL query in this keyspace with the given consistency
|
210
|
+
#
|
211
|
+
# @param statement [String] CQL string
|
212
|
+
# @param bind_vars [Array] array of values for bind variables
|
213
|
+
# @param consistency [Symbol] consistency at which to execute query
|
214
|
+
# @return [Enumerable] the results of the query
|
215
|
+
#
|
216
|
+
# @since 1.1.0
|
217
|
+
#
|
218
|
+
def execute_with_consistency(statement, bind_vars, consistency)
|
219
|
+
execute_with_options(statement, bind_vars, {consistency: consistency || default_consistency})
|
216
220
|
end
|
217
221
|
|
218
222
|
#
|
@@ -51,9 +51,16 @@ module Cequel
|
|
51
51
|
private
|
52
52
|
|
53
53
|
def format_for_log(label, timing, statement, bind_vars)
|
54
|
+
bind_vars = bind_vars.map{|it| String === it ? limit_length(it) : it }
|
54
55
|
format('%s (%s) %s', label, timing, sanitize(statement, bind_vars))
|
55
56
|
end
|
56
57
|
|
58
|
+
def limit_length(str)
|
59
|
+
return str if str.length < 100
|
60
|
+
|
61
|
+
str[0..25] + "..." + str[-25..-1]
|
62
|
+
end
|
63
|
+
|
57
64
|
def_delegator 'Cequel::Metal::Keyspace', :sanitize
|
58
65
|
private :sanitize
|
59
66
|
end
|
@@ -40,6 +40,8 @@ module Cequel
|
|
40
40
|
add_bounds
|
41
41
|
add_order
|
42
42
|
set_consistency
|
43
|
+
set_page_size
|
44
|
+
set_paging_state
|
43
45
|
data_set
|
44
46
|
end
|
45
47
|
|
@@ -51,7 +53,7 @@ module Cequel
|
|
51
53
|
:scoped_key_names, :scoped_key_values,
|
52
54
|
:scoped_indexed_column, :lower_bound,
|
53
55
|
:upper_bound, :reversed?, :order_by_column,
|
54
|
-
:query_consistency, :ascends_by?
|
56
|
+
:query_consistency, :query_page_size, :query_paging_state, :ascends_by?
|
55
57
|
|
56
58
|
private
|
57
59
|
|
@@ -97,6 +99,18 @@ module Cequel
|
|
97
99
|
end
|
98
100
|
end
|
99
101
|
|
102
|
+
def set_page_size
|
103
|
+
if query_page_size
|
104
|
+
self.data_set = data_set.page_size(query_page_size)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def set_paging_state
|
109
|
+
if query_paging_state
|
110
|
+
self.data_set = data_set.paging_state(query_paging_state)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
100
114
|
def sort_direction
|
101
115
|
ascends_by?(order_by_column) ? :asc : :desc
|
102
116
|
end
|
@@ -464,6 +464,30 @@ module Cequel
|
|
464
464
|
scoped(query_consistency: consistency)
|
465
465
|
end
|
466
466
|
|
467
|
+
#
|
468
|
+
# Set the page_size at which to read records into the record set.
|
469
|
+
#
|
470
|
+
# @param page_size [Integer] page_size for reads
|
471
|
+
# @return [RecordSet] record set tuned to given page_size
|
472
|
+
#
|
473
|
+
def page_size(page_size)
|
474
|
+
scoped(query_page_size: page_size)
|
475
|
+
end
|
476
|
+
|
477
|
+
#
|
478
|
+
# Set the paging_state at which to read records into the record set.
|
479
|
+
#
|
480
|
+
# @param paging_state [String] paging_state for reads
|
481
|
+
# @return [RecordSet] record set tuned to given paging_state
|
482
|
+
#
|
483
|
+
def paging_state(paging_state)
|
484
|
+
scoped(query_paging_state: paging_state)
|
485
|
+
end
|
486
|
+
|
487
|
+
def next_paging_state
|
488
|
+
data_set.next_paging_state
|
489
|
+
end
|
490
|
+
|
467
491
|
#
|
468
492
|
# @overload first
|
469
493
|
# @return [Record] the first record in this record set
|
@@ -667,9 +691,11 @@ module Cequel
|
|
667
691
|
attr_reader :attributes
|
668
692
|
hattr_reader :attributes, :select_columns, :scoped_key_values,
|
669
693
|
:row_limit, :lower_bound, :upper_bound,
|
670
|
-
:scoped_indexed_column, :query_consistency
|
694
|
+
:scoped_indexed_column, :query_consistency,
|
695
|
+
:query_page_size, :query_paging_state
|
671
696
|
protected :select_columns, :scoped_key_values, :row_limit, :lower_bound,
|
672
|
-
:upper_bound, :scoped_indexed_column, :query_consistency
|
697
|
+
:upper_bound, :scoped_indexed_column, :query_consistency,
|
698
|
+
:query_page_size, :query_paging_state
|
673
699
|
hattr_inquirer :attributes, :reversed
|
674
700
|
protected :reversed?
|
675
701
|
|
@@ -75,7 +75,7 @@ module Cequel
|
|
75
75
|
def read_partition_keys
|
76
76
|
validators = table_data['key_validator']
|
77
77
|
types = parse_composite_types(validators) || [validators]
|
78
|
-
columns = partition_columns.
|
78
|
+
columns = partition_columns.sort_by { |c| c['component_index'] }
|
79
79
|
.map { |c| c['column_name'] }
|
80
80
|
|
81
81
|
columns.zip(types) do |name, type|
|
data/lib/cequel/version.rb
CHANGED
@@ -654,6 +654,30 @@ describe Cequel::Metal::DataSet do
|
|
654
654
|
end
|
655
655
|
end
|
656
656
|
|
657
|
+
describe '#page_size' do
|
658
|
+
let(:data_set) { cequel[:posts].page_size(1) }
|
659
|
+
|
660
|
+
it 'should issue SELECT with scoped page size' do
|
661
|
+
expect_query_with_options(/SELECT/, :page_size => 1) { data_set.to_a }
|
662
|
+
end
|
663
|
+
|
664
|
+
it 'should issue COUNT with scoped page size' do
|
665
|
+
expect_query_with_options(/SELECT.*COUNT/, :page_size => 1) { data_set.count }
|
666
|
+
end
|
667
|
+
end
|
668
|
+
|
669
|
+
describe '#paging_state' do
|
670
|
+
let(:data_set) { cequel[:posts].paging_state(nil) }
|
671
|
+
|
672
|
+
it 'should issue SELECT with scoped paging state' do
|
673
|
+
expect_query_with_options(/SELECT/, :paging_state => nil) { data_set.to_a }
|
674
|
+
end
|
675
|
+
|
676
|
+
it 'should issue COUNT with scoped paging state' do
|
677
|
+
expect_query_with_options(/SELECT.*COUNT/, :paging_state => nil) { data_set.count }
|
678
|
+
end
|
679
|
+
end
|
680
|
+
|
657
681
|
describe 'result enumeration' do
|
658
682
|
let(:row) { row_keys.merge(:title => 'Big Data') }
|
659
683
|
|
@@ -128,8 +128,8 @@ describe Cequel::Record::Persistence do
|
|
128
128
|
it 'should save with specified TTL' do
|
129
129
|
blog.name = 'Cequel 1.4'
|
130
130
|
blog.save(ttl: 10)
|
131
|
-
expect(cequel[Blog.table_name].select_ttl(:name).first.ttl(:name))
|
132
|
-
to
|
131
|
+
expect(cequel[Blog.table_name].select_ttl(:name).first.ttl(:name))
|
132
|
+
.to be_between(9,10).inclusive
|
133
133
|
end
|
134
134
|
|
135
135
|
it 'should save with specified timestamp' do
|
@@ -53,6 +53,11 @@ describe Cequel::Record::Properties do
|
|
53
53
|
title).to eq('Big Data')
|
54
54
|
end
|
55
55
|
|
56
|
+
it 'should mark the attribute as dirty when setting attributes' do
|
57
|
+
expect(Post.new { |post| post.title = 'Big Data' }.changed).to eq(['title'])
|
58
|
+
expect(Post.new { |post| post.title = 'Big Data' }.changes).to eq({'title' => [nil,'Big Data']})
|
59
|
+
end
|
60
|
+
|
56
61
|
it 'should get attributes with indifferent access' do
|
57
62
|
post = Post.new.tap { |post| post.attributes = {:downcased_title => 'big data' }}
|
58
63
|
expect(post.attributes[:title]).to eq 'Big Data'
|
@@ -811,6 +811,41 @@ describe Cequel::Record::RecordSet do
|
|
811
811
|
end
|
812
812
|
end
|
813
813
|
|
814
|
+
describe '#page_size' do
|
815
|
+
it 'should return the number of records specified by page_size' do
|
816
|
+
expect(Post.page_size(2).to_a.length).to be(2)
|
817
|
+
end
|
818
|
+
end
|
819
|
+
|
820
|
+
describe '#next_paging_state' do
|
821
|
+
it 'should return the paging state of the result' do
|
822
|
+
expect(Post.page_size(1).next_paging_state).not_to eq(nil)
|
823
|
+
end
|
824
|
+
end
|
825
|
+
|
826
|
+
describe '#paging_state' do
|
827
|
+
let(:page_one) { Post.page_size(1) }
|
828
|
+
let(:page_two) { Post.page_size(1).paging_state(page_one.next_paging_state) }
|
829
|
+
let(:page_size) { 3 }
|
830
|
+
|
831
|
+
it 'should page through all records' do
|
832
|
+
all_pages = []
|
833
|
+
next_paging_state = nil
|
834
|
+
|
835
|
+
loop do
|
836
|
+
a_page = Post.page_size(page_size).paging_state(next_paging_state)
|
837
|
+
next_paging_state = a_page.next_paging_state
|
838
|
+
|
839
|
+
# There may be less than page size records on final page
|
840
|
+
expect(a_page.to_a.length).to be <= page_size
|
841
|
+
all_pages.concat(a_page.to_a)
|
842
|
+
break if next_paging_state.nil?
|
843
|
+
end
|
844
|
+
|
845
|
+
expect(all_pages).to eq(posts.to_a)
|
846
|
+
end
|
847
|
+
end
|
848
|
+
|
814
849
|
describe '#count' do
|
815
850
|
let(:records) { blogs }
|
816
851
|
|
@@ -73,6 +73,48 @@ describe Cequel::Record::Schema do
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
+
context 'CQL3 table with non-dictionary-ordered partition columns' do
|
77
|
+
let(:table_name) { 'accesses_' + SecureRandom.hex(4) }
|
78
|
+
|
79
|
+
let(:model) do
|
80
|
+
model_table_name = table_name
|
81
|
+
Class.new do
|
82
|
+
include Cequel::Record
|
83
|
+
self.table_name = model_table_name
|
84
|
+
|
85
|
+
key :serial, :text, partition: true
|
86
|
+
key :username, :text, partition: true
|
87
|
+
key :date, :text, partition: true
|
88
|
+
key :access_time, :timeuuid
|
89
|
+
column :url, :text
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
let(:model_modified) do
|
94
|
+
model_table_name = table_name
|
95
|
+
Class.new do
|
96
|
+
include Cequel::Record
|
97
|
+
self.table_name = model_table_name
|
98
|
+
|
99
|
+
key :serial, :text, partition: true
|
100
|
+
key :username, :text, partition: true
|
101
|
+
key :date, :text, partition: true
|
102
|
+
key :access_time, :timeuuid
|
103
|
+
column :url, :text
|
104
|
+
column :user_agent, :text
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
before { model.synchronize_schema }
|
109
|
+
after { cequel.schema.drop_table(table_name) }
|
110
|
+
|
111
|
+
it 'should be able to synchronize schema again' do
|
112
|
+
expect {
|
113
|
+
model_modified.synchronize_schema
|
114
|
+
}.not_to raise_error
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
76
118
|
context 'wide-row legacy table' do
|
77
119
|
let(:table_name) { 'legacy_posts_' + SecureRandom.hex(4) }
|
78
120
|
|
@@ -2,16 +2,17 @@
|
|
2
2
|
require File.expand_path('../../spec_helper', __FILE__)
|
3
3
|
|
4
4
|
describe Cequel::Schema::TableReader do
|
5
|
+
let(:table_name) { :"posts_#{SecureRandom.hex(4)}" }
|
5
6
|
|
6
7
|
after do
|
7
|
-
cequel.schema.drop_table(
|
8
|
+
cequel.schema.drop_table(table_name)
|
8
9
|
end
|
9
10
|
|
10
|
-
let(:table) { cequel.schema.read_table(
|
11
|
+
let(:table) { cequel.schema.read_table(table_name) }
|
11
12
|
|
12
13
|
describe 'reading simple key' do
|
13
14
|
before do
|
14
|
-
cequel.execute("CREATE TABLE
|
15
|
+
cequel.execute("CREATE TABLE #{table_name} (permalink text PRIMARY KEY)")
|
15
16
|
end
|
16
17
|
|
17
18
|
it 'should read name correctly' do
|
@@ -30,7 +31,7 @@ describe Cequel::Schema::TableReader do
|
|
30
31
|
describe 'reading single non-partition key' do
|
31
32
|
before do
|
32
33
|
cequel.execute <<-CQL
|
33
|
-
CREATE TABLE
|
34
|
+
CREATE TABLE #{table_name} (
|
34
35
|
blog_subdomain text,
|
35
36
|
permalink ascii,
|
36
37
|
PRIMARY KEY (blog_subdomain, permalink)
|
@@ -63,7 +64,7 @@ describe Cequel::Schema::TableReader do
|
|
63
64
|
describe 'reading reverse-ordered non-partition key' do
|
64
65
|
before do
|
65
66
|
cequel.execute <<-CQL
|
66
|
-
CREATE TABLE
|
67
|
+
CREATE TABLE #{table_name} (
|
67
68
|
blog_subdomain text,
|
68
69
|
permalink ascii,
|
69
70
|
PRIMARY KEY (blog_subdomain, permalink)
|
@@ -89,7 +90,7 @@ describe Cequel::Schema::TableReader do
|
|
89
90
|
describe 'reading compound non-partition key' do
|
90
91
|
before do
|
91
92
|
cequel.execute <<-CQL
|
92
|
-
CREATE TABLE
|
93
|
+
CREATE TABLE #{table_name} (
|
93
94
|
blog_subdomain text,
|
94
95
|
permalink ascii,
|
95
96
|
author_id uuid,
|
@@ -116,7 +117,7 @@ describe Cequel::Schema::TableReader do
|
|
116
117
|
describe 'reading compound partition key' do
|
117
118
|
before do
|
118
119
|
cequel.execute <<-CQL
|
119
|
-
CREATE TABLE
|
120
|
+
CREATE TABLE #{table_name} (
|
120
121
|
blog_subdomain text,
|
121
122
|
permalink ascii,
|
122
123
|
PRIMARY KEY ((blog_subdomain, permalink))
|
@@ -142,7 +143,7 @@ describe Cequel::Schema::TableReader do
|
|
142
143
|
describe 'reading compound partition and non-partition keys' do
|
143
144
|
before do
|
144
145
|
cequel.execute <<-CQL
|
145
|
-
CREATE TABLE
|
146
|
+
CREATE TABLE #{table_name} (
|
146
147
|
blog_subdomain text,
|
147
148
|
permalink ascii,
|
148
149
|
author_id uuid,
|
@@ -183,7 +184,7 @@ describe Cequel::Schema::TableReader do
|
|
183
184
|
|
184
185
|
before do
|
185
186
|
cequel.execute <<-CQL
|
186
|
-
CREATE TABLE
|
187
|
+
CREATE TABLE #{table_name} (
|
187
188
|
blog_subdomain text,
|
188
189
|
permalink ascii,
|
189
190
|
title text,
|
@@ -194,7 +195,7 @@ describe Cequel::Schema::TableReader do
|
|
194
195
|
PRIMARY KEY (blog_subdomain, permalink)
|
195
196
|
)
|
196
197
|
CQL
|
197
|
-
cequel.execute(
|
198
|
+
cequel.execute("CREATE INDEX posts_author_id_idx ON #{table_name} (author_id)")
|
198
199
|
end
|
199
200
|
|
200
201
|
it 'should read types of scalar data columns' do
|
@@ -255,7 +256,7 @@ describe Cequel::Schema::TableReader do
|
|
255
256
|
|
256
257
|
before do
|
257
258
|
cequel.execute <<-CQL
|
258
|
-
CREATE TABLE
|
259
|
+
CREATE TABLE #{table_name} (permalink text PRIMARY KEY)
|
259
260
|
WITH bloom_filter_fp_chance = 0.02
|
260
261
|
AND comment = 'Posts table'
|
261
262
|
AND compaction = {
|
@@ -315,7 +316,7 @@ describe Cequel::Schema::TableReader do
|
|
315
316
|
describe 'skinny-row compact storage' do
|
316
317
|
before do
|
317
318
|
cequel.execute <<-CQL
|
318
|
-
CREATE TABLE
|
319
|
+
CREATE TABLE #{table_name} (permalink text PRIMARY KEY, title text, body text)
|
319
320
|
WITH COMPACT STORAGE
|
320
321
|
CQL
|
321
322
|
end
|
@@ -333,7 +334,7 @@ describe Cequel::Schema::TableReader do
|
|
333
334
|
describe 'wide-row compact storage' do
|
334
335
|
before do
|
335
336
|
cequel.execute <<-CQL
|
336
|
-
CREATE TABLE
|
337
|
+
CREATE TABLE #{table_name} (
|
337
338
|
blog_subdomain text,
|
338
339
|
id uuid,
|
339
340
|
data text,
|
@@ -356,7 +357,7 @@ describe Cequel::Schema::TableReader do
|
|
356
357
|
describe 'skinny-row legacy table', thrift: true do
|
357
358
|
before do
|
358
359
|
legacy_connection.execute <<-CQL
|
359
|
-
CREATE TABLE
|
360
|
+
CREATE TABLE #{table_name} (permalink text PRIMARY KEY, title text, body text)
|
360
361
|
CQL
|
361
362
|
end
|
362
363
|
subject { table }
|
@@ -375,7 +376,7 @@ describe Cequel::Schema::TableReader do
|
|
375
376
|
describe 'wide-row legacy table', thrift: true do
|
376
377
|
before do
|
377
378
|
legacy_connection.execute(<<-CQL2)
|
378
|
-
CREATE COLUMNFAMILY
|
379
|
+
CREATE COLUMNFAMILY #{table_name} (blog_subdomain text PRIMARY KEY)
|
379
380
|
WITH comparator=uuid AND default_validation=text
|
380
381
|
CQL2
|
381
382
|
end
|