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

Sign up to get free protection for your applications and to get access to all the features.
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