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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '02197372c02d45a05efd88997b4cd8c01d66c869eafd6ca867f86da791ffe7b4'
4
- data.tar.gz: 1753f4f6986c4fedf82f09d9a6d9ebe0b9fb630d59261011fc3c0667108e4ed0
3
+ metadata.gz: fa391fbff6c5016740bc28cfb0692fcc79ee2e1361d31541a635691e6cbbc8a7
4
+ data.tar.gz: ef1fbb6307221f616576e844ced0ed9398ff9e6db436fde0142e58c89be8c9f5
5
5
  SHA512:
6
- metadata.gz: facc871951901270b2b61410ae471cd6d62fcb33d2a914da76855e41fbccfb5039ee4e0d086deced77bcf39bf8c07fe865c635d6659093a2acac181291c78c2a
7
- data.tar.gz: feca9c73d6145784b74dc4ce5442c2b764efda51719ff58e5fa6896d8dfd89186224d7aaa4f9ae282d58043bf5aa4f0e3576998d40ec0d9983c51d917d6d8022
6
+ metadata.gz: e37d29e7d93b1aa61d6266b5feccc3789087f697c1751830893adc4c795761f587bafdaa44f34de6b5786712d8983e66511d3d0f10fa1b0922ec6921e4201e66
7
+ data.tar.gz: 0ccaf8bbb67bceb9136806a93da4447ace996ab9709e82d8f6861249e6a62246680c3a618a1479481b931127e568e966038569da2d1814540ef64b7ab3dd155e
@@ -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!
@@ -1,33 +1,36 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- athens (0.1.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.1)
11
- aws-partitions (1.136.0)
12
- aws-sdk-athena (1.7.0)
13
- aws-sdk-core (~> 3, >= 3.39.0)
14
- aws-sigv4 (~> 1.0)
15
- aws-sdk-core (3.46.0)
16
- aws-eventstream (~> 1.0)
17
- aws-partitions (~> 1.0)
18
- aws-sigv4 (~> 1.0)
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.0.3)
20
+ aws-sigv4 (1.2.2)
21
+ aws-eventstream (~> 1, >= 1.0.2)
21
22
  jmespath (1.4.0)
22
- rake (10.5.0)
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 (~> 1.17)
30
- rake (~> 10.0)
31
+ bundler (>= 1.17)
32
+ rake (~> 13.0)
33
+ rexml (~> 3.2)
31
34
 
32
35
  BUNDLED WITH
33
- 1.17.2
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
@@ -1,2 +1 @@
1
1
  require "bundler/gem_tasks"
2
- task :default => :spec
@@ -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 = '~> 2.4'
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", "~> 1.17"
40
- spec.add_development_dependency "rake", "~> 10.0"
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
@@ -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
 
@@ -4,5 +4,6 @@ module Athens
4
4
  class QueryFailedError < Error; end
5
5
  class QueryCancelledError < Error; end
6
6
  class InvalidRequestError < Error; end
7
+ class InvalidNullError < Error; end
7
8
 
8
9
  end
@@ -69,12 +69,10 @@ module Athens
69
69
  end
70
70
  end
71
71
 
72
- def to_a(header_row: true)
72
+ def rows
73
73
  raise InvalidRequestError.new("Query must be in SUCCEEDED state to return results") unless @state == 'SUCCEEDED'
74
74
 
75
- if @results.nil?
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
- @results << rows.shift.data.map {|col| col.var_char_value}
86
+ y << rows.shift.data.map {|col| col.var_char_value}
89
87
  first = false
90
88
  end
91
89
 
92
- rows.each do |row|
93
- @results << map_types(metadata, row)
94
- end
90
+ rows.each {|row| y << map_types(metadata, row)}
95
91
 
96
- if result.next_token
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
- if header_row
109
- return @results
110
- else
111
- return @results[1, @results.size]
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 to_h
116
- if @hash_results.nil?
117
- all_rows = self.to_a(header_row: true)
118
-
119
- headers = all_rows.shift
120
-
121
- @hash_results = []
102
+ def records
103
+ Enumerator.new do |y|
104
+ headers = nil
122
105
 
123
- unless headers.nil?
124
- all_rows.each do |row|
125
- map = {}
126
- headers.each_with_index do |header, index|
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
- return @hash_results
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
- case col.type
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
- when 'float', 'double'
163
- mapped << data.to_f
164
- when 'decimal'
165
- if @decimal_without_new
166
- mapped << BigDecimal(data)
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
- mapped << BigDecimal.new(data)
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
 
@@ -1,3 +1,3 @@
1
1
  module Athens
2
- VERSION = "0.1.0"
2
+ VERSION = "0.3.3"
3
3
  end
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.1.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: 2019-03-01 00:00:00.000000000 Z
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: '10.0'
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: '10.0'
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
- rubyforge_project:
103
- rubygems_version: 2.7.8
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: []