trino-client 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/CODEOWNERS +1 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +18 -0
- data/.github/workflows/ruby.yml +30 -0
- data/.gitignore +4 -0
- data/ChangeLog.md +168 -0
- data/Gemfile +7 -0
- data/LICENSE +202 -0
- data/README.md +131 -0
- data/Rakefile +45 -0
- data/lib/trino-client.rb +1 -0
- data/lib/trino/client.rb +23 -0
- data/lib/trino/client/client.rb +78 -0
- data/lib/trino/client/errors.rb +46 -0
- data/lib/trino/client/faraday_client.rb +242 -0
- data/lib/trino/client/model_versions/0.149.rb +1683 -0
- data/lib/trino/client/model_versions/0.153.rb +1719 -0
- data/lib/trino/client/model_versions/0.173.rb +1685 -0
- data/lib/trino/client/model_versions/0.178.rb +1964 -0
- data/lib/trino/client/model_versions/0.205.rb +2169 -0
- data/lib/trino/client/model_versions/303.rb +2574 -0
- data/lib/trino/client/model_versions/316.rb +2595 -0
- data/lib/trino/client/model_versions/351.rb +2726 -0
- data/lib/trino/client/models.rb +38 -0
- data/lib/trino/client/query.rb +144 -0
- data/lib/trino/client/statement_client.rb +279 -0
- data/lib/trino/client/version.rb +20 -0
- data/modelgen/model_versions.rb +280 -0
- data/modelgen/modelgen.rb +119 -0
- data/modelgen/models.rb +31 -0
- data/modelgen/trino_models.rb +270 -0
- data/release.rb +56 -0
- data/spec/basic_query_spec.rb +82 -0
- data/spec/client_spec.rb +75 -0
- data/spec/gzip_spec.rb +40 -0
- data/spec/model_spec.rb +35 -0
- data/spec/spec_helper.rb +42 -0
- data/spec/statement_client_spec.rb +637 -0
- data/spec/tpch/q01.sql +21 -0
- data/spec/tpch/q02.sql +43 -0
- data/spec/tpch_query_spec.rb +41 -0
- data/trino-client.gemspec +31 -0
- metadata +211 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
#
|
2
|
+
# Trino client for Ruby
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
module Trino
|
17
|
+
module Client
|
18
|
+
VERSION = "1.0.0"
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,280 @@
|
|
1
|
+
#
|
2
|
+
# Trino client for Ruby
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
module Trino::Client::ModelVersions
|
17
|
+
|
18
|
+
####
|
19
|
+
## lib/trino/client/model_versions/*.rb is automatically generated using "rake modelgen:all" command.
|
20
|
+
## You should not edit this file directly. To modify the class definitions, edit
|
21
|
+
## modelgen/model_versions.rb file and run "rake modelgen:all".
|
22
|
+
##
|
23
|
+
|
24
|
+
module V<%= @model_version.gsub(".", "_") %>
|
25
|
+
class Base < Struct
|
26
|
+
class << self
|
27
|
+
alias_method :new_struct, :new
|
28
|
+
|
29
|
+
def new(*args)
|
30
|
+
new_struct(*args) do
|
31
|
+
# make it immutable
|
32
|
+
undef_method :"[]="
|
33
|
+
members.each do |m|
|
34
|
+
undef_method :"#{m}="
|
35
|
+
end
|
36
|
+
|
37
|
+
# replace constructor to receive hash instead of array
|
38
|
+
alias_method :initialize_struct, :initialize
|
39
|
+
|
40
|
+
def initialize(params={})
|
41
|
+
initialize_struct(*members.map {|m| params[m] })
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class StageId < String
|
49
|
+
def initialize(str)
|
50
|
+
super
|
51
|
+
splitted = split('.', 2)
|
52
|
+
@query_id = splitted[0]
|
53
|
+
@id = splitted[1]
|
54
|
+
end
|
55
|
+
|
56
|
+
attr_reader :query_id, :id
|
57
|
+
end
|
58
|
+
|
59
|
+
class TaskId < String
|
60
|
+
def initialize(str)
|
61
|
+
super
|
62
|
+
splitted = split('.', 3)
|
63
|
+
@stage_id = StageId.new("#{splitted[0]}.#{splitted[1]}")
|
64
|
+
@query_id = @stage_id.query_id
|
65
|
+
@id = splitted[2]
|
66
|
+
end
|
67
|
+
|
68
|
+
attr_reader :query_id, :stage_id, :id
|
69
|
+
end
|
70
|
+
|
71
|
+
class Lifespan < String
|
72
|
+
def initialize(str)
|
73
|
+
super
|
74
|
+
if str == "TaskWide"
|
75
|
+
@grouped = false
|
76
|
+
@group_id = 0
|
77
|
+
else
|
78
|
+
# Group1
|
79
|
+
@grouped = true
|
80
|
+
@group_id = str[5..-1].to_i
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
attr_reader :grouped, :group_id
|
85
|
+
end
|
86
|
+
|
87
|
+
class ConnectorSession < Hash
|
88
|
+
def initialize(hash)
|
89
|
+
super()
|
90
|
+
merge!(hash)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
module PlanNode
|
95
|
+
def self.decode(hash)
|
96
|
+
unless hash.is_a?(Hash)
|
97
|
+
raise TypeError, "Can't convert #{hash.class} to Hash"
|
98
|
+
end
|
99
|
+
model_class = case hash["@type"]
|
100
|
+
when "output" then OutputNode
|
101
|
+
when "project" then ProjectNode
|
102
|
+
when "tablescan" then TableScanNode
|
103
|
+
when "values" then ValuesNode
|
104
|
+
when "aggregation" then AggregationNode
|
105
|
+
when "markDistinct" then MarkDistinctNode
|
106
|
+
when "filter" then FilterNode
|
107
|
+
when "window" then WindowNode
|
108
|
+
when "rowNumber" then RowNumberNode
|
109
|
+
when "topnRowNumber" then TopNRowNumberNode
|
110
|
+
when "limit" then LimitNode
|
111
|
+
when "distinctlimit" then DistinctLimitNode
|
112
|
+
when "topn" then TopNNode
|
113
|
+
when "sample" then SampleNode
|
114
|
+
when "sort" then SortNode
|
115
|
+
when "remoteSource" then RemoteSourceNode
|
116
|
+
when "join" then JoinNode
|
117
|
+
when "semijoin" then SemiJoinNode
|
118
|
+
when "spatialjoin" then SpatialJoinNode
|
119
|
+
when "indexjoin" then IndexJoinNode
|
120
|
+
when "indexsource" then IndexSourceNode
|
121
|
+
when "tablewriter" then TableWriterNode
|
122
|
+
when "delete" then DeleteNode
|
123
|
+
when "metadatadelete" then MetadataDeleteNode
|
124
|
+
when "tablecommit" then TableFinishNode
|
125
|
+
when "unnest" then UnnestNode
|
126
|
+
when "exchange" then ExchangeNode
|
127
|
+
when "union" then UnionNode
|
128
|
+
when "intersect" then IntersectNode
|
129
|
+
when "scalar" then EnforceSingleRowNode
|
130
|
+
when "groupid" then GroupIdNode
|
131
|
+
when "explainAnalyze" then ExplainAnalyzeNode
|
132
|
+
when "apply" then ApplyNode
|
133
|
+
when "assignUniqueId" then AssignUniqueId
|
134
|
+
when "correlatedJoin" then CorrelatedJoinNode
|
135
|
+
when "statisticsWriterNode" then StatisticsWriterNode
|
136
|
+
end
|
137
|
+
if model_class
|
138
|
+
node = model_class.decode(hash)
|
139
|
+
class << node
|
140
|
+
attr_accessor :plan_node_type
|
141
|
+
end
|
142
|
+
node.plan_node_type = hash['@type']
|
143
|
+
node
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# io.airlift.stats.Distribution.DistributionSnapshot
|
149
|
+
class << DistributionSnapshot =
|
150
|
+
Base.new(:max_error, :count, :total, :p01, :p05, :p10, :p25, :p50, :p75, :p90, :p95, :p99, :min, :max)
|
151
|
+
def decode(hash)
|
152
|
+
unless hash.is_a?(Hash)
|
153
|
+
raise TypeError, "Can't convert #{hash.class} to Hash"
|
154
|
+
end
|
155
|
+
obj = allocate
|
156
|
+
obj.send(:initialize_struct,
|
157
|
+
hash["maxError"],
|
158
|
+
hash["count"],
|
159
|
+
hash["total"],
|
160
|
+
hash["p01"],
|
161
|
+
hash["p05"],
|
162
|
+
hash["p10"],
|
163
|
+
hash["p25"],
|
164
|
+
hash["p50"],
|
165
|
+
hash["p75"],
|
166
|
+
hash["p90"],
|
167
|
+
hash["p95"],
|
168
|
+
hash["p99"],
|
169
|
+
hash["min"],
|
170
|
+
hash["max"],
|
171
|
+
)
|
172
|
+
obj
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# This is a hybrid of JoinNode.EquiJoinClause and IndexJoinNode.EquiJoinClause
|
177
|
+
class << EquiJoinClause =
|
178
|
+
Base.new(:left, :right, :probe, :index)
|
179
|
+
def decode(hash)
|
180
|
+
unless hash.is_a?(Hash)
|
181
|
+
raise TypeError, "Can't convert #{hash.class} to Hash"
|
182
|
+
end
|
183
|
+
obj = allocate
|
184
|
+
obj.send(:initialize_struct,
|
185
|
+
hash["left"],
|
186
|
+
hash["right"],
|
187
|
+
hash["probe"],
|
188
|
+
hash["index"],
|
189
|
+
)
|
190
|
+
obj
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
class << WriterTarget =
|
195
|
+
Base.new(:type, :handle)
|
196
|
+
def decode(hash)
|
197
|
+
unless hash.is_a?(Hash)
|
198
|
+
raise TypeError, "Can't convert #{hash.class} to Hash"
|
199
|
+
end
|
200
|
+
obj = allocate
|
201
|
+
model_class = case hash["@type"]
|
202
|
+
when "CreateTarget" then CreateTarget
|
203
|
+
when "InsertTarget" then InsertTarget
|
204
|
+
when "DeleteTarget" then DeleteTarget
|
205
|
+
end
|
206
|
+
if model_class
|
207
|
+
model_class.decode(hash)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
class << WriteStatisticsTarget =
|
213
|
+
Base.new(:type, :handle)
|
214
|
+
def decode(hash)
|
215
|
+
unless hash.is_a?(Hash)
|
216
|
+
raise TypeError, "Can't convert #{hash.class} to Hash"
|
217
|
+
end
|
218
|
+
obj = allocate
|
219
|
+
model_class = case hash["@type"]
|
220
|
+
when "WriteStatisticsHandle" then WriteStatisticsHandle
|
221
|
+
end
|
222
|
+
if model_class
|
223
|
+
model_class.decode(hash)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# Inner classes
|
229
|
+
module OperatorInfo
|
230
|
+
def self.decode(hash)
|
231
|
+
unless hash.is_a?(Hash)
|
232
|
+
raise TypeError, "Can't convert #{hash.class} to Hash"
|
233
|
+
end
|
234
|
+
model_class = case hash["@type"]
|
235
|
+
when "exchangeClientStatus" then ExchangeClientStatus
|
236
|
+
when "localExchangeBuffer" then LocalExchangeBufferInfo
|
237
|
+
when "tableFinish" then TableFinishInfo
|
238
|
+
when "splitOperator" then SplitOperatorInfo
|
239
|
+
when "hashCollisionsInfo" then HashCollisionsInfo
|
240
|
+
when "partitionedOutput" then PartitionedOutputInfo
|
241
|
+
when "joinOperatorInfo" then JoinOperatorInfo
|
242
|
+
when "windowInfo" then WindowInfo
|
243
|
+
when "tableWriter" then TableWriterInfo
|
244
|
+
end
|
245
|
+
if model_class
|
246
|
+
model_class.decode(hash)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
class << HashCollisionsInfo =
|
252
|
+
Base.new(:weighted_hash_collisions, :weighted_sum_squared_hash_collisions, :weighted_expectedHash_collisions)
|
253
|
+
def decode(hash)
|
254
|
+
unless hash.is_a?(Hash)
|
255
|
+
raise TypeError, "Can't convert #{hash.class} to Hash"
|
256
|
+
end
|
257
|
+
obj = allocate
|
258
|
+
obj.send(:initialize_struct,
|
259
|
+
hash["weighted_hash_collisions"],
|
260
|
+
hash["weighted_sum_squared_hash_collisions"],
|
261
|
+
hash["weighted_expectedHash_collisions"]
|
262
|
+
)
|
263
|
+
obj
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
class ResourceGroupId < Array
|
268
|
+
def initialize(array)
|
269
|
+
super()
|
270
|
+
concat(array)
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
##
|
275
|
+
# Those model classes are automatically generated
|
276
|
+
#
|
277
|
+
|
278
|
+
<%= @contents %>
|
279
|
+
end
|
280
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
|
2
|
+
if ARGV.length != 4
|
3
|
+
puts "usage: <model-version> <trino-source-dir> <template.erb> <output.rb>"
|
4
|
+
exit 1
|
5
|
+
end
|
6
|
+
|
7
|
+
model_version, source_dir, template_path, output_path = *ARGV
|
8
|
+
|
9
|
+
require_relative 'trino_models'
|
10
|
+
|
11
|
+
require 'erb'
|
12
|
+
erb = ERB.new(File.read(template_path))
|
13
|
+
|
14
|
+
source_path = source_dir
|
15
|
+
|
16
|
+
predefined_simple_classes = %w[StageId TaskId Lifespan ConnectorSession ResourceGroupId]
|
17
|
+
predefined_models = %w[DistributionSnapshot PlanNode EquiJoinClause WriterTarget WriteStatisticsTarget OperatorInfo HashCollisionsInfo]
|
18
|
+
|
19
|
+
assume_primitive = %w[Object Type Long Symbol QueryId PlanNodeId PlanFragmentId MemoryPoolId TransactionId URI Duration DataSize DateTime ColumnHandle ConnectorTableHandle ConnectorOutputTableHandle ConnectorIndexHandle ConnectorColumnHandle ConnectorInsertTableHandle ConnectorTableLayoutHandle Expression FunctionCall TimeZoneKey Locale TypeSignature Frame TupleDomain<ColumnHandle> SerializableNativeValue ConnectorTransactionHandle OutputBufferId ConnectorPartitioningHandle NullableValue ConnectorId HostAddress JsonNode Node CatalogName QualifiedObjectName FunctionId DynamicFilterId Instant]
|
20
|
+
enum_types = %w[QueryState StageState TaskState QueueState PlanDistribution OutputPartitioning Step SortOrder BufferState NullPartitioning BlockedReason ParameterKind FunctionKind PartitionFunctionHandle Scope ErrorType DistributionType PipelineExecutionStrategy JoinType ExchangeNode.Type ColumnStatisticType TableStatisticType StageExecutionStrategy SemanticErrorCode QueryType]
|
21
|
+
|
22
|
+
root_models = %w[QueryResults QueryInfo BasicQueryInfo] + %w[
|
23
|
+
OutputNode
|
24
|
+
ProjectNode
|
25
|
+
TableScanNode
|
26
|
+
ValuesNode
|
27
|
+
AggregationNode
|
28
|
+
MarkDistinctNode
|
29
|
+
FilterNode
|
30
|
+
WindowNode
|
31
|
+
RowNumberNode
|
32
|
+
TopNRowNumberNode
|
33
|
+
LimitNode
|
34
|
+
DistinctLimitNode
|
35
|
+
TopNNode
|
36
|
+
SampleNode
|
37
|
+
SortNode
|
38
|
+
RemoteSourceNode
|
39
|
+
JoinNode
|
40
|
+
SemiJoinNode
|
41
|
+
SpatialJoinNode
|
42
|
+
IndexJoinNode
|
43
|
+
IndexSourceNode
|
44
|
+
TableWriterNode
|
45
|
+
DeleteNode
|
46
|
+
TableFinishNode
|
47
|
+
UnnestNode
|
48
|
+
ExchangeNode
|
49
|
+
UnionNode
|
50
|
+
IntersectNode
|
51
|
+
EnforceSingleRowNode
|
52
|
+
GroupIdNode
|
53
|
+
ExplainAnalyzeNode
|
54
|
+
ApplyNode
|
55
|
+
AssignUniqueId
|
56
|
+
CorrelatedJoinNode
|
57
|
+
StatisticsWriterNode
|
58
|
+
] + %w[
|
59
|
+
ExchangeClientStatus
|
60
|
+
LocalExchangeBufferInfo
|
61
|
+
TableFinishInfo
|
62
|
+
SplitOperatorInfo
|
63
|
+
PartitionedOutputInfo
|
64
|
+
JoinOperatorInfo
|
65
|
+
WindowInfo
|
66
|
+
TableWriterInfo
|
67
|
+
]
|
68
|
+
|
69
|
+
name_mapping = Hash[*%w[
|
70
|
+
StatementStats StageStats ClientStageStats
|
71
|
+
ClientStageStats StageStats ClientStageStats
|
72
|
+
QueryResults Column ClientColumn
|
73
|
+
].each_slice(3).map { |x, y, z| [[x,y], z] }.flatten(1)]
|
74
|
+
|
75
|
+
path_mapping = Hash[*%w[
|
76
|
+
ClientColumn client/trino-client/src/main/java/io/trino/client/Column.java
|
77
|
+
ClientStageStats client/trino-client/src/main/java/io/trino/client/StageStats.java
|
78
|
+
Column core/trino-main/src/main/java/io/trino/execution/Column.java
|
79
|
+
QueryStats core/trino-main/src/main/java/io/trino/execution/QueryStats.java
|
80
|
+
StageStats core/trino-main/src/main/java/io/trino/execution/StageStats.java
|
81
|
+
PartitionedOutputInfo core/trino-main/src/main/java/io/trino/operator/PartitionedOutputOperator.java
|
82
|
+
TableWriterInfo core/trino-main/src/main/java/io/trino/operator/TableWriterOperator.java
|
83
|
+
TableInfo core/trino-main/src/main/java/io/trino/execution/TableInfo.java
|
84
|
+
DynamicFiltersStats core/trino-main/src/main/java/io/trino/server/DynamicFilterService.java
|
85
|
+
].map.with_index { |v,i| i % 2 == 0 ? v : (source_path + "/" + v) }]
|
86
|
+
|
87
|
+
# model => [ [key,nullable,type], ... ]
|
88
|
+
extra_fields = {
|
89
|
+
'QueryInfo' => [['finalQueryInfo', nil, 'boolean']]
|
90
|
+
}
|
91
|
+
|
92
|
+
analyzer = TrinoModels::ModelAnalyzer.new(
|
93
|
+
source_path,
|
94
|
+
skip_models: predefined_models + predefined_simple_classes + assume_primitive + enum_types,
|
95
|
+
path_mapping: path_mapping,
|
96
|
+
name_mapping: name_mapping,
|
97
|
+
extra_fields: extra_fields
|
98
|
+
)
|
99
|
+
analyzer.analyze(root_models)
|
100
|
+
models = analyzer.models
|
101
|
+
skipped_models = analyzer.skipped_models
|
102
|
+
|
103
|
+
formatter = TrinoModels::ModelFormatter.new(
|
104
|
+
base_indent_count: 2,
|
105
|
+
struct_class: "Base",
|
106
|
+
special_struct_initialize_method: "initialize_struct",
|
107
|
+
primitive_types: assume_primitive,
|
108
|
+
skip_types: skipped_models,
|
109
|
+
simple_classes: predefined_simple_classes,
|
110
|
+
enum_types: enum_types,
|
111
|
+
)
|
112
|
+
formatter.format(models)
|
113
|
+
|
114
|
+
@contents = formatter.contents
|
115
|
+
@model_version = model_version
|
116
|
+
|
117
|
+
data = erb.result
|
118
|
+
File.write(output_path, data)
|
119
|
+
|
data/modelgen/models.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#
|
2
|
+
# Trino client for Ruby
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
module Trino::Client
|
17
|
+
|
18
|
+
####
|
19
|
+
## lib/trino/client/models.rb is automatically generated using "rake modelgen:latest" command.
|
20
|
+
## You should not edit this file directly. To modify the class definitions, edit
|
21
|
+
## modelgen/models.rb file and run "rake modelgen:latest".
|
22
|
+
##
|
23
|
+
|
24
|
+
module ModelVersions
|
25
|
+
end
|
26
|
+
<% @versions.each do |ver| %>
|
27
|
+
require 'trino/client/model_versions/<%= ver %>.rb'<% end %>
|
28
|
+
|
29
|
+
Models = ModelVersions::V<%= @latest_version.gsub(".", "_") %>
|
30
|
+
|
31
|
+
end
|