cql-rb 1.2.2 → 2.0.0.pre0

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.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +4 -0
  3. data/README.md +139 -17
  4. data/lib/cql/client.rb +237 -8
  5. data/lib/cql/client/asynchronous_client.rb +138 -54
  6. data/lib/cql/client/asynchronous_prepared_statement.rb +41 -6
  7. data/lib/cql/client/authenticators.rb +46 -0
  8. data/lib/cql/client/batch.rb +115 -0
  9. data/lib/cql/client/connector.rb +255 -0
  10. data/lib/cql/client/execute_options_decoder.rb +25 -9
  11. data/lib/cql/client/keyspace_changer.rb +5 -5
  12. data/lib/cql/client/peer_discovery.rb +33 -0
  13. data/lib/cql/client/query_result.rb +124 -1
  14. data/lib/cql/client/request_runner.rb +4 -2
  15. data/lib/cql/client/synchronous_client.rb +14 -2
  16. data/lib/cql/client/synchronous_prepared_statement.rb +19 -1
  17. data/lib/cql/future.rb +97 -50
  18. data/lib/cql/io/connection.rb +0 -1
  19. data/lib/cql/io/io_reactor.rb +1 -1
  20. data/lib/cql/protocol.rb +8 -1
  21. data/lib/cql/protocol/cql_protocol_handler.rb +2 -2
  22. data/lib/cql/protocol/decoding.rb +10 -15
  23. data/lib/cql/protocol/frame_decoder.rb +2 -1
  24. data/lib/cql/protocol/frame_encoder.rb +5 -4
  25. data/lib/cql/protocol/requests/auth_response_request.rb +31 -0
  26. data/lib/cql/protocol/requests/batch_request.rb +59 -0
  27. data/lib/cql/protocol/requests/credentials_request.rb +1 -1
  28. data/lib/cql/protocol/requests/execute_request.rb +45 -17
  29. data/lib/cql/protocol/requests/options_request.rb +1 -1
  30. data/lib/cql/protocol/requests/prepare_request.rb +1 -1
  31. data/lib/cql/protocol/requests/query_request.rb +97 -5
  32. data/lib/cql/protocol/requests/register_request.rb +1 -1
  33. data/lib/cql/protocol/requests/startup_request.rb +4 -4
  34. data/lib/cql/protocol/response.rb +2 -2
  35. data/lib/cql/protocol/responses/auth_challenge_response.rb +25 -0
  36. data/lib/cql/protocol/responses/auth_success_response.rb +25 -0
  37. data/lib/cql/protocol/responses/authenticate_response.rb +1 -1
  38. data/lib/cql/protocol/responses/detailed_error_response.rb +1 -1
  39. data/lib/cql/protocol/responses/error_response.rb +3 -2
  40. data/lib/cql/protocol/responses/event_response.rb +3 -2
  41. data/lib/cql/protocol/responses/prepared_result_response.rb +10 -6
  42. data/lib/cql/protocol/responses/raw_rows_result_response.rb +27 -0
  43. data/lib/cql/protocol/responses/ready_response.rb +1 -1
  44. data/lib/cql/protocol/responses/result_response.rb +2 -2
  45. data/lib/cql/protocol/responses/rows_result_response.rb +43 -23
  46. data/lib/cql/protocol/responses/schema_change_event_response.rb +1 -1
  47. data/lib/cql/protocol/responses/schema_change_result_response.rb +1 -1
  48. data/lib/cql/protocol/responses/set_keyspace_result_response.rb +1 -1
  49. data/lib/cql/protocol/responses/status_change_event_response.rb +1 -1
  50. data/lib/cql/protocol/responses/supported_response.rb +1 -1
  51. data/lib/cql/protocol/responses/void_result_response.rb +1 -1
  52. data/lib/cql/protocol/type_converter.rb +2 -2
  53. data/lib/cql/uuid.rb +2 -2
  54. data/lib/cql/version.rb +1 -1
  55. data/spec/cql/client/asynchronous_client_spec.rb +493 -50
  56. data/spec/cql/client/asynchronous_prepared_statement_spec.rb +193 -11
  57. data/spec/cql/client/authenticators_spec.rb +56 -0
  58. data/spec/cql/client/batch_spec.rb +277 -0
  59. data/spec/cql/client/connector_spec.rb +606 -0
  60. data/spec/cql/client/execute_options_decoder_spec.rb +95 -0
  61. data/spec/cql/client/keyspace_changer_spec.rb +8 -8
  62. data/spec/cql/client/peer_discovery_spec.rb +92 -0
  63. data/spec/cql/client/query_result_spec.rb +352 -0
  64. data/spec/cql/client/request_runner_spec.rb +31 -5
  65. data/spec/cql/client/synchronous_client_spec.rb +44 -1
  66. data/spec/cql/client/synchronous_prepared_statement_spec.rb +63 -1
  67. data/spec/cql/future_spec.rb +50 -2
  68. data/spec/cql/protocol/cql_protocol_handler_spec.rb +16 -5
  69. data/spec/cql/protocol/decoding_spec.rb +16 -6
  70. data/spec/cql/protocol/encoding_spec.rb +3 -1
  71. data/spec/cql/protocol/frame_encoder_spec.rb +99 -50
  72. data/spec/cql/protocol/requests/auth_response_request_spec.rb +62 -0
  73. data/spec/cql/protocol/requests/batch_request_spec.rb +155 -0
  74. data/spec/cql/protocol/requests/credentials_request_spec.rb +1 -1
  75. data/spec/cql/protocol/requests/execute_request_spec.rb +184 -71
  76. data/spec/cql/protocol/requests/options_request_spec.rb +1 -1
  77. data/spec/cql/protocol/requests/prepare_request_spec.rb +1 -1
  78. data/spec/cql/protocol/requests/query_request_spec.rb +255 -32
  79. data/spec/cql/protocol/requests/register_request_spec.rb +1 -1
  80. data/spec/cql/protocol/requests/startup_request_spec.rb +12 -6
  81. data/spec/cql/protocol/responses/auth_challenge_response_spec.rb +31 -0
  82. data/spec/cql/protocol/responses/auth_success_response_spec.rb +31 -0
  83. data/spec/cql/protocol/responses/authenticate_response_spec.rb +2 -1
  84. data/spec/cql/protocol/responses/detailed_error_response_spec.rb +14 -7
  85. data/spec/cql/protocol/responses/error_response_spec.rb +4 -2
  86. data/spec/cql/protocol/responses/event_response_spec.rb +7 -4
  87. data/spec/cql/protocol/responses/prepared_result_response_spec.rb +89 -34
  88. data/spec/cql/protocol/responses/raw_rows_result_response_spec.rb +66 -0
  89. data/spec/cql/protocol/responses/ready_response_spec.rb +1 -1
  90. data/spec/cql/protocol/responses/result_response_spec.rb +19 -7
  91. data/spec/cql/protocol/responses/rows_result_response_spec.rb +56 -11
  92. data/spec/cql/protocol/responses/schema_change_event_response_spec.rb +2 -1
  93. data/spec/cql/protocol/responses/schema_change_result_response_spec.rb +2 -1
  94. data/spec/cql/protocol/responses/set_keyspace_result_response_spec.rb +1 -1
  95. data/spec/cql/protocol/responses/status_change_event_response_spec.rb +2 -1
  96. data/spec/cql/protocol/responses/supported_response_spec.rb +2 -1
  97. data/spec/cql/protocol/responses/topology_change_event_response_spec.rb +2 -1
  98. data/spec/cql/protocol/responses/void_result_response_spec.rb +1 -1
  99. data/spec/cql/protocol/type_converter_spec.rb +21 -4
  100. data/spec/cql/uuid_spec.rb +10 -3
  101. data/spec/integration/client_spec.rb +251 -28
  102. data/spec/integration/protocol_spec.rb +213 -62
  103. data/spec/integration/regression_spec.rb +4 -1
  104. data/spec/integration/uuid_spec.rb +4 -1
  105. data/spec/support/fake_io_reactor.rb +5 -5
  106. metadata +36 -7
  107. data/lib/cql/client/connection_helper.rb +0 -181
  108. data/spec/cql/client/connection_helper_spec.rb +0 -429
@@ -0,0 +1,62 @@
1
+ # encoding: ascii-8bit
2
+
3
+ require 'spec_helper'
4
+
5
+
6
+ module Cql
7
+ module Protocol
8
+ describe AuthResponseRequest do
9
+ describe '#write' do
10
+ it 'encodes an AUTH_RESPONSE request frame' do
11
+ bytes = described_class.new('bingbongpong').write(2, '')
12
+ bytes.should == "\x00\x00\x00\x0cbingbongpong"
13
+ end
14
+
15
+ it 'encodes a nil token' do
16
+ bytes = described_class.new(nil).write(2, '')
17
+ bytes.should == "\xff\xff\xff\xff"
18
+ end
19
+ end
20
+
21
+ describe '#to_s' do
22
+ it 'returns a string representation including the number of bytes in the token' do
23
+ described_class.new('bingbongpong').to_s.should == 'AUTH_RESPONSE 12'
24
+ end
25
+ end
26
+
27
+ describe '#eql?' do
28
+ it 'is equal to another with the same token' do
29
+ r1 = described_class.new('foo')
30
+ r2 = described_class.new('foo')
31
+ r1.should eql(r2)
32
+ end
33
+
34
+ it 'is not equal when the token is different' do
35
+ r1 = described_class.new('foo')
36
+ r2 = described_class.new('bar')
37
+ r1.should_not eql(r2)
38
+ end
39
+
40
+ it 'is aliased as #==' do
41
+ r1 = described_class.new('foo')
42
+ r2 = described_class.new('foo')
43
+ r1.should == r2
44
+ end
45
+ end
46
+
47
+ describe '#hash' do
48
+ it 'is the same when the token is the same' do
49
+ r1 = described_class.new('foo')
50
+ r2 = described_class.new('foo')
51
+ r1.hash.should == r2.hash
52
+ end
53
+
54
+ it 'is not the same when the token is different' do
55
+ r1 = described_class.new('foo')
56
+ r2 = described_class.new('bar')
57
+ r1.hash.should_not == r2.hash
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,155 @@
1
+ # encoding: ascii-8bit
2
+
3
+ require 'spec_helper'
4
+
5
+
6
+ module Cql
7
+ module Protocol
8
+ describe BatchRequest do
9
+ let :statement_id do
10
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
11
+ end
12
+
13
+ let :metadata do
14
+ [['ks', 'tbl', 'things', :varchar], ['ks', 'tbl', 'things', :int]]
15
+ end
16
+
17
+ describe '#write' do
18
+ it 'encodes a BATCH request frame with a single prepared query' do
19
+ batch = described_class.new(described_class::LOGGED_TYPE, :two)
20
+ batch.add_prepared(statement_id, metadata, ['arg', 3])
21
+ bytes = batch.write(2, '')
22
+ bytes.should == (
23
+ "\x00" +
24
+ "\x00\x01" +
25
+ "\x01" +
26
+ "\x00\x10" + statement_id +
27
+ "\x00\x02" + "\x00\x00\x00\x03arg" + "\x00\x00\x00\x04\x00\x00\x00\x03" +
28
+ "\x00\x02"
29
+ )
30
+ end
31
+
32
+ it 'encodes a BATCH request frame with a single query' do
33
+ batch = described_class.new(described_class::LOGGED_TYPE, :one)
34
+ batch.add_query(%<INSERT INTO things (a, b) VALUES ('foo', 3)>)
35
+ bytes = batch.write(2, '')
36
+ bytes.should == (
37
+ "\x00" +
38
+ "\x00\x01" +
39
+ "\x00" +
40
+ "\x00\x00\x00\x2bINSERT INTO things (a, b) VALUES ('foo', 3)" +
41
+ "\x00\x00" +
42
+ "\x00\x01"
43
+ )
44
+ end
45
+
46
+ it 'encodes a BATCH request frame with a single query with on-the-fly bound values' do
47
+ batch = described_class.new(described_class::LOGGED_TYPE, :two)
48
+ batch.add_query('INSERT INTO things (a, b) VALUES (?, ?)', ['foo', 5])
49
+ bytes = batch.write(2, '')
50
+ bytes.should == (
51
+ "\x00" +
52
+ "\x00\x01" +
53
+ "\x00" +
54
+ "\x00\x00\x00\x27INSERT INTO things (a, b) VALUES (?, ?)" +
55
+ "\x00\x02" + "\x00\x00\x00\x03foo" + "\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x05" +
56
+ "\x00\x02"
57
+ )
58
+ end
59
+
60
+ it 'encodes a BATCH request frame with a a mix of prepared and non-prepared queries' do
61
+ batch = described_class.new(described_class::LOGGED_TYPE, :two)
62
+ batch.add_prepared(statement_id, metadata, ['arg', 3])
63
+ batch.add_query(%<INSERT INTO things (a, b) VALUES (?, ?)>, ['foo', 5])
64
+ batch.add_query(%<INSERT INTO things (a, b) VALUES ('foo', 3)>)
65
+ bytes = batch.write(2, '')
66
+ bytes.should == (
67
+ "\x00" +
68
+ "\x00\x03" +
69
+ "\x01" +
70
+ "\x00\x10" + statement_id +
71
+ "\x00\x02" + "\x00\x00\x00\x03arg" + "\x00\x00\x00\x04\x00\x00\x00\x03" +
72
+ "\x00" +
73
+ "\x00\x00\x00\x27INSERT INTO things (a, b) VALUES (?, ?)" +
74
+ "\x00\x02" + "\x00\x00\x00\x03foo" + "\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x05" +
75
+ "\x00" +
76
+ "\x00\x00\x00\x2bINSERT INTO things (a, b) VALUES ('foo', 3)" +
77
+ "\x00\x00" +
78
+ "\x00\x02"
79
+ )
80
+ end
81
+
82
+ it 'encodes the type when it is "logged"' do
83
+ batch = described_class.new(described_class::LOGGED_TYPE, :two)
84
+ batch.add_prepared(statement_id, metadata, ['arg', 3])
85
+ bytes = batch.write(2, '')
86
+ bytes[0].should == "\x00"
87
+ end
88
+
89
+ it 'encodes the type when it is "unlogged"' do
90
+ batch = described_class.new(described_class::UNLOGGED_TYPE, :two)
91
+ batch.add_prepared(statement_id, metadata, ['arg', 3])
92
+ bytes = batch.write(2, '')
93
+ bytes[0].should == "\x01"
94
+ end
95
+
96
+ it 'encodes the type when it is "counter"' do
97
+ batch = described_class.new(described_class::COUNTER_TYPE, :two)
98
+ batch.add_prepared(statement_id, metadata, ['arg', 3])
99
+ bytes = batch.write(2, '')
100
+ bytes[0].should == "\x02"
101
+ end
102
+
103
+ it 'encodes the number of statements in the batch' do
104
+ batch = described_class.new(described_class::LOGGED_TYPE, :two)
105
+ batch.add_prepared(statement_id, metadata, ['arg', 3])
106
+ batch.add_prepared(statement_id, metadata, ['foo', 4])
107
+ batch.add_prepared(statement_id, metadata, ['bar', 5])
108
+ bytes = batch.write(2, '')
109
+ bytes[1, 2].should == "\x00\x03"
110
+ end
111
+
112
+ it 'encodes the type of each statement' do
113
+ batch = described_class.new(described_class::LOGGED_TYPE, :two)
114
+ batch.add_prepared(statement_id, metadata, ['arg', 3])
115
+ batch.add_query(%<INSERT INTO things (a, b) VALUES ('arg', 3)>)
116
+ bytes = batch.write(2, '')
117
+ bytes[3, 1].should == "\x01"
118
+ bytes[39, 1].should == "\x00"
119
+ end
120
+
121
+ it 'uses the type hints given to #add_query' do
122
+ batch = described_class.new(described_class::LOGGED_TYPE, :two)
123
+ batch.add_query(%<INSERT INTO things (a, b) VALUES (?, ?)>, ['foo', 3], [nil, :int])
124
+ bytes = batch.write(2, '')
125
+ bytes[56, 8].should == "\x00\x00\x00\x04\x00\x00\x00\x03"
126
+ end
127
+ end
128
+
129
+ describe '#to_s' do
130
+ context 'when the type is LOGGED' do
131
+ it 'returns a string representation of the batch request' do
132
+ batch = described_class.new(described_class::LOGGED_TYPE, :local_quorum)
133
+ batch.add_prepared(statement_id, metadata, ['arg', 3])
134
+ batch.add_query(%<INSERT INTO things (a, b) VALUES ('arg', 3)>)
135
+ batch.to_s.should == %(BATCH LOGGED 2 LOCAL_QUORUM)
136
+ end
137
+ end
138
+
139
+ context 'when the type is UNLOGGED' do
140
+ it 'returns a string representation of the batch request' do
141
+ batch = described_class.new(described_class::UNLOGGED_TYPE, :one)
142
+ batch.to_s.should == %(BATCH UNLOGGED 0 ONE)
143
+ end
144
+ end
145
+
146
+ context 'when the type is COUNTER' do
147
+ it 'returns a string representation of the batch request' do
148
+ batch = described_class.new(described_class::COUNTER_TYPE, :two)
149
+ batch.to_s.should == %(BATCH COUNTER 0 TWO)
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
@@ -8,7 +8,7 @@ module Cql
8
8
  describe CredentialsRequest do
9
9
  describe '#write' do
10
10
  it 'encodes a CREDENTIALS request frame' do
11
- bytes = CredentialsRequest.new('username' => 'cassandra', 'password' => 'ardnassac').write('')
11
+ bytes = CredentialsRequest.new('username' => 'cassandra', 'password' => 'ardnassac').write(1, '')
12
12
  bytes.should == (
13
13
  "\x00\x02" +
14
14
  "\x00\x08username" +
@@ -24,152 +24,265 @@ module Cql
24
24
 
25
25
  describe '#initialize' do
26
26
  it 'raises an error when the metadata and values don\'t have the same size' do
27
- expect { ExecuteRequest.new(id, column_metadata, ['hello', 42], :each_quorum) }.to raise_error(ArgumentError)
27
+ expect { ExecuteRequest.new(id, column_metadata, ['hello', 42], true, :each_quorum, nil, nil, nil, false) }.to raise_error(ArgumentError)
28
+ end
29
+
30
+ it 'raises an error when the consistency is nil' do
31
+ expect { ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], true, nil, nil, nil, nil, false) }.to raise_error(ArgumentError)
32
+ end
33
+
34
+ it 'raises an error when the consistency is invalid' do
35
+ expect { ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], true, :hello, nil, nil, nil, false) }.to raise_error(ArgumentError)
36
+ end
37
+
38
+ it 'raises an error when the serial consistency is invalid' do
39
+ expect { ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], true, :quorum, :foo, nil, nil, false) }.to raise_error(ArgumentError)
40
+ end
41
+
42
+ it 'raises an error when paging state is given but no page size' do
43
+ expect { ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], true, :quorum, nil, nil, 'foo', false) }.to raise_error(ArgumentError)
28
44
  end
29
45
 
30
46
  it 'raises an error for unsupported column types' do
31
47
  column_metadata[2][3] = :imaginary
32
- expect { ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], :each_quorum) }.to raise_error(UnsupportedColumnTypeError)
48
+ expect { ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], true, :each_quorum, nil, nil, nil, false) }.to raise_error(UnsupportedColumnTypeError)
33
49
  end
34
50
 
35
51
  it 'raises an error for unsupported column collection types' do
36
52
  column_metadata[2][3] = [:imaginary, :varchar]
37
- expect { ExecuteRequest.new(id, column_metadata, ['hello', 42, ['foo']], :each_quorum) }.to raise_error(UnsupportedColumnTypeError)
53
+ expect { ExecuteRequest.new(id, column_metadata, ['hello', 42, ['foo']], true, :each_quorum, nil, nil, nil, false) }.to raise_error(UnsupportedColumnTypeError)
38
54
  end
39
55
 
40
56
  it 'raises an error when collection values are not enumerable' do
41
57
  column_metadata[2][3] = [:set, :varchar]
42
- expect { ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], :each_quorum) }.to raise_error(InvalidValueError)
58
+ expect { ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], true, :each_quorum, nil, nil, nil, false) }.to raise_error(InvalidValueError)
43
59
  end
44
60
 
45
61
  it 'raises an error when it cannot encode the argument' do
46
- expect { ExecuteRequest.new(id, column_metadata, ['hello', 'not an int', 'foo'], :each_quorum) }.to raise_error(TypeError, /cannot be encoded as INT/)
62
+ expect { ExecuteRequest.new(id, column_metadata, ['hello', 'not an int', 'foo'], true, :each_quorum, nil, nil, nil, false) }.to raise_error(TypeError, /cannot be encoded as INT/)
47
63
  end
48
64
  end
49
65
 
50
66
  describe '#write' do
51
- it 'encodes an EXECUTE request frame' do
52
- bytes = ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], :each_quorum).write('')
53
- bytes.should == "\x00\x10\xCAH\x7F\x1Ez\x82\xD2<N\x8A\xF35Qq\xA5/\x00\x03\x00\x00\x00\x05hello\x00\x00\x00\x04\x00\x00\x00\x2a\x00\x00\x00\x03foo\x00\x07"
54
- end
55
-
56
- specs = [
57
- [:ascii, 'test', "test"],
58
- [:bigint, 1012312312414123, "\x00\x03\x98\xB1S\xC8\x7F\xAB"],
59
- [:blob, "\xab\xcd", "\xab\xcd"],
60
- [:boolean, false, "\x00"],
61
- [:boolean, true, "\x01"],
62
- [:decimal, BigDecimal.new('1042342234234.123423435647768234'), "\x00\x00\x00\x12\r'\xFDI\xAD\x80f\x11g\xDCfV\xAA"],
63
- [:double, 10000.123123123, "@\xC3\x88\x0F\xC2\x7F\x9DU"],
64
- [:float, 12.13, "AB\x14{"],
65
- [:inet, IPAddr.new('8.8.8.8'), "\x08\x08\x08\x08"],
66
- [:inet, IPAddr.new('::1'), "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"],
67
- [:int, 12348098, "\x00\xBCj\xC2"],
68
- [:text, 'FOOBAR', 'FOOBAR'],
69
- [:timestamp, Time.at(1358013521.123), "\x00\x00\x01</\xE9\xDC\xE3"],
70
- [:timeuuid, Uuid.new('a4a70900-24e1-11df-8924-001ff3591711'), "\xA4\xA7\t\x00$\xE1\x11\xDF\x89$\x00\x1F\xF3Y\x17\x11"],
71
- [:uuid, Uuid.new('cfd66ccc-d857-4e90-b1e5-df98a3d40cd6'), "\xCF\xD6l\xCC\xD8WN\x90\xB1\xE5\xDF\x98\xA3\xD4\f\xD6"],
72
- [:varchar, 'hello', 'hello'],
73
- [:varint, 1231312312331283012830129382342342412123, "\x03\x9EV \x15\f\x03\x9DK\x18\xCDI\\$?\a["],
74
- [:varint, -234234234234, "\xC9v\x8D:\x86"],
75
- [[:list, :timestamp], [Time.at(1358013521.123)], "\x00\x01" + "\x00\x08\x00\x00\x01</\xE9\xDC\xE3"],
76
- [[:list, :boolean], [true, false, true, true], "\x00\x04" + "\x00\x01\x01" + "\x00\x01\x00" + "\x00\x01\x01" + "\x00\x01\x01"],
77
- [[:map, :uuid, :int], {Uuid.new('cfd66ccc-d857-4e90-b1e5-df98a3d40cd6') => 45345, Uuid.new('a4a70900-24e1-11df-8924-001ff3591711') => 98765}, "\x00\x02" + "\x00\x10\xCF\xD6l\xCC\xD8WN\x90\xB1\xE5\xDF\x98\xA3\xD4\f\xD6" + "\x00\x04\x00\x00\xb1\x21" + "\x00\x10\xA4\xA7\t\x00$\xE1\x11\xDF\x89$\x00\x1F\xF3Y\x17\x11" + "\x00\x04\x00\x01\x81\xcd"],
78
- [[:map, :ascii, :blob], {'hello' => 'world', 'one' => "\x01", 'two' => "\x02"}, "\x00\x03" + "\x00\x05hello" + "\x00\x05world" + "\x00\x03one" + "\x00\x01\x01" + "\x00\x03two" + "\x00\x01\x02"],
79
- [[:map, :varchar, :float], {'hello' => 1, 'würld'.force_encoding('utf-8') => 2.0}, "\x00\x02" + "\x00\x05hello" + "\x00\x04?\x80\x00\x00" + "\x00\x06w\xC3\xBCrld" + "\x00\x04@\x00\x00\x00"],
80
- [[:set, :int], Set.new([13, 3453, 456456, 123, 768678]), "\x00\x05" + "\x00\x04\x00\x00\x00\x0d" + "\x00\x04\x00\x00\x0d\x7d" + "\x00\x04\x00\x06\xf7\x08" + "\x00\x04\x00\x00\x00\x7b" + "\x00\x04\x00\x0b\xba\xa6"],
81
- [[:set, :varchar], Set.new(['foo', 'bar', 'baz']), "\x00\x03" + "\x00\x03foo" + "\x00\x03bar" + "\x00\x03baz"],
82
- [[:set, :int], [13, 3453, 456456, 123, 768678], "\x00\x05" + "\x00\x04\x00\x00\x00\x0d" + "\x00\x04\x00\x00\x0d\x7d" + "\x00\x04\x00\x06\xf7\x08" + "\x00\x04\x00\x00\x00\x7b" + "\x00\x04\x00\x0b\xba\xa6"],
83
- [[:set, :varchar], ['foo', 'bar', 'baz'], "\x00\x03" + "\x00\x03foo" + "\x00\x03bar" + "\x00\x03baz"]
84
- ]
85
- specs.each do |type, value, expected_bytes|
86
- it "encodes #{type} values" do
87
- metadata = [['ks', 'tbl', 'id_column', type]]
88
- buffer = ExecuteRequest.new(id, metadata, [value], :one).write(ByteBuffer.new)
89
- buffer.discard(2 + 16 + 2)
90
- length = buffer.read_int
91
- result_bytes = buffer.read(length)
92
- result_bytes.should eql_bytes(expected_bytes)
67
+ context 'when the protocol version is 1' do
68
+ let :frame_bytes do
69
+ ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], true, :each_quorum, nil, nil, nil, false).write(1, '')
70
+ end
71
+
72
+ it 'writes the statement ID' do
73
+ frame_bytes.to_s[0, 18].should == "\x00\x10\xCAH\x7F\x1Ez\x82\xD2<N\x8A\xF35Qq\xA5/"
74
+ end
75
+
76
+ it 'writes the number of bound variables' do
77
+ frame_bytes.to_s[18, 2].should == "\x00\x03"
78
+ end
79
+
80
+ it 'writes the bound variables' do
81
+ frame_bytes.to_s[20, 24].should == "\x00\x00\x00\x05hello\x00\x00\x00\x04\x00\x00\x00\x2a\x00\x00\x00\x03foo"
82
+ end
83
+
84
+ it 'writes the consistency' do
85
+ frame_bytes.to_s[44, 999].should == "\x00\x07"
86
+ end
87
+ end
88
+
89
+ context 'when the protocol version is 2' do
90
+ let :frame_bytes do
91
+ ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], true, :each_quorum, nil, nil, nil, false).write(2, '')
92
+ end
93
+
94
+ it 'writes the statement ID' do
95
+ frame_bytes.to_s[0, 18].should == "\x00\x10\xCAH\x7F\x1Ez\x82\xD2<N\x8A\xF35Qq\xA5/"
96
+ end
97
+
98
+ it 'writes the consistency' do
99
+ frame_bytes.to_s[18, 2].should == "\x00\x07"
100
+ end
101
+
102
+ it 'writes flags saying that there will be bound values values' do
103
+ frame_bytes.to_s[20, 1].should == "\x01"
104
+ end
105
+
106
+ it 'does not write the bound values flag when there are no values, and does not write anything more' do
107
+ frame_bytes = ExecuteRequest.new(id, [], [], true, :each_quorum, nil, nil, nil, false).write(2, '')
108
+ frame_bytes.to_s[20, 999].should == "\x00"
109
+ end
110
+
111
+ it 'writes flags saying that the result doesn\'t need to contain metadata' do
112
+ frame_bytes = ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], false, :each_quorum, nil, nil, nil, false).write(2, '')
113
+ frame_bytes.to_s[20, 1].should == "\x03"
114
+ end
115
+
116
+ it 'writes the number of bound values' do
117
+ frame_bytes.to_s[21, 2].should == "\x00\x03"
118
+ end
119
+
120
+ it 'writes the bound values' do
121
+ frame_bytes.to_s[23, 999].should == "\x00\x00\x00\x05hello\x00\x00\x00\x04\x00\x00\x00\x2a\x00\x00\x00\x03foo"
122
+ end
123
+
124
+ it 'sets the serial flag and includes the serial consistency' do
125
+ frame_bytes = ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], false, :each_quorum, :local_serial, false).write(2, '')
126
+ frame_bytes.to_s[20, 1].should == "\x13"
127
+ frame_bytes.to_s[47, 2].should == "\x00\x09"
128
+ end
129
+
130
+ it 'writes the page size flag and page size' do
131
+ frame_bytes = ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], true, :one, nil, 10, nil, false).write(2, '')
132
+ (frame_bytes[20, 1].ord & 0x04).should == 0x04
133
+ frame_bytes[47, 4].should == "\x00\x00\x00\x0a"
134
+ end
135
+
136
+ it 'writes the page size and paging state flag and the page size and paging state' do
137
+ frame_bytes = ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], true, :one, nil, 10, 'foobar', false).write(2, '')
138
+ (frame_bytes[20, 1].ord & 0x0c).should == 0x0c
139
+ frame_bytes[47, 4].should == "\x00\x00\x00\x0a"
140
+ frame_bytes[51, 10].should == "\x00\x00\x00\x06foobar"
141
+ end
142
+ end
143
+
144
+ context 'with different data types' do
145
+ specs = [
146
+ [:ascii, 'test', "test"],
147
+ [:bigint, 1012312312414123, "\x00\x03\x98\xB1S\xC8\x7F\xAB"],
148
+ [:blob, "\xab\xcd", "\xab\xcd"],
149
+ [:boolean, false, "\x00"],
150
+ [:boolean, true, "\x01"],
151
+ [:decimal, BigDecimal.new('1042342234234.123423435647768234'), "\x00\x00\x00\x12\r'\xFDI\xAD\x80f\x11g\xDCfV\xAA"],
152
+ [:double, 10000.123123123, "@\xC3\x88\x0F\xC2\x7F\x9DU"],
153
+ [:float, 12.13, "AB\x14{"],
154
+ [:inet, IPAddr.new('8.8.8.8'), "\x08\x08\x08\x08"],
155
+ [:inet, IPAddr.new('::1'), "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"],
156
+ [:int, 12348098, "\x00\xBCj\xC2"],
157
+ [:text, 'FOOBAR', 'FOOBAR'],
158
+ [:timestamp, Time.at(1358013521.123), "\x00\x00\x01</\xE9\xDC\xE3"],
159
+ [:timeuuid, Uuid.new('a4a70900-24e1-11df-8924-001ff3591711'), "\xA4\xA7\t\x00$\xE1\x11\xDF\x89$\x00\x1F\xF3Y\x17\x11"],
160
+ [:uuid, Uuid.new('cfd66ccc-d857-4e90-b1e5-df98a3d40cd6'), "\xCF\xD6l\xCC\xD8WN\x90\xB1\xE5\xDF\x98\xA3\xD4\f\xD6"],
161
+ [:varchar, 'hello', 'hello'],
162
+ [:varint, 1231312312331283012830129382342342412123, "\x03\x9EV \x15\f\x03\x9DK\x18\xCDI\\$?\a["],
163
+ [:varint, -234234234234, "\xC9v\x8D:\x86"],
164
+ [[:list, :timestamp], [Time.at(1358013521.123)], "\x00\x01" + "\x00\x08\x00\x00\x01</\xE9\xDC\xE3"],
165
+ [[:list, :boolean], [true, false, true, true], "\x00\x04" + "\x00\x01\x01" + "\x00\x01\x00" + "\x00\x01\x01" + "\x00\x01\x01"],
166
+ [[:map, :uuid, :int], {Uuid.new('cfd66ccc-d857-4e90-b1e5-df98a3d40cd6') => 45345, Uuid.new('a4a70900-24e1-11df-8924-001ff3591711') => 98765}, "\x00\x02" + "\x00\x10\xCF\xD6l\xCC\xD8WN\x90\xB1\xE5\xDF\x98\xA3\xD4\f\xD6" + "\x00\x04\x00\x00\xb1\x21" + "\x00\x10\xA4\xA7\t\x00$\xE1\x11\xDF\x89$\x00\x1F\xF3Y\x17\x11" + "\x00\x04\x00\x01\x81\xcd"],
167
+ [[:map, :ascii, :blob], {'hello' => 'world', 'one' => "\x01", 'two' => "\x02"}, "\x00\x03" + "\x00\x05hello" + "\x00\x05world" + "\x00\x03one" + "\x00\x01\x01" + "\x00\x03two" + "\x00\x01\x02"],
168
+ [[:set, :int], Set.new([13, 3453, 456456, 123, 768678]), "\x00\x05" + "\x00\x04\x00\x00\x00\x0d" + "\x00\x04\x00\x00\x0d\x7d" + "\x00\x04\x00\x06\xf7\x08" + "\x00\x04\x00\x00\x00\x7b" + "\x00\x04\x00\x0b\xba\xa6"],
169
+ [[:set, :varchar], Set.new(['foo', 'bar', 'baz']), "\x00\x03" + "\x00\x03foo" + "\x00\x03bar" + "\x00\x03baz"],
170
+ [[:set, :int], [13, 3453, 456456, 123, 768678], "\x00\x05" + "\x00\x04\x00\x00\x00\x0d" + "\x00\x04\x00\x00\x0d\x7d" + "\x00\x04\x00\x06\xf7\x08" + "\x00\x04\x00\x00\x00\x7b" + "\x00\x04\x00\x0b\xba\xa6"],
171
+ [[:set, :varchar], ['foo', 'bar', 'baz'], "\x00\x03" + "\x00\x03foo" + "\x00\x03bar" + "\x00\x03baz"]
172
+ ]
173
+ specs.each do |type, value, expected_bytes|
174
+ it "encodes #{type} values" do
175
+ metadata = [['ks', 'tbl', 'id_column', type]]
176
+ buffer = ExecuteRequest.new(id, metadata, [value], true, :one, nil, nil, nil, false).write(1, ByteBuffer.new)
177
+ buffer.discard(2 + 16 + 2)
178
+ length = buffer.read_int
179
+ result_bytes = buffer.read(length)
180
+ result_bytes.should eql_bytes(expected_bytes)
181
+ end
93
182
  end
94
183
  end
95
184
  end
96
185
 
97
186
  describe '#to_s' do
98
187
  it 'returns a pretty string' do
99
- request = ExecuteRequest.new(id, column_metadata, values, :each_quorum)
188
+ request = ExecuteRequest.new(id, column_metadata, values, true, :each_quorum, nil, nil, nil, false)
100
189
  request.to_s.should == 'EXECUTE ca487f1e7a82d23c4e8af3355171a52f ["hello", 42, "foo"] EACH_QUORUM'
101
190
  end
102
191
  end
103
192
 
104
193
  describe '#eql?' do
105
194
  it 'returns true when the ID, metadata, values and consistency are the same' do
106
- e1 = ExecuteRequest.new(id, column_metadata, values, :one)
107
- e2 = ExecuteRequest.new(id, column_metadata, values, :one)
195
+ e1 = ExecuteRequest.new(id, column_metadata, values, true, :one, nil, nil, nil, false)
196
+ e2 = ExecuteRequest.new(id, column_metadata, values, true, :one, nil, nil, nil, false)
108
197
  e1.should eql(e2)
109
198
  end
110
199
 
111
200
  it 'returns false when the ID is different' do
112
- e1 = ExecuteRequest.new(id, column_metadata, values, :one)
113
- e2 = ExecuteRequest.new(id.reverse, column_metadata, values, :one)
201
+ e1 = ExecuteRequest.new(id, column_metadata, values, true, :one, nil, nil, nil, false)
202
+ e2 = ExecuteRequest.new(id.reverse, column_metadata, values, true, :one, nil, nil, nil, false)
114
203
  e1.should_not eql(e2)
115
204
  end
116
205
 
117
206
  it 'returns false when the metadata is different' do
118
- e1 = ExecuteRequest.new(id, column_metadata, values, :one)
119
- e2 = ExecuteRequest.new(id, column_metadata.reverse, values, :one)
207
+ e1 = ExecuteRequest.new(id, column_metadata, values, true, :one, nil, nil, nil, false)
208
+ e2 = ExecuteRequest.new(id, column_metadata.reverse, values, true, :one, nil, nil, nil, false)
120
209
  e1.should_not eql(e2)
121
210
  end
122
211
 
123
212
  it 'returns false when the values are different' do
124
- e1 = ExecuteRequest.new(id, column_metadata, values, :one)
125
- e2 = ExecuteRequest.new(id, column_metadata, values.reverse, :one)
213
+ e1 = ExecuteRequest.new(id, column_metadata, values, true, :one, nil, nil, nil, false)
214
+ e2 = ExecuteRequest.new(id, column_metadata, values.reverse, true, :one, nil, nil, nil, false)
126
215
  e1.should_not eql(e2)
127
216
  end
128
217
 
129
218
  it 'returns false when the consistency is different' do
130
- e1 = ExecuteRequest.new(id, column_metadata, values, :one)
131
- e2 = ExecuteRequest.new(id, column_metadata, values, :two)
219
+ e1 = ExecuteRequest.new(id, column_metadata, values, true, :one, nil, nil, nil, false)
220
+ e2 = ExecuteRequest.new(id, column_metadata, values, true, :two, nil, nil, nil, false)
221
+ e1.should_not eql(e2)
222
+ end
223
+
224
+ it 'returns false when the serial consistency is different' do
225
+ e1 = ExecuteRequest.new(id, column_metadata, values, true, :one, :serial, nil, nil, false)
226
+ e2 = ExecuteRequest.new(id, column_metadata, values, true, :one, :local_serial, nil, nil, false)
227
+ e1.should_not eql(e2)
228
+ end
229
+
230
+ it 'returns false when the page size is different' do
231
+ e1 = ExecuteRequest.new(id, column_metadata, values, true, :one, nil, 10, nil, false)
232
+ e2 = ExecuteRequest.new(id, column_metadata, values, true, :one, nil, 20, nil, false)
233
+ e1.should_not eql(e2)
234
+ end
235
+
236
+ it 'returns false when the paging state is different' do
237
+ e1 = ExecuteRequest.new(id, column_metadata, values, true, :one, nil, 10, 'foo', false)
238
+ e2 = ExecuteRequest.new(id, column_metadata, values, true, :one, nil, 10, 'bar', false)
132
239
  e1.should_not eql(e2)
133
240
  end
134
241
 
135
242
  it 'is aliased as ==' do
136
- e1 = ExecuteRequest.new(id, column_metadata, values, :one)
137
- e2 = ExecuteRequest.new(id, column_metadata, values, :one)
243
+ e1 = ExecuteRequest.new(id, column_metadata, values, true, :one, nil, nil, nil, false)
244
+ e2 = ExecuteRequest.new(id, column_metadata, values, true, :one, nil, nil, nil, false)
138
245
  e1.should == e2
139
246
  end
140
247
  end
141
248
 
142
249
  describe '#hash' do
143
250
  it 'has the same hash code as another identical object' do
144
- e1 = ExecuteRequest.new(id, column_metadata, values, :one)
145
- e2 = ExecuteRequest.new(id, column_metadata, values, :one)
251
+ e1 = ExecuteRequest.new(id, column_metadata, values, true, :one, nil, nil, nil, false)
252
+ e2 = ExecuteRequest.new(id, column_metadata, values, true, :one, nil, nil, nil, false)
146
253
  e1.hash.should == e2.hash
147
254
  end
148
255
 
149
256
  it 'does not have the same hash code when the ID is different' do
150
- e1 = ExecuteRequest.new(id, column_metadata, values, :one)
151
- e2 = ExecuteRequest.new(id.reverse, column_metadata, values, :one)
257
+ e1 = ExecuteRequest.new(id, column_metadata, values, true, :one, nil, nil, nil, false)
258
+ e2 = ExecuteRequest.new(id.reverse, column_metadata, values, true, :one, nil, nil, nil, false)
152
259
  e1.hash.should_not == e2.hash
153
260
  end
154
261
 
155
262
  it 'does not have the same hash code when the metadata is different' do
156
- e1 = ExecuteRequest.new(id, column_metadata, values, :one)
157
- e2 = ExecuteRequest.new(id, column_metadata.reverse, values, :one)
263
+ e1 = ExecuteRequest.new(id, column_metadata, values, true, :one, nil, nil, nil, false)
264
+ e2 = ExecuteRequest.new(id, column_metadata.reverse, values, true, :one, nil, nil, nil, false)
158
265
  e1.hash.should_not == e2.hash
159
266
  end
160
267
 
161
268
  it 'does not have the same hash code when the values are different' do
162
- e1 = ExecuteRequest.new(id, column_metadata, values, :one)
163
- e2 = ExecuteRequest.new(id, column_metadata, values.reverse, :one)
269
+ e1 = ExecuteRequest.new(id, column_metadata, values, true, :one, nil, nil, nil, false)
270
+ e2 = ExecuteRequest.new(id, column_metadata, values.reverse, true, :one, nil, nil, nil, false)
164
271
  e1.hash.should_not == e2.hash
165
272
  end
166
273
 
167
274
  it 'does not have the same hash code when the consistency is different' do
168
- e1 = ExecuteRequest.new(id, column_metadata, values, :one)
169
- e2 = ExecuteRequest.new(id, column_metadata, values, :two)
275
+ e1 = ExecuteRequest.new(id, column_metadata, values, true, :one, nil, nil, nil, false)
276
+ e2 = ExecuteRequest.new(id, column_metadata, values, true, :two, nil, nil, nil, false)
277
+ e1.hash.should_not == e2.hash
278
+ end
279
+
280
+ it 'does not have the same hash code when the serial consistency is different' do
281
+ e1 = ExecuteRequest.new(id, column_metadata, values, true, :one, nil, nil, nil, false)
282
+ e2 = ExecuteRequest.new(id, column_metadata, values, true, :one, :serial, nil, nil, false)
170
283
  e1.hash.should_not == e2.hash
171
284
  end
172
285
  end
173
286
  end
174
287
  end
175
- end
288
+ end