trino-client 1.0.0
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/.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
data/README.md
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
# Trino client library for Ruby
|
2
|
+
|
3
|
+
[](https://travis-ci.org/treasure-data/trino-client-ruby) [](https://rubygems.org/gems/trino-client) [](https://rubygems.org/gems/trino-client) []()
|
4
|
+
|
5
|
+
Trino is a distributed SQL query engine for big data:
|
6
|
+
https://trino.io/
|
7
|
+
|
8
|
+
This is a client library for Ruby to run queries on Trino.
|
9
|
+
|
10
|
+
## Example
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
require 'trino-client'
|
14
|
+
|
15
|
+
# create a client object:
|
16
|
+
client = Trino::Client.new(
|
17
|
+
server: "localhost:8880", # required option
|
18
|
+
ssl: {verify: false},
|
19
|
+
catalog: "native",
|
20
|
+
schema: "default",
|
21
|
+
user: "frsyuki",
|
22
|
+
password: "********",
|
23
|
+
time_zone: "US/Pacific",
|
24
|
+
language: "English",
|
25
|
+
properties: {
|
26
|
+
"hive.force_local_scheduling": true,
|
27
|
+
"raptor.reader_stream_buffer_size": "32MB"
|
28
|
+
},
|
29
|
+
http_proxy: "proxy.example.com:8080",
|
30
|
+
http_debug: true
|
31
|
+
)
|
32
|
+
|
33
|
+
# run a query and get results as an array of arrays:
|
34
|
+
columns, rows = client.run("select * from sys.node")
|
35
|
+
rows.each {|row|
|
36
|
+
p row # row is an array
|
37
|
+
}
|
38
|
+
|
39
|
+
# run a query and get results as an array of hashes:
|
40
|
+
results = client.run_with_names("select alpha, 1 AS beta from tablename")
|
41
|
+
results.each {|row|
|
42
|
+
p row['alpha'] # access by name
|
43
|
+
p row['beta']
|
44
|
+
p row.values[0] # access by index
|
45
|
+
p row.values[1]
|
46
|
+
}
|
47
|
+
|
48
|
+
# run a query and fetch results streamingly:
|
49
|
+
client.query("select * from sys.node") do |q|
|
50
|
+
# get columns:
|
51
|
+
q.columns.each {|column|
|
52
|
+
puts "column: #{column.name}.#{column.type}"
|
53
|
+
}
|
54
|
+
|
55
|
+
# get query results. it feeds more rows until
|
56
|
+
# query execution finishes:
|
57
|
+
q.each_row {|row|
|
58
|
+
p row # row is an array
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
# killing a query
|
63
|
+
query = client.query("select * from sys.node")
|
64
|
+
query_id = query.query_info.query_id
|
65
|
+
query.each_row {|row| ... } # when a thread is processing the query,
|
66
|
+
client.kill(query_id) # another thread / process can kill the query.
|
67
|
+
```
|
68
|
+
|
69
|
+
## Build models
|
70
|
+
|
71
|
+
```
|
72
|
+
$ bundle exec rake modelgen:latest
|
73
|
+
```
|
74
|
+
|
75
|
+
## Options
|
76
|
+
|
77
|
+
* **server** sets address (and port) of a Trino coordinator server.
|
78
|
+
* **ssl** enables https.
|
79
|
+
* Setting `true` enables SSL and verifies server certificate using system's built-in certificates.
|
80
|
+
* Setting `{verify: false}` enables SSL but doesn't verify server certificate.
|
81
|
+
* Setting a Hash object enables SSL and verify server certificate with options:
|
82
|
+
* **ca_file**: path of a CA certification file in PEM format
|
83
|
+
* **ca_path**: path of a CA certification directory containing certifications in PEM format
|
84
|
+
* **cert_store**: a `OpenSSL::X509::Store` object used for verification
|
85
|
+
* **client_cert**: a `OpenSSL::X509::Certificate` object as client certificate
|
86
|
+
* **client_key**: a `OpenSSL::PKey::RSA` or `OpenSSL::PKey::DSA` object used for client certificate
|
87
|
+
* **catalog** sets catalog (connector) name of Trino such as `hive-cdh4`, `hive-hadoop1`, etc.
|
88
|
+
* **schema** sets default schema name of Trino. You need to use qualified name like `FROM myschema.table1` to use non-default schemas.
|
89
|
+
* **source** sets source name to connect to a Trino. This name is shown on Trino web interface.
|
90
|
+
* **client_info** sets client info to queries. It can be a string to pass a raw string, or an object that can be encoded to JSON.
|
91
|
+
* **client_tags** sets client tags to queries. It needs to be an array of strings. The tags are shown on web interface.
|
92
|
+
* **user** sets user name to connect to a Trino.
|
93
|
+
* **password** sets a password to connect to Trino using basic auth.
|
94
|
+
* **time_zone** sets time zone of queries. Time zone affects some functions such as `format_datetime`.
|
95
|
+
* **language** sets language of queries. Language affects some functions such as `format_datetime`.
|
96
|
+
* **properties** set session properties. Session properties affect internal behavior such as `hive.force_local_scheduling: true`, `raptor.reader_stream_buffer_size: "32MB"`, etc.
|
97
|
+
* **query_timeout** sets timeout in seconds for the entire query execution (from the first API call until there're no more output data). If timeout happens, client raises TrinoQueryTimeoutError. Default is nil (disabled).
|
98
|
+
* **plan_timeout** sets timeout in seconds for query planning execution (from the first API call until result columns become available). If timeout happens, client raises TrinoQueryTimeoutError. Default is nil (disabled).
|
99
|
+
* **http_headers** sets custom HTTP headers. It must be a Hash of string to string.
|
100
|
+
* **http_proxy** sets host:port of a HTTP proxy server.
|
101
|
+
* **http_debug** enables debug message to STDOUT for each HTTP requests.
|
102
|
+
* **http_open_timeout** sets timeout in seconds to open new HTTP connection.
|
103
|
+
* **http_timeout** sets timeout in seconds to read data from a server.
|
104
|
+
* **gzip** enables gzip compression.
|
105
|
+
* **follow_redirect** enables HTTP redirection support.
|
106
|
+
* **model_version** set the Trino version to which a job is submitted. Supported versions are 351, 316, 303, 0.205, 0.178, 0.173, 0.153 and 0.149. Default is 351.
|
107
|
+
|
108
|
+
See [RDoc](http://www.rubydoc.info/gems/presto-client/) for the full documentation.
|
109
|
+
|
110
|
+
## Development
|
111
|
+
|
112
|
+
### Releasing a new version
|
113
|
+
|
114
|
+
1. First update `lib/trino/client/version.rb` to the next version.
|
115
|
+
2. Run the following command which will update `ChangeLog.md` file automatically.
|
116
|
+
```
|
117
|
+
$ ruby release.rb
|
118
|
+
```
|
119
|
+
|
120
|
+
3. Create tag
|
121
|
+
```
|
122
|
+
$ git commit -am "vX.Y.Z"
|
123
|
+
$ git tag "vX.Y.Z"
|
124
|
+
% git push --tags
|
125
|
+
```
|
126
|
+
|
127
|
+
4. Push package
|
128
|
+
```
|
129
|
+
$ gem build trino-client.gemspec
|
130
|
+
$ gem push trino-client-X.Y.Z.gem
|
131
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/clean'
|
6
|
+
|
7
|
+
require 'rspec/core/rake_task'
|
8
|
+
|
9
|
+
RSpec::Core::RakeTask.new(:spec)
|
10
|
+
|
11
|
+
task :default => [:spec, :build]
|
12
|
+
|
13
|
+
GEN_MODEL_VERSIONS = %w[
|
14
|
+
351
|
15
|
+
]
|
16
|
+
|
17
|
+
namespace "modelgen" do
|
18
|
+
task :latest => :all do
|
19
|
+
require 'erb'
|
20
|
+
erb = ERB.new(File.read("modelgen/models.rb"))
|
21
|
+
@versions = GEN_MODEL_VERSIONS
|
22
|
+
@latest_version = GEN_MODEL_VERSIONS.last
|
23
|
+
data = erb.result
|
24
|
+
File.write("lib/trino/client/models.rb", data)
|
25
|
+
end
|
26
|
+
|
27
|
+
task :all => GEN_MODEL_VERSIONS
|
28
|
+
|
29
|
+
GEN_MODEL_VERSIONS.each do |ver|
|
30
|
+
file "build/trino-#{ver}.tar.gz" do
|
31
|
+
mkdir_p "build"
|
32
|
+
sh "curl -L -o build/trino-#{ver}.tar.gz https://github.com/trinodb/trino/archive/#{ver}.tar.gz"
|
33
|
+
end
|
34
|
+
|
35
|
+
file "lib/trino/client/model_versions/#{ver}.rb" => "build/trino-#{ver}.tar.gz" do
|
36
|
+
sh "tar zxf build/trino-#{ver}.tar.gz -C build"
|
37
|
+
mkdir_p "lib/trino/client/model_versions"
|
38
|
+
sh "#{RbConfig.ruby} modelgen/modelgen.rb #{ver} build/trino-#{ver} modelgen/model_versions.rb lib/trino/client/model_versions/#{ver}.rb"
|
39
|
+
puts "Generated lib/trino/client/model_versions/#{ver}.rb."
|
40
|
+
end
|
41
|
+
|
42
|
+
task ver => "lib/trino/client/model_versions/#{ver}.rb"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
data/lib/trino-client.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'trino/client'
|
data/lib/trino/client.rb
ADDED
@@ -0,0 +1,23 @@
|
|
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
|
+
|
19
|
+
require 'trino/client/version'
|
20
|
+
require 'trino/client/client'
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,78 @@
|
|
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
|
+
require 'trino/client/models'
|
19
|
+
require 'trino/client/query'
|
20
|
+
|
21
|
+
class Client
|
22
|
+
def initialize(options)
|
23
|
+
@options = options
|
24
|
+
end
|
25
|
+
|
26
|
+
def query(query, &block)
|
27
|
+
q = Query.start(query, @options)
|
28
|
+
if block
|
29
|
+
begin
|
30
|
+
yield q
|
31
|
+
ensure
|
32
|
+
q.close
|
33
|
+
end
|
34
|
+
else
|
35
|
+
return q
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def resume_query(next_uri)
|
40
|
+
return Query.resume(next_uri, @options)
|
41
|
+
end
|
42
|
+
|
43
|
+
def kill(query_id)
|
44
|
+
return Query.kill(query_id, @options)
|
45
|
+
end
|
46
|
+
|
47
|
+
def run(query)
|
48
|
+
q = Query.start(query, @options)
|
49
|
+
begin
|
50
|
+
columns = q.columns
|
51
|
+
if columns.empty?
|
52
|
+
return [], []
|
53
|
+
end
|
54
|
+
return columns, q.rows
|
55
|
+
ensure
|
56
|
+
q.close
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Accepts the raw response from the Trino Client and returns an
|
61
|
+
# array of hashes where you can access the data in each row using the
|
62
|
+
# output name specified in the query with AS:
|
63
|
+
# SELECT expression AS output_name
|
64
|
+
def run_with_names(query)
|
65
|
+
columns, rows = run(query)
|
66
|
+
|
67
|
+
column_names = columns.map(&:name)
|
68
|
+
|
69
|
+
rows.map do |row|
|
70
|
+
Hash[column_names.zip(row)]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.new(*args)
|
76
|
+
Client.new(*args)
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,46 @@
|
|
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
|
+
class TrinoError < StandardError
|
18
|
+
end
|
19
|
+
|
20
|
+
class TrinoHttpError < TrinoError
|
21
|
+
def initialize(status, message)
|
22
|
+
super(message)
|
23
|
+
@status = status
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :status
|
27
|
+
end
|
28
|
+
|
29
|
+
class TrinoClientError < TrinoError
|
30
|
+
end
|
31
|
+
|
32
|
+
class TrinoQueryError < TrinoError
|
33
|
+
def initialize(message, query_id, error_code, error_name, failure_info)
|
34
|
+
super(message)
|
35
|
+
@query_id = query_id
|
36
|
+
@error_code = error_code
|
37
|
+
@error_name = error_name
|
38
|
+
@failure_info = failure_info
|
39
|
+
end
|
40
|
+
|
41
|
+
attr_reader :error_code, :error_name, :failure_info
|
42
|
+
end
|
43
|
+
|
44
|
+
class TrinoQueryTimeoutError < TrinoError
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,242 @@
|
|
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
|
+
require 'cgi'
|
19
|
+
|
20
|
+
module TrinoHeaders
|
21
|
+
TRINO_USER = "X-Trino-User"
|
22
|
+
TRINO_SOURCE = "X-Trino-Source"
|
23
|
+
TRINO_CATALOG = "X-Trino-Catalog"
|
24
|
+
TRINO_SCHEMA = "X-Trino-Schema"
|
25
|
+
TRINO_TIME_ZONE = "X-Trino-Time-Zone"
|
26
|
+
TRINO_LANGUAGE = "X-Trino-Language"
|
27
|
+
TRINO_SESSION = "X-Trino-Session"
|
28
|
+
TRINO_CLIENT_INFO = "X-Trino-Client-Info";
|
29
|
+
TRINO_CLIENT_TAGS = "X-Trino-Client-Tags";
|
30
|
+
|
31
|
+
TRINO_CURRENT_STATE = "X-Trino-Current-State"
|
32
|
+
TRINO_MAX_WAIT = "X-Trino-Max-Wait"
|
33
|
+
TRINO_MAX_SIZE = "X-Trino-Max-Size"
|
34
|
+
TRINO_PAGE_SEQUENCE_ID = "X-Trino-Page-Sequence-Id"
|
35
|
+
end
|
36
|
+
|
37
|
+
module PrestoHeaders
|
38
|
+
PRESTO_USER = "X-Presto-User"
|
39
|
+
PRESTO_SOURCE = "X-Presto-Source"
|
40
|
+
PRESTO_CATALOG = "X-Presto-Catalog"
|
41
|
+
PRESTO_SCHEMA = "X-Presto-Schema"
|
42
|
+
PRESTO_TIME_ZONE = "X-Presto-Time-Zone"
|
43
|
+
PRESTO_LANGUAGE = "X-Presto-Language"
|
44
|
+
PRESTO_SESSION = "X-Presto-Session"
|
45
|
+
PRESTO_CLIENT_INFO = "X-Presto-Client-Info";
|
46
|
+
PRESTO_CLIENT_TAGS = "X-Presto-Client-Tags";
|
47
|
+
|
48
|
+
PRESTO_CURRENT_STATE = "X-Presto-Current-State"
|
49
|
+
PRESTO_MAX_WAIT = "X-Presto-Max-Wait"
|
50
|
+
PRESTO_MAX_SIZE = "X-Presto-Max-Size"
|
51
|
+
PRESTO_PAGE_SEQUENCE_ID = "X-Presto-Page-Sequence-Id"
|
52
|
+
end
|
53
|
+
|
54
|
+
HEADERS = {
|
55
|
+
"User-Agent" => "trino-ruby/#{VERSION}",
|
56
|
+
}
|
57
|
+
|
58
|
+
def self.faraday_client(options)
|
59
|
+
server = options[:server]
|
60
|
+
unless server
|
61
|
+
raise ArgumentError, ":server option is required"
|
62
|
+
end
|
63
|
+
|
64
|
+
ssl = faraday_ssl_options(options)
|
65
|
+
|
66
|
+
if options[:password] && !ssl
|
67
|
+
raise ArgumentError, "Protocol must be https when passing a password"
|
68
|
+
end
|
69
|
+
|
70
|
+
url = "#{ssl ? "https" : "http"}://#{server}"
|
71
|
+
proxy = options[:http_proxy] || options[:proxy] # :proxy is obsoleted
|
72
|
+
|
73
|
+
faraday_options = {url: url, proxy: "#{proxy}"}
|
74
|
+
faraday_options[:ssl] = ssl if ssl
|
75
|
+
|
76
|
+
faraday = Faraday.new(faraday_options) do |faraday|
|
77
|
+
if options[:user] && options[:password]
|
78
|
+
faraday.basic_auth(options[:user], options[:password])
|
79
|
+
end
|
80
|
+
if options[:follow_redirect]
|
81
|
+
faraday.use FaradayMiddleware::FollowRedirects
|
82
|
+
end
|
83
|
+
if options[:gzip]
|
84
|
+
faraday.use FaradayMiddleware::Gzip
|
85
|
+
end
|
86
|
+
faraday.response :logger if options[:http_debug]
|
87
|
+
faraday.adapter Faraday.default_adapter
|
88
|
+
end
|
89
|
+
|
90
|
+
faraday.headers.merge!(HEADERS)
|
91
|
+
faraday.headers.merge!(optional_headers(options))
|
92
|
+
|
93
|
+
return faraday
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.faraday_ssl_options(options)
|
97
|
+
ssl = options[:ssl]
|
98
|
+
|
99
|
+
case ssl
|
100
|
+
when true
|
101
|
+
ssl = {verify: true}
|
102
|
+
|
103
|
+
when Hash
|
104
|
+
verify = ssl.fetch(:verify, true)
|
105
|
+
case verify
|
106
|
+
when true
|
107
|
+
# detailed SSL options. pass through to faraday
|
108
|
+
when nil, false
|
109
|
+
ssl = {verify: false}
|
110
|
+
else
|
111
|
+
raise ArgumentError, "Can't convert #{verify.class} of :verify option of :ssl option to true or false"
|
112
|
+
end
|
113
|
+
|
114
|
+
when nil, false
|
115
|
+
ssl = false
|
116
|
+
|
117
|
+
else
|
118
|
+
raise ArgumentError, "Can't convert #{ssl.class} of :ssl option to true, false, or Hash"
|
119
|
+
end
|
120
|
+
|
121
|
+
return ssl
|
122
|
+
end
|
123
|
+
|
124
|
+
def self.optional_headers(options)
|
125
|
+
usePrestoHeader = false
|
126
|
+
if v = options[:model_version] && v < 351
|
127
|
+
usePrestoHeader = true
|
128
|
+
end
|
129
|
+
|
130
|
+
headers = {}
|
131
|
+
if v = options[:user]
|
132
|
+
if usePrestoHeader
|
133
|
+
headers[PrestoHeaders::PRESTO_USER] = v
|
134
|
+
else
|
135
|
+
headers[TrinoHeaders::TRINO_USER] = v
|
136
|
+
end
|
137
|
+
end
|
138
|
+
if v = options[:source]
|
139
|
+
if usePrestoHeader
|
140
|
+
headers[PrestoHeaders::PRESTO_SOURCE] = v
|
141
|
+
else
|
142
|
+
headers[TrinoHeaders::TRINO_SOURCE] = v
|
143
|
+
end
|
144
|
+
end
|
145
|
+
if v = options[:catalog]
|
146
|
+
if usePrestoHeader
|
147
|
+
headers[PrestoHeaders::PRESTO_CATALOG] = v
|
148
|
+
else
|
149
|
+
headers[TrinoHeaders::TRINO_CATALOG] = v
|
150
|
+
end
|
151
|
+
end
|
152
|
+
if v = options[:schema]
|
153
|
+
if usePrestoHeader
|
154
|
+
headers[PrestoHeaders::PRESTO_SCHEMA] = v
|
155
|
+
else
|
156
|
+
headers[TrinoHeaders::TRINO_SCHEMA] = v
|
157
|
+
end
|
158
|
+
end
|
159
|
+
if v = options[:time_zone]
|
160
|
+
if usePrestoHeader
|
161
|
+
headers[PrestoHeaders::PRESTO_TIME_ZONE] = v
|
162
|
+
else
|
163
|
+
headers[TrinoHeaders::TRINO_TIME_ZONE] = v
|
164
|
+
end
|
165
|
+
end
|
166
|
+
if v = options[:language]
|
167
|
+
if usePrestoHeader
|
168
|
+
headers[PrestoHeaders::PRESTO_LANGUAGE] = v
|
169
|
+
else
|
170
|
+
headers[TrinoHeaders::TRINO_LANGUAGE] = v
|
171
|
+
end
|
172
|
+
end
|
173
|
+
if v = options[:properties]
|
174
|
+
if usePrestoHeader
|
175
|
+
headers[PrestoHeaders::PRESTO_SESSION] = encode_properties(v)
|
176
|
+
else
|
177
|
+
headers[TrinoHeaders::TRINO_SESSION] = encode_properties(v)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
if v = options[:client_info]
|
181
|
+
if usePrestoHeader
|
182
|
+
headers[PrestoHeaders::PRESTO_CLIENT_INFO] = encode_client_info(v)
|
183
|
+
else
|
184
|
+
headers[TrinoHeaders::TRINO_CLIENT_INFO] = encode_client_info(v)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
if v = options[:client_tags]
|
188
|
+
if usePrestoHeader
|
189
|
+
headers[PrestoHeaders::PRESTO_CLIENT_TAGS] = encode_client_tags(v)
|
190
|
+
else
|
191
|
+
headers[TrinoHeaders::TRINO_CLIENT_TAGS] = encode_client_tags(v)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
if options[:enable_x_msgpack]
|
195
|
+
# option name is enable_"x"_msgpack because "Accept: application/x-msgpack" header is
|
196
|
+
# not officially supported by Trino. We can use this option only if a proxy server
|
197
|
+
# decodes & encodes response body. Once this option is supported by Trino, option
|
198
|
+
# name should be enable_msgpack, which might be slightly different behavior.
|
199
|
+
headers['Accept'] = 'application/x-msgpack,application/json'
|
200
|
+
end
|
201
|
+
if v = options[:http_headers]
|
202
|
+
headers.merge!(v)
|
203
|
+
end
|
204
|
+
headers
|
205
|
+
end
|
206
|
+
|
207
|
+
HTTP11_SEPARATOR = ["(", ")", "<", ">", "@", ",", ";", ":", "\\", "<", ">", "/", "[", "]", "?", "=", "{", "}", " ", "\v"]
|
208
|
+
HTTP11_TOKEN_CHARSET = (32..126).map {|x| x.chr } - HTTP11_SEPARATOR
|
209
|
+
HTTP11_TOKEN_REGEXP = /^[#{Regexp.escape(HTTP11_TOKEN_CHARSET.join)}]+\z/
|
210
|
+
HTTP11_CTL_CHARSET = (0..31).map {|x| x.chr } + [127.chr]
|
211
|
+
HTTP11_CTL_CHARSET_REGEXP = /[#{Regexp.escape(HTTP11_CTL_CHARSET.join)}]/
|
212
|
+
|
213
|
+
def self.encode_properties(properties)
|
214
|
+
properties.map do |k, v|
|
215
|
+
token = k.to_s
|
216
|
+
field_value = v.to_s # TODO LWS encoding is not implemented
|
217
|
+
unless k =~ HTTP11_TOKEN_REGEXP
|
218
|
+
raise Faraday::ClientError, "Key of properties can't include HTTP/1.1 control characters or separators (#{HTTP11_SEPARATOR.map {|c| c =~ /\s/ ? c.dump : c }.join(' ')})"
|
219
|
+
end
|
220
|
+
if field_value =~ HTTP11_CTL_CHARSET_REGEXP
|
221
|
+
raise Faraday::ClientError, "Value of properties can't include HTTP/1.1 control characters"
|
222
|
+
end
|
223
|
+
field_value = CGI.escape(field_value)
|
224
|
+
"#{token}=#{field_value}"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def self.encode_client_info(info)
|
229
|
+
if info.is_a?(String)
|
230
|
+
info
|
231
|
+
else
|
232
|
+
JSON.dump(info)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def self.encode_client_tags(tags)
|
237
|
+
Array(tags).join(",")
|
238
|
+
end
|
239
|
+
|
240
|
+
private_class_method :faraday_ssl_options, :optional_headers, :encode_properties, :encode_client_info, :encode_client_tags
|
241
|
+
|
242
|
+
end
|