athens 0.1.0 → 0.3.3
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 +4 -4
- data/CHANGELOG.md +23 -0
- data/Gemfile.lock +18 -15
- data/README.md +24 -0
- data/Rakefile +0 -1
- data/athens.gemspec +4 -3
- data/lib/athens/connection.rb +7 -5
- data/lib/athens/error.rb +1 -0
- data/lib/athens/query.rb +52 -57
- data/lib/athens/version.rb +1 -1
- metadata +25 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa391fbff6c5016740bc28cfb0692fcc79ee2e1361d31541a635691e6cbbc8a7
|
4
|
+
data.tar.gz: ef1fbb6307221f616576e844ced0ed9398ff9e6db436fde0142e58c89be8c9f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e37d29e7d93b1aa61d6266b5feccc3789087f697c1751830893adc4c795761f587bafdaa44f34de6b5786712d8983e66511d3d0f10fa1b0922ec6921e4201e66
|
7
|
+
data.tar.gz: 0ccaf8bbb67bceb9136806a93da4447ace996ab9709e82d8f6861249e6a62246680c3a618a1479481b931127e568e966038569da2d1814540ef64b7ab3dd155e
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,26 @@
|
|
1
|
+
## 0.3.3 / 2021-01-12
|
2
|
+
|
3
|
+
* Added support for Ruby 3.0 (thanks [blackjiro](https://github.com/blackjiro))
|
4
|
+
|
5
|
+
## 0.3.2 / 2020-11-24
|
6
|
+
|
7
|
+
* Added optional `request_token` and `work_group` parameters to the query execute method (thanks [mediafinger](https://github.com/mediafinger))
|
8
|
+
|
9
|
+
## 0.3.1 / 2020-07-20
|
10
|
+
|
11
|
+
* Bumped development rake version from 0.10 to 0.13 for security fixes
|
12
|
+
* Fixed warning about string defaulting to string (#2)
|
13
|
+
|
14
|
+
## 0.3.0 / 2019-07-02
|
15
|
+
|
16
|
+
* Added enumerator-based result access methods: `#rows` and `#records`
|
17
|
+
* Fixed bug dropping headers from memoized rows across `#to_h` and `#to_a(header_row: true)`
|
18
|
+
|
19
|
+
## 0.2.0 / 2019-03-20
|
20
|
+
|
21
|
+
* Added support for NULL values. Columns with a nullable status of "NULLABLE" or "UNKNOWN" will return nil for NULL values
|
22
|
+
* If a NOT_NULL column returns a nil value an InvalidNullError will be raised
|
23
|
+
|
1
24
|
## 0.1.0 / 2019-03-01
|
2
25
|
|
3
26
|
* Initial release!
|
data/Gemfile.lock
CHANGED
@@ -1,33 +1,36 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
athens (0.
|
4
|
+
athens (0.3.3)
|
5
5
|
aws-sdk-athena (~> 1)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
aws-eventstream (1.0
|
11
|
-
aws-partitions (1.
|
12
|
-
aws-sdk-athena (1.
|
13
|
-
aws-sdk-core (~> 3, >= 3.
|
14
|
-
aws-sigv4 (~> 1.
|
15
|
-
aws-sdk-core (3.
|
16
|
-
aws-eventstream (~> 1.0)
|
17
|
-
aws-partitions (~> 1.0)
|
18
|
-
aws-sigv4 (~> 1.
|
10
|
+
aws-eventstream (1.1.0)
|
11
|
+
aws-partitions (1.416.0)
|
12
|
+
aws-sdk-athena (1.33.0)
|
13
|
+
aws-sdk-core (~> 3, >= 3.109.0)
|
14
|
+
aws-sigv4 (~> 1.1)
|
15
|
+
aws-sdk-core (3.111.0)
|
16
|
+
aws-eventstream (~> 1, >= 1.0.2)
|
17
|
+
aws-partitions (~> 1, >= 1.239.0)
|
18
|
+
aws-sigv4 (~> 1.1)
|
19
19
|
jmespath (~> 1.0)
|
20
|
-
aws-sigv4 (1.
|
20
|
+
aws-sigv4 (1.2.2)
|
21
|
+
aws-eventstream (~> 1, >= 1.0.2)
|
21
22
|
jmespath (1.4.0)
|
22
|
-
rake (
|
23
|
+
rake (13.0.1)
|
24
|
+
rexml (3.2.4)
|
23
25
|
|
24
26
|
PLATFORMS
|
25
27
|
ruby
|
26
28
|
|
27
29
|
DEPENDENCIES
|
28
30
|
athens!
|
29
|
-
bundler (
|
30
|
-
rake (~>
|
31
|
+
bundler (>= 1.17)
|
32
|
+
rake (~> 13.0)
|
33
|
+
rexml (~> 3.2)
|
31
34
|
|
32
35
|
BUNDLED WITH
|
33
|
-
|
36
|
+
2.2.5
|
data/README.md
CHANGED
@@ -61,6 +61,23 @@ results = query.to_h
|
|
61
61
|
# ]
|
62
62
|
```
|
63
63
|
|
64
|
+
Results are also available as unbuffered enumerators of row arrays:
|
65
|
+
```ruby
|
66
|
+
query.rows.each {|row| ...}
|
67
|
+
# ['column_1', 'column_2', 'column_3']
|
68
|
+
# [15, 'data', true]
|
69
|
+
# [20, 'foo', false],
|
70
|
+
# ...
|
71
|
+
```
|
72
|
+
|
73
|
+
Or hashes:
|
74
|
+
```ruby
|
75
|
+
query.records.each {|record| ...}
|
76
|
+
# {'column_1': 15, 'column_2': 'data', 'column_3': true}
|
77
|
+
# {'column_1': 20, 'column_2': 'foo', 'column_3': false}
|
78
|
+
# ...
|
79
|
+
```
|
80
|
+
|
64
81
|
Athens attempts to parse the sql data types into their ruby equivalents, although there's currently no support for the more complex Array/Map types.
|
65
82
|
|
66
83
|
### Configuration
|
@@ -129,6 +146,13 @@ query.cancel # Attempts to cancel an in-progress query, returns true or false
|
|
129
146
|
query.to_a(header_row: false) # If you want your query results returned without a header row of column names
|
130
147
|
```
|
131
148
|
|
149
|
+
The execute method also optionally supports the `request_token` and `work_group` [parameters](https://docs.aws.amazon.com/athena/latest/APIReference/API_StartQueryExecution.html#API_StartQueryExecution_RequestSyntax):
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
conn = Athens::Connection.new(database: 'sample')
|
153
|
+
query = conn.execute("SELECT * FROM mytable", request_token: single_use_token, work_group: my_work_group)
|
154
|
+
```
|
155
|
+
|
132
156
|
## Development
|
133
157
|
|
134
158
|
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/Rakefile
CHANGED
data/athens.gemspec
CHANGED
@@ -32,10 +32,11 @@ Gem::Specification.new do |spec|
|
|
32
32
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
33
33
|
spec.require_paths = ["lib"]
|
34
34
|
|
35
|
-
spec.required_ruby_version = '
|
35
|
+
spec.required_ruby_version = '>= 2.4'
|
36
36
|
|
37
37
|
spec.add_dependency "aws-sdk-athena", "~> 1"
|
38
38
|
|
39
|
-
spec.add_development_dependency "bundler", "
|
40
|
-
spec.add_development_dependency "rake", "~>
|
39
|
+
spec.add_development_dependency "bundler", ">= 1.17"
|
40
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
41
|
+
spec.add_development_dependency "rexml", "~> 3.2"
|
41
42
|
end
|
data/lib/athens/connection.rb
CHANGED
@@ -8,7 +8,7 @@ module Athens
|
|
8
8
|
def initialize(database: nil, aws_client_override: {})
|
9
9
|
@database_name = database
|
10
10
|
|
11
|
-
client_config = {
|
11
|
+
client_config = {
|
12
12
|
access_key_id: Athens.configuration.aws_access_key,
|
13
13
|
secret_access_key: Athens.configuration.aws_secret_key,
|
14
14
|
region: Athens.configuration.aws_region
|
@@ -19,26 +19,28 @@ module Athens
|
|
19
19
|
|
20
20
|
# Runs a query against Athena, returning an Athens::Query object
|
21
21
|
# that you can use to wait for it to finish or get the results
|
22
|
-
def execute(query)
|
22
|
+
def execute(query, request_token: nil, work_group: nil)
|
23
23
|
if @database_name
|
24
24
|
resp = @client.start_query_execution(
|
25
25
|
query_string: query,
|
26
26
|
query_execution_context: context,
|
27
|
-
result_configuration: result_config
|
27
|
+
result_configuration: result_config,
|
28
|
+
client_request_token: request_token,
|
29
|
+
work_group: work_group
|
28
30
|
)
|
29
31
|
else
|
30
32
|
resp = @client.start_query_execution(
|
31
33
|
query_string: query,
|
32
34
|
result_configuration: result_config
|
33
35
|
)
|
34
|
-
end
|
36
|
+
end
|
35
37
|
|
36
38
|
return Athens::Query.new(self, resp.query_execution_id)
|
37
39
|
end
|
38
40
|
|
39
41
|
private
|
40
42
|
|
41
|
-
def context
|
43
|
+
def context
|
42
44
|
Aws::Athena::Types::QueryExecutionContext.new(database: @database_name)
|
43
45
|
end
|
44
46
|
|
data/lib/athens/error.rb
CHANGED
data/lib/athens/query.rb
CHANGED
@@ -69,12 +69,10 @@ module Athens
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
def
|
72
|
+
def rows
|
73
73
|
raise InvalidRequestError.new("Query must be in SUCCEEDED state to return results") unless @state == 'SUCCEEDED'
|
74
74
|
|
75
|
-
|
76
|
-
# Need to load and map all of the rows from the original result
|
77
|
-
@results = []
|
75
|
+
Enumerator.new do |y|
|
78
76
|
result = @connection.client.get_query_results({query_execution_id: @query_execution_id})
|
79
77
|
|
80
78
|
metadata = result.result_set.result_set_metadata
|
@@ -85,53 +83,43 @@ module Athens
|
|
85
83
|
break if rows.empty?
|
86
84
|
|
87
85
|
if first
|
88
|
-
|
86
|
+
y << rows.shift.data.map {|col| col.var_char_value}
|
89
87
|
first = false
|
90
88
|
end
|
91
89
|
|
92
|
-
rows.each
|
93
|
-
@results << map_types(metadata, row)
|
94
|
-
end
|
90
|
+
rows.each {|row| y << map_types(metadata, row)}
|
95
91
|
|
96
|
-
|
97
|
-
result = @connection.client.get_query_results({
|
98
|
-
query_execution_id: @query_execution_id,
|
99
|
-
next_token: result.next_token
|
100
|
-
})
|
101
|
-
else
|
102
|
-
# No more rows, break out and return our mapped data
|
103
|
-
break
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
92
|
+
break unless result.next_token
|
107
93
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
94
|
+
result = @connection.client.get_query_results({
|
95
|
+
query_execution_id: @query_execution_id,
|
96
|
+
next_token: result.next_token
|
97
|
+
})
|
98
|
+
end
|
112
99
|
end
|
113
100
|
end
|
114
101
|
|
115
|
-
def
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
headers = all_rows.shift
|
120
|
-
|
121
|
-
@hash_results = []
|
102
|
+
def records
|
103
|
+
Enumerator.new do |y|
|
104
|
+
headers = nil
|
122
105
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
map[header] = row[index]
|
128
|
-
end
|
129
|
-
@hash_results << map
|
106
|
+
rows.each_with_index do |row|
|
107
|
+
if headers.nil?
|
108
|
+
headers = row
|
109
|
+
next
|
130
110
|
end
|
111
|
+
|
112
|
+
y << Hash[headers.zip(row)]
|
131
113
|
end
|
132
114
|
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def to_a(header_row: true)
|
118
|
+
(@results ||= rows.to_a).drop(header_row ? 0 : 1)
|
119
|
+
end
|
133
120
|
|
134
|
-
|
121
|
+
def to_h
|
122
|
+
@hash_results ||= records.to_a
|
135
123
|
end
|
136
124
|
|
137
125
|
private
|
@@ -151,29 +139,36 @@ module Athens
|
|
151
139
|
|
152
140
|
metadata.column_info.each_with_index do |col, index|
|
153
141
|
data = row.data[index].var_char_value
|
142
|
+
nullable = ["UNKNOWN", "NULLABLE"].include?(col.nullable)
|
154
143
|
|
155
|
-
|
156
|
-
when 'tinyint', 'smallint', 'int', 'integer', 'bigint'
|
157
|
-
mapped << data.to_i
|
158
|
-
when 'timestamp'
|
159
|
-
mapped << Time.parse(data)
|
160
|
-
when 'varchar'
|
144
|
+
if nullable && data.nil?
|
161
145
|
mapped << data
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
146
|
+
elsif !nullable && data.nil?
|
147
|
+
raise InvalidNullError.new("Got null data from a non-null field (#{col.name})")
|
148
|
+
else
|
149
|
+
case col.type
|
150
|
+
when 'tinyint', 'smallint', 'int', 'integer', 'bigint'
|
151
|
+
mapped << data.to_i
|
152
|
+
when 'timestamp'
|
153
|
+
mapped << Time.parse(data)
|
154
|
+
when 'varchar', 'string'
|
155
|
+
mapped << data
|
156
|
+
when 'float', 'double'
|
157
|
+
mapped << data.to_f
|
158
|
+
when 'decimal'
|
159
|
+
if @decimal_without_new
|
160
|
+
mapped << BigDecimal(data)
|
161
|
+
else
|
162
|
+
mapped << BigDecimal.new(data)
|
163
|
+
end
|
164
|
+
when 'date'
|
165
|
+
mapped << Date.parse(data)
|
166
|
+
when 'boolean'
|
167
|
+
mapped << (data == "true")
|
167
168
|
else
|
168
|
-
|
169
|
+
puts "WARNING: Unsupported type: #{col.type}, defaulting to string"
|
170
|
+
mapped << data
|
169
171
|
end
|
170
|
-
when 'date'
|
171
|
-
mapped << Date.parse(data)
|
172
|
-
when 'boolean'
|
173
|
-
mapped << (data == "true")
|
174
|
-
else
|
175
|
-
puts "WARNING: Unsupported type: #{col.type}, defaulting to string"
|
176
|
-
mapped << data
|
177
172
|
end
|
178
173
|
end
|
179
174
|
|
data/lib/athens/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: athens
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Schulte
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-athena
|
@@ -28,14 +28,14 @@ dependencies:
|
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '1.17'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.17'
|
41
41
|
- !ruby/object:Gem::Dependency
|
@@ -44,14 +44,28 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '13.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '13.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rexml
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.2'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
68
|
+
version: '3.2'
|
55
69
|
description: Allows you to easily access AWS Athena databases and run queries
|
56
70
|
email:
|
57
71
|
- chris@oceanbreezesoftware.com
|
@@ -84,13 +98,13 @@ metadata:
|
|
84
98
|
homepage_uri: https://github.com/getletterpress/athens
|
85
99
|
source_code_uri: https://github.com/getletterpress/athens
|
86
100
|
changelog_uri: https://github.com/getletterpress/athens/CHANGELOG.md
|
87
|
-
post_install_message:
|
101
|
+
post_install_message:
|
88
102
|
rdoc_options: []
|
89
103
|
require_paths:
|
90
104
|
- lib
|
91
105
|
required_ruby_version: !ruby/object:Gem::Requirement
|
92
106
|
requirements:
|
93
|
-
- - "
|
107
|
+
- - ">="
|
94
108
|
- !ruby/object:Gem::Version
|
95
109
|
version: '2.4'
|
96
110
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
@@ -99,9 +113,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
99
113
|
- !ruby/object:Gem::Version
|
100
114
|
version: '0'
|
101
115
|
requirements: []
|
102
|
-
|
103
|
-
|
104
|
-
signing_key:
|
116
|
+
rubygems_version: 3.1.4
|
117
|
+
signing_key:
|
105
118
|
specification_version: 4
|
106
119
|
summary: Run simple SQL queries in AWS Athena
|
107
120
|
test_files: []
|