yugabyte-ycql-driver 3.2.3.1
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.
- checksums.yaml +7 -0
- data/.yardopts +13 -0
- data/README.md +242 -0
- data/ext/cassandra_murmur3/cassandra_murmur3.c +178 -0
- data/ext/cassandra_murmur3/extconf.rb +2 -0
- data/lib/cassandra/address_resolution.rb +36 -0
- data/lib/cassandra/address_resolution/policies.rb +2 -0
- data/lib/cassandra/address_resolution/policies/ec2_multi_region.rb +56 -0
- data/lib/cassandra/address_resolution/policies/none.rb +35 -0
- data/lib/cassandra/aggregate.rb +123 -0
- data/lib/cassandra/argument.rb +51 -0
- data/lib/cassandra/attr_boolean.rb +33 -0
- data/lib/cassandra/auth.rb +100 -0
- data/lib/cassandra/auth/providers.rb +17 -0
- data/lib/cassandra/auth/providers/password.rb +65 -0
- data/lib/cassandra/cassandra_logger.rb +80 -0
- data/lib/cassandra/cluster.rb +331 -0
- data/lib/cassandra/cluster/client.rb +1612 -0
- data/lib/cassandra/cluster/connection_pool.rb +78 -0
- data/lib/cassandra/cluster/connector.rb +372 -0
- data/lib/cassandra/cluster/control_connection.rb +962 -0
- data/lib/cassandra/cluster/failed_connection.rb +35 -0
- data/lib/cassandra/cluster/metadata.rb +142 -0
- data/lib/cassandra/cluster/options.rb +145 -0
- data/lib/cassandra/cluster/registry.rb +284 -0
- data/lib/cassandra/cluster/schema.rb +405 -0
- data/lib/cassandra/cluster/schema/cql_type_parser.rb +112 -0
- data/lib/cassandra/cluster/schema/fetchers.rb +1627 -0
- data/lib/cassandra/cluster/schema/fqcn_type_parser.rb +175 -0
- data/lib/cassandra/cluster/schema/partitioners.rb +21 -0
- data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +45 -0
- data/lib/cassandra/cluster/schema/partitioners/ordered.rb +37 -0
- data/lib/cassandra/cluster/schema/partitioners/random.rb +37 -0
- data/lib/cassandra/cluster/schema/replication_strategies.rb +21 -0
- data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +102 -0
- data/lib/cassandra/cluster/schema/replication_strategies/none.rb +39 -0
- data/lib/cassandra/cluster/schema/replication_strategies/simple.rb +44 -0
- data/lib/cassandra/column.rb +66 -0
- data/lib/cassandra/column_container.rb +326 -0
- data/lib/cassandra/compression.rb +69 -0
- data/lib/cassandra/compression/compressors/lz4.rb +73 -0
- data/lib/cassandra/compression/compressors/snappy.rb +69 -0
- data/lib/cassandra/custom_data.rb +53 -0
- data/lib/cassandra/driver.rb +260 -0
- data/lib/cassandra/errors.rb +784 -0
- data/lib/cassandra/execution/info.rb +69 -0
- data/lib/cassandra/execution/options.rb +267 -0
- data/lib/cassandra/execution/profile.rb +153 -0
- data/lib/cassandra/execution/profile_manager.rb +71 -0
- data/lib/cassandra/execution/trace.rb +192 -0
- data/lib/cassandra/executors.rb +113 -0
- data/lib/cassandra/function.rb +156 -0
- data/lib/cassandra/function_collection.rb +85 -0
- data/lib/cassandra/future.rb +794 -0
- data/lib/cassandra/host.rb +102 -0
- data/lib/cassandra/index.rb +118 -0
- data/lib/cassandra/keyspace.rb +473 -0
- data/lib/cassandra/listener.rb +87 -0
- data/lib/cassandra/load_balancing.rb +121 -0
- data/lib/cassandra/load_balancing/policies.rb +20 -0
- data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +172 -0
- data/lib/cassandra/load_balancing/policies/round_robin.rb +141 -0
- data/lib/cassandra/load_balancing/policies/token_aware.rb +149 -0
- data/lib/cassandra/load_balancing/policies/white_list.rb +100 -0
- data/lib/cassandra/materialized_view.rb +92 -0
- data/lib/cassandra/null_logger.rb +56 -0
- data/lib/cassandra/protocol.rb +102 -0
- data/lib/cassandra/protocol/coder.rb +1085 -0
- data/lib/cassandra/protocol/cql_byte_buffer.rb +418 -0
- data/lib/cassandra/protocol/cql_protocol_handler.rb +448 -0
- data/lib/cassandra/protocol/request.rb +41 -0
- data/lib/cassandra/protocol/requests/auth_response_request.rb +51 -0
- data/lib/cassandra/protocol/requests/batch_request.rb +117 -0
- data/lib/cassandra/protocol/requests/credentials_request.rb +51 -0
- data/lib/cassandra/protocol/requests/execute_request.rb +122 -0
- data/lib/cassandra/protocol/requests/options_request.rb +39 -0
- data/lib/cassandra/protocol/requests/prepare_request.rb +59 -0
- data/lib/cassandra/protocol/requests/query_request.rb +112 -0
- data/lib/cassandra/protocol/requests/register_request.rb +38 -0
- data/lib/cassandra/protocol/requests/startup_request.rb +49 -0
- data/lib/cassandra/protocol/requests/void_query_request.rb +24 -0
- data/lib/cassandra/protocol/response.rb +28 -0
- data/lib/cassandra/protocol/responses/already_exists_error_response.rb +50 -0
- data/lib/cassandra/protocol/responses/auth_challenge_response.rb +36 -0
- data/lib/cassandra/protocol/responses/auth_success_response.rb +36 -0
- data/lib/cassandra/protocol/responses/authenticate_response.rb +36 -0
- data/lib/cassandra/protocol/responses/error_response.rb +142 -0
- data/lib/cassandra/protocol/responses/event_response.rb +30 -0
- data/lib/cassandra/protocol/responses/function_failure_error_response.rb +52 -0
- data/lib/cassandra/protocol/responses/prepared_result_response.rb +62 -0
- data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +59 -0
- data/lib/cassandra/protocol/responses/read_failure_error_response.rb +71 -0
- data/lib/cassandra/protocol/responses/read_timeout_error_response.rb +61 -0
- data/lib/cassandra/protocol/responses/ready_response.rb +43 -0
- data/lib/cassandra/protocol/responses/result_response.rb +42 -0
- data/lib/cassandra/protocol/responses/rows_result_response.rb +39 -0
- data/lib/cassandra/protocol/responses/schema_change_event_response.rb +73 -0
- data/lib/cassandra/protocol/responses/schema_change_result_response.rb +70 -0
- data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +37 -0
- data/lib/cassandra/protocol/responses/status_change_event_response.rb +39 -0
- data/lib/cassandra/protocol/responses/supported_response.rb +36 -0
- data/lib/cassandra/protocol/responses/topology_change_event_response.rb +33 -0
- data/lib/cassandra/protocol/responses/unavailable_error_response.rb +58 -0
- data/lib/cassandra/protocol/responses/unprepared_error_response.rb +48 -0
- data/lib/cassandra/protocol/responses/void_result_response.rb +34 -0
- data/lib/cassandra/protocol/responses/write_failure_error_response.rb +73 -0
- data/lib/cassandra/protocol/responses/write_timeout_error_response.rb +63 -0
- data/lib/cassandra/protocol/v1.rb +326 -0
- data/lib/cassandra/protocol/v3.rb +358 -0
- data/lib/cassandra/protocol/v4.rb +478 -0
- data/lib/cassandra/reconnection.rb +49 -0
- data/lib/cassandra/reconnection/policies.rb +20 -0
- data/lib/cassandra/reconnection/policies/constant.rb +46 -0
- data/lib/cassandra/reconnection/policies/exponential.rb +79 -0
- data/lib/cassandra/result.rb +276 -0
- data/lib/cassandra/retry.rb +154 -0
- data/lib/cassandra/retry/policies.rb +21 -0
- data/lib/cassandra/retry/policies/default.rb +53 -0
- data/lib/cassandra/retry/policies/downgrading_consistency.rb +73 -0
- data/lib/cassandra/retry/policies/fallthrough.rb +39 -0
- data/lib/cassandra/session.rb +270 -0
- data/lib/cassandra/statement.rb +32 -0
- data/lib/cassandra/statements.rb +23 -0
- data/lib/cassandra/statements/batch.rb +146 -0
- data/lib/cassandra/statements/bound.rb +65 -0
- data/lib/cassandra/statements/prepared.rb +235 -0
- data/lib/cassandra/statements/simple.rb +118 -0
- data/lib/cassandra/statements/void.rb +38 -0
- data/lib/cassandra/table.rb +240 -0
- data/lib/cassandra/time.rb +103 -0
- data/lib/cassandra/time_uuid.rb +78 -0
- data/lib/cassandra/timestamp_generator.rb +37 -0
- data/lib/cassandra/timestamp_generator/simple.rb +38 -0
- data/lib/cassandra/timestamp_generator/ticking_on_duplicate.rb +58 -0
- data/lib/cassandra/trigger.rb +67 -0
- data/lib/cassandra/tuple.rb +131 -0
- data/lib/cassandra/types.rb +1704 -0
- data/lib/cassandra/udt.rb +443 -0
- data/lib/cassandra/util.rb +464 -0
- data/lib/cassandra/uuid.rb +110 -0
- data/lib/cassandra/uuid/generator.rb +212 -0
- data/lib/cassandra/version.rb +21 -0
- data/lib/datastax/cassandra.rb +47 -0
- data/lib/ycql.rb +842 -0
- metadata +243 -0
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# Copyright DataStax, Inc.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#++
|
|
18
|
+
|
|
19
|
+
module Cassandra
|
|
20
|
+
# A user-defined type value representation
|
|
21
|
+
class UDT
|
|
22
|
+
# @private
|
|
23
|
+
class Strict < UDT
|
|
24
|
+
def initialize(keyspace, name, fields, values)
|
|
25
|
+
@keyspace = keyspace
|
|
26
|
+
@name = name
|
|
27
|
+
@fields = fields
|
|
28
|
+
@values = values
|
|
29
|
+
@name_to_type = fields.each_with_object(::Hash.new) do |f, index|
|
|
30
|
+
index[f.name] = f.type
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def method_missing(method, *args, &block)
|
|
35
|
+
return super if block_given? || args.size > 1
|
|
36
|
+
|
|
37
|
+
field = method.to_s
|
|
38
|
+
assign = !field.chomp!('=').nil?
|
|
39
|
+
|
|
40
|
+
return super if assign && args.empty?
|
|
41
|
+
return super unless @name_to_type.key?(field)
|
|
42
|
+
|
|
43
|
+
if assign
|
|
44
|
+
value = args.first
|
|
45
|
+
Util.assert_type(@name_to_type[field], value)
|
|
46
|
+
@values[field] = value
|
|
47
|
+
else
|
|
48
|
+
@values[field]
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Returns true if a field with a given name is present in this value
|
|
53
|
+
#
|
|
54
|
+
# @param method [Symbol] name of the field
|
|
55
|
+
#
|
|
56
|
+
# @return [Boolean] whether a field is present
|
|
57
|
+
def respond_to?(method)
|
|
58
|
+
field = method.to_s
|
|
59
|
+
field.chomp!('=')
|
|
60
|
+
|
|
61
|
+
return true if @name_to_type.key?(field)
|
|
62
|
+
super
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Returns value of the field.
|
|
66
|
+
#
|
|
67
|
+
# @param field [String, Integer] name or numeric index of the field
|
|
68
|
+
# @return [Object] value of the field
|
|
69
|
+
def [](field)
|
|
70
|
+
case field
|
|
71
|
+
when ::Integer
|
|
72
|
+
return nil if field < 0 || field >= @fields.size
|
|
73
|
+
@values[@fields[field][0]]
|
|
74
|
+
when ::String
|
|
75
|
+
@values[field]
|
|
76
|
+
else
|
|
77
|
+
raise ::ArgumentError, "unrecognized field #{field} in UDT: " \
|
|
78
|
+
"#{Util.escape_name(@keyspace)}.#{Util.escape_name(@name)}"
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Returns value of the field.
|
|
83
|
+
#
|
|
84
|
+
# @param field [String, Integer] name or numeric index of the field to
|
|
85
|
+
# lookup
|
|
86
|
+
#
|
|
87
|
+
# @raise [IndexError] when numeric index given is out of bounds
|
|
88
|
+
# @raise [KeyError] when field with a given name is not present
|
|
89
|
+
# @raise [ArgumentError] when neither a numeric index nor a field name given
|
|
90
|
+
#
|
|
91
|
+
# @return [Object] value of the field
|
|
92
|
+
def fetch(field)
|
|
93
|
+
case field
|
|
94
|
+
when ::Integer
|
|
95
|
+
if field < 0 || field >= @fields.size
|
|
96
|
+
raise ::IndexError,
|
|
97
|
+
"field index #{field} is not present in UDT: " \
|
|
98
|
+
"#{Util.escape_name(@keyspace)}.#{Util.escape_name(@name)}"
|
|
99
|
+
end
|
|
100
|
+
@values[@fields[field][0]]
|
|
101
|
+
when ::String
|
|
102
|
+
unless @name_to_type.key?(field)
|
|
103
|
+
raise ::KeyError,
|
|
104
|
+
"field #{field} is not defined in UDT: " \
|
|
105
|
+
"#{Util.escape_name(@keyspace)}.#{Util.escape_name(@name)}"
|
|
106
|
+
end
|
|
107
|
+
@values[field]
|
|
108
|
+
else
|
|
109
|
+
raise ::ArgumentError, "unrecognized field #{field} in UDT: " \
|
|
110
|
+
"#{Util.escape_name(@keyspace)}.#{Util.escape_name(@name)}"
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Sets value of the field.
|
|
115
|
+
#
|
|
116
|
+
# @param field [String, Integer] name or numeric index of the field
|
|
117
|
+
# @param value [Object] new value for the field
|
|
118
|
+
#
|
|
119
|
+
# @raise [IndexError] when numeric index given is out of bounds
|
|
120
|
+
# @raise [KeyError] when field with a given name is not present
|
|
121
|
+
# @raise [ArgumentError] when neither a numeric index nor a field name
|
|
122
|
+
# given
|
|
123
|
+
#
|
|
124
|
+
# @return [Object] value.
|
|
125
|
+
def []=(field, value)
|
|
126
|
+
case field
|
|
127
|
+
when ::Integer
|
|
128
|
+
if field < 0 || field >= @fields.size
|
|
129
|
+
raise ::IndexError,
|
|
130
|
+
"field index #{field} is not present in UDT: " \
|
|
131
|
+
"#{Util.escape_name(@keyspace)}.#{Util.escape_name(@name)}"
|
|
132
|
+
end
|
|
133
|
+
Util.assert_type(@fields[field][1], value)
|
|
134
|
+
@values[@fields[field][0]] = value
|
|
135
|
+
when ::String
|
|
136
|
+
unless @name_to_type.key?(field)
|
|
137
|
+
raise ::KeyError,
|
|
138
|
+
"field #{field} is not defined in UDT: " \
|
|
139
|
+
"#{Util.escape_name(@keyspace)}.#{Util.escape_name(@name)}"
|
|
140
|
+
end
|
|
141
|
+
Util.assert_type(@name_to_type[field], value)
|
|
142
|
+
@values[field] = value
|
|
143
|
+
else
|
|
144
|
+
raise ::ArgumentError, "unrecognized field #{field} in UDT: " \
|
|
145
|
+
"#{Util.escape_name(@keyspace)}.#{Util.escape_name(@name)}"
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Iterates over all fields of the UDT
|
|
150
|
+
# @yieldparam name [String] field name
|
|
151
|
+
# @yieldparam value [Object] field value
|
|
152
|
+
# @return [Cassandra::UDT] self
|
|
153
|
+
def each(&block)
|
|
154
|
+
@fields.each do |f|
|
|
155
|
+
n = f.name
|
|
156
|
+
yield(n, @values[n])
|
|
157
|
+
end
|
|
158
|
+
self
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Returns UDT size
|
|
162
|
+
# @return [Integer] UDT size
|
|
163
|
+
def size
|
|
164
|
+
@fields.size
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def inspect
|
|
168
|
+
"#<Cassandra::UDT:0x#{object_id.to_s(16)} #{self}>"
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def eql?(other)
|
|
172
|
+
(other.is_a?(Strict) && @values.all? {|n, v| v == other[n]}) ||
|
|
173
|
+
(other.is_a?(UDT) && other == self)
|
|
174
|
+
end
|
|
175
|
+
alias == eql?
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
include Enumerable
|
|
179
|
+
|
|
180
|
+
# Creates a UDT instance
|
|
181
|
+
# @param values [Hash<String, Object>, Array<Array<String, Object>>,
|
|
182
|
+
# *Object, *Array<String, Object>] - UDT field values
|
|
183
|
+
# @example Various ways of creating the same UDT instance
|
|
184
|
+
# Cassandra::UDT.new({'street' => '123 Main St.',
|
|
185
|
+
# 'city' => 'Whatever',
|
|
186
|
+
# 'state' => 'XZ',
|
|
187
|
+
# 'zip' => '10020'})
|
|
188
|
+
#
|
|
189
|
+
# Cassandra::UDT.new(street: '123 Main St.',
|
|
190
|
+
# city: 'Whatever',
|
|
191
|
+
# state: 'XZ',
|
|
192
|
+
# zip: '10020')
|
|
193
|
+
#
|
|
194
|
+
# Cassandra::UDT.new('street', '123 Main St.',
|
|
195
|
+
# 'city', 'Whatever',
|
|
196
|
+
# 'state', 'XZ',
|
|
197
|
+
# 'zip', '10020')
|
|
198
|
+
#
|
|
199
|
+
# Cassandra::UDT.new(:street, '123 Main St.',
|
|
200
|
+
# :city, 'Whatever',
|
|
201
|
+
# :state, 'XZ',
|
|
202
|
+
# :zip, '10020')
|
|
203
|
+
#
|
|
204
|
+
# Cassandra::UDT.new(['street', '123 Main St.'],
|
|
205
|
+
# ['city', 'Whatever'],
|
|
206
|
+
# ['state', 'XZ'],
|
|
207
|
+
# ['zip', '10020'])
|
|
208
|
+
#
|
|
209
|
+
# Cassandra::UDT.new([:street, '123 Main St.'],
|
|
210
|
+
# [:city, 'Whatever'],
|
|
211
|
+
# [:state, 'XZ'],
|
|
212
|
+
# [:zip, '10020'])
|
|
213
|
+
#
|
|
214
|
+
# Cassandra::UDT.new([['street', '123 Main St.'],
|
|
215
|
+
# ['city', 'Whatever'],
|
|
216
|
+
# ['state', 'XZ'],
|
|
217
|
+
# ['zip', '10020']])
|
|
218
|
+
#
|
|
219
|
+
# Cassandra::UDT.new([[:street, '123 Main St.'],
|
|
220
|
+
# [:city, 'Whatever'],
|
|
221
|
+
# [:state, 'XZ'],
|
|
222
|
+
# [:zip, '10020']])
|
|
223
|
+
def initialize(*values)
|
|
224
|
+
values = Array(values.first) if values.one?
|
|
225
|
+
|
|
226
|
+
Util.assert_not_empty(values,
|
|
227
|
+
'user-defined type must contain at least one value')
|
|
228
|
+
|
|
229
|
+
if values.first.is_a?(::Array)
|
|
230
|
+
@values = values.map do |pair|
|
|
231
|
+
Util.assert(pair.size == 2,
|
|
232
|
+
'values of a user-defined type must be an Array of name and ' \
|
|
233
|
+
"value pairs, #{pair.inspect} given")
|
|
234
|
+
name, value = pair
|
|
235
|
+
|
|
236
|
+
[String(name), value]
|
|
237
|
+
end
|
|
238
|
+
else
|
|
239
|
+
Util.assert(values.size.even?,
|
|
240
|
+
'values of a user-defined type must be an Array of alternating ' \
|
|
241
|
+
"names and values pairs, #{values.inspect} given")
|
|
242
|
+
@values = values.each_slice(2).map do |(name, value)|
|
|
243
|
+
[String(name), value]
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# @!visibility public
|
|
249
|
+
# Allows access to properties of a User-Defined Type.
|
|
250
|
+
#
|
|
251
|
+
# @example Getting and setting field values
|
|
252
|
+
# session.execute("CREATE TYPE address (street text, zipcode int)")
|
|
253
|
+
# session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
|
|
254
|
+
# row = session.execute("SELECT * FROM users WHERE id = 123").first
|
|
255
|
+
# address = row['address']
|
|
256
|
+
#
|
|
257
|
+
# puts address.street
|
|
258
|
+
# address.street = '123 SomePlace Cir'
|
|
259
|
+
#
|
|
260
|
+
# @overload method_missing(field)
|
|
261
|
+
# @param field [Symbol] name of the field to lookup
|
|
262
|
+
# @raise [NoMethodError] if the field is not present
|
|
263
|
+
# @return [Object] value of the field if present
|
|
264
|
+
# @overload method_missing(field, value)
|
|
265
|
+
# @param field [Symbol] name of the field (suffixed with `=`) to set
|
|
266
|
+
# the value for
|
|
267
|
+
# @param value [Symbol] new value for the field
|
|
268
|
+
# @raise [NoMethodError] if the field is not present
|
|
269
|
+
# @return [Cassandra::UDT] self.
|
|
270
|
+
def method_missing(field, *args, &block)
|
|
271
|
+
return super if block_given? || args.size > 1
|
|
272
|
+
|
|
273
|
+
key = field.to_s
|
|
274
|
+
set = !key.chomp!('=').nil?
|
|
275
|
+
|
|
276
|
+
return super if set && args.empty?
|
|
277
|
+
|
|
278
|
+
index = @values.index {|(name, _)| name == key}
|
|
279
|
+
return super unless index
|
|
280
|
+
|
|
281
|
+
if set
|
|
282
|
+
@values[index][1] = args.first
|
|
283
|
+
else
|
|
284
|
+
@values[index][1]
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# Returns true if a field with a given name is present
|
|
289
|
+
#
|
|
290
|
+
# @param field [Symbol] method or name of the field
|
|
291
|
+
#
|
|
292
|
+
# @return [Boolean] whether a field is present
|
|
293
|
+
def respond_to?(field)
|
|
294
|
+
key = field.to_s
|
|
295
|
+
key.chomp!('=')
|
|
296
|
+
|
|
297
|
+
return true if @values.any? {|(name, _)| name == key}
|
|
298
|
+
super
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
# Returns value of the field.
|
|
302
|
+
#
|
|
303
|
+
# @param field [String, Integer] name or numeric index of the field to
|
|
304
|
+
# lookup
|
|
305
|
+
#
|
|
306
|
+
# @raise [ArgumentError] when neither a numeric index nor a field name given
|
|
307
|
+
#
|
|
308
|
+
# @return [Object] value of the field, or nil if the field is not present
|
|
309
|
+
def [](field)
|
|
310
|
+
case field
|
|
311
|
+
when ::Integer
|
|
312
|
+
return nil if field >= 0 && field < @values.size
|
|
313
|
+
|
|
314
|
+
@values[field][1]
|
|
315
|
+
when ::String
|
|
316
|
+
index = @values.index {|(n, _)| field == n}
|
|
317
|
+
|
|
318
|
+
index && @values[index][1]
|
|
319
|
+
else
|
|
320
|
+
raise ::ArgumentError, "Unrecognized field #{field.inspect}"
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
# Returns value of the field.
|
|
325
|
+
#
|
|
326
|
+
# @param field [String, Integer] name or numeric index of the field to
|
|
327
|
+
# lookup
|
|
328
|
+
#
|
|
329
|
+
# @raise [IndexError] when numeric index given is out of bounds
|
|
330
|
+
# @raise [KeyError] when field with a given name is not present
|
|
331
|
+
# @raise [ArgumentError] when neither a numeric index nor a field name given
|
|
332
|
+
#
|
|
333
|
+
# @return [Object] value of the field
|
|
334
|
+
def fetch(field)
|
|
335
|
+
case field
|
|
336
|
+
when ::Integer
|
|
337
|
+
raise ::IndexError, "Field index #{field.inspect} is not present" if field >= 0 && field < @values.size
|
|
338
|
+
|
|
339
|
+
@values[field][1]
|
|
340
|
+
when ::String
|
|
341
|
+
index = @values.index {|(n, _)| field == n}
|
|
342
|
+
|
|
343
|
+
raise ::KeyError, "Unsupported field #{field.inspect}" unless index
|
|
344
|
+
|
|
345
|
+
@values[index][1]
|
|
346
|
+
else
|
|
347
|
+
raise ::ArgumentError, "Unrecognized field #{field.inspect}"
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
# @param field [String, Integer] name or numeric index of the field to
|
|
352
|
+
# lookup
|
|
353
|
+
#
|
|
354
|
+
# @return [Boolean] whether the field is present in this UDT
|
|
355
|
+
def has_field?(field)
|
|
356
|
+
case field
|
|
357
|
+
when ::Integer
|
|
358
|
+
return false if field < 0 || field >= @values.size
|
|
359
|
+
when ::String
|
|
360
|
+
return false unless @values.index {|(n, _)| field == n}
|
|
361
|
+
else
|
|
362
|
+
return false
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
true
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
alias include? has_field?
|
|
369
|
+
|
|
370
|
+
# Sets value of the field.
|
|
371
|
+
#
|
|
372
|
+
# @param field [String] name of the field to set
|
|
373
|
+
# @param value [Object] new value for the field
|
|
374
|
+
#
|
|
375
|
+
# @raise [IndexError] when numeric index given is out of bounds
|
|
376
|
+
# @raise [KeyError] when field with a given name is not present
|
|
377
|
+
# @raise [ArgumentError] when neither a numeric index nor a field name given
|
|
378
|
+
#
|
|
379
|
+
# @return [Object] value.
|
|
380
|
+
def []=(field, value)
|
|
381
|
+
case field
|
|
382
|
+
when ::Integer
|
|
383
|
+
raise ::IndexError, "Field index #{field.inspect} is not present" if field < 0 || field >= @values.size
|
|
384
|
+
|
|
385
|
+
@values[field][1] = value
|
|
386
|
+
when ::String
|
|
387
|
+
index = @values.index {|(n, _)| field == n}
|
|
388
|
+
|
|
389
|
+
raise ::KeyError, "Unsupported field #{field.inspect}" unless index
|
|
390
|
+
|
|
391
|
+
@values[index][1] = value
|
|
392
|
+
else
|
|
393
|
+
raise ::ArgumentError, "Unrecognized field #{field.inspect}"
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
# Iterates over all fields of the UDT
|
|
398
|
+
# @yieldparam name [String] field name
|
|
399
|
+
# @yieldparam value [Object] field value
|
|
400
|
+
# @return [Cassandra::UDT] self
|
|
401
|
+
def each(&block)
|
|
402
|
+
@values.each {|(n, v)| yield(n, v)}
|
|
403
|
+
self
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
# Returns UDT size
|
|
407
|
+
# @return [Integer] UDT size
|
|
408
|
+
def size
|
|
409
|
+
@values.size
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
# Hash representation of the UDT
|
|
413
|
+
def to_h
|
|
414
|
+
@values.each_with_object(::Hash.new) do |(n, v), hash|
|
|
415
|
+
hash[n] = v
|
|
416
|
+
end
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
# String representation of the UDT
|
|
420
|
+
def to_s
|
|
421
|
+
'{ ' + @values.map {|(n, v)| "#{n}: #{v.inspect}"}.join(', ') + ' }'
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
# @private
|
|
425
|
+
def inspect
|
|
426
|
+
"#<Cassandra::UDT:0x#{object_id.to_s(16)} #{self}>"
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
# @private
|
|
430
|
+
def eql?(other)
|
|
431
|
+
other.is_a?(UDT) && @values.all? {|(n, v)| v == other[n]}
|
|
432
|
+
end
|
|
433
|
+
alias == eql?
|
|
434
|
+
|
|
435
|
+
# @private
|
|
436
|
+
def hash
|
|
437
|
+
@values.inject(17) do |h, (n, v)|
|
|
438
|
+
h = 31 * h + n.hash
|
|
439
|
+
31 * h + v.hash
|
|
440
|
+
end
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
end
|
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# Copyright DataStax, Inc.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#++
|
|
18
|
+
|
|
19
|
+
module Cassandra
|
|
20
|
+
# @private
|
|
21
|
+
module Util
|
|
22
|
+
module_function
|
|
23
|
+
|
|
24
|
+
def encode_hash(hash, io = StringIO.new)
|
|
25
|
+
first = true
|
|
26
|
+
|
|
27
|
+
io.putc(CRL_OPN)
|
|
28
|
+
hash.each do |k, v|
|
|
29
|
+
if first
|
|
30
|
+
first = false
|
|
31
|
+
else
|
|
32
|
+
io.print(COMMA)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
encode_object(k, io)
|
|
36
|
+
io.print(COLON)
|
|
37
|
+
encode_object(v, io)
|
|
38
|
+
end
|
|
39
|
+
io.putc(CRL_CLS)
|
|
40
|
+
|
|
41
|
+
io.string
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def encode_set(set, io = StringIO.new)
|
|
45
|
+
first = true
|
|
46
|
+
|
|
47
|
+
io.putc(CRL_OPN)
|
|
48
|
+
set.each do |object|
|
|
49
|
+
if first
|
|
50
|
+
first = false
|
|
51
|
+
else
|
|
52
|
+
io.print(COMMA)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
encode_object(object, io)
|
|
56
|
+
end
|
|
57
|
+
io.putc(CRL_CLS)
|
|
58
|
+
|
|
59
|
+
io.string
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def encode_array(array, io = StringIO.new)
|
|
63
|
+
first = true
|
|
64
|
+
|
|
65
|
+
io.putc(SQR_OPN)
|
|
66
|
+
array.each do |object|
|
|
67
|
+
if first
|
|
68
|
+
first = false
|
|
69
|
+
else
|
|
70
|
+
io.print(COMMA)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
encode_object(object, io)
|
|
74
|
+
end
|
|
75
|
+
io.putc(SQR_CLS)
|
|
76
|
+
|
|
77
|
+
io.string
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def encode_string(string, io = StringIO.new)
|
|
81
|
+
io.putc(QUOT)
|
|
82
|
+
string.chars do |c|
|
|
83
|
+
case c
|
|
84
|
+
when QUOT then io.print(ESC_QUOT)
|
|
85
|
+
else
|
|
86
|
+
io.putc(c)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
io.putc(QUOT)
|
|
90
|
+
|
|
91
|
+
io.string
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def encode_object(object, io = StringIO.new)
|
|
95
|
+
case object
|
|
96
|
+
when ::Hash then encode_hash(object, io)
|
|
97
|
+
when ::Array then encode_array(object, io)
|
|
98
|
+
when ::Set then encode_set(object, io)
|
|
99
|
+
when ::String then encode_string(object, io)
|
|
100
|
+
when ::Time then encode_timestamp(object, io)
|
|
101
|
+
when ::Numeric then encode_number(object, io)
|
|
102
|
+
when ::IPAddr then encode_inet(object, io)
|
|
103
|
+
when Uuid then encode_uuid(object, io)
|
|
104
|
+
when Tuple then encode_tuple(object, io)
|
|
105
|
+
when Time then encode_time(object, io)
|
|
106
|
+
when UDT then encode_udt(object, io)
|
|
107
|
+
when nil then io.print(NULL_STR)
|
|
108
|
+
when false then io.print(FALSE_STR)
|
|
109
|
+
when true then io.print(TRUE_STR)
|
|
110
|
+
else
|
|
111
|
+
raise ::ArgumentError, "unsupported type: #{object.inspect}"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
io.string
|
|
115
|
+
end
|
|
116
|
+
alias encode encode_object
|
|
117
|
+
|
|
118
|
+
def encode_time(time, io = StringIO.new)
|
|
119
|
+
encode_string(time.to_s, io)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def encode_udt(udt, io = StringIO.new)
|
|
123
|
+
encode_hash(udt.to_h, io)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def encode_timestamp(time, io = StringIO.new)
|
|
127
|
+
io.print(time.to_i)
|
|
128
|
+
io.string
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def encode_number(number, io = StringIO.new)
|
|
132
|
+
io.print(number)
|
|
133
|
+
io.string
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def encode_uuid(uuid, io = StringIO.new)
|
|
137
|
+
io.print(uuid)
|
|
138
|
+
io.string
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def encode_inet(inet, io = StringIO.new)
|
|
142
|
+
io.putc(QUOT)
|
|
143
|
+
io.print(inet)
|
|
144
|
+
io.putc(QUOT)
|
|
145
|
+
io.string
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def encode_tuple(tuple, io = StringIO.new)
|
|
149
|
+
first = true
|
|
150
|
+
|
|
151
|
+
io.putc(PRN_OPN)
|
|
152
|
+
tuple.each do |object|
|
|
153
|
+
if first
|
|
154
|
+
first = false
|
|
155
|
+
else
|
|
156
|
+
io.print(COMMA)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
encode_object(object, io)
|
|
160
|
+
end
|
|
161
|
+
io.putc(PRN_CLS)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def escape_name(name)
|
|
165
|
+
# If name only contains lower-case chars and it's not a reserved word, return it
|
|
166
|
+
# as-is. Otherwise, quote.
|
|
167
|
+
return name if name[LOWERCASE_REGEXP] == name && !RESERVED_WORDS.include?(name)
|
|
168
|
+
|
|
169
|
+
# Replace double-quotes within name with two double-quotes (if any) and surround the whole
|
|
170
|
+
# thing with double-quotes
|
|
171
|
+
DBL_QUOT + name.gsub('"', '""') + DBL_QUOT
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def guess_type(object)
|
|
175
|
+
case object
|
|
176
|
+
when ::String then Types.varchar
|
|
177
|
+
when ::Integer then object.size > 8 ? Types.varint : Types.bigint
|
|
178
|
+
when ::Float then Types.double
|
|
179
|
+
when ::BigDecimal then Types.decimal
|
|
180
|
+
when ::TrueClass then Types.boolean
|
|
181
|
+
when ::FalseClass then Types.boolean
|
|
182
|
+
when ::NilClass then Types.bigint
|
|
183
|
+
when Uuid then Types.uuid
|
|
184
|
+
when TimeUuid then Types.timeuuid
|
|
185
|
+
when ::IPAddr then Types.inet
|
|
186
|
+
when ::Time then Types.timestamp
|
|
187
|
+
when ::Hash
|
|
188
|
+
pair = object.first
|
|
189
|
+
Types.map(guess_type(pair[0]), guess_type(pair[1]))
|
|
190
|
+
when ::Array then Types.list(guess_type(object.first))
|
|
191
|
+
when ::Set then Types.set(guess_type(object.first))
|
|
192
|
+
when Tuple::Strict then Types.tuple(*object.types)
|
|
193
|
+
when Tuple then Types.tuple(*object.map {|v| guess_type(v)})
|
|
194
|
+
when UDT::Strict
|
|
195
|
+
Types.udt(object.keyspace, object.name, object.types)
|
|
196
|
+
when UDT
|
|
197
|
+
Types.udt('unknown', 'unknown', object.map {|k, v| [k, guess_type(v)]})
|
|
198
|
+
when Cassandra::CustomData then object.class.type
|
|
199
|
+
else
|
|
200
|
+
raise ::ArgumentError,
|
|
201
|
+
"Unable to guess the type of the argument: #{object.inspect}"
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def assert_type(type, value, message = nil, &block)
|
|
206
|
+
assert_instance_of(Cassandra::Type, type, message, &block)
|
|
207
|
+
return if value.nil?
|
|
208
|
+
type.assert(value, message, &block)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def assert_instance_of(kind, value, message = nil, &block)
|
|
212
|
+
unless value.is_a?(kind)
|
|
213
|
+
message = yield if block_given?
|
|
214
|
+
message ||= "value must be an instance of #{kind}, #{value.inspect} given"
|
|
215
|
+
|
|
216
|
+
raise ::ArgumentError, message
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def assert_instance_of_one_of(kinds, value, message = nil, &block)
|
|
221
|
+
unless kinds.any? {|kind| value.is_a?(kind)}
|
|
222
|
+
message = yield if block_given?
|
|
223
|
+
message ||= "value must be an instance of one of #{kinds.inspect}, " \
|
|
224
|
+
"#{value.inspect} given"
|
|
225
|
+
|
|
226
|
+
raise ::ArgumentError, message
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def assert_responds_to(method, value, message = nil, &block)
|
|
231
|
+
unless value.respond_to?(method)
|
|
232
|
+
message = yield if block_given?
|
|
233
|
+
message ||= "value #{value.inspect} must respond to #{method.inspect}, " \
|
|
234
|
+
"but doesn't"
|
|
235
|
+
|
|
236
|
+
raise ::ArgumentError, message
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def assert_responds_to_all(methods, value, message = nil, &block)
|
|
241
|
+
unless methods.all? {|method| value.respond_to?(method)}
|
|
242
|
+
message = yield if block_given?
|
|
243
|
+
message ||= "value #{value.inspect} must respond to all methods " \
|
|
244
|
+
"#{methods.inspect}, but doesn't"
|
|
245
|
+
|
|
246
|
+
raise ::ArgumentError, message
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def assert_not_empty(value, message = nil, &block)
|
|
251
|
+
if value.empty?
|
|
252
|
+
message = yield if block_given?
|
|
253
|
+
message ||= 'value cannot be empty'
|
|
254
|
+
|
|
255
|
+
raise ::ArgumentError, message
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def assert_file_exists(path, message = nil, &block)
|
|
260
|
+
unless ::File.exist?(path)
|
|
261
|
+
message = yield if block_given?
|
|
262
|
+
message ||= "expected file at #{path.inspect} to exist, but it doesn't"
|
|
263
|
+
|
|
264
|
+
raise ::ArgumentError, message
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def assert_one_of(range, value, message = nil, &block)
|
|
269
|
+
unless range.include?(value)
|
|
270
|
+
message = yield if block_given?
|
|
271
|
+
message ||= "value must be included in #{value.inspect}, #{value.inspect} given"
|
|
272
|
+
|
|
273
|
+
raise ::ArgumentError, message
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def assert_size(size, value, message = nil, &block)
|
|
278
|
+
unless value.size == size
|
|
279
|
+
message = yield if block_given?
|
|
280
|
+
message ||= "value #{value.inspect} must have size equal to " \
|
|
281
|
+
"#{size.inspect}, but doesn't"
|
|
282
|
+
|
|
283
|
+
raise ::ArgumentError, message
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def assert(condition, message = nil, &block)
|
|
288
|
+
unless condition
|
|
289
|
+
message = yield if block_given?
|
|
290
|
+
message ||= 'assertion failed'
|
|
291
|
+
|
|
292
|
+
raise ::ArgumentError, message
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def assert_equal(expected, actual, message = nil, &block)
|
|
297
|
+
unless expected == actual
|
|
298
|
+
message = yield if block_given?
|
|
299
|
+
message ||= "expected #{actual.inspect} to equal #{expected.inspect}"
|
|
300
|
+
|
|
301
|
+
raise ::ArgumentError, message
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
# @private
|
|
306
|
+
LOWERCASE_REGEXP = /[[:lower:]\_]*/
|
|
307
|
+
# @private
|
|
308
|
+
NULL_STR = 'null'.freeze
|
|
309
|
+
# @private
|
|
310
|
+
FALSE_STR = 'false'.freeze
|
|
311
|
+
# @private
|
|
312
|
+
TRUE_STR = 'true'.freeze
|
|
313
|
+
# @private
|
|
314
|
+
CRL_OPN = '{'.freeze
|
|
315
|
+
# @private
|
|
316
|
+
CRL_CLS = '}'.freeze
|
|
317
|
+
# @private
|
|
318
|
+
SQR_OPN = '['.freeze
|
|
319
|
+
# @private
|
|
320
|
+
SQR_CLS = ']'.freeze
|
|
321
|
+
# @private
|
|
322
|
+
COMMA = ', '.freeze
|
|
323
|
+
# @private
|
|
324
|
+
COLON = ': '.freeze
|
|
325
|
+
# @private
|
|
326
|
+
QUOT = "'".freeze
|
|
327
|
+
# @private
|
|
328
|
+
ESC_QUOT = "''".freeze
|
|
329
|
+
# @private
|
|
330
|
+
DBL_QUOT = '"'.freeze
|
|
331
|
+
# @private
|
|
332
|
+
PRN_OPN = '('.freeze
|
|
333
|
+
# @private
|
|
334
|
+
PRN_CLS = ')'.freeze
|
|
335
|
+
RESERVED_WORDS = Set.new(%w(
|
|
336
|
+
add
|
|
337
|
+
aggregate
|
|
338
|
+
all
|
|
339
|
+
allow
|
|
340
|
+
alter
|
|
341
|
+
and
|
|
342
|
+
apply
|
|
343
|
+
as
|
|
344
|
+
asc
|
|
345
|
+
ascii
|
|
346
|
+
authorize
|
|
347
|
+
batch
|
|
348
|
+
begin
|
|
349
|
+
bigint
|
|
350
|
+
blob
|
|
351
|
+
boolean
|
|
352
|
+
by
|
|
353
|
+
called
|
|
354
|
+
clustering
|
|
355
|
+
columnfamily
|
|
356
|
+
compact
|
|
357
|
+
contains
|
|
358
|
+
count
|
|
359
|
+
counter
|
|
360
|
+
create
|
|
361
|
+
custom
|
|
362
|
+
date
|
|
363
|
+
decimal
|
|
364
|
+
delete
|
|
365
|
+
desc
|
|
366
|
+
describe
|
|
367
|
+
distinct
|
|
368
|
+
double
|
|
369
|
+
drop
|
|
370
|
+
entries
|
|
371
|
+
execute
|
|
372
|
+
exists
|
|
373
|
+
filtering
|
|
374
|
+
finalfunc
|
|
375
|
+
float
|
|
376
|
+
from
|
|
377
|
+
frozen
|
|
378
|
+
full
|
|
379
|
+
function
|
|
380
|
+
functions
|
|
381
|
+
grant
|
|
382
|
+
if
|
|
383
|
+
in
|
|
384
|
+
index
|
|
385
|
+
inet
|
|
386
|
+
infinity
|
|
387
|
+
initcond
|
|
388
|
+
input
|
|
389
|
+
insert
|
|
390
|
+
int
|
|
391
|
+
into
|
|
392
|
+
is
|
|
393
|
+
json
|
|
394
|
+
key
|
|
395
|
+
keys
|
|
396
|
+
keyspace
|
|
397
|
+
keyspaces
|
|
398
|
+
language
|
|
399
|
+
limit
|
|
400
|
+
list
|
|
401
|
+
login
|
|
402
|
+
map
|
|
403
|
+
materialized
|
|
404
|
+
modify
|
|
405
|
+
nan
|
|
406
|
+
nologin
|
|
407
|
+
norecursive
|
|
408
|
+
nosuperuser
|
|
409
|
+
not
|
|
410
|
+
null
|
|
411
|
+
of
|
|
412
|
+
on
|
|
413
|
+
options
|
|
414
|
+
or
|
|
415
|
+
order
|
|
416
|
+
password
|
|
417
|
+
permission
|
|
418
|
+
permissions
|
|
419
|
+
primary
|
|
420
|
+
rename
|
|
421
|
+
replace
|
|
422
|
+
returns
|
|
423
|
+
revoke
|
|
424
|
+
role
|
|
425
|
+
roles
|
|
426
|
+
schema
|
|
427
|
+
select
|
|
428
|
+
set
|
|
429
|
+
sfunc
|
|
430
|
+
smallint
|
|
431
|
+
static
|
|
432
|
+
storage
|
|
433
|
+
stype
|
|
434
|
+
superuser
|
|
435
|
+
table
|
|
436
|
+
text
|
|
437
|
+
time
|
|
438
|
+
timestamp
|
|
439
|
+
timeuuid
|
|
440
|
+
tinyint
|
|
441
|
+
to
|
|
442
|
+
token
|
|
443
|
+
trigger
|
|
444
|
+
truncate
|
|
445
|
+
ttl
|
|
446
|
+
tuple
|
|
447
|
+
type
|
|
448
|
+
unlogged
|
|
449
|
+
update
|
|
450
|
+
use
|
|
451
|
+
user
|
|
452
|
+
users
|
|
453
|
+
using
|
|
454
|
+
uuid
|
|
455
|
+
values
|
|
456
|
+
varchar
|
|
457
|
+
varint
|
|
458
|
+
view
|
|
459
|
+
where
|
|
460
|
+
with
|
|
461
|
+
writetime
|
|
462
|
+
)).freeze
|
|
463
|
+
end
|
|
464
|
+
end
|