cql-rb 1.0.6 → 1.1.0.pre0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/README.md +4 -9
  2. data/lib/cql.rb +1 -0
  3. data/lib/cql/byte_buffer.rb +23 -7
  4. data/lib/cql/client.rb +11 -6
  5. data/lib/cql/client/asynchronous_client.rb +37 -83
  6. data/lib/cql/client/asynchronous_prepared_statement.rb +10 -4
  7. data/lib/cql/client/column_metadata.rb +16 -0
  8. data/lib/cql/client/request_runner.rb +46 -0
  9. data/lib/cql/future.rb +4 -5
  10. data/lib/cql/io.rb +2 -5
  11. data/lib/cql/io/connection.rb +220 -0
  12. data/lib/cql/io/io_reactor.rb +213 -185
  13. data/lib/cql/protocol.rb +1 -0
  14. data/lib/cql/protocol/cql_protocol_handler.rb +201 -0
  15. data/lib/cql/protocol/decoding.rb +6 -31
  16. data/lib/cql/protocol/encoding.rb +1 -5
  17. data/lib/cql/protocol/request.rb +4 -0
  18. data/lib/cql/protocol/responses/schema_change_result_response.rb +15 -0
  19. data/lib/cql/protocol/type_converter.rb +56 -76
  20. data/lib/cql/time_uuid.rb +104 -0
  21. data/lib/cql/uuid.rb +4 -2
  22. data/lib/cql/version.rb +1 -1
  23. data/spec/cql/client/asynchronous_client_spec.rb +47 -71
  24. data/spec/cql/client/asynchronous_prepared_statement_spec.rb +68 -0
  25. data/spec/cql/client/client_shared.rb +3 -3
  26. data/spec/cql/client/column_metadata_spec.rb +80 -0
  27. data/spec/cql/client/request_runner_spec.rb +120 -0
  28. data/spec/cql/future_spec.rb +26 -11
  29. data/spec/cql/io/connection_spec.rb +460 -0
  30. data/spec/cql/io/io_reactor_spec.rb +212 -265
  31. data/spec/cql/protocol/cql_protocol_handler_spec.rb +216 -0
  32. data/spec/cql/protocol/decoding_spec.rb +9 -28
  33. data/spec/cql/protocol/encoding_spec.rb +0 -5
  34. data/spec/cql/protocol/request_spec.rb +16 -0
  35. data/spec/cql/protocol/response_frame_spec.rb +2 -2
  36. data/spec/cql/protocol/responses/schema_change_result_response_spec.rb +70 -0
  37. data/spec/cql/time_uuid_spec.rb +136 -0
  38. data/spec/cql/uuid_spec.rb +1 -5
  39. data/spec/integration/client_spec.rb +34 -38
  40. data/spec/integration/io_spec.rb +283 -0
  41. data/spec/integration/protocol_spec.rb +53 -113
  42. data/spec/integration/regression_spec.rb +124 -0
  43. data/spec/integration/uuid_spec.rb +76 -0
  44. data/spec/spec_helper.rb +12 -9
  45. data/spec/support/fake_io_reactor.rb +52 -21
  46. data/spec/support/fake_server.rb +2 -2
  47. metadata +33 -10
  48. checksums.yaml +0 -15
  49. data/lib/cql/io/node_connection.rb +0 -209
  50. data/spec/cql/protocol/type_converter_spec.rb +0 -52
@@ -0,0 +1,124 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+
6
+ describe 'Regressions' do
7
+ let :connection_options do
8
+ {:host => ENV['CASSANDRA_HOST'], :credentials => {:username => 'cassandra', :password => 'cassandra'}}
9
+ end
10
+
11
+ let :client do
12
+ Cql::Client.connect(connection_options)
13
+ end
14
+
15
+ before do
16
+ client.execute('DROP KEYSPACE cql_rb_client_spec') rescue nil
17
+ client.execute(%(CREATE KEYSPACE cql_rb_client_spec WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor': 1}))
18
+ client.use('cql_rb_client_spec')
19
+ end
20
+
21
+ after do
22
+ client.execute('DROP KEYSPACE cql_rb_client_spec') rescue nil
23
+ client.close rescue nil
24
+ end
25
+
26
+ context 'with multibyte characters' do
27
+ it 'executes queries with multibyte characters' do
28
+ client.execute(%(CREATE TABLE users (user_id VARCHAR PRIMARY KEY, first VARCHAR, last VARCHAR, age INT)))
29
+ client.execute(%(INSERT INTO users (user_id, first, last, age) VALUES ('test', 'ümlaut', 'test', 1)))
30
+ end
31
+
32
+ it 'executes prepared statements with multibyte characters' do
33
+ client.execute(%(CREATE TABLE users (user_id VARCHAR PRIMARY KEY, first VARCHAR, last VARCHAR, age INT)))
34
+ client.execute("INSERT INTO users (user_id, first, last, age) VALUES ('test', 'ümlaut', 'test', 1)")
35
+ statement = client.prepare('INSERT INTO users (user_id, first, last, age) VALUES (?, ?, ?, ?)')
36
+ statement.execute('test2', 'test2', 'test2', 2)
37
+ statement.execute('test3', 'ümlaut', 'test3', 3)
38
+ end
39
+ end
40
+
41
+ context 'with collections' do
42
+ it 'prepares and executes a statement with an append to a set' do
43
+ client.execute(%(CREATE TABLE users (name VARCHAR PRIMARY KEY, emails SET<VARCHAR>)))
44
+ statement = client.prepare(%(UPDATE users SET emails = emails + ? WHERE name = 'eve'))
45
+ statement.execute(['eve@gmail.com'])
46
+ end
47
+
48
+ it 'prepares and executes a statement with an append to a list' do
49
+ client.execute(%(CREATE TABLE users (name VARCHAR PRIMARY KEY, emails LIST<VARCHAR>)))
50
+ statement = client.prepare(%(UPDATE users SET emails = emails + ? WHERE name = 'eve'))
51
+ statement.execute(['eve@gmail.com', 'eve@yahoo.com'])
52
+ end
53
+
54
+ it 'prepares and executes a statement with an append to a map' do
55
+ client.execute(%(CREATE TABLE users (name VARCHAR PRIMARY KEY, emails MAP<VARCHAR, VARCHAR>)))
56
+ statement = client.prepare(%(UPDATE users SET emails = emails + ? WHERE name = 'eve'))
57
+ statement.execute({'home' => 'eve@yahoo.com'})
58
+ end
59
+
60
+ it 'prepares and executes a statement with a map assignment' do
61
+ client.execute(%(CREATE TABLE users (name VARCHAR PRIMARY KEY, emails MAP<VARCHAR, VARCHAR>)))
62
+ statement = client.prepare(%(UPDATE users SET emails['home'] = ? WHERE name = 'eve'))
63
+ statement.execute('eve@gmail.com')
64
+ end
65
+ end
66
+
67
+ context 'with null values' do
68
+ it 'decodes null counters' do
69
+ client.execute(%<CREATE TABLE counters (id ASCII, counter1 COUNTER, counter2 COUNTER, PRIMARY KEY (id))>)
70
+ client.execute(%<UPDATE counters SET counter1 = counter1 + 1 WHERE id = 'foo'>)
71
+ result = client.execute(%<SELECT counter1, counter2 FROM counters WHERE id = 'foo'>)
72
+ result.first['counter1'].should == 1
73
+ result.first['counter2'].should be_nil
74
+ end
75
+
76
+ it 'decodes null values' do
77
+ client.execute(<<-CQL)
78
+ CREATE TABLE lots_of_types (
79
+ id INT,
80
+ ascii_column ASCII,
81
+ bigint_column BIGINT,
82
+ blob_column BLOB,
83
+ boolean_column BOOLEAN,
84
+ decimal_column DECIMAL,
85
+ double_column DOUBLE,
86
+ float_column FLOAT,
87
+ int_column INT,
88
+ text_column TEXT,
89
+ timestamp_column TIMESTAMP,
90
+ uuid_column UUID,
91
+ varchar_column VARCHAR,
92
+ varint_column VARINT,
93
+ timeuuid_column TIMEUUID,
94
+ inet_column INET,
95
+ list_column LIST<ASCII>,
96
+ map_column MAP<TEXT, BOOLEAN>,
97
+ set_column SET<BLOB>,
98
+ PRIMARY KEY (id)
99
+ )
100
+ CQL
101
+ client.execute(%<INSERT INTO lots_of_types (id) VALUES (3)>)
102
+ result = client.execute(%<SELECT * FROM lots_of_types WHERE id = 3>)
103
+ row = result.first
104
+ row['ascii_column'].should be_nil
105
+ row['bigint_column'].should be_nil
106
+ row['blob_column'].should be_nil
107
+ row['boolean_column'].should be_nil
108
+ row['decimal_column'].should be_nil
109
+ row['double_column'].should be_nil
110
+ row['float_column'].should be_nil
111
+ row['int_column'].should be_nil
112
+ row['text_column'].should be_nil
113
+ row['timestamp_column'].should be_nil
114
+ row['uuid_column'].should be_nil
115
+ row['varchar_column'].should be_nil
116
+ row['varint_column'].should be_nil
117
+ row['timeuuid_column'].should be_nil
118
+ row['inet_column'].should be_nil
119
+ row['list_column'].should be_nil
120
+ row['map_column'].should be_nil
121
+ row['set_column'].should be_nil
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,76 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+
6
+ describe 'Loading and storing UUIDs' do
7
+ let :connection_options do
8
+ {:host => ENV['CASSANDRA_HOST'], :credentials => {:username => 'cassandra', :password => 'cassandra'}}
9
+ end
10
+
11
+ let :client do
12
+ Cql::Client.connect(connection_options)
13
+ end
14
+
15
+ let :keyspace_name do
16
+ "cql_rb_#{rand(1000)}"
17
+ end
18
+
19
+ before do
20
+ client.connect
21
+ client.execute(%<CREATE KEYSPACE #{keyspace_name} WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}>)
22
+ client.use(keyspace_name)
23
+ end
24
+
25
+ after do
26
+ client.execute(%<DROP KEYSPACE #{keyspace_name}>)
27
+ client.close
28
+ end
29
+
30
+ context Cql::Uuid do
31
+ let :store_statement do
32
+ client.prepare(%<INSERT INTO ids (id, data) VALUES (?, ?)>)
33
+ end
34
+
35
+ before do
36
+ client.execute(%<CREATE TABLE ids (id UUID PRIMARY KEY, data TEXT)>)
37
+ end
38
+
39
+ it 'can be used to store data in UUID cells' do
40
+ store_statement.execute(Cql::Uuid.new('39bc6ab8-d0f5-11e2-b041-adb2253022a3'), 'hello world')
41
+ end
42
+
43
+ it 'will be used when loading data from UUID cells' do
44
+ store_statement.execute(Cql::Uuid.new('39bc6ab8-d0f5-11e2-b041-adb2253022a3'), 'hello world')
45
+ client.execute(%<SELECT * FROM ids>).first['id'].should == Cql::Uuid.new('39bc6ab8-d0f5-11e2-b041-adb2253022a3')
46
+ end
47
+ end
48
+
49
+ context Cql::TimeUuid::Generator do
50
+ let :store_statement do
51
+ client.prepare(%<INSERT INTO timeline (id, time, value) VALUES (?, ?, ?)>)
52
+ end
53
+
54
+ let :generator do
55
+ Cql::TimeUuid::Generator.new
56
+ end
57
+
58
+ before do
59
+ client.execute(%<CREATE TABLE timeline (id ASCII, time TIMEUUID, value INT, PRIMARY KEY (id, time))>)
60
+ end
61
+
62
+ it 'can be used to generate values for TIMEUUID cells' do
63
+ store_statement.execute('foo', generator.next, 1)
64
+ store_statement.execute('foo', generator.next, 2)
65
+ store_statement.execute('foo', generator.next, 3)
66
+ result = client.execute(%<SELECT * FROM timeline WHERE id = 'foo'>)
67
+ result.map { |row| row['value'] }.should == [1, 2, 3]
68
+ end
69
+
70
+ it 'will be used when loading data from TIMEUUID cells' do
71
+ store_statement.execute('foo', generator.next, 1)
72
+ result = client.execute(%<SELECT * FROM timeline WHERE id = 'foo'>)
73
+ result.first['time'].should be_a(Cql::TimeUuid)
74
+ end
75
+ end
76
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,26 +1,29 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'bundler/setup'
4
- require 'simplecov'; SimpleCov.start
5
- require 'cql'
6
-
7
3
  ENV['CASSANDRA_HOST'] ||= '127.0.0.1'
8
4
 
9
5
  require 'bundler/setup'
10
6
 
7
+ require 'support/bytes_helper'
8
+ require 'support/await_helper'
9
+ require 'support/fake_server'
10
+ require 'support/fake_io_reactor'
11
+
11
12
  unless ENV['COVERAGE'] == 'no'
13
+ require 'coveralls'
12
14
  require 'simplecov'
15
+
16
+ if ENV.include?('TRAVIS')
17
+ Coveralls.wear!
18
+ SimpleCov.formatter = Coveralls::SimpleCov::Formatter
19
+ end
20
+
13
21
  SimpleCov.start do
14
22
  add_group 'Source', 'lib'
15
23
  add_group 'Unit tests', 'spec/cql'
16
24
  add_group 'Integration tests', 'spec/integration'
17
- add_group 'Test support', 'spec/support'
18
25
  end
19
26
  end
20
27
 
21
28
  require 'cql'
22
29
 
23
- require 'support/bytes_helper'
24
- require 'support/await_helper'
25
- require 'support/fake_server'
26
- require 'support/fake_io_reactor'
@@ -8,48 +8,79 @@ class FakeIoReactor
8
8
  @connections = []
9
9
  @queued_responses = Hash.new { |h, k| h[k] = [] }
10
10
  @default_host = nil
11
+ @connection_listeners = []
12
+ @started_future = Cql::Future.new
13
+ @startup_delay = 0
11
14
  end
12
15
 
13
- def queue_response(response, host=nil)
14
- @queued_responses[host] << response
16
+ def startup_delay=(n)
17
+ @startup_delay = n
18
+ end
19
+
20
+ def connect(host, port, timeout)
21
+ connection = FakeConnection.new(host, port, timeout)
22
+ @connections << connection
23
+ @connection_listeners.each do |listener|
24
+ listener.call(connection)
25
+ end
26
+ Cql::Future.completed(connection)
27
+ end
28
+
29
+ def on_connection(&listener)
30
+ @connection_listeners << listener
15
31
  end
16
32
 
17
33
  def start
18
34
  @running = true
19
- @connections = []
20
- @connections.each do |connection|
21
- connection[:future].complete! unless connection[:future].complete?
35
+ Thread.start do
36
+ sleep(@startup_delay)
37
+ @started_future.complete!(self)
22
38
  end
23
- Cql::Future.completed
39
+ @started_future
24
40
  end
25
41
 
26
42
  def stop
27
43
  @running = false
44
+ @connections.each(&:close)
28
45
  Cql::Future.completed
29
46
  end
30
47
 
31
48
  def running?
32
49
  @running
33
50
  end
51
+ end
34
52
 
35
- def add_connection(host, port)
36
- @default_host ||= host
37
- future = Cql::Future.new
38
- connection = {:host => host, :port => port, :future => future, :requests => []}
39
- @connections << connection
40
- future.complete!(connection.object_id) if @running
41
- future
53
+ class FakeConnection
54
+ attr_reader :host, :port, :timeout, :requests, :keyspace
55
+
56
+ def initialize(host, port, timeout)
57
+ @host = host
58
+ @port = port
59
+ @timeout = timeout
60
+ @requests = []
61
+ @responses = []
62
+ @closed = false
63
+ @keyspace = nil
64
+ end
65
+
66
+ def close
67
+ @closed = true
68
+ end
69
+
70
+ def queue_response(response)
71
+ @responses << response
42
72
  end
43
73
 
44
- def queue_request(request, connection_id=nil)
45
- if connection_id
46
- connection = @connections.find { |c| c.object_id == connection_id }
74
+ def send_request(request)
75
+ if @closed
76
+ Cql::Future.failed(Cql::NotConnectedError.new)
47
77
  else
48
- connection = @connections.sample
78
+ @requests << request
79
+ response = @responses.shift
80
+ if response.is_a?(Cql::Protocol::SetKeyspaceResultResponse)
81
+ @keyspace = response.keyspace
82
+ end
83
+ Cql::Future.completed(response)
49
84
  end
50
- connection[:requests] << request
51
- response = @queued_responses[connection[:host]].shift || @queued_responses[nil].shift
52
- @last_used_connection = connection
53
- Cql::Future.completed([response, connection.object_id])
54
85
  end
55
86
  end
@@ -1,9 +1,9 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  class FakeServer
4
- attr_reader :connects, :disconnects
4
+ attr_reader :port, :connects, :disconnects
5
5
 
6
- def initialize(port)
6
+ def initialize(port=(2**15 + rand(2**15)))
7
7
  @port = port
8
8
  @state = {}
9
9
  @lock = Mutex.new
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cql-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.6
4
+ version: 1.1.0.pre0
5
+ prerelease: 6
5
6
  platform: ruby
6
7
  authors:
7
8
  - Theo Hultberg
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2013-10-14 00:00:00.000000000 Z
12
+ date: 2013-07-04 00:00:00.000000000 Z
12
13
  dependencies: []
13
14
  description: A pure Ruby CQL3 driver for Cassandra
14
15
  email:
@@ -22,14 +23,16 @@ files:
22
23
  - lib/cql/client/asynchronous_prepared_statement.rb
23
24
  - lib/cql/client/column_metadata.rb
24
25
  - lib/cql/client/query_result.rb
26
+ - lib/cql/client/request_runner.rb
25
27
  - lib/cql/client/result_metadata.rb
26
28
  - lib/cql/client/synchronous_client.rb
27
29
  - lib/cql/client/synchronous_prepared_statement.rb
28
30
  - lib/cql/client.rb
29
31
  - lib/cql/future.rb
32
+ - lib/cql/io/connection.rb
30
33
  - lib/cql/io/io_reactor.rb
31
- - lib/cql/io/node_connection.rb
32
34
  - lib/cql/io.rb
35
+ - lib/cql/protocol/cql_protocol_handler.rb
33
36
  - lib/cql/protocol/decoding.rb
34
37
  - lib/cql/protocol/encoding.rb
35
38
  - lib/cql/protocol/request.rb
@@ -59,6 +62,7 @@ files:
59
62
  - lib/cql/protocol/responses/void_result_response.rb
60
63
  - lib/cql/protocol/type_converter.rb
61
64
  - lib/cql/protocol.rb
65
+ - lib/cql/time_uuid.rb
62
66
  - lib/cql/uuid.rb
63
67
  - lib/cql/version.rb
64
68
  - lib/cql.rb
@@ -66,11 +70,16 @@ files:
66
70
  - README.md
67
71
  - spec/cql/byte_buffer_spec.rb
68
72
  - spec/cql/client/asynchronous_client_spec.rb
73
+ - spec/cql/client/asynchronous_prepared_statement_spec.rb
69
74
  - spec/cql/client/client_shared.rb
75
+ - spec/cql/client/column_metadata_spec.rb
76
+ - spec/cql/client/request_runner_spec.rb
70
77
  - spec/cql/client/synchronous_client_spec.rb
71
78
  - spec/cql/client/synchronous_prepared_statement_spec.rb
72
79
  - spec/cql/future_spec.rb
80
+ - spec/cql/io/connection_spec.rb
73
81
  - spec/cql/io/io_reactor_spec.rb
82
+ - spec/cql/protocol/cql_protocol_handler_spec.rb
74
83
  - spec/cql/protocol/decoding_spec.rb
75
84
  - spec/cql/protocol/encoding_spec.rb
76
85
  - spec/cql/protocol/request_spec.rb
@@ -82,10 +91,14 @@ files:
82
91
  - spec/cql/protocol/requests/register_request_spec.rb
83
92
  - spec/cql/protocol/requests/startup_request_spec.rb
84
93
  - spec/cql/protocol/response_frame_spec.rb
85
- - spec/cql/protocol/type_converter_spec.rb
94
+ - spec/cql/protocol/responses/schema_change_result_response_spec.rb
95
+ - spec/cql/time_uuid_spec.rb
86
96
  - spec/cql/uuid_spec.rb
87
97
  - spec/integration/client_spec.rb
98
+ - spec/integration/io_spec.rb
88
99
  - spec/integration/protocol_spec.rb
100
+ - spec/integration/regression_spec.rb
101
+ - spec/integration/uuid_spec.rb
89
102
  - spec/spec_helper.rb
90
103
  - spec/support/await_helper.rb
91
104
  - spec/support/bytes_helper.rb
@@ -94,35 +107,41 @@ files:
94
107
  homepage: http://github.com/iconara/cql-rb
95
108
  licenses:
96
109
  - Apache
97
- metadata: {}
98
110
  post_install_message:
99
111
  rdoc_options: []
100
112
  require_paths:
101
113
  - lib
102
114
  required_ruby_version: !ruby/object:Gem::Requirement
115
+ none: false
103
116
  requirements:
104
117
  - - ! '>='
105
118
  - !ruby/object:Gem::Version
106
119
  version: 1.9.2
107
120
  required_rubygems_version: !ruby/object:Gem::Requirement
121
+ none: false
108
122
  requirements:
109
- - - ! '>='
123
+ - - ! '>'
110
124
  - !ruby/object:Gem::Version
111
- version: '0'
125
+ version: 1.3.1
112
126
  requirements: []
113
127
  rubyforge_project:
114
- rubygems_version: 2.1.5
128
+ rubygems_version: 1.8.23
115
129
  signing_key:
116
- specification_version: 4
130
+ specification_version: 3
117
131
  summary: Cassandra CQL3 driver
118
132
  test_files:
119
133
  - spec/cql/byte_buffer_spec.rb
120
134
  - spec/cql/client/asynchronous_client_spec.rb
135
+ - spec/cql/client/asynchronous_prepared_statement_spec.rb
121
136
  - spec/cql/client/client_shared.rb
137
+ - spec/cql/client/column_metadata_spec.rb
138
+ - spec/cql/client/request_runner_spec.rb
122
139
  - spec/cql/client/synchronous_client_spec.rb
123
140
  - spec/cql/client/synchronous_prepared_statement_spec.rb
124
141
  - spec/cql/future_spec.rb
142
+ - spec/cql/io/connection_spec.rb
125
143
  - spec/cql/io/io_reactor_spec.rb
144
+ - spec/cql/protocol/cql_protocol_handler_spec.rb
126
145
  - spec/cql/protocol/decoding_spec.rb
127
146
  - spec/cql/protocol/encoding_spec.rb
128
147
  - spec/cql/protocol/request_spec.rb
@@ -134,10 +153,14 @@ test_files:
134
153
  - spec/cql/protocol/requests/register_request_spec.rb
135
154
  - spec/cql/protocol/requests/startup_request_spec.rb
136
155
  - spec/cql/protocol/response_frame_spec.rb
137
- - spec/cql/protocol/type_converter_spec.rb
156
+ - spec/cql/protocol/responses/schema_change_result_response_spec.rb
157
+ - spec/cql/time_uuid_spec.rb
138
158
  - spec/cql/uuid_spec.rb
139
159
  - spec/integration/client_spec.rb
160
+ - spec/integration/io_spec.rb
140
161
  - spec/integration/protocol_spec.rb
162
+ - spec/integration/regression_spec.rb
163
+ - spec/integration/uuid_spec.rb
141
164
  - spec/spec_helper.rb
142
165
  - spec/support/await_helper.rb
143
166
  - spec/support/bytes_helper.rb