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,71 @@
|
|
|
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
|
+
module Execution
|
|
21
|
+
# @private
|
|
22
|
+
class ProfileManager
|
|
23
|
+
attr_reader :profiles
|
|
24
|
+
attr_reader :load_balancing_policies
|
|
25
|
+
|
|
26
|
+
def initialize(default_profile, profiles)
|
|
27
|
+
# default_profile is the default profile that we constructed internally. However, the user can override it
|
|
28
|
+
# with their own :default profile. If that happens, ignore the internally generated default profile.
|
|
29
|
+
|
|
30
|
+
profiles[:default] = default_profile unless profiles.key?(:default)
|
|
31
|
+
|
|
32
|
+
# Save off all of the load-balancing policies for easy access.
|
|
33
|
+
@load_balancing_policies = Set.new
|
|
34
|
+
profiles.each do |name, profile|
|
|
35
|
+
@load_balancing_policies << profile.load_balancing_policy
|
|
36
|
+
end
|
|
37
|
+
@profiles = profiles
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def default_profile
|
|
41
|
+
@profiles[:default]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def distance(host)
|
|
45
|
+
# Return the min distance to the host, as per each lbp.
|
|
46
|
+
distances = Set.new
|
|
47
|
+
@load_balancing_policies.each do |lbp|
|
|
48
|
+
distances.add(lbp.distance(host))
|
|
49
|
+
end
|
|
50
|
+
return :local if distances.include?(:local)
|
|
51
|
+
return :remote if distances.include?(:remote)
|
|
52
|
+
|
|
53
|
+
# Fall back to ignore the host.
|
|
54
|
+
:ignore
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# NOTE: It's only safe to call add_profile when setting up the cluster object. In particular,
|
|
58
|
+
# this is only ok before calling Driver#connect.
|
|
59
|
+
def add_profile(name, profile)
|
|
60
|
+
@profiles[name] = profile
|
|
61
|
+
@load_balancing_policies << profile.load_balancing_policy
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @private
|
|
65
|
+
def inspect
|
|
66
|
+
"#<#{self.class.name}:0x#{object_id.to_s(16)} " \
|
|
67
|
+
"profiles=#{@profiles.inspect}>"
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,192 @@
|
|
|
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
|
+
module Execution
|
|
21
|
+
class Trace
|
|
22
|
+
class Event
|
|
23
|
+
# @return [Cassandra::Uuid] event uuid
|
|
24
|
+
attr_reader :id
|
|
25
|
+
|
|
26
|
+
# @return [String] description of activity
|
|
27
|
+
attr_reader :activity
|
|
28
|
+
|
|
29
|
+
attr_reader :source
|
|
30
|
+
attr_reader :source_elapsed
|
|
31
|
+
attr_reader :thread
|
|
32
|
+
|
|
33
|
+
# @private
|
|
34
|
+
def initialize(id, activity, source, source_elapsed, thread)
|
|
35
|
+
@id = id
|
|
36
|
+
@activity = activity
|
|
37
|
+
@source = source
|
|
38
|
+
@source_elapsed = source_elapsed
|
|
39
|
+
@thread = thread
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @private
|
|
43
|
+
def ==(other)
|
|
44
|
+
other == @id
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
alias eql? ==
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
include MonitorMixin
|
|
51
|
+
|
|
52
|
+
# @return [Cassandra::Uuid] trace id
|
|
53
|
+
attr_reader :id
|
|
54
|
+
|
|
55
|
+
# @private
|
|
56
|
+
def initialize(id, client, load_balancing_policy)
|
|
57
|
+
@id = id
|
|
58
|
+
@client = client
|
|
59
|
+
@coordinator = nil
|
|
60
|
+
@duration = nil
|
|
61
|
+
@parameters = nil
|
|
62
|
+
@request = nil
|
|
63
|
+
@started_at = nil
|
|
64
|
+
@events = nil
|
|
65
|
+
@client_ip = nil
|
|
66
|
+
@loaded = false
|
|
67
|
+
@loaded_events = false
|
|
68
|
+
@load_balancing_policy = load_balancing_policy
|
|
69
|
+
|
|
70
|
+
mon_initialize
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Returns the ip of coordinator node. Typically the same as
|
|
74
|
+
# {Cassandra::Execution::Info#hosts}`.last`
|
|
75
|
+
#
|
|
76
|
+
# @return [IPAddr] ip of the coordinator node
|
|
77
|
+
def coordinator
|
|
78
|
+
load unless @loaded
|
|
79
|
+
|
|
80
|
+
@coordinator
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Returns the ip of the client node, the node that ran the driver
|
|
84
|
+
# instance that started tracing.
|
|
85
|
+
#
|
|
86
|
+
# @return [IPAddr, nil] ip of the client node running the driver
|
|
87
|
+
def client
|
|
88
|
+
load unless @loaded
|
|
89
|
+
|
|
90
|
+
@client_ip
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def duration
|
|
94
|
+
load unless @loaded
|
|
95
|
+
|
|
96
|
+
@duration
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def parameters
|
|
100
|
+
load unless @loaded
|
|
101
|
+
|
|
102
|
+
@parameters
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def request
|
|
106
|
+
load unless @loaded
|
|
107
|
+
|
|
108
|
+
@request
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def started_at
|
|
112
|
+
load unless @loaded
|
|
113
|
+
|
|
114
|
+
@started_at
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Returns all trace events
|
|
118
|
+
#
|
|
119
|
+
# @return [Array<Cassandra::Execution::Trace::Event>] events
|
|
120
|
+
def events
|
|
121
|
+
load_events unless @loaded_events
|
|
122
|
+
|
|
123
|
+
@events
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# @private
|
|
127
|
+
def inspect
|
|
128
|
+
"#<#{self.class.name}:0x#{object_id.to_s(16)} @id=#{@id.inspect}>"
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
private
|
|
132
|
+
|
|
133
|
+
# @private
|
|
134
|
+
SELECT_SESSION = 'SELECT * FROM system_traces.sessions WHERE session_id = %s'.freeze
|
|
135
|
+
# @private
|
|
136
|
+
SELECT_EVENTS = 'SELECT * FROM system_traces.events WHERE session_id = %s'.freeze
|
|
137
|
+
|
|
138
|
+
# @private
|
|
139
|
+
def load
|
|
140
|
+
synchronize do
|
|
141
|
+
return if @loaded
|
|
142
|
+
|
|
143
|
+
attempt = 1
|
|
144
|
+
data = @client.query(Statements::Simple.new(SELECT_SESSION % @id),
|
|
145
|
+
VOID_OPTIONS.override(load_balancing_policy: @load_balancing_policy)).get.first
|
|
146
|
+
|
|
147
|
+
while data.nil? && attempt <= 5
|
|
148
|
+
sleep(attempt * 0.4)
|
|
149
|
+
data = @client.query(Statements::Simple.new(SELECT_SESSION % @id),
|
|
150
|
+
VOID_OPTIONS.override(load_balancing_policy: @load_balancing_policy)).get.first
|
|
151
|
+
break if data
|
|
152
|
+
attempt += 1
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
raise ::RuntimeError, "unable to load trace #{@id}" if data.nil?
|
|
156
|
+
|
|
157
|
+
@coordinator = data['coordinator']
|
|
158
|
+
@duration = data['duration']
|
|
159
|
+
@parameters = data['parameters']
|
|
160
|
+
@request = data['request']
|
|
161
|
+
@started_at = data['started_at']
|
|
162
|
+
@client_ip = data['client']
|
|
163
|
+
@loaded = true
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
nil
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# @private
|
|
170
|
+
def load_events
|
|
171
|
+
synchronize do
|
|
172
|
+
return if @loaded_events
|
|
173
|
+
|
|
174
|
+
@events = []
|
|
175
|
+
|
|
176
|
+
@client.query(Statements::Simple.new(SELECT_EVENTS % @id),
|
|
177
|
+
VOID_OPTIONS.override(load_balancing_policy: @load_balancing_policy)).get.each do |row|
|
|
178
|
+
@events << Event.new(row['event_id'],
|
|
179
|
+
row['activity'],
|
|
180
|
+
row['source'],
|
|
181
|
+
row['source_elapsed'],
|
|
182
|
+
row['thread'])
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
@events.freeze
|
|
186
|
+
|
|
187
|
+
@loaded_events = true
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
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 Executors
|
|
22
|
+
class ThreadPool
|
|
23
|
+
# @private
|
|
24
|
+
class Task
|
|
25
|
+
def initialize(*args, &block)
|
|
26
|
+
@args = args
|
|
27
|
+
@block = block
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def run
|
|
31
|
+
@block.call(*@args)
|
|
32
|
+
rescue ::Exception
|
|
33
|
+
ensure
|
|
34
|
+
@args = @block = nil
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
include MonitorMixin
|
|
39
|
+
|
|
40
|
+
def initialize(size)
|
|
41
|
+
mon_initialize
|
|
42
|
+
|
|
43
|
+
@cond = new_cond
|
|
44
|
+
@tasks = ::Array.new
|
|
45
|
+
@waiting = 0
|
|
46
|
+
@term = false
|
|
47
|
+
@pool = ::Array.new(size, &method(:spawn_thread))
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def execute(*args, &block)
|
|
51
|
+
synchronize do
|
|
52
|
+
return if @term
|
|
53
|
+
|
|
54
|
+
@tasks << Task.new(*args, &block)
|
|
55
|
+
@cond.signal if @waiting > 0
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
nil
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def shutdown
|
|
62
|
+
execute do
|
|
63
|
+
synchronize do
|
|
64
|
+
@term = true
|
|
65
|
+
@cond.broadcast if @waiting > 0
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
nil
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
def spawn_thread(i)
|
|
75
|
+
Thread.new(&method(:run))
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def run
|
|
79
|
+
Thread.current.abort_on_exception = true
|
|
80
|
+
|
|
81
|
+
loop do
|
|
82
|
+
tasks = nil
|
|
83
|
+
|
|
84
|
+
synchronize do
|
|
85
|
+
@waiting += 1
|
|
86
|
+
@cond.wait while !@term && @tasks.empty?
|
|
87
|
+
@waiting -= 1
|
|
88
|
+
|
|
89
|
+
return if @tasks.empty?
|
|
90
|
+
|
|
91
|
+
tasks = @tasks
|
|
92
|
+
@tasks = ::Array.new
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
tasks.each(&:run).clear
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
class SameThread
|
|
101
|
+
def execute(*args, &block)
|
|
102
|
+
yield(*args)
|
|
103
|
+
nil
|
|
104
|
+
rescue ::Exception
|
|
105
|
+
nil
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def shutdown
|
|
109
|
+
nil
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,156 @@
|
|
|
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
|
+
# Represents a cassandra user defined function
|
|
21
|
+
# @see Cassandra::Keyspace#each_function
|
|
22
|
+
# @see Cassandra::Keyspace#function
|
|
23
|
+
# @see Cassandra::Keyspace#has_function?
|
|
24
|
+
class Function
|
|
25
|
+
# @private
|
|
26
|
+
attr_reader :keyspace
|
|
27
|
+
# @return [String] function name
|
|
28
|
+
attr_reader :name
|
|
29
|
+
# @return [String] function language
|
|
30
|
+
attr_reader :language
|
|
31
|
+
# @return [Cassandra::Type] function return type
|
|
32
|
+
attr_reader :type
|
|
33
|
+
# @return [String] function body
|
|
34
|
+
attr_reader :body
|
|
35
|
+
|
|
36
|
+
# @private
|
|
37
|
+
def initialize(keyspace, name, language, type, arguments, body, called_on_null)
|
|
38
|
+
@keyspace = keyspace
|
|
39
|
+
@name = name
|
|
40
|
+
@language = language
|
|
41
|
+
@type = type
|
|
42
|
+
@arguments = arguments
|
|
43
|
+
@body = body
|
|
44
|
+
@called_on_null = called_on_null
|
|
45
|
+
|
|
46
|
+
# Build up an arguments hash keyed on arg-name.
|
|
47
|
+
@arguments_hash = @arguments.each_with_object({}) do |arg, h|
|
|
48
|
+
h[arg.name] = arg
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @return [Boolean] whether this function will be called on null input
|
|
53
|
+
def called_on_null?
|
|
54
|
+
@called_on_null
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# @param name [String] argument name
|
|
58
|
+
# @return [Boolean] whether this function has a given argument
|
|
59
|
+
def has_argument?(name)
|
|
60
|
+
@arguments_hash.key?(name)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# @param name [String] argument name
|
|
64
|
+
# @return [Cassandra::Argument, nil] an argument or nil
|
|
65
|
+
def argument(name)
|
|
66
|
+
@arguments_hash[name]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Yield or enumerate each argument defined in this function
|
|
70
|
+
# @overload each_argument
|
|
71
|
+
# @yieldparam argument [Cassandra::Argument] current argument
|
|
72
|
+
# @return [Cassandra::Table] self
|
|
73
|
+
# @overload each_argument
|
|
74
|
+
# @return [Array<Cassandra::Argument>] a list of arguments
|
|
75
|
+
def each_argument(&block)
|
|
76
|
+
if block_given?
|
|
77
|
+
@arguments.each(&block)
|
|
78
|
+
self
|
|
79
|
+
else
|
|
80
|
+
# We return a dup of the arguments so that the caller can manipulate
|
|
81
|
+
# the array however they want without affecting the source.
|
|
82
|
+
@arguments.dup
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
alias arguments each_argument
|
|
86
|
+
|
|
87
|
+
# Get the list of argument types for this function.
|
|
88
|
+
# @return [Array<Cassandra::Type>] a list of argument types.
|
|
89
|
+
def argument_types
|
|
90
|
+
@arguments.map(&:type)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# @private
|
|
94
|
+
def eql?(other)
|
|
95
|
+
other.is_a?(Function) && \
|
|
96
|
+
@keyspace == other.keyspace && \
|
|
97
|
+
@name == other.name && \
|
|
98
|
+
@language == other.language && \
|
|
99
|
+
@type == other.type && \
|
|
100
|
+
@arguments == other.arguments && \
|
|
101
|
+
@body == other.body && \
|
|
102
|
+
@called_on_null == other.called_on_null?
|
|
103
|
+
end
|
|
104
|
+
alias == eql?
|
|
105
|
+
|
|
106
|
+
# @private
|
|
107
|
+
def hash
|
|
108
|
+
@hash ||= begin
|
|
109
|
+
h = 17
|
|
110
|
+
h = 31 * h + @keyspace.hash
|
|
111
|
+
h = 31 * h + @name.hash
|
|
112
|
+
h = 31 * h + @language.hash
|
|
113
|
+
h = 31 * h + @type.hash
|
|
114
|
+
h = 31 * h + @arguments.hash
|
|
115
|
+
h = 31 * h + @body.hash
|
|
116
|
+
h = 31 * h + @called_on_null.hash
|
|
117
|
+
h
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# @private
|
|
122
|
+
def inspect
|
|
123
|
+
"#<Cassandra::Function:0x#{object_id.to_s(16)} " \
|
|
124
|
+
"@keyspace=#{@keyspace.inspect}, " \
|
|
125
|
+
"@name=#{@name.inspect}, " \
|
|
126
|
+
"@language=#{@language.inspect}, " \
|
|
127
|
+
"@type=#{@type.inspect}, " \
|
|
128
|
+
"@arguments=#{@arguments.inspect} " \
|
|
129
|
+
"@body=#{@body.inspect}>"
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# @return [String] a cql representation of this function
|
|
133
|
+
def to_cql
|
|
134
|
+
cql = "CREATE FUNCTION #{Util.escape_name(@keyspace)}.#{Util.escape_name(@name)}("
|
|
135
|
+
first = true
|
|
136
|
+
@arguments.each do |argument|
|
|
137
|
+
if first
|
|
138
|
+
first = false
|
|
139
|
+
else
|
|
140
|
+
cql << ', '
|
|
141
|
+
end
|
|
142
|
+
cql << "#{argument.name} #{argument.type}"
|
|
143
|
+
end
|
|
144
|
+
cql << ')'
|
|
145
|
+
cql << if @called_on_null
|
|
146
|
+
"\n CALLED ON NULL INPUT"
|
|
147
|
+
else
|
|
148
|
+
"\n RETURNS NULL ON NULL INPUT"
|
|
149
|
+
end
|
|
150
|
+
cql << "\n RETURNS #{@type}"
|
|
151
|
+
cql << "\n LANGUAGE #{@language}"
|
|
152
|
+
cql << "\n AS $$#{@body}$$"
|
|
153
|
+
cql << ';'
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|