presto-client 0.5.14 → 0.6.4

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.
@@ -9,7 +9,7 @@ Gem::Specification.new do |gem|
9
9
  gem.description = %q{Presto client library}
10
10
  gem.summary = %q{Presto client library}
11
11
  gem.homepage = "https://github.com/treasure-data/presto-client-ruby"
12
- gem.license = "Apache 2.0"
12
+ gem.license = "Apache-2.0"
13
13
 
14
14
  gem.files = `git ls-files`.split($\)
15
15
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
@@ -20,6 +20,7 @@ Gem::Specification.new do |gem|
20
20
  gem.required_ruby_version = ">= 1.9.1"
21
21
 
22
22
  gem.add_dependency "faraday", ["~> 0.12"]
23
+ gem.add_dependency "faraday_middleware", ["~> 0.12.2"]
23
24
  gem.add_dependency "msgpack", [">= 0.7.0"]
24
25
 
25
26
  gem.add_development_dependency "rake", [">= 0.9.2", "< 11.0"]
data/release.rb ADDED
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'fileutils'
4
+
5
+ PREFIX = 'https://github.com/treasure-data/presto-client-ruby'
6
+ RELEASE_NOTES_FILE = "ChangeLog.md"
7
+
8
+ last_tag = `git describe --tags --abbrev=0`.chomp
9
+ last_version = last_tag.sub("v", "")
10
+ puts "last version: #{last_version}"
11
+
12
+ print "next version? "
13
+ next_version = STDIN.gets.chomp
14
+
15
+ abort("Can't use empty version string") if next_version.empty?
16
+
17
+ logs = `git log #{last_tag}..HEAD --pretty=format:'%h %s'`
18
+ # Add links to GitHub issues
19
+ logs = logs.gsub(/\#([0-9]+)/, "[#\\1](#{PREFIX}/issues/\\1)")
20
+
21
+ new_release_notes = []
22
+ new_release_notes <<= "\#\# #{next_version}\n"
23
+ new_release_notes <<= logs.split(/\n/)
24
+ .reject{|line| line.include?("#{last_version} release notes")}
25
+ .map{|x|
26
+ rev = x[0..6]
27
+ "- #{x[8..-1]} [[#{rev}](#{PREFIX}/commit/#{rev})]\n"
28
+ }
29
+
30
+ release_notes = []
31
+ notes = File.readlines(RELEASE_NOTES_FILE)
32
+
33
+ release_notes <<= notes[0..1]
34
+ release_notes <<= new_release_notes
35
+ release_notes <<= "\n"
36
+ release_notes <<= notes[2..-1]
37
+
38
+ TMP_RELEASE_NOTES_FILE = "#{RELEASE_NOTES_FILE}.tmp"
39
+ File.delete(TMP_RELEASE_NOTES_FILE) if File.exists?(TMP_RELEASE_NOTES_FILE)
40
+ File.write("#{TMP_RELEASE_NOTES_FILE}", release_notes.join)
41
+ system("cat #{TMP_RELEASE_NOTES_FILE} | vim - -c ':f #{TMP_RELEASE_NOTES_FILE}' -c ':9'")
42
+
43
+ abort("The release note file is not saved. Aborted") unless File.exists?(TMP_RELEASE_NOTES_FILE)
44
+
45
+ def run(cmd)
46
+ puts cmd
47
+ system cmd
48
+ end
49
+
50
+ FileUtils.cp(TMP_RELEASE_NOTES_FILE, RELEASE_NOTES_FILE)
51
+ File.delete(TMP_RELEASE_NOTES_FILE)
52
+
53
+ # run "git commit #{RELEASE_NOTES_FILE} -m \"Add #{next_version} release notes\""
54
+ # run "git tag v#{next_version}"
55
+ # run "git push"
56
+ # run "git push --tags"
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ describe Presto::Client::Client do
4
+ before(:all) do
5
+ WebMock.disable!
6
+ @cluster = TinyPresto::Cluster.new('316')
7
+ @container = @cluster.run
8
+ @client = Presto::Client.new(server: 'localhost:8080', catalog: 'memory', user: 'test-user', schema: 'default')
9
+ loop do
10
+ begin
11
+ @client.run('show schemas')
12
+ break
13
+ rescue StandardError => exception
14
+ puts "Waiting for cluster ready... #{exception}"
15
+ sleep(3)
16
+ end
17
+ end
18
+ puts 'Cluster is ready'
19
+ end
20
+
21
+ after(:all) do
22
+ @cluster.stop
23
+ WebMock.enable!
24
+ end
25
+
26
+ it 'show schemas' do
27
+ columns, rows = run_with_retry(@client, 'show schemas')
28
+ expect(columns.length).to be(1)
29
+ expect(rows.length).to be(2)
30
+ end
31
+
32
+ it 'ctas' do
33
+ expected = [[1, 'a'], [2, 'b']]
34
+ run_with_retry(@client, "create table ctas1 as select * from (values (1, 'a'), (2, 'b')) t(c1, c2)")
35
+ columns, rows = run_with_retry(@client, 'select * from ctas1')
36
+ expect(columns.map(&:name)).to match_array(%w[c1 c2])
37
+ expect(rows).to eq(expected)
38
+ end
39
+
40
+ it 'next_uri' do
41
+ @client.query('show schemas') do |q|
42
+ expect(q.next_uri).to start_with('http://localhost:8080/v1/statement/')
43
+ end
44
+ end
45
+
46
+ it 'advance' do
47
+ @client.query('show schemas') do |q|
48
+ expect(q.advance).to be(true)
49
+ end
50
+ end
51
+
52
+ it 'current query result' do
53
+ @client.query('show schemas') do |q|
54
+ expect(q.current_results.info_uri).to start_with('http://localhost:8080/ui/query.html')
55
+ end
56
+ end
57
+
58
+ it 'statement stats' do
59
+ @client.query('show schemas') do |q|
60
+ stats = q.current_results.stats
61
+ # Immediate subsequent request should get queued result
62
+ expect(stats.queued).to be(true)
63
+ expect(stats.scheduled).to be(false)
64
+ end
65
+ end
66
+
67
+ it 'partial cancel' do
68
+ @client.query('show schemas') do |q|
69
+ q.cancel
70
+ expect { q.query_info }.to raise_error(Presto::Client::PrestoHttpError, /Error 410 Gone/)
71
+ end
72
+ end
73
+
74
+ it 'row chunk' do
75
+ expected_schemas = %w[default information_schema]
76
+ @client.query('show schemas') do |q|
77
+ q.each_row do |r|
78
+ expect(expected_schemas).to include(r[0])
79
+ end
80
+ end
81
+ end
82
+ end
data/spec/spec_helper.rb CHANGED
@@ -16,3 +16,27 @@ require 'webmock/rspec'
16
16
 
17
17
  require 'presto-client'
18
18
  include Presto::Client
19
+
20
+ require 'tiny-presto'
21
+
22
+ MAX_RETRY_COUNT = 5
23
+ RETRYABLE_ERRORS = [
24
+ /No nodes available to run query/
25
+ ]
26
+
27
+ def run_with_retry(client, sql)
28
+ i = 0
29
+ while i < MAX_RETRY_COUNT
30
+ begin
31
+ columns, rows = @client.run(sql)
32
+ return columns, rows
33
+ rescue Presto::Client::PrestoQueryError => e
34
+ if RETRYABLE_ERRORS.any? { |error| e.message =~ error }
35
+ sleep(i)
36
+ i += 1
37
+ next
38
+ end
39
+ raise "Fail to run query: #{e}"
40
+ end
41
+ end
42
+ end
@@ -10,6 +10,7 @@ describe Presto::Client::StatementClient do
10
10
  time_zone: "US/Pacific",
11
11
  language: "ja_JP",
12
12
  debug: true,
13
+ follow_redirect: true
13
14
  }
14
15
  end
15
16
 
@@ -112,24 +113,53 @@ describe Presto::Client::StatementClient do
112
113
  retry_p.should be_true
113
114
  end
114
115
 
115
- it "decodes DeleteHandle" do
116
- dh = Models::DeleteHandle.decode({
117
- "handle" => {
118
- "connectorId" => "c1",
119
- "connectorHandle" => {}
120
- }
121
- })
122
- dh.handle.should be_a_kind_of Models::TableHandle
123
- dh.handle.connector_id.should == "c1"
124
- dh.handle.connector_handle.should == {}
125
- end
116
+ # presto version could be "V0_ddd" or "Vddd"
117
+ /\APresto::Client::ModelVersions::V(\w+)/ =~ Presto::Client::Models.to_s
118
+
119
+ # https://github.com/prestosql/presto/commit/80a2c5113d47e3390bf6dc041486a1c9dfc04592
120
+ # renamed DeleteHandle to DeleteTarget, then DeleteHandle exists when presto version
121
+ # is less than 313.
122
+ if $1[0, 2] == "0_" || $1.to_i < 314
123
+ it "decodes DeleteHandle" do
124
+ dh = Models::DeleteHandle.decode({
125
+ "handle" => {
126
+ "connectorId" => "c1",
127
+ "connectorHandle" => {}
128
+ }
129
+ })
130
+ dh.handle.should be_a_kind_of Models::TableHandle
131
+ dh.handle.connector_id.should == "c1"
132
+ dh.handle.connector_handle.should == {}
133
+ end
126
134
 
127
- it "validates models" do
128
- lambda do
129
- Models::DeleteHandle.decode({
130
- "handle" => "invalid"
135
+ it "validates models" do
136
+ lambda do
137
+ Models::DeleteHandle.decode({
138
+ "handle" => "invalid"
139
+ })
140
+ end.should raise_error(TypeError, /String to Hash/)
141
+ end
142
+ else
143
+ it "decodes DeleteTarget" do
144
+ dh = Models::DeleteTarget.decode({
145
+ "handle" => {
146
+ "catalogName" => "c1",
147
+ "connectorHandle" => {}
148
+ }
131
149
  })
132
- end.should raise_error(TypeError, /String to Hash/)
150
+ dh.handle.should be_a_kind_of Models::TableHandle
151
+ dh.handle.catalog_name.should == "c1"
152
+ dh.handle.connector_handle.should == {}
153
+ end
154
+
155
+ it "validates models" do
156
+ lambda do
157
+ Models::DeleteTarget.decode({
158
+ "catalogName" => "c1",
159
+ "handle" => "invalid"
160
+ })
161
+ end.should raise_error(TypeError, /String to Hash/)
162
+ end
133
163
  end
134
164
 
135
165
  it "receives headers of POST" do
@@ -148,6 +178,22 @@ describe Presto::Client::StatementClient do
148
178
  q.current_results_headers["X-Test-Header"].should == "123"
149
179
  end
150
180
 
181
+ describe "#query_id" do
182
+ it "returns query_id" do
183
+ stub_request(:post, "localhost/v1/statement").
184
+ with(body: query).to_return(body: response_json2.to_json, headers: {"X-Test-Header" => "123"})
185
+
186
+ stub_request(:get, "localhost/v1/next_uri").
187
+ to_return(body: response_json.to_json, headers: {"X-Test-Header" => "123"})
188
+
189
+ sc = StatementClient.new(faraday, query, options.merge(http_open_timeout: 1))
190
+ sc.query_id.should == "queryid"
191
+ sc.has_next?.should be_true
192
+ sc.advance.should be_true
193
+ sc.query_id.should == "queryid"
194
+ end
195
+ end
196
+
151
197
  describe '#query_info' do
152
198
  let :headers do
153
199
  {
@@ -184,6 +230,19 @@ describe Presto::Client::StatementClient do
184
230
  statement_client.query_info
185
231
  end.should raise_error(PrestoHttpError, /Presto API returned unexpected data format./)
186
232
  end
233
+
234
+ it "is redirected if server returned 301" do
235
+ stub_request(:get, "http://localhost/v1/query/#{response_json2[:id]}").
236
+ with(headers: headers).
237
+ to_return(status: 301, headers: {"Location" => "http://localhost/v1/query/redirected"})
238
+
239
+ stub_request(:get, "http://localhost/v1/query/redirected").
240
+ with(headers: headers).
241
+ to_return(body: {"queryId" => "queryid"}.to_json)
242
+
243
+ query_info = statement_client.query_info
244
+ query_info.query_id.should == "queryid"
245
+ end
187
246
  end
188
247
 
189
248
  describe "Killing a query" do
@@ -564,11 +623,13 @@ describe Presto::Client::StatementClient do
564
623
  to_return(body: early_running_response.to_json)
565
624
  client.advance
566
625
 
567
- sleep 1
568
626
  stub_request(:get, "localhost/v1/next_uri").
569
627
  with(headers: headers).
570
628
  to_return(body: done_response.to_json)
571
- client.advance
629
+ client.advance # set finished
630
+
631
+ sleep 1
632
+ client.advance # set finished
572
633
  end
573
634
 
574
635
  end
data/spec/tpch/q01.sql ADDED
@@ -0,0 +1,21 @@
1
+ SELECT
2
+ l.returnflag,
3
+ l.linestatus,
4
+ sum(l.quantity) AS sum_qty,
5
+ sum(l.extendedprice) AS sum_base_price,
6
+ sum(l.extendedprice * (1 - l.discount)) AS sum_disc_price,
7
+ sum(l.extendedprice * (1 - l.discount) * (1 + l.tax)) AS sum_charge,
8
+ avg(l.quantity) AS avg_qty,
9
+ avg(l.extendedprice) AS avg_price,
10
+ avg(l.discount) AS avg_disc,
11
+ count(*) AS count_order
12
+ FROM
13
+ "tpch"."tiny"."lineitem" AS l
14
+ WHERE
15
+ l.shipdate <= DATE '1998-12-01' - INTERVAL '90' DAY
16
+ GROUP BY
17
+ l.returnflag,
18
+ l.linestatus
19
+ ORDER BY
20
+ l.returnflag,
21
+ l.linestatus
data/spec/tpch/q02.sql ADDED
@@ -0,0 +1,43 @@
1
+ SELECT
2
+ s.acctbal,
3
+ s.name,
4
+ n.name,
5
+ p.partkey,
6
+ p.mfgr,
7
+ s.address,
8
+ s.phone,
9
+ s.comment
10
+ FROM
11
+ "tpch"."tiny"."part" p,
12
+ "tpch"."tiny"."supplier" s,
13
+ "tpch"."tiny"."partsupp" ps,
14
+ "tpch"."tiny"."nation" n,
15
+ "tpch"."tiny"."region" r
16
+ WHERE
17
+ p.partkey = ps.partkey
18
+ AND s.suppkey = ps.suppkey
19
+ AND p.size = 15
20
+ AND p.type like '%BRASS'
21
+ AND s.nationkey = n.nationkey
22
+ AND n.regionkey = r.regionkey
23
+ AND r.name = 'EUROPE'
24
+ AND ps.supplycost = (
25
+ SELECT
26
+ min(ps.supplycost)
27
+ FROM
28
+ "tpch"."tiny"."partsupp" ps,
29
+ "tpch"."tiny"."supplier" s,
30
+ "tpch"."tiny"."nation" n,
31
+ "tpch"."tiny"."region" r
32
+ WHERE
33
+ p.partkey = ps.partkey
34
+ AND s.suppkey = ps.suppkey
35
+ AND s.nationkey = n.nationkey
36
+ AND n.regionkey = r.regionkey
37
+ AND r.name = 'EUROPE'
38
+ )
39
+ ORDER BY
40
+ s.acctbal desc,
41
+ n.name,
42
+ s.name,
43
+ p.partkey
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Presto::Client::Client do
4
+ before(:all) do
5
+ @spec_path = File.dirname(__FILE__)
6
+ WebMock.disable!
7
+ @cluster = TinyPresto::Cluster.new('316')
8
+ @container = @cluster.run
9
+ @client = Presto::Client.new(server: 'localhost:8080', catalog: 'tpch', user: 'test-user', schema: 'tiny')
10
+ loop do
11
+ begin
12
+ # Make sure to all workers are available.
13
+ @client.run('select 1234')
14
+ break
15
+ rescue StandardError => exception
16
+ puts "Waiting for cluster ready... #{exception}"
17
+ sleep(5)
18
+ end
19
+ end
20
+ puts 'Cluster is ready'
21
+ end
22
+
23
+ after(:all) do
24
+ @cluster.stop
25
+ WebMock.enable!
26
+ end
27
+
28
+ it 'q01' do
29
+ q = File.read("#{@spec_path}/tpch/q01.sql")
30
+ columns, rows = run_with_retry(@client, q)
31
+ expect(columns.length).to be(10)
32
+ expect(rows.length).to be(4)
33
+ end
34
+
35
+ it 'q02' do
36
+ q = File.read("#{@spec_path}/tpch/q02.sql")
37
+ columns, rows = run_with_retry(@client, q)
38
+ expect(columns.length).to be(8)
39
+ expect(rows.length).to be(4)
40
+ end
41
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: presto-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.14
4
+ version: 0.6.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-30 00:00:00.000000000 Z
11
+ date: 2021-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday_middleware
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.12.2
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.12.2
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: msgpack
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -121,10 +135,13 @@ executables: []
121
135
  extensions: []
122
136
  extra_rdoc_files: []
123
137
  files:
138
+ - ".github/CODEOWNERS"
139
+ - ".github/PULL_REQUEST_TEMPLATE.md"
124
140
  - ".gitignore"
125
141
  - ".travis.yml"
126
- - ChangeLog
142
+ - ChangeLog.md
127
143
  - Gemfile
144
+ - LICENSE
128
145
  - README.md
129
146
  - Rakefile
130
147
  - lib/presto-client.rb
@@ -137,6 +154,8 @@ files:
137
154
  - lib/presto/client/model_versions/0.173.rb
138
155
  - lib/presto/client/model_versions/0.178.rb
139
156
  - lib/presto/client/model_versions/0.205.rb
157
+ - lib/presto/client/model_versions/303.rb
158
+ - lib/presto/client/model_versions/316.rb
140
159
  - lib/presto/client/models.rb
141
160
  - lib/presto/client/query.rb
142
161
  - lib/presto/client/statement_client.rb
@@ -146,13 +165,18 @@ files:
146
165
  - modelgen/models.rb
147
166
  - modelgen/presto_models.rb
148
167
  - presto-client.gemspec
168
+ - release.rb
169
+ - spec/basic_query_spec.rb
149
170
  - spec/client_spec.rb
150
171
  - spec/model_spec.rb
151
172
  - spec/spec_helper.rb
152
173
  - spec/statement_client_spec.rb
174
+ - spec/tpch/q01.sql
175
+ - spec/tpch/q02.sql
176
+ - spec/tpch_query_spec.rb
153
177
  homepage: https://github.com/treasure-data/presto-client-ruby
154
178
  licenses:
155
- - Apache 2.0
179
+ - Apache-2.0
156
180
  metadata: {}
157
181
  post_install_message:
158
182
  rdoc_options: []
@@ -169,13 +193,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
169
193
  - !ruby/object:Gem::Version
170
194
  version: '0'
171
195
  requirements: []
172
- rubyforge_project:
173
- rubygems_version: 2.6.13
196
+ rubygems_version: 3.0.3
174
197
  signing_key:
175
198
  specification_version: 4
176
199
  summary: Presto client library
177
200
  test_files:
201
+ - spec/basic_query_spec.rb
178
202
  - spec/client_spec.rb
179
203
  - spec/model_spec.rb
180
204
  - spec/spec_helper.rb
181
205
  - spec/statement_client_spec.rb
206
+ - spec/tpch/q01.sql
207
+ - spec/tpch/q02.sql
208
+ - spec/tpch_query_spec.rb