cassandra-driver 2.1.7-java → 3.0.0.beta.1-java

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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +31 -53
  3. data/lib/cassandra.rb +22 -3
  4. data/lib/cassandra/aggregate.rb +109 -0
  5. data/lib/cassandra/argument.rb +51 -0
  6. data/lib/cassandra/auth/providers/password.rb +7 -4
  7. data/lib/cassandra/cluster.rb +14 -3
  8. data/lib/cassandra/cluster/client.rb +56 -34
  9. data/lib/cassandra/cluster/connector.rb +6 -6
  10. data/lib/cassandra/cluster/control_connection.rb +204 -251
  11. data/lib/cassandra/cluster/metadata.rb +2 -0
  12. data/lib/cassandra/cluster/schema.rb +131 -209
  13. data/lib/cassandra/cluster/schema/cql_type_parser.rb +104 -0
  14. data/lib/cassandra/cluster/schema/fetchers.rb +1174 -0
  15. data/lib/cassandra/cluster/schema/{type_parser.rb → fqcn_type_parser.rb} +7 -3
  16. data/lib/cassandra/column.rb +2 -2
  17. data/lib/cassandra/driver.rb +27 -9
  18. data/lib/cassandra/errors.rb +179 -25
  19. data/lib/cassandra/execution/info.rb +8 -1
  20. data/lib/cassandra/execution/options.rb +34 -0
  21. data/lib/cassandra/execution/trace.rb +42 -10
  22. data/lib/cassandra/function.rb +150 -0
  23. data/lib/cassandra/future.rb +66 -35
  24. data/lib/cassandra/host.rb +7 -4
  25. data/lib/cassandra/keyspace.rb +112 -13
  26. data/lib/cassandra/load_balancing.rb +1 -1
  27. data/lib/cassandra/protocol.rb +9 -3
  28. data/lib/cassandra/protocol/coder.rb +434 -155
  29. data/lib/cassandra/protocol/cql_byte_buffer.rb +43 -0
  30. data/lib/cassandra/protocol/cql_protocol_handler.rb +4 -1
  31. data/lib/cassandra/protocol/request.rb +4 -0
  32. data/lib/cassandra/protocol/requests/auth_response_request.rb +5 -1
  33. data/lib/cassandra/protocol/requests/batch_request.rb +7 -2
  34. data/lib/cassandra/protocol/requests/credentials_request.rb +5 -1
  35. data/lib/cassandra/protocol/requests/execute_request.rb +16 -10
  36. data/lib/cassandra/protocol/requests/prepare_request.rb +12 -3
  37. data/lib/cassandra/protocol/requests/query_request.rb +20 -11
  38. data/lib/cassandra/protocol/responses/already_exists_error_response.rb +4 -4
  39. data/lib/cassandra/protocol/responses/error_response.rb +14 -14
  40. data/lib/cassandra/protocol/responses/function_failure_error_response.rb +41 -0
  41. data/lib/cassandra/protocol/responses/prepared_result_response.rb +12 -9
  42. data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +5 -3
  43. data/lib/cassandra/protocol/responses/read_failure_error_response.rb +43 -0
  44. data/lib/cassandra/protocol/responses/read_timeout_error_response.rb +4 -4
  45. data/lib/cassandra/protocol/responses/ready_response.rb +5 -1
  46. data/lib/cassandra/protocol/responses/result_response.rb +3 -3
  47. data/lib/cassandra/protocol/responses/rows_result_response.rb +2 -2
  48. data/lib/cassandra/protocol/responses/schema_change_event_response.rb +25 -24
  49. data/lib/cassandra/protocol/responses/schema_change_result_response.rb +20 -23
  50. data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +2 -2
  51. data/lib/cassandra/protocol/responses/unavailable_error_response.rb +4 -4
  52. data/lib/cassandra/protocol/responses/unprepared_error_response.rb +4 -4
  53. data/lib/cassandra/protocol/responses/write_failure_error_response.rb +45 -0
  54. data/lib/cassandra/protocol/responses/write_timeout_error_response.rb +4 -4
  55. data/lib/cassandra/protocol/v1.rb +38 -13
  56. data/lib/cassandra/protocol/v3.rb +34 -29
  57. data/lib/cassandra/protocol/v4.rb +334 -0
  58. data/lib/cassandra/result.rb +10 -9
  59. data/lib/cassandra/retry.rb +17 -3
  60. data/lib/cassandra/retry/policies/default.rb +9 -3
  61. data/lib/cassandra/session.rb +15 -7
  62. data/lib/cassandra/statement.rb +5 -0
  63. data/lib/cassandra/statements/batch.rb +36 -12
  64. data/lib/cassandra/statements/bound.rb +2 -1
  65. data/lib/cassandra/statements/prepared.rb +106 -35
  66. data/lib/cassandra/statements/simple.rb +4 -2
  67. data/lib/cassandra/table.rb +70 -105
  68. data/lib/cassandra/time.rb +98 -0
  69. data/lib/cassandra/time_uuid.rb +1 -1
  70. data/lib/cassandra/tuple.rb +7 -0
  71. data/lib/cassandra/types.rb +472 -272
  72. data/lib/cassandra/udt.rb +10 -0
  73. data/lib/cassandra/util.rb +32 -1
  74. data/lib/cassandra/uuid.rb +6 -1
  75. data/lib/cassandra/uuid/generator.rb +7 -7
  76. data/lib/cassandra/version.rb +1 -1
  77. data/lib/cassandra_murmur3.jar +0 -0
  78. data/lib/datastax/cassandra.rb +5 -2
  79. metadata +27 -17
@@ -61,17 +61,20 @@ module Cassandra
61
61
 
62
62
  # @private
63
63
  def hash
64
- @hash ||= @ip.hash
64
+ @hash ||= begin
65
+ h = 17
66
+ h = 31 * h + @ip.hash
67
+ h
68
+ end
65
69
  end
66
70
 
67
- # @param other [Cassandra::Host] a host to compare
68
- # @return [Boolean] whether this host has the same ip as the other
71
+ # @private
69
72
  def eql?(other)
70
73
  other.eql?(@ip)
71
74
  end
72
75
  alias :== :eql?
73
76
 
74
- # @return [String] a CLI-friendly host representation
77
+ # @private
75
78
  def inspect
76
79
  "#<#{self.class.name}:0x#{self.object_id.to_s(16)} @ip=#{@ip}>"
77
80
  end
@@ -51,12 +51,14 @@ module Cassandra
51
51
  attr_reader :replication
52
52
 
53
53
  # @private
54
- def initialize(name, durable_writes, replication, tables, types)
54
+ def initialize(name, durable_writes, replication, tables, types, functions, aggregates)
55
55
  @name = name
56
56
  @durable_writes = durable_writes
57
57
  @replication = replication
58
58
  @tables = tables
59
59
  @types = types
60
+ @functions = functions
61
+ @aggregates = aggregates
60
62
  end
61
63
 
62
64
  # @return [Boolean] whether durables writes are enabled for this keyspace
@@ -121,23 +123,88 @@ module Cassandra
121
123
  end
122
124
  alias :types :each_type
123
125
 
124
- # @return [String] a cql representation of this table
126
+ # @return [Boolean] whether this keyspace has a function with the given name and arguments
127
+ # @param name [String] function name
128
+ # @param args [Array<String>] (var-args style) function argument types
129
+ def has_function?(name, *args)
130
+ @functions.has_key?([name.downcase, args])
131
+ end
132
+
133
+ # @return [Cassandra::Function, nil] a function or nil
134
+ # @param name [String] function name
135
+ # @param args [Array<String>] (var-args style) function argument types
136
+ def function(name, *args)
137
+ # The functions_hash datastructure is a hash <[func-name, args], Function>.
138
+ # So construct the array-key we're looking for.
139
+ @functions[[name.downcase, args]]
140
+ end
141
+
142
+ # Yield or enumerate each function defined in this keyspace
143
+ # @overload each_function
144
+ # @yieldparam function [Cassandra::Function] current function
145
+ # @return [Cassandra::Keyspace] self
146
+ # @overload each_function
147
+ # @return [Array<Cassandra::Function>] a list of functions
148
+ def each_function(&block)
149
+ if block_given?
150
+ @functions.each_value(&block)
151
+ self
152
+ else
153
+ @functions.values
154
+ end
155
+ end
156
+ alias :functions :each_function
157
+
158
+ # @return [Boolean] whether this keyspace has an aggregate with the given
159
+ # name and arguments
160
+ # @param name [String] aggregate name
161
+ # @param args [Array<String>] (var-args style) aggregate function argument types
162
+ def has_aggregate?(name, *args)
163
+ @aggregates.has_key?([name.downcase, args])
164
+ end
165
+
166
+ # @return [Cassandra::Aggregate, nil] an aggregate or nil
167
+ # @param name [String] aggregate name
168
+ # @param args [Array<String>] (var-args style) aggregate function argument types
169
+ def aggregate(name, *args)
170
+ @aggregates[[name.downcase, args]]
171
+ end
172
+
173
+ # Yield or enumerate each aggregate defined in this keyspace
174
+ # @overload each_aggregate
175
+ # @yieldparam aggregate [Cassandra::Aggregate] current aggregate
176
+ # @return [Cassandra::Keyspace] self
177
+ # @overload each_aggregate
178
+ # @return [Array<Cassandra::Aggregate>] a list of aggregates
179
+ def each_aggregate(&block)
180
+ if block_given?
181
+ @aggregates.each_value(&block)
182
+ self
183
+ else
184
+ @aggregates.values
185
+ end
186
+ end
187
+ alias :aggregates :each_aggregate
188
+
189
+ # @return [String] a cql representation of this keyspace
125
190
  def to_cql
126
- "CREATE KEYSPACE #{Util.escape_name(@name)} WITH REPLICATION = #{@replication.to_cql} AND DURABLE_WRITES = #{@durable_writes};"
191
+ "CREATE KEYSPACE #{Util.escape_name(@name)} WITH replication = #{@replication.to_cql} AND durable_writes = #{@durable_writes};"
127
192
  end
128
193
 
129
- # @return [Boolean] whether this keyspace is equal to the other
194
+ # @private
130
195
  def eql?(other)
131
196
  other.is_a?(Keyspace) &&
132
197
  @name == other.name &&
133
198
  @durable_writes == other.durable_writes &&
134
199
  @replication == other.replication &&
135
200
  @tables == other.raw_tables &&
136
- @types == other.raw_types
201
+ @types == other.raw_types &&
202
+ @functions == other.raw_functions &&
203
+ @aggregates == other.raw_aggregates
137
204
  end
138
205
  alias :== :eql?
139
206
 
140
- # @return [String] a CLI-friendly keyspace representation
207
+ # @private
141
208
  def inspect
142
209
  "#<#{self.class.name}:0x#{self.object_id.to_s(16)} @name=#{@name}>"
143
210
  end
@@ -146,34 +213,56 @@ module Cassandra
146
213
  def update_table(table)
147
214
  tables = @tables.dup
148
215
  tables[table.name] = table
149
- Keyspace.new(@name, @durable_writes, @replication, tables, @types)
216
+ Keyspace.new(@name, @durable_writes, @replication, tables, @types, @functions, @aggregates)
150
217
  end
151
218
 
152
219
  # @private
153
220
  def delete_table(table_name)
154
221
  tables = @tables.dup
155
222
  tables.delete(table_name)
156
- Keyspace.new(@name, @durable_writes, @replication, tables, @types)
223
+ Keyspace.new(@name, @durable_writes, @replication, tables, @types, @functions, @aggregates)
157
224
  end
158
225
 
159
226
  # @private
160
227
  def update_type(type)
161
228
  types = @types.dup
162
229
  types[type.name] = type
163
- Keyspace.new(@name, @durable_writes, @replication, @tables, types)
230
+ Keyspace.new(@name, @durable_writes, @replication, @tables, types, @functions, @aggregates)
164
231
  end
165
232
 
166
233
  # @private
167
234
  def delete_type(type_name)
168
235
  types = @types.dup
169
236
  types.delete(type_name)
170
- Keyspace.new(@name, @durable_writes, @replication, @tables, types)
237
+ Keyspace.new(@name, @durable_writes, @replication, @tables, types, @functions, @aggregates)
238
+ end
239
+
240
+ # @private
241
+ def update_function(function)
242
+ functions = @functions.dup
243
+ functions[[function.name, function.argument_types]] = function
244
+ Keyspace.new(@name, @durable_writes, @replication, @tables, @types, functions, @aggregates)
245
+ end
246
+
247
+ # @private
248
+ def delete_function(function_name, function_args)
249
+ functions = @functions.dup
250
+ functions.delete([function_name, function_args])
251
+ Keyspace.new(@name, @durable_writes, @replication, @tables, @types, functions, @aggregates)
171
252
  end
172
253
 
173
254
  # @private
174
- def create_partition_key(table, values)
175
- table = @tables[table]
176
- table && table.create_partition_key(values)
255
+ def update_aggregate(aggregate)
256
+ aggregates = @aggregates.dup
257
+ aggregates[[aggregate.name, aggregate.argument_types]] = aggregate
258
+ Keyspace.new(@name, @durable_writes, @replication, @tables, @types, @functions, aggregates)
259
+ end
260
+
261
+ # @private
262
+ def delete_aggregate(aggregate_name, aggregate_args)
263
+ aggregates = @aggregates.dup
264
+ aggregates.delete([aggregate_name, aggregate_args])
265
+ Keyspace.new(@name, @durable_writes, @replication, @tables, @types, @functions, aggregates)
177
266
  end
178
267
 
179
268
  # @private
@@ -191,5 +280,15 @@ module Cassandra
191
280
  def raw_types
192
281
  @types
193
282
  end
283
+
284
+ # @private
285
+ def raw_functions
286
+ @functions
287
+ end
288
+
289
+ # @private
290
+ def raw_aggregates
291
+ @aggregates
292
+ end
194
293
  end
195
294
  end
@@ -81,7 +81,7 @@ module Cassandra
81
81
  def plan(keyspace, statement, options)
82
82
  end
83
83
 
84
- # @return [String] a console-friendly representation of this policy
84
+ # @private
85
85
  def inspect
86
86
  "#<#{self.class.name}:0x#{self.object_id.to_s(16)}>"
87
87
  end
@@ -36,9 +36,11 @@ module Cassandra
36
36
  PROTOCOL_VERSION = "\x01".freeze
37
37
  COMPRESSION_OFF = "\x00".freeze
38
38
 
39
- SCHEMA_CHANGE_TARGET_KEYSPACE = 'KEYSPACE'.freeze
40
- SCHEMA_CHANGE_TARGET_TABLE = 'TABLE'.freeze
41
- SCHEMA_CHANGE_TARGET_UDT = 'TYPE'.freeze
39
+ SCHEMA_CHANGE_TARGET_KEYSPACE = 'KEYSPACE'.freeze
40
+ SCHEMA_CHANGE_TARGET_TABLE = 'TABLE'.freeze
41
+ SCHEMA_CHANGE_TARGET_UDT = 'TYPE'.freeze
42
+ SCHEMA_CHANGE_TARGET_FUNCTION = 'FUNCTION'.freeze
43
+ SCHEMA_CHANGE_TARGET_AGGREGATE = 'AGGREGATE'.freeze
42
44
  end
43
45
  end
44
46
  end
@@ -67,6 +69,9 @@ require 'cassandra/protocol/responses/event_response'
67
69
  require 'cassandra/protocol/responses/schema_change_event_response'
68
70
  require 'cassandra/protocol/responses/status_change_event_response'
69
71
  require 'cassandra/protocol/responses/topology_change_event_response'
72
+ require 'cassandra/protocol/responses/read_failure_error_response'
73
+ require 'cassandra/protocol/responses/write_failure_error_response'
74
+ require 'cassandra/protocol/responses/function_failure_error_response'
70
75
  require 'cassandra/protocol/request'
71
76
  require 'cassandra/protocol/requests/auth_response_request'
72
77
  require 'cassandra/protocol/requests/batch_request'
@@ -81,4 +86,5 @@ require 'cassandra/protocol/requests/execute_request'
81
86
  require 'cassandra/protocol/cql_protocol_handler'
82
87
  require 'cassandra/protocol/v1'
83
88
  require 'cassandra/protocol/v3'
89
+ require 'cassandra/protocol/v4'
84
90
  require 'cassandra/protocol/coder'
@@ -23,12 +23,12 @@ module Cassandra
23
23
  HAS_MORE_PAGES_FLAG = 0x02
24
24
  NO_METADATA_FLAG = 0x04
25
25
 
26
- def write_values_v3(buffer, values, types, names = EMPTY_LIST)
26
+ def write_values_v4(buffer, values, types, names = EMPTY_LIST)
27
27
  if values && values.size > 0
28
28
  buffer.append_short(values.size)
29
29
  values.zip(types, names) do |(value, type, name)|
30
30
  buffer.append_string(name) if name
31
- write_value_v3(buffer, value, type)
31
+ write_value_v4(buffer, value, type)
32
32
  end
33
33
  buffer
34
34
  else
@@ -36,7 +36,60 @@ module Cassandra
36
36
  end
37
37
  end
38
38
 
39
- def write_value_v3(buffer, value, type)
39
+ def write_list_v4(buffer, list, type)
40
+ raw = CqlByteBuffer.new
41
+
42
+ raw.append_int(list.size)
43
+ list.each do |element|
44
+ write_value_v4(raw, element, type)
45
+ end
46
+
47
+ buffer.append_bytes(raw)
48
+ end
49
+
50
+ def write_map_v4(buffer, map, key_type, value_type)
51
+ raw = CqlByteBuffer.new
52
+
53
+ raw.append_int(map.size)
54
+ map.each do |key, value|
55
+ write_value_v4(raw, key, key_type)
56
+ write_value_v4(raw, value, value_type)
57
+ end
58
+
59
+ buffer.append_bytes(raw)
60
+ end
61
+
62
+ def write_udt_v4(buffer, value, fields)
63
+ raw = CqlByteBuffer.new
64
+
65
+ fields.each do |field|
66
+ write_value_v4(raw, value[field.name], field.type)
67
+ end
68
+
69
+ buffer.append_bytes(raw)
70
+ end
71
+
72
+ def write_tuple_v4(buffer, value, members)
73
+ raw = CqlByteBuffer.new
74
+
75
+ members.each_with_index do |type, i|
76
+ write_value_v4(raw, value[i], type)
77
+ end
78
+
79
+ buffer.append_bytes(raw)
80
+ end
81
+
82
+ def write_value_v4(buffer, value, type)
83
+ if value.nil?
84
+ buffer.append_int(-1)
85
+ return
86
+ end
87
+
88
+ if NOT_SET.eql?(value)
89
+ buffer.append_int(-2)
90
+ return
91
+ end
92
+
40
93
  case type.kind
41
94
  when :ascii then write_ascii(buffer, value)
42
95
  when :bigint, :counter then write_bigint(buffer, value)
@@ -49,64 +102,285 @@ module Cassandra
49
102
  when :inet then write_inet(buffer, value)
50
103
  when :timestamp then write_timestamp(buffer, value)
51
104
  when :uuid, :timeuuid then write_uuid(buffer, value)
52
- when :varchar then write_varchar(buffer, value)
105
+ when :text then write_text(buffer, value)
53
106
  when :varint then write_varint(buffer, value)
54
- when :list, :set
55
- if value
56
- raw = CqlByteBuffer.new
57
- value_type = type.value_type
107
+ when :tinyint then write_tinyint(buffer, value)
108
+ when :smallint then write_smallint(buffer, value)
109
+ when :time then write_time(buffer, value)
110
+ when :date then write_date(buffer, value)
111
+ when :list, :set then write_list_v4(buffer, value, type.value_type)
112
+ when :map then write_map_v4(buffer, value, type.key_type, type.value_type)
113
+ when :udt then write_udt_v4(buffer, value, type.fields)
114
+ when :tuple then write_tuple_v4(buffer, value, type.members)
115
+ else
116
+ raise Errors::EncodingError, %(Unsupported value type: #{type})
117
+ end
118
+ end
58
119
 
59
- raw.append_int(value.size)
60
- value.each do |element|
61
- write_value_v3(raw, element, value_type)
62
- end
120
+ def read_prepared_metadata_v4(buffer)
121
+ flags = buffer.read_int
122
+ columns_count = buffer.read_int
123
+ pk_count = buffer.read_int
124
+ pk_specs = ::Array.new(pk_count) {|i| buffer.read_short}
125
+
126
+ if flags & GLOBAL_TABLES_SPEC_FLAG == GLOBAL_TABLES_SPEC_FLAG
127
+ keyspace_name = buffer.read_string
128
+ table_name = buffer.read_string
129
+
130
+ column_specs = ::Array.new(columns_count) do |i|
131
+ [keyspace_name, table_name, buffer.read_string, read_type_v4(buffer)]
132
+ end
133
+ else
134
+ column_specs = ::Array.new(columns_count) do |i|
135
+ [buffer.read_string, buffer.read_string, buffer.read_string, read_type_v4(buffer)]
136
+ end
137
+ end
138
+
139
+ [pk_specs, column_specs]
140
+ end
141
+
142
+ def read_metadata_v4(buffer)
143
+ flags = buffer.read_int
144
+ count = buffer.read_int
145
+
146
+ paging_state = nil
147
+ paging_state = buffer.read_bytes if flags & HAS_MORE_PAGES_FLAG != 0
148
+ column_specs = nil
149
+
150
+ if flags & NO_METADATA_FLAG == 0
151
+ if flags & GLOBAL_TABLES_SPEC_FLAG != 0
152
+ keyspace_name = buffer.read_string
153
+ table_name = buffer.read_string
63
154
 
64
- buffer.append_bytes(raw)
155
+ column_specs = ::Array.new(count) do |i|
156
+ [keyspace_name, table_name, buffer.read_string, read_type_v4(buffer)]
157
+ end
65
158
  else
66
- buffer.append_int(-1)
159
+ column_specs = ::Array.new(count) do |i|
160
+ [buffer.read_string, buffer.read_string, buffer.read_string, read_type_v4(buffer)]
161
+ end
162
+ end
163
+ end
164
+
165
+ [column_specs, paging_state]
166
+ end
167
+
168
+ def read_type_v4(buffer)
169
+ id = buffer.read_unsigned_short
170
+ case id
171
+ when 0x0000 then Types.custom(buffer.read_string)
172
+ when 0x0001 then Types.ascii
173
+ when 0x0002 then Types.bigint
174
+ when 0x0003 then Types.blob
175
+ when 0x0004 then Types.boolean
176
+ when 0x0005 then Types.counter
177
+ when 0x0006 then Types.decimal
178
+ when 0x0007 then Types.double
179
+ when 0x0008 then Types.float
180
+ when 0x0009 then Types.int
181
+ when 0x000B then Types.timestamp
182
+ when 0x000C then Types.uuid
183
+ when 0x000D then Types.text
184
+ when 0x000E then Types.varint
185
+ when 0x000F then Types.timeuuid
186
+ when 0x0010 then Types.inet
187
+ when 0x0011 then Types.date
188
+ when 0x0012 then Types.time
189
+ when 0x0013 then Types.smallint
190
+ when 0x0014 then Types.tinyint
191
+ when 0x0020 then Types.list(read_type_v4(buffer))
192
+ when 0x0021 then Types.map(read_type_v4(buffer), read_type_v4(buffer))
193
+ when 0x0022 then Types.set(read_type_v4(buffer))
194
+ when 0x0030
195
+ keyspace = buffer.read_string
196
+ name = buffer.read_string
197
+ fields = ::Array.new(buffer.read_short) { [buffer.read_string, read_type_v4(buffer)] }
198
+
199
+ Types.udt(keyspace, name, fields)
200
+ when 0x0031 then Types.tuple(*::Array.new(buffer.read_short) { read_type_v4(buffer) })
201
+ else
202
+ raise Errors::DecodingError, %(Unsupported column type: #{id})
203
+ end
204
+ end
205
+
206
+ def read_values_v4(buffer, column_metadata)
207
+ ::Array.new(buffer.read_int) do |i|
208
+ row = ::Hash.new
209
+
210
+ column_metadata.each do |(_, _, column, type)|
211
+ row[column] = read_value_v4(buffer, type)
67
212
  end
213
+
214
+ row
215
+ end
216
+ end
217
+
218
+ def read_value_v4(buffer, type)
219
+ case type.kind
220
+ when :ascii then read_ascii(buffer)
221
+ when :bigint, :counter then read_bigint(buffer)
222
+ when :blob then buffer.read_bytes
223
+ when :boolean then read_boolean(buffer)
224
+ when :decimal then read_decimal(buffer)
225
+ when :double then read_double(buffer)
226
+ when :float then read_float(buffer)
227
+ when :int then read_int(buffer)
228
+ when :timestamp then read_timestamp(buffer)
229
+ when :uuid then read_uuid(buffer)
230
+ when :timeuuid then read_uuid(buffer, TimeUuid)
231
+ when :text then read_text(buffer)
232
+ when :varint then read_varint(buffer)
233
+ when :inet then read_inet(buffer)
234
+ when :tinyint then read_tinyint(buffer)
235
+ when :smallint then read_smallint(buffer)
236
+ when :time then read_time(buffer)
237
+ when :date then read_date(buffer)
238
+ when :list
239
+ return nil unless read_size(buffer)
240
+
241
+ value_type = type.value_type
242
+ ::Array.new(buffer.read_signed_int) { read_value_v4(buffer, value_type) }
68
243
  when :map
69
- if value
70
- raw = CqlByteBuffer.new
71
- key_type = type.key_type
72
- value_type = type.value_type
73
-
74
- raw.append_int(value.size)
75
- value.each do |key, value|
76
- write_value_v3(raw, key, key_type)
77
- write_value_v3(raw, value, value_type)
78
- end
244
+ return nil unless read_size(buffer)
79
245
 
80
- buffer.append_bytes(raw)
81
- else
82
- buffer.append_int(-1)
246
+ key_type = type.key_type
247
+ value_type = type.value_type
248
+ value = ::Hash.new
249
+
250
+ buffer.read_signed_int.times do
251
+ value[read_value_v4(buffer, key_type)] = read_value_v4(buffer, value_type)
252
+ end
253
+
254
+ value
255
+ when :set
256
+ return nil unless read_size(buffer)
257
+
258
+ value_type = type.value_type
259
+ value = ::Set.new
260
+
261
+ buffer.read_signed_int.times do
262
+ value << read_value_v4(buffer, value_type)
83
263
  end
264
+
265
+ value
84
266
  when :udt
85
- if value
86
- raw = CqlByteBuffer.new
87
- fields = type.fields
267
+ size = read_size(buffer)
268
+ return nil unless size
88
269
 
89
- fields.each do |field|
90
- write_value_v3(raw, value[field.name], field.type)
91
- end
270
+ length = buffer.length
271
+ keyspace = type.keyspace
272
+ name = type.name
273
+ fields = type.fields
274
+ values = ::Hash.new
92
275
 
93
- buffer.append_bytes(raw)
94
- else
95
- buffer.append_int(-1)
276
+ fields.each do |field|
277
+ if length - buffer.length >= size
278
+ values[field.name] = nil
279
+ else
280
+ values[field.name] = read_value_v4(buffer, field.type)
281
+ end
96
282
  end
283
+
284
+ Cassandra::UDT::Strict.new(keyspace, name, fields, values)
97
285
  when :tuple
98
- if value
99
- raw = CqlByteBuffer.new
100
- members = type.members
286
+ return nil unless read_size(buffer)
101
287
 
102
- members.each_with_index do |member_type, i|
103
- write_value_v3(raw, value[i], member_type)
104
- end
288
+ members = type.members
289
+ values = ::Array.new
105
290
 
106
- buffer.append_bytes(raw)
107
- else
108
- buffer.append_int(-1)
291
+ members.each do |member_type|
292
+ break if buffer.empty?
293
+ values << read_value_v4(buffer, member_type)
294
+ end
295
+
296
+ values.fill(nil, values.length, (members.length - values.length))
297
+
298
+ Cassandra::Tuple::Strict.new(members, values)
299
+ else
300
+ raise Errors::DecodingError, %(Unsupported value type: #{type})
301
+ end
302
+ end
303
+
304
+ def write_values_v3(buffer, values, types, names = EMPTY_LIST)
305
+ if values && values.size > 0
306
+ buffer.append_short(values.size)
307
+ values.zip(types, names) do |(value, type, name)|
308
+ buffer.append_string(name) if name
309
+ write_value_v3(buffer, value, type)
109
310
  end
311
+ buffer
312
+ else
313
+ buffer.append_short(0)
314
+ end
315
+ end
316
+
317
+ def write_list_v3(buffer, list, type)
318
+ raw = CqlByteBuffer.new
319
+
320
+ raw.append_int(list.size)
321
+ list.each do |element|
322
+ write_value_v3(raw, element, type)
323
+ end
324
+
325
+ buffer.append_bytes(raw)
326
+ end
327
+
328
+ def write_map_v3(buffer, map, key_type, value_type)
329
+ raw = CqlByteBuffer.new
330
+
331
+ raw.append_int(map.size)
332
+ map.each do |key, value|
333
+ write_value_v3(raw, key, key_type)
334
+ write_value_v3(raw, value, value_type)
335
+ end
336
+
337
+ buffer.append_bytes(raw)
338
+ end
339
+
340
+ def write_udt_v3(buffer, value, fields)
341
+ raw = CqlByteBuffer.new
342
+
343
+ fields.each do |field|
344
+ write_value_v3(raw, value[field.name], field.type)
345
+ end
346
+
347
+ buffer.append_bytes(raw)
348
+ end
349
+
350
+ def write_tuple_v3(buffer, value, members)
351
+ raw = CqlByteBuffer.new
352
+
353
+ members.each_with_index do |type, i|
354
+ write_value_v3(raw, value[i], type)
355
+ end
356
+
357
+ buffer.append_bytes(raw)
358
+ end
359
+
360
+ def write_value_v3(buffer, value, type)
361
+ if value.nil?
362
+ buffer.append_int(-1)
363
+ return
364
+ end
365
+
366
+ case type.kind
367
+ when :ascii then write_ascii(buffer, value)
368
+ when :bigint, :counter then write_bigint(buffer, value)
369
+ when :blob then write_blob(buffer, value)
370
+ when :boolean then write_boolean(buffer, value)
371
+ when :decimal then write_decimal(buffer, value)
372
+ when :double then write_double(buffer, value)
373
+ when :float then write_float(buffer, value)
374
+ when :int then write_int(buffer, value)
375
+ when :inet then write_inet(buffer, value)
376
+ when :timestamp then write_timestamp(buffer, value)
377
+ when :uuid, :timeuuid then write_uuid(buffer, value)
378
+ when :text then write_text(buffer, value)
379
+ when :varint then write_varint(buffer, value)
380
+ when :list, :set then write_list_v3(buffer, value, type.value_type)
381
+ when :map then write_map_v3(buffer, value, type.key_type, type.value_type)
382
+ when :udt then write_udt_v3(buffer, value, type.fields)
383
+ when :tuple then write_tuple_v3(buffer, value, type.members)
110
384
  else
111
385
  raise Errors::EncodingError, %(Unsupported value type: #{type})
112
386
  end
@@ -137,7 +411,7 @@ module Cassandra
137
411
  when :timestamp then read_timestamp(buffer)
138
412
  when :uuid then read_uuid(buffer)
139
413
  when :timeuuid then read_uuid(buffer, TimeUuid)
140
- when :varchar then read_varchar(buffer)
414
+ when :text then read_text(buffer)
141
415
  when :varint then read_varint(buffer)
142
416
  when :inet then read_inet(buffer)
143
417
  when :list
@@ -169,15 +443,17 @@ module Cassandra
169
443
 
170
444
  value
171
445
  when :udt
172
- return nil unless read_size(buffer)
446
+ size = read_size(buffer)
447
+ return nil unless size
173
448
 
449
+ length = buffer.length
174
450
  keyspace = type.keyspace
175
451
  name = type.name
176
452
  fields = type.fields
177
453
  values = ::Hash.new
178
454
 
179
455
  fields.each do |field|
180
- if buffer.empty?
456
+ if length - buffer.length >= size
181
457
  values[field.name] = nil
182
458
  else
183
459
  values[field.name] = read_value_v3(buffer, field.type)
@@ -231,7 +507,8 @@ module Cassandra
231
507
  end
232
508
 
233
509
  def read_type_v3(buffer)
234
- case buffer.read_unsigned_short
510
+ id = buffer.read_unsigned_short
511
+ case id
235
512
  when 0x0000 then Types.custom(buffer.read_string)
236
513
  when 0x0001 then Types.ascii
237
514
  when 0x0002 then Types.bigint
@@ -244,15 +521,20 @@ module Cassandra
244
521
  when 0x0009 then Types.int
245
522
  when 0x000B then Types.timestamp
246
523
  when 0x000C then Types.uuid
247
- when 0x000D then Types.varchar
524
+ when 0x000D then Types.text
248
525
  when 0x000E then Types.varint
249
526
  when 0x000F then Types.timeuuid
250
527
  when 0x0010 then Types.inet
251
528
  when 0x0020 then Types.list(read_type_v3(buffer))
252
529
  when 0x0021 then Types.map(read_type_v3(buffer), read_type_v3(buffer))
253
530
  when 0x0022 then Types.set(read_type_v3(buffer))
254
- when 0x0030 then Types.udt(*read_user_defined_type(buffer))
255
- when 0x0031 then Types.tuple(*read_tuple(buffer))
531
+ when 0x0030
532
+ keyspace = buffer.read_string
533
+ name = buffer.read_string
534
+ fields = ::Array.new(buffer.read_short) { [buffer.read_string, read_type_v3(buffer)] }
535
+
536
+ Types.udt(keyspace, name, fields)
537
+ when 0x0031 then Types.tuple(*::Array.new(buffer.read_short) { read_type_v3(buffer) })
256
538
  else
257
539
  raise Errors::DecodingError, %(Unsupported column type: #{id})
258
540
  end
@@ -270,7 +552,35 @@ module Cassandra
270
552
  end
271
553
  end
272
554
 
555
+ def write_list_v1(buffer, list, type)
556
+ raw = CqlByteBuffer.new
557
+
558
+ raw.append_short(list.size)
559
+ list.each do |element|
560
+ write_short_value(raw, element, type)
561
+ end
562
+
563
+ buffer.append_bytes(raw)
564
+ end
565
+
566
+ def write_map_v1(buffer, map, key_type, value_type)
567
+ raw = CqlByteBuffer.new
568
+
569
+ raw.append_short(map.size)
570
+ map.each do |key, value|
571
+ write_short_value(raw, key, key_type)
572
+ write_short_value(raw, value, value_type)
573
+ end
574
+
575
+ buffer.append_bytes(raw)
576
+ end
577
+
273
578
  def write_value_v1(buffer, value, type)
579
+ if value.nil?
580
+ buffer.append_int(-1)
581
+ return
582
+ end
583
+
274
584
  case type.kind
275
585
  when :ascii then write_ascii(buffer, value)
276
586
  when :bigint, :counter then write_bigint(buffer, value)
@@ -281,40 +591,12 @@ module Cassandra
281
591
  when :float then write_float(buffer, value)
282
592
  when :int then write_int(buffer, value)
283
593
  when :inet then write_inet(buffer, value)
284
- when :varchar, :text then write_varchar(buffer, value)
594
+ when :text then write_text(buffer, value)
285
595
  when :timestamp then write_timestamp(buffer, value)
286
596
  when :timeuuid, :uuid then write_uuid(buffer, value)
287
597
  when :varint then write_varint(buffer, value)
288
- when :list, :set
289
- if value
290
- raw = CqlByteBuffer.new
291
- value_type = type.value_type
292
-
293
- raw.append_short(value.size)
294
- value.each do |element|
295
- write_short_value(raw, element, value_type)
296
- end
297
-
298
- buffer.append_bytes(raw)
299
- else
300
- buffer.append_int(-1)
301
- end
302
- when :map
303
- if value
304
- raw = CqlByteBuffer.new
305
- key_type = type.key_type
306
- value_type = type.value_type
307
-
308
- raw.append_short(value.size)
309
- value.each do |key, value|
310
- write_short_value(raw, key, key_type)
311
- write_short_value(raw, value, value_type)
312
- end
313
-
314
- buffer.append_bytes(raw)
315
- else
316
- buffer.append_int(-1)
317
- end
598
+ when :list, :set then write_list_v1(buffer, value, type.value_type)
599
+ when :map then write_map_v1(buffer, value, type.key_type, type.value_type)
318
600
  else
319
601
  raise Errors::EncodingError, %(Unsupported value type: #{type})
320
602
  end
@@ -343,7 +625,7 @@ module Cassandra
343
625
  when :float then read_float(buffer)
344
626
  when :int then read_int(buffer)
345
627
  when :timestamp then read_timestamp(buffer)
346
- when :varchar, :text then read_varchar(buffer)
628
+ when :text then read_text(buffer)
347
629
  when :varint then read_varint(buffer)
348
630
  when :uuid then read_uuid(buffer)
349
631
  when :timeuuid then read_uuid(buffer, TimeUuid)
@@ -426,7 +708,7 @@ module Cassandra
426
708
  when 0x000A then Types.text
427
709
  when 0x000B then Types.timestamp
428
710
  when 0x000C then Types.uuid
429
- when 0x000D then Types.varchar
711
+ when 0x000D then Types.text
430
712
  when 0x000E then Types.varint
431
713
  when 0x000F then Types.timeuuid
432
714
  when 0x0010 then Types.inet
@@ -484,7 +766,7 @@ module Cassandra
484
766
  read_size(buffer) && buffer.read_uuid(klass)
485
767
  end
486
768
 
487
- def read_varchar(buffer)
769
+ def read_text(buffer)
488
770
  value = buffer.read_bytes
489
771
  value && value.force_encoding(::Encoding::UTF_8)
490
772
  end
@@ -499,99 +781,108 @@ module Cassandra
499
781
  size && ::IPAddr.new_ntoh(buffer.read(size))
500
782
  end
501
783
 
784
+ def read_tinyint(buffer)
785
+ read_size(buffer) && buffer.read_tinyint
786
+ end
787
+
788
+ def read_smallint(buffer)
789
+ read_size(buffer) && buffer.read_smallint
790
+ end
791
+
792
+ def read_time(buffer)
793
+ return nil unless read_size(buffer)
794
+
795
+ Time.new(buffer.read_long)
796
+ end
797
+
798
+ def read_date(buffer)
799
+ return nil unless read_size(buffer)
800
+
801
+ ::Date.jd(DATE_OFFSET + buffer.read_int, ::Date::GREGORIAN)
802
+ end
803
+
502
804
  def write_ascii(buffer, value)
503
- buffer.append_bytes(value && value.encode(::Encoding::ASCII))
805
+ buffer.append_bytes(value.encode(::Encoding::ASCII))
504
806
  end
505
807
 
506
808
  def write_bigint(buffer, value)
507
- if value
508
- buffer.append_int(8)
509
- buffer.append_long(value)
510
- else
511
- buffer.append_int(-1)
512
- end
809
+ buffer.append_int(8)
810
+ buffer.append_long(value)
513
811
  end
514
812
 
515
813
  alias :write_counter :write_bigint
516
814
 
517
815
  def write_blob(buffer, value)
518
- buffer.append_bytes(value && value.encode(::Encoding::BINARY))
816
+ buffer.append_bytes(value.encode(::Encoding::BINARY))
519
817
  end
520
818
 
521
819
  def write_boolean(buffer, value)
522
- if !value.nil?
523
- buffer.append_int(1)
524
- buffer.append(value ? Constants::TRUE_BYTE : Constants::FALSE_BYTE)
525
- else
526
- buffer.append_int(-1)
527
- end
820
+ buffer.append_int(1)
821
+ buffer.append(value ? Constants::TRUE_BYTE : Constants::FALSE_BYTE)
528
822
  end
529
823
 
530
824
  def write_decimal(buffer, value)
531
- buffer.append_bytes(value && CqlByteBuffer.new.append_decimal(value))
825
+ buffer.append_bytes(CqlByteBuffer.new.append_decimal(value))
532
826
  end
533
827
 
534
828
  def write_double(buffer, value)
535
- if value
536
- buffer.append_int(8)
537
- buffer.append_double(value)
538
- else
539
- buffer.append_int(-1)
540
- end
829
+ buffer.append_int(8)
830
+ buffer.append_double(value)
541
831
  end
542
832
 
543
833
  def write_float(buffer, value)
544
- if value
545
- buffer.append_int(4)
546
- buffer.append_float(value)
547
- else
548
- buffer.append_int(-1)
549
- end
834
+ buffer.append_int(4)
835
+ buffer.append_float(value)
550
836
  end
551
837
 
552
838
  def write_int(buffer, value)
553
- if value
554
- buffer.append_int(4)
555
- buffer.append_int(value)
556
- else
557
- buffer.append_int(-1)
558
- end
839
+ buffer.append_int(4)
840
+ buffer.append_int(value)
559
841
  end
560
842
 
561
843
  def write_inet(buffer, value)
562
- if value
563
- buffer.append_int(value.ipv6? ? 16 : 4)
564
- buffer.append(value.hton)
565
- else
566
- buffer.append_int(-1)
567
- end
844
+ buffer.append_int(value.ipv6? ? 16 : 4)
845
+ buffer.append(value.hton)
568
846
  end
569
847
 
570
848
  def write_timestamp(buffer, value)
571
- if value
572
- ms = (value.to_r.to_f * 1000).to_i
573
- buffer.append_int(8)
574
- buffer.append_long(ms)
575
- else
576
- buffer.append_int(-1)
577
- end
849
+ ms = (value.to_r.to_f * 1000).to_i
850
+ buffer.append_int(8)
851
+ buffer.append_long(ms)
578
852
  end
579
853
 
580
- def write_varchar(buffer, value)
581
- buffer.append_bytes(value && value.encode(::Encoding::UTF_8))
854
+ def write_text(buffer, value)
855
+ buffer.append_bytes(value.encode(::Encoding::UTF_8))
582
856
  end
583
857
 
584
858
  def write_uuid(buffer, value)
585
- if value
586
- buffer.append_int(16)
587
- buffer.append_uuid(value)
588
- else
589
- buffer.append_int(-1)
590
- end
859
+ buffer.append_int(16)
860
+ buffer.append_uuid(value)
591
861
  end
592
862
 
593
863
  def write_varint(buffer, value)
594
- buffer.append_bytes(value && CqlByteBuffer.new.append_varint(value))
864
+ buffer.append_bytes(CqlByteBuffer.new.append_varint(value))
865
+ end
866
+
867
+ def write_tinyint(buffer, value)
868
+ buffer.append_int(1)
869
+ buffer.append_tinyint(value)
870
+ end
871
+
872
+ def write_smallint(buffer, value)
873
+ buffer.append_int(2)
874
+ buffer.append_smallint(value)
875
+ end
876
+
877
+ def write_time(buffer, value)
878
+ ns = value.to_nanoseconds
879
+ buffer.append_int(8)
880
+ buffer.append_long(ns)
881
+ end
882
+
883
+ def write_date(buffer, value)
884
+ buffer.append_int(4)
885
+ buffer.append_int(value.gregorian.jd - DATE_OFFSET)
595
886
  end
596
887
 
597
888
  def read_short_size(buffer)
@@ -626,7 +917,7 @@ module Cassandra
626
917
  when :inet
627
918
  size = read_short_size(buffer)
628
919
  size && ::IPAddr.new_ntoh(buffer.read(size))
629
- when :varchar, :text
920
+ when :text
630
921
  value = buffer.read_short_bytes
631
922
  value && value.force_encoding(::Encoding::UTF_8)
632
923
  when :timestamp
@@ -699,7 +990,7 @@ module Cassandra
699
990
  else
700
991
  buffer.append_short(-1)
701
992
  end
702
- when :varchar, :text
993
+ when :text
703
994
  buffer.append_short_bytes(value && value.encode(::Encoding::UTF_8))
704
995
  when :timestamp
705
996
  if value
@@ -729,18 +1020,6 @@ module Cassandra
729
1020
 
730
1021
  size
731
1022
  end
732
-
733
- def read_tuple(buffer)
734
- ::Array.new(buffer.read_short) { read_type_v3(buffer) }
735
- end
736
-
737
- def read_user_defined_type(buffer)
738
- keyspace = buffer.read_string
739
- name = buffer.read_string
740
- fields = ::Array.new(buffer.read_short) { [buffer.read_string, read_type_v3(buffer)] }
741
-
742
- [keyspace, name, fields]
743
- end
744
1023
  end
745
1024
  end
746
1025
  end