drill-sergeant 0.1.0 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 5cdb7282b775f1c7230459d0a2479c1e555f951d
4
- data.tar.gz: 1233bc819be136fccf7a3016cd703dc7b84835d1
2
+ SHA256:
3
+ metadata.gz: a9a45ee9fd9196539d55c04641748ea43915edc39b2de7a57acc066ec829a493
4
+ data.tar.gz: d38d61d15324267e96a19d93284cece7fdf37a035dccdc5eb7f3a73e0872c9fa
5
5
  SHA512:
6
- metadata.gz: e3f4a2c584488f9cdd57d99d847d735bd705422c912abdf8c6be59e5c363d8b814b6d9497f99b3d29c407207065062bd6f7941a3fe5cd3a21992f621c5f78831
7
- data.tar.gz: a34d46fd69ceb73ebcc876a8bb9dc24c8f2df2e62513c597d5ab9804dc6fc35e65cb8e4158e3bb12370f42471565d2d936f9f790f1cb699a6dba459e27ad4262
6
+ metadata.gz: 7bd8f5dc9e71be3bb905f092794ea5d91effae2dd80420f11d998382d5cee12d2945b856d06ae1f8248f27b7fbae4261a5280a72d53ea6c5501c479bdd538799
7
+ data.tar.gz: f4fc88b864649e84dbb3115e15703897bd24e50f0eefc9c956b4163fbe6da8bb4c20a89f5008b06a915ad611f0a5539c35ba1096d314305c6c1d19190471c043
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
- ## 0.1.0
1
+ ## 0.1.4 (2022-01-16)
2
+
3
+ - Added `server_version` method
4
+ - Fixed error with failed queries with Drill 1.19+
5
+
6
+ ## 0.1.3 (2019-08-10)
7
+
8
+ - Added more endpoints
9
+
10
+ ## 0.1.2 (2018-07-22)
11
+
12
+ - Added support for HTTPS
13
+ - Added `open_timeout` and `read_timeout` options
14
+
15
+ ## 0.1.1 (2017-03-24)
16
+
17
+ - Return columns in correct order
18
+
19
+ ## 0.1.0 (2017-03-24)
2
20
 
3
21
  - First release
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2017-2020 Andrew Kane
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -2,27 +2,91 @@
2
2
 
3
3
  Ruby client for Apache Drill
4
4
 
5
+ [![Build Status](https://github.com/ankane/drill-sergeant/workflows/build/badge.svg?branch=master)](https://github.com/ankane/drill-sergeant/actions)
6
+
5
7
  ## Installation
6
8
 
7
- First, [download Apache Drill](https://drill.apache.org/docs/installing-drill-on-linux-and-mac-os-x/). Start it with:
9
+ First, [install Apache Drill](https://drill.apache.org/docs/installing-drill-on-linux-and-mac-os-x/). For Homebrew, use:
8
10
 
9
11
  ```sh
10
- bin/drill-embedded
12
+ brew install apache-drill
13
+ drill-embedded
11
14
  ```
12
15
 
13
- Then add this line to your application’s Gemfile:
16
+ And add this line to your application’s Gemfile:
14
17
 
15
18
  ```ruby
16
- gem 'drill-sergeant'
19
+ gem "drill-sergeant"
17
20
  ```
18
21
 
19
22
  ## How to Use
20
23
 
24
+ Create a client
25
+
21
26
  ```ruby
22
27
  drill = Drill.new(url: "http://localhost:8047")
28
+ ```
29
+
30
+ And query away
31
+
32
+ ```ruby
23
33
  drill.query("SELECT * FROM dfs.`/path/to/some/file.csvh`")
24
34
  ```
25
35
 
36
+ ## Endpoints
37
+
38
+ [API docs](https://drill.apache.org/docs/rest-api-introduction/)
39
+
40
+ Get profiles
41
+
42
+ ```ruby
43
+ drill.profiles
44
+ ```
45
+
46
+ Get profile by query id
47
+
48
+ ```ruby
49
+ drill.profiles(query_id)
50
+ ```
51
+
52
+ Get storage
53
+
54
+ ```ruby
55
+ drill.storage
56
+ ```
57
+
58
+ Get storage by name
59
+
60
+ ```ruby
61
+ drill.storage(name)
62
+ ```
63
+
64
+ Get cluster info
65
+
66
+ ```ruby
67
+ drill.cluster
68
+ ```
69
+
70
+ Get metrics
71
+
72
+ ```ruby
73
+ drill.metrics
74
+ ```
75
+
76
+ Get options
77
+
78
+ ```ruby
79
+ drill.options
80
+ ```
81
+
82
+ ## Reference
83
+
84
+ Set timeouts
85
+
86
+ ```ruby
87
+ Drill.new(open_timeout: 5, read_timeout: 120)
88
+ ```
89
+
26
90
  ## History
27
91
 
28
92
  View the [changelog](https://github.com/ankane/drill-sergeant/blob/master/CHANGELOG.md)
@@ -35,3 +99,12 @@ Everyone is encouraged to help improve this project. Here are a few ways you can
35
99
  - Fix bugs and [submit pull requests](https://github.com/ankane/drill-sergeant/pulls)
36
100
  - Write, clarify, or fix documentation
37
101
  - Suggest or add new features
102
+
103
+ To get started with development:
104
+
105
+ ```sh
106
+ git clone https://github.com/ankane/drill-sergeant.git
107
+ cd drill-sergeant
108
+ bundle install
109
+ bundle exec rake test
110
+ ```
data/lib/drill/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Drill
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.4"
3
3
  end
@@ -0,0 +1,119 @@
1
+ # dependencies
2
+ require "cgi"
3
+ require "json"
4
+ require "net/http"
5
+
6
+ # modules
7
+ require "drill/version"
8
+
9
+ # TODO make module and move to client
10
+ class Drill
11
+ class Error < StandardError; end
12
+
13
+ HEADERS = {
14
+ "Content-Type" => "application/json",
15
+ "Accept" => "application/json"
16
+ }
17
+
18
+ def initialize(url: nil, open_timeout: 3, read_timeout: nil)
19
+ url ||= ENV["DRILL_URL"] || "http://localhost:8047"
20
+ # remove trailing slash
21
+ @uri = URI.parse(url.chomp("/"))
22
+ @http = Net::HTTP.new(@uri.host, @uri.port)
23
+ @http.use_ssl = true if @uri.scheme == "https"
24
+ @http.open_timeout = open_timeout if open_timeout
25
+ @http.read_timeout = read_timeout if read_timeout
26
+ end
27
+
28
+ def query(statement)
29
+ options = {}
30
+ if Gem::Version.new(server_version) >= Gem::Version.new("1.19.0")
31
+ options["drill.exec.http.rest.errors.verbose"] = true
32
+ end
33
+ run_query(statement, options)
34
+ end
35
+
36
+ def profiles(query_id = nil)
37
+ path = query_id ? "profiles/#{escape_path(query_id)}.json" : "profiles.json"
38
+ get(path)
39
+ end
40
+
41
+ def storage(name = nil)
42
+ path = name ? "storage/#{escape_path(name)}.json" : "storage.json"
43
+ get(path)
44
+ end
45
+
46
+ def cluster
47
+ get("cluster.json")
48
+ end
49
+
50
+ def metrics
51
+ # no .json suffix
52
+ get("status/metrics")
53
+ end
54
+
55
+ def options
56
+ get("options.json")
57
+ end
58
+
59
+ def server_version
60
+ @server_version ||= run_query("SELECT version FROM sys.version", {})[0]["version"]
61
+ end
62
+
63
+ private
64
+
65
+ def run_query(statement, options)
66
+ data = {
67
+ queryType: "sql",
68
+ query: statement,
69
+ options: options
70
+ }
71
+
72
+ body = post("query.json", data)
73
+
74
+ # errors return 200 with Drill 1.19+
75
+ if body["queryState"] != "COMPLETED"
76
+ raise Error, body["errorMessage"] || "Bad state: #{body["queryState"]}"
77
+ end
78
+
79
+ # return columns in order
80
+ result = []
81
+ columns = body["columns"]
82
+ body["rows"].each do |row|
83
+ result << columns.each_with_object({}) { |c, memo| memo[c] = row[c] }
84
+ end
85
+ result
86
+ end
87
+
88
+ def get(path)
89
+ handle_response do
90
+ @http.get("#{@uri.request_uri}#{path}", HEADERS)
91
+ end
92
+ end
93
+
94
+ def post(path, data)
95
+ handle_response do
96
+ @http.post("#{@uri.request_uri}#{path}", data.to_json, HEADERS)
97
+ end
98
+ end
99
+
100
+ def handle_response
101
+ begin
102
+ response = yield
103
+ rescue Errno::ECONNREFUSED => e
104
+ raise Error, e.message
105
+ end
106
+
107
+ unless response.kind_of?(Net::HTTPSuccess)
108
+ body = JSON.parse(response.body) rescue {}
109
+ message = body["errorMessage"] || "Bad response: #{response.code}"
110
+ raise Error, message
111
+ end
112
+
113
+ JSON.parse(response.body)
114
+ end
115
+
116
+ def escape_path(path)
117
+ CGI.escape(path).gsub("+", "%20")
118
+ end
119
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: drill-sergeant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
- autorequire:
9
- bindir: exe
8
+ autorequire:
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-24 00:00:00.000000000 Z
11
+ date: 2022-01-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,26 +52,22 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- description:
56
- email:
57
- - andrew@chartkick.com
55
+ description:
56
+ email: andrew@chartkick.com
58
57
  executables: []
59
58
  extensions: []
60
59
  extra_rdoc_files: []
61
60
  files:
62
- - ".gitignore"
63
61
  - CHANGELOG.md
64
- - Gemfile
62
+ - LICENSE.txt
65
63
  - README.md
66
- - Rakefile
67
- - drill-sergeant.gemspec
68
- - lib/drill.rb
69
- - lib/drill/sergeant.rb
64
+ - lib/drill-sergeant.rb
70
65
  - lib/drill/version.rb
71
66
  homepage: https://github.com/ankane/drill-sergeant
72
- licenses: []
67
+ licenses:
68
+ - MIT
73
69
  metadata: {}
74
- post_install_message:
70
+ post_install_message:
75
71
  rdoc_options: []
76
72
  require_paths:
77
73
  - lib
@@ -79,16 +75,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
79
75
  requirements:
80
76
  - - ">="
81
77
  - !ruby/object:Gem::Version
82
- version: '0'
78
+ version: '2.4'
83
79
  required_rubygems_version: !ruby/object:Gem::Requirement
84
80
  requirements:
85
81
  - - ">="
86
82
  - !ruby/object:Gem::Version
87
83
  version: '0'
88
84
  requirements: []
89
- rubyforge_project:
90
- rubygems_version: 2.6.8
91
- signing_key:
85
+ rubygems_version: 3.3.3
86
+ signing_key:
92
87
  specification_version: 4
93
88
  summary: Ruby client for Apache Drill
94
89
  test_files: []
data/.gitignore DELETED
@@ -1,9 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
data/Gemfile DELETED
@@ -1,3 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gemspec
data/Rakefile DELETED
@@ -1,11 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
3
-
4
- Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
8
- t.warning = false
9
- end
10
-
11
- task default: :test
@@ -1,25 +0,0 @@
1
- # coding: utf-8
2
- lib = File.expand_path("../lib", __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "drill/version"
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = "drill-sergeant"
8
- spec.version = Drill::VERSION
9
- spec.authors = ["Andrew Kane"]
10
- spec.email = ["andrew@chartkick.com"]
11
-
12
- spec.summary = "Ruby client for Apache Drill"
13
- spec.homepage = "https://github.com/ankane/drill-sergeant"
14
-
15
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
16
- f.match(%r{^(test|spec|features)/})
17
- end
18
- spec.bindir = "exe"
19
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
- spec.require_paths = ["lib"]
21
-
22
- spec.add_development_dependency "bundler"
23
- spec.add_development_dependency "rake"
24
- spec.add_development_dependency "minitest"
25
- end
@@ -1 +0,0 @@
1
- require "drill"
data/lib/drill.rb DELETED
@@ -1,34 +0,0 @@
1
- require "json"
2
- require "net/http"
3
- require "drill/version"
4
-
5
- class Drill
6
- class Error < StandardError; end
7
-
8
- def initialize(url: nil)
9
- url ||= ENV["DRILL_URL"] || "http://localhost:8047"
10
- @uri = URI.parse("#{url}/query.json")
11
- @http = Net::HTTP.new(@uri.host, @uri.port)
12
- end
13
-
14
- def query(statement)
15
- header = {"Content-Type" => "application/json", "Accept" => "application/json"}
16
- data = {
17
- queryType: "sql",
18
- query: statement
19
- }
20
-
21
- begin
22
- response = @http.post(@uri.request_uri, data.to_json, header)
23
- rescue Errno::ECONNREFUSED => e
24
- raise Drill::Error, e.message
25
- end
26
-
27
- body = JSON.parse(response.body)
28
- if body["errorMessage"]
29
- raise Drill::Error, body["errorMessage"].split("\n")[0]
30
- end
31
-
32
- body["rows"]
33
- end
34
- end