drill-sergeant 0.1.0 → 0.1.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.
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