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
@@ -23,7 +23,7 @@ module Cassandra
23
23
  # Query execution information, such as number of retries and all tried hosts, etc.
24
24
  # @return [Cassandra::Execution::Info]
25
25
  def execution_info
26
- @info ||= Execution::Info.new(@keyspace, @statement, @options, @hosts, @consistency, @retries, @trace_id ? Execution::Trace.new(@trace_id, @client) : nil)
26
+ @info ||= Execution::Info.new(@payload, @warnings, @keyspace, @statement, @options, @hosts, @consistency, @retries, @trace_id ? Execution::Trace.new(@trace_id, @client) : nil)
27
27
  end
28
28
 
29
29
  # @return [Boolean] whether it has any rows
@@ -96,7 +96,9 @@ module Cassandra
96
96
  class Paged < Result
97
97
  attr_reader :paging_state
98
98
 
99
- def initialize(rows, paging_state, trace_id, keyspace, statement, options, hosts, consistency, retries, client, futures_factory)
99
+ def initialize(payload, warnings, rows, paging_state, trace_id, keyspace, statement, options, hosts, consistency, retries, client, futures_factory)
100
+ @payload = payload
101
+ @warnings = warnings
100
102
  @rows = rows
101
103
  @paging_state = paging_state
102
104
  @trace_id = trace_id
@@ -156,13 +158,16 @@ module Cassandra
156
158
  end
157
159
  end
158
160
 
161
+ # @private
159
162
  def inspect
160
163
  "#<Cassandra::Result:0x#{self.object_id.to_s(16)} @rows=#{@rows.inspect} @last_page=#{@paging_state.nil?}>"
161
164
  end
162
165
  end
163
166
 
164
167
  class Void < Result
165
- def initialize(trace_id, keyspace, statement, options, hosts, consistency, retries, client, futures_factory)
168
+ def initialize(payload, warnings, trace_id, keyspace, statement, options, hosts, consistency, retries, client, futures_factory)
169
+ @payload = payload
170
+ @warnings = warnings
166
171
  @trace_id = trace_id
167
172
  @keyspace = keyspace
168
173
  @statement = statement
@@ -191,10 +196,10 @@ module Cassandra
191
196
  # @return [Cassandra::Result]
192
197
  def each(&block)
193
198
  if block_given?
194
- NO_ROWS.each(&block)
199
+ EMPTY_LIST.each(&block)
195
200
  self
196
201
  else
197
- NO_ROWS.each
202
+ EMPTY_LIST.each
198
203
  end
199
204
  end
200
205
  alias :rows :each
@@ -231,10 +236,6 @@ module Cassandra
231
236
  def inspect
232
237
  "#<Cassandra::Result:0x#{self.object_id.to_s(16)} @rows=[] @last_page=true>"
233
238
  end
234
-
235
- private
236
-
237
- NO_ROWS = [].freeze
238
239
  end
239
240
  end
240
241
  end
@@ -106,11 +106,20 @@ module Cassandra
106
106
 
107
107
  # Returns a decision that signals to driver to ignore the error
108
108
  #
109
- # @return [Cassandra::Policies::Retry::Decision] tell driver to ignore the error
110
- # and return an empty result to the application
109
+ # @return [Cassandra::Policies::Retry::Decision] tell driver to ignore
110
+ # the error and return an empty result to the application
111
111
  def ignore
112
112
  DECISION_IGNORE
113
113
  end
114
+
115
+ # Returns a decision that signals to the driver attempt execution on the
116
+ # next host in the load balancing plan
117
+ #
118
+ # @return [Cassandra::Policies::Retry::Decision] tell the driver to
119
+ # re-execute the statement on another host
120
+ def try_next_host
121
+ DECISION_TRY_NEXT_HOST
122
+ end
114
123
  end
115
124
 
116
125
  # @private
@@ -128,12 +137,17 @@ module Cassandra
128
137
 
129
138
  class Ignore
130
139
  end
140
+
141
+ class TryNextHost
142
+ end
131
143
  end
132
144
 
133
145
  # @private
134
146
  DECISION_RERAISE = Decisions::Reraise.new
135
147
  # @private
136
- DECISION_IGNORE = Decisions::Ignore.new
148
+ DECISION_IGNORE = Decisions::Ignore.new
149
+ # @private
150
+ DECISION_TRY_NEXT_HOST = Decisions::TryNextHost.new
137
151
  end
138
152
  end
139
153
 
@@ -28,18 +28,24 @@ module Cassandra
28
28
  if received >= required && !retrieved
29
29
  try_again(consistency)
30
30
  else
31
- reraise
31
+ try_next_host
32
32
  end
33
33
  end
34
34
 
35
35
  def write_timeout(statement, consistency, type, required, received, retries)
36
36
  return reraise if retries > 0
37
37
 
38
- type == :batch_log ? try_again(consistency) : reraise
38
+ if statement.idempotent? && received.zero?
39
+ try_next_host
40
+ elsif type == :batch_log
41
+ try_again(consistency)
42
+ else
43
+ reraise
44
+ end
39
45
  end
40
46
 
41
47
  def unavailable(statement, consistency, required, alive, retries)
42
- reraise
48
+ try_next_host
43
49
  end
44
50
  end
45
51
  end
@@ -57,9 +57,13 @@ module Cassandra
57
57
  # initial request.
58
58
  # @option options [Array, Hash] :arguments (nil) positional or named
59
59
  # arguments for the statement.
60
- # @option options [Array, Hash] :type_hints (nil) override Util.guess_type to
61
- # determine the CQL type for an argument; nil elements will fall-back
60
+ # @option options [Array, Hash] :type_hints (nil) override Util.guess_type
61
+ # to determine the CQL type for an argument; nil elements will fall-back
62
62
  # to Util.guess_type.
63
+ # @option options [Boolean] :idempotent (false) specify whether this
64
+ # statement can be retried safely on timeout.
65
+ # @option options [Hash<[String, Symbol], String>] :payload (nil) custom
66
+ # outgoing payload to be sent with the request.
63
67
  #
64
68
  # @see Cassandra.cluster Options that can be specified on the cluster-level
65
69
  # and their default values.
@@ -83,7 +87,7 @@ module Cassandra
83
87
 
84
88
  case statement
85
89
  when ::String
86
- @client.query(Statements::Simple.new(statement, options.arguments, options.type_hints), options)
90
+ @client.query(Statements::Simple.new(statement, options.arguments, options.type_hints, options.idempotent?), options)
87
91
  when Statements::Simple
88
92
  @client.query(statement, options)
89
93
  when Statements::Prepared
@@ -91,6 +95,7 @@ module Cassandra
91
95
  when Statements::Bound
92
96
  @client.execute(statement, options)
93
97
  when Statements::Batch
98
+ Util.assert_not_empty(statement.statements) { "batch cannot be empty" }
94
99
  @client.batch(statement, options)
95
100
  else
96
101
  @futures.error(::ArgumentError.new("unsupported statement #{statement.inspect}"))
@@ -131,6 +136,9 @@ module Cassandra
131
136
  # @option options [Boolean] :trace (false) whether to enable request tracing
132
137
  # @option options [Numeric] :timeout (nil) if specified, it is a number of
133
138
  # seconds after which to time out the request if it hasn't completed
139
+ # @option options [Boolean] :idempotent (false) specify whether the
140
+ # statement being prepared can be retried safely on timeout during
141
+ # execution.
134
142
  #
135
143
  # @return [Cassandra::Future<Cassandra::Statements::Prepared>] future
136
144
  # prepared statement
@@ -169,7 +177,7 @@ module Cassandra
169
177
  # @yieldparam batch [Statements::Batch] a logged batch
170
178
  # @return [Statements::Batch] a logged batch
171
179
  def logged_batch(&block)
172
- statement = Statements::Batch::Logged.new
180
+ statement = Statements::Batch::Logged.new(@options)
173
181
  yield(statement) if block_given?
174
182
  statement
175
183
  end
@@ -180,7 +188,7 @@ module Cassandra
180
188
  # @yieldparam batch [Statements::Batch] an unlogged batch
181
189
  # @return [Statements::Batch] an unlogged batch
182
190
  def unlogged_batch
183
- statement = Statements::Batch::Unlogged.new
191
+ statement = Statements::Batch::Unlogged.new(@options)
184
192
  yield(statement) if block_given?
185
193
  statement
186
194
  end
@@ -190,7 +198,7 @@ module Cassandra
190
198
  # @yieldparam batch [Statements::Batch] a counter batch
191
199
  # @return [Statements::Batch] a counter batch
192
200
  def counter_batch
193
- statement = Statements::Batch::Counter.new
201
+ statement = Statements::Batch::Counter.new(@options)
194
202
  yield(statement) if block_given?
195
203
  statement
196
204
  end
@@ -222,7 +230,7 @@ module Cassandra
222
230
  close_async.get
223
231
  end
224
232
 
225
- # @return [String] a CLI-friendly session representation
233
+ # @private
226
234
  def inspect
227
235
  "#<#{self.class.name}:0x#{self.object_id.to_s(16)}>"
228
236
  end
@@ -18,5 +18,10 @@
18
18
 
19
19
  module Cassandra
20
20
  module Statement
21
+ # Determines whether or not the statement is safe to retry on timeout
22
+ # @return [Boolean] whether the statement is safe to retry on timeout
23
+ def idempotent?
24
+ !!@idempotent
25
+ end
21
26
  end
22
27
  end
@@ -18,7 +18,8 @@
18
18
 
19
19
  module Cassandra
20
20
  module Statements
21
- # Batch statement groups several {Cassandra::Statement}. There are several types of Batch statements available:
21
+ # Batch statement groups several {Cassandra::Statement}. There are several
22
+ # types of Batch statements available:
22
23
  # @see Cassandra::Session#batch
23
24
  # @see Cassandra::Session#logged_batch
24
25
  # @see Cassandra::Session#unlogged_batch
@@ -43,6 +44,13 @@ module Cassandra
43
44
  def type
44
45
  :counter
45
46
  end
47
+
48
+ # Determines whether or not the statement is safe to retry on timeout
49
+ # Counter batches are never considered idempotent.
50
+ # @return [Boolean] whether the statement is safe to retry on timeout
51
+ def idempotent?
52
+ false
53
+ end
46
54
  end
47
55
 
48
56
  include Statement
@@ -51,7 +59,8 @@ module Cassandra
51
59
  attr_reader :statements
52
60
 
53
61
  # @private
54
- def initialize
62
+ def initialize(options)
63
+ @options = options
55
64
  @statements = []
56
65
  end
57
66
 
@@ -60,11 +69,16 @@ module Cassandra
60
69
  # @param statement [String, Cassandra::Statements::Simple,
61
70
  # Cassandra::Statements::Prepared, Cassandra::Statements::Bound]
62
71
  # statement to add.
63
- # @param args [Array, Hash] (nil) positional or named arguments to bind,
64
- # must contain the same number of parameters as the number of positional
65
- # (`?`) or named (`:name`) markers in the CQL passed.
66
- # @param type_hints [Array, Hash] (nil) specified CQL types for positional
67
- # or named arguments to override type guessing.
72
+ # @param options [Hash] (nil) a customizable set of options
73
+ # @option options [Array, Hash] :arguments (nil) positional or named
74
+ # arguments to bind, must contain the same number of parameters as the
75
+ # number of positional (`?`) or named (`:name`) markers in the CQL
76
+ # passed.
77
+ # @option options [Array, Hash] :type_hints (nil) override Util.guess_type
78
+ # to determine the CQL type for an argument; nil elements will fall-back
79
+ # to Util.guess_type.
80
+ # @option options [Boolean] :idempotent (false) specify whether this
81
+ # statement can be retried safely on timeout.
68
82
  #
69
83
  # @note Positional arguments for simple statements are only supported
70
84
  # starting with Apache Cassandra 2.0 and above.
@@ -73,15 +87,18 @@ module Cassandra
73
87
  # starting with Apache Cassandra 2.1 and above.
74
88
  #
75
89
  # @return [self]
76
- def add(statement, args = nil, type_hints = nil)
77
- args ||= EMPTY_LIST
78
- type_hints ||= EMPTY_LIST
90
+ def add(statement, options = nil)
91
+ if options.is_a?(::Hash)
92
+ options = @options.override(options)
93
+ else
94
+ options = @options
95
+ end
79
96
 
80
97
  case statement
81
98
  when String
82
- @statements << Simple.new(statement, args, type_hints)
99
+ @statements << Simple.new(statement, options.arguments, options.type_hints, options.idempotent?)
83
100
  when Prepared
84
- @statements << statement.bind(args)
101
+ @statements << statement.bind(options.arguments)
85
102
  when Bound, Simple
86
103
  @statements << statement
87
104
  else
@@ -91,6 +108,13 @@ module Cassandra
91
108
  self
92
109
  end
93
110
 
111
+ # Determines whether or not the statement is safe to retry on timeout
112
+ # Batches are idempotent only when all statements in a batch are.
113
+ # @return [Boolean] whether the statement is safe to retry on timeout
114
+ def idempotent?
115
+ @statements.all?(&:idempotent?)
116
+ end
117
+
94
118
  # A batch statement doesn't really have any cql of its own as it is composed of multiple different statements
95
119
  # @return [nil] nothing
96
120
  def cql
@@ -30,13 +30,14 @@ module Cassandra
30
30
  attr_reader :params_types, :result_metadata, :keyspace, :partition_key
31
31
 
32
32
  # @private
33
- def initialize(cql, params_types, result_metadata, params, keyspace = nil, partition_key = nil)
33
+ def initialize(cql, params_types, result_metadata, params, keyspace = nil, partition_key = nil, idempotent = false)
34
34
  @cql = cql
35
35
  @params_types = params_types
36
36
  @result_metadata = result_metadata
37
37
  @params = params
38
38
  @keyspace = keyspace
39
39
  @partition_key = partition_key
40
+ @idempotent = idempotent
40
41
  end
41
42
 
42
43
  # @return [String] a CLI-friendly bound statement representation
@@ -29,19 +29,24 @@ module Cassandra
29
29
  attr_reader :result_metadata
30
30
 
31
31
  # @private
32
- def initialize(cql, params_metadata, result_metadata, trace_id, keyspace, statement, options, hosts, consistency, retries, client, futures_factory, schema)
33
- @cql = cql
34
- @params_metadata = params_metadata
35
- @result_metadata = result_metadata
36
- @trace_id = trace_id
37
- @keyspace = keyspace
38
- @statement = statement
39
- @options = options
40
- @hosts = hosts
41
- @consistency = consistency
42
- @retries = retries
43
- @client = client
44
- @schema = schema
32
+ def initialize(payload, warnings, cql, params_metadata, result_metadata, partition_key, trace_id, keyspace, statement, options, hosts, consistency, retries, client, connection_options)
33
+ @payload = payload
34
+ @warnings = warnings
35
+ @cql = cql
36
+ @params_metadata = params_metadata
37
+ @result_metadata = result_metadata
38
+ @partition_key = partition_key
39
+ @trace_id = trace_id
40
+ @keyspace = keyspace
41
+ @statement = statement
42
+ @options = options
43
+ @hosts = hosts
44
+ @consistency = consistency
45
+ @retries = retries
46
+ @client = client
47
+ @connection_options = connection_options
48
+ @idempotent = options.idempotent?
49
+ @payload = payload
45
50
  end
46
51
 
47
52
  # Creates a statement bound with specific arguments
@@ -59,48 +64,114 @@ module Cassandra
59
64
  args = EMPTY_LIST
60
65
  end
61
66
 
62
- if args.is_a?(Hash)
63
- args = @params_metadata.map do |(_, _, name, type)|
64
- unless args.has_key?(name)
65
- name = name.to_sym
66
- raise ::ArgumentError, "argument :#{name} must be present in #{args.inspect}, but isn't" unless args.has_key?(name)
67
+ params = []
68
+ param_types = []
69
+
70
+ if args.is_a?(::Hash)
71
+ @params_metadata.each do |(_, _, name, type)|
72
+ name = name.to_sym unless args.has_key?(name)
73
+ value = args.fetch(name, NOT_SET)
74
+
75
+ if NOT_SET.eql?(value)
76
+ if @connection_options.protocol_version < 4
77
+ raise ::ArgumentError, "argument #{name.inspect} it not present in #{args.inspect}"
78
+ end
79
+ else
80
+ Util.assert_type(type, value) { "argument for #{name.inspect} must be #{type}, #{value} given" }
67
81
  end
68
82
 
69
- args[name]
83
+ params << value
84
+ param_types << type
70
85
  end
71
86
  else
72
87
  Util.assert_equal(@params_metadata.size, args.size) { "expecting exactly #{@params_metadata.size} bind parameters, #{args.size} given" }
73
- end
88
+ @params_metadata.zip(args) do |(_, _, name, type), value|
89
+ if NOT_SET.eql?(value)
90
+ if @connection_options.protocol_version < 4
91
+ raise ::ArgumentError, "argument #{name.inspect} it not present in #{args.inspect}"
92
+ end
93
+ else
94
+ Util.assert_type(type, value) { "argument for #{name.inspect} must be #{type}, #{value} given" }
95
+ end
74
96
 
75
- params_types = @params_metadata.each_with_index.map do |(_, _, name, type), i|
76
- Util.assert_type(type, args[i]) { "argument for #{name.inspect} must be #{type}, #{args[i]} given" }
77
- type
97
+ params << value
98
+ param_types << type
99
+ end
78
100
  end
79
101
 
80
- return Bound.new(@cql, params_types, @result_metadata, args) if @params_metadata.empty?
81
-
82
- keyspace, table, _, _ = @params_metadata.first
83
- return Bound.new(@cql, params_types, @result_metadata, args, keyspace) unless keyspace && table
84
-
85
- values = ::Hash.new
86
- @params_metadata.zip(args) do |(keyspace, table, column, type), value|
87
- values[column] = value
88
- end
102
+ keyspace_name, _ = @params_metadata.first
89
103
 
90
- partition_key = @schema.create_partition_key(keyspace, table, values)
104
+ partition_key = create_partition_key(params)
91
105
 
92
- Bound.new(@cql, params_types, @result_metadata, args, keyspace, partition_key)
106
+ Bound.new(@cql, param_types, @result_metadata, params, keyspace_name, partition_key, @idempotent)
93
107
  end
94
108
 
95
109
  # @return [Cassandra::Execution::Info] execution info for PREPARE request
96
110
  def execution_info
97
- @info ||= Execution::Info.new(@keyspace, @statement, @options, @hosts, @consistency, @retries, @trace_id ? Execution::Trace.new(@trace_id, @client) : nil)
111
+ @info ||= Execution::Info.new(@payload, @warnings, @keyspace, @statement, @options, @hosts, @consistency, @retries, @trace_id ? Execution::Trace.new(@trace_id, @client) : nil)
98
112
  end
99
113
 
100
114
  # @return [String] a CLI-friendly prepared statement representation
101
115
  def inspect
102
116
  "#<#{self.class.name}:0x#{self.object_id.to_s(16)} @cql=#{@cql.inspect}>"
103
117
  end
118
+
119
+ private
120
+
121
+ def create_partition_key(values)
122
+ partition_key = @partition_key
123
+ return nil if partition_key.empty? || partition_key.size > values.size
124
+ params_metadata = @params_metadata
125
+
126
+ buffer = Protocol::CqlByteBuffer.new
127
+ if partition_key.one?
128
+ i = partition_key.first
129
+ value = values[i]
130
+ metadata = params_metadata[i]
131
+ name = metadata[2]
132
+ type = metadata[3]
133
+
134
+ if NOT_SET.eql?(value)
135
+ raise ::ArgumentError, "argument #{name.inspect} is a part of " \
136
+ "the partition key and must be present."
137
+ end
138
+
139
+ if @connection_options.protocol_version >= 3
140
+ Protocol::Coder.write_value_v3(buffer, value, type)
141
+ else
142
+ Protocol::Coder.write_value_v1(buffer, value, type)
143
+ end
144
+
145
+ buffer.discard(4) # discard size
146
+ else
147
+ buf = Protocol::CqlByteBuffer.new
148
+ partition_key.each do |i|
149
+ value = values[i]
150
+ metadata = params_metadata[i]
151
+ name = metadata[2]
152
+ type = metadata[3]
153
+
154
+ if NOT_SET.eql?(value)
155
+ raise ::ArgumentError, "argument #{name.inspect} is a part of " \
156
+ "the partition key and must be present."
157
+ end
158
+
159
+ if @connection_options.protocol_version >= 3
160
+ Protocol::Coder.write_value_v3(buf, value, type)
161
+ else
162
+ Protocol::Coder.write_value_v1(buf, value, type)
163
+ end
164
+
165
+ buf.discard(4) # discard size
166
+
167
+ size = buf.length
168
+ buffer.append_short(size)
169
+ buffer << buf.read(size) << NULL_BYTE
170
+ end
171
+ end
172
+
173
+ buffer.to_str
174
+ end
104
175
  end
105
176
  end
106
177
  end