trino-client 2.0.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ChangeLog.md +4 -0
- data/lib/trino/client/column_value_parser.rb +115 -0
- data/lib/trino/client/query.rb +28 -0
- data/lib/trino/client/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 887c8e77f79998cb038d93f27879b2ca268d455343cb4628b865306ba894ab1d
|
4
|
+
data.tar.gz: 2f28c84bc26e36da9de4f5b3d275d099ecd304341f6640bd75c973fd8d14eded
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34c0baa8b9f349abc713cb1ddfcd639d04a755308c8836a504fe6e58b62992f5cea14c34e8df3d29ae0351770550519aaf3d70f12ba8a63b5a8d28ffec463dc4
|
7
|
+
data.tar.gz: fd12c7387e02b80911b2a1f6f95e68fa2e4ce798b3dea762c9097d9809847993840d424a4b47a95e62bf1ff6649294649ec184065beb83b86f12b5ba2a655900
|
data/ChangeLog.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
trino-client-ruby
|
2
2
|
====
|
3
|
+
## 2.1.0
|
4
|
+
- Add utility for transforming Trino ROW type columns into Ruby hashes ([#117](https://github.com/treasure-data/trino-client-ruby/issues/117)) [[e14251c](https://github.com/treasure-data/trino-client-ruby/commit/e14251c)]
|
5
|
+
- Bump actions/checkout from 3 to 4 ([#116](https://github.com/treasure-data/trino-client-ruby/issues/116)) [[ebd9d9e](https://github.com/treasure-data/trino-client-ruby/commit/ebd9d9e)]
|
6
|
+
|
3
7
|
## 2.0.1
|
4
8
|
- Reduce published gem size ([#113](https://github.com/treasure-data/trino-client-ruby/issues/113)) [[4e03819](https://github.com/treasure-data/trino-client-ruby/commit/4e03819)]
|
5
9
|
- Update standard requirement from ~> 1.24.3 to ~> 1.30.1 ([#112](https://github.com/treasure-data/trino-client-ruby/issues/112)) [[b9f9c0c](https://github.com/treasure-data/trino-client-ruby/commit/b9f9c0c)]
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module Trino::Client
|
2
|
+
class ColumnValueParser
|
3
|
+
INSIDE_MATCHING_PARENS_REGEX = /\((?>[^)(]+|\g<0>)*\)/
|
4
|
+
|
5
|
+
attr_reader :name, :type, :scalar_parser
|
6
|
+
|
7
|
+
def initialize(column, scalar_parser = nil)
|
8
|
+
@name = column.name
|
9
|
+
@type = prepare_type_for_parsing(column.type)
|
10
|
+
@scalar_parser = scalar_parser
|
11
|
+
end
|
12
|
+
|
13
|
+
# Public: Parse the value of a row's field by using its column's Trino type.
|
14
|
+
# Trino types can be scalars like VARCHAR and TIMESTAMP or complex types
|
15
|
+
# like ARRAY and ROW. ROW types are treated as objects.
|
16
|
+
# An ARRAY column's type is an array of types as you'd expect. A ROW
|
17
|
+
# column's type is a comma-separated list of space-separated (name, type) tuples.
|
18
|
+
#
|
19
|
+
# data - The value of a row's field. Can be a string, number, an array of those,
|
20
|
+
# or an arrays of arrays, etc.
|
21
|
+
# dtype - The Trino type string of the column. See above explanation.
|
22
|
+
#
|
23
|
+
# Returns:
|
24
|
+
# - The given value for strings and numbers
|
25
|
+
# - A Time for timestamps
|
26
|
+
# - A Hash of { field1 => value1, field2 => value2, ...etc } for row types
|
27
|
+
# - An array of the above for array types
|
28
|
+
def value(data, dtype = type)
|
29
|
+
# Convert Trino ARRAY elements into Ruby Arrays
|
30
|
+
if starts_with?(dtype, 'array(')
|
31
|
+
return parse_array_element(data, dtype)
|
32
|
+
|
33
|
+
# Convert Trino ROW elements into Ruby Hashes
|
34
|
+
elsif starts_with?(dtype, 'row(')
|
35
|
+
return parse_row_element(data, dtype)
|
36
|
+
|
37
|
+
# If defined, use scalar_parser to convert scalar types
|
38
|
+
elsif !scalar_parser.nil?
|
39
|
+
return scalar_parser.call(data, dtype)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Otherwise, values are returned unaltered
|
43
|
+
data
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# Private: Remove quotation marks and handle recent versions of
|
49
|
+
# Trino having a 'with time zone' suffix on some fields that breaks
|
50
|
+
# out assumption that types don't have spaces in them.
|
51
|
+
#
|
52
|
+
# Returns a string.
|
53
|
+
def prepare_type_for_parsing(type)
|
54
|
+
type.gsub('"', '').gsub(' with time zone', '_with_time_zone')
|
55
|
+
end
|
56
|
+
|
57
|
+
def parse_array_element(data, dtype)
|
58
|
+
# If the element is empty, return an empty array
|
59
|
+
return [] if blank?(data)
|
60
|
+
|
61
|
+
# Inner data type will be the current dtype with `array(` and `)` chopped off
|
62
|
+
inner_dtype = dtype.match(INSIDE_MATCHING_PARENS_REGEX)[0][1..-2]
|
63
|
+
|
64
|
+
data.map { |inner_data| value(inner_data, inner_dtype) }
|
65
|
+
end
|
66
|
+
|
67
|
+
def parse_row_element(data, dtype)
|
68
|
+
# If the element is empty, return an empty object
|
69
|
+
return {} if blank?(data)
|
70
|
+
|
71
|
+
parsed_row_element = {}
|
72
|
+
|
73
|
+
inner_dtype = dtype.match(INSIDE_MATCHING_PARENS_REGEX)[0][1..-2]
|
74
|
+
elems = inner_dtype.split(' ')
|
75
|
+
num_elems_to_skip = 0
|
76
|
+
field_position = 0
|
77
|
+
|
78
|
+
# Iterate over each datatype of the row and mutate parsed_row_element
|
79
|
+
# to have a key of the field name and value for that field's value.
|
80
|
+
elems.each_with_index do |field, i|
|
81
|
+
# We detected an array or row and are skipping all of the elements within it
|
82
|
+
# since its conversion was handled by calling `value` recursively.
|
83
|
+
if num_elems_to_skip.positive?
|
84
|
+
num_elems_to_skip -= 1
|
85
|
+
next
|
86
|
+
end
|
87
|
+
|
88
|
+
# Field names never have these characters and are never the last element.
|
89
|
+
next if field.include?(',') || field.include?('(') || field.include?(')') || i == elems.length - 1
|
90
|
+
|
91
|
+
type = elems[(i + 1)..].join(' ')
|
92
|
+
|
93
|
+
# If this row has a nested array or row, the type of this field is that array or row's type.
|
94
|
+
if starts_with?(type, 'array(') || starts_with?(type, 'row(')
|
95
|
+
datatype = type.sub(/\(.*/, '')
|
96
|
+
type = "#{datatype}#{type.match(INSIDE_MATCHING_PARENS_REGEX)[0]}"
|
97
|
+
num_elems_to_skip = type.split(' ').length # see above comment about num_elems_to_skip
|
98
|
+
end
|
99
|
+
|
100
|
+
parsed_row_element[field] = value(data[field_position], type)
|
101
|
+
field_position += 1
|
102
|
+
end
|
103
|
+
|
104
|
+
parsed_row_element
|
105
|
+
end
|
106
|
+
|
107
|
+
def blank?(obj)
|
108
|
+
obj.respond_to?(:empty?) ? !!obj.empty? : !obj
|
109
|
+
end
|
110
|
+
|
111
|
+
def starts_with?(str, prefix)
|
112
|
+
prefix.respond_to?(:to_str) && str[0, prefix.length] == prefix
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
data/lib/trino/client/query.rb
CHANGED
@@ -18,6 +18,7 @@ module Trino::Client
|
|
18
18
|
require 'faraday'
|
19
19
|
require 'faraday/gzip'
|
20
20
|
require 'faraday/follow_redirects'
|
21
|
+
require 'trino/client/column_value_parser'
|
21
22
|
require 'trino/client/models'
|
22
23
|
require 'trino/client/errors'
|
23
24
|
require 'trino/client/faraday_client'
|
@@ -44,6 +45,19 @@ module Trino::Client
|
|
44
45
|
Trino::Client.faraday_client(options)
|
45
46
|
end
|
46
47
|
|
48
|
+
def self.transform_row(column_value_parsers, row)
|
49
|
+
row_object = {}
|
50
|
+
|
51
|
+
row.each_with_index do |element, i|
|
52
|
+
column = column_value_parsers[i]
|
53
|
+
value = column.value(element)
|
54
|
+
|
55
|
+
row_object[column.name] = value
|
56
|
+
end
|
57
|
+
|
58
|
+
row_object
|
59
|
+
end
|
60
|
+
|
47
61
|
def initialize(api)
|
48
62
|
@api = api
|
49
63
|
end
|
@@ -86,6 +100,20 @@ module Trino::Client
|
|
86
100
|
return @api.current_results.columns
|
87
101
|
end
|
88
102
|
|
103
|
+
def column_value_parsers
|
104
|
+
@column_value_parsers ||= columns.map {|column|
|
105
|
+
ColumnValueParser.new(column)
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
def transform_rows
|
110
|
+
rows.map(&:transform_row)
|
111
|
+
end
|
112
|
+
|
113
|
+
def transform_row(row)
|
114
|
+
self.class.transform_row(column_value_parsers, row)
|
115
|
+
end
|
116
|
+
|
89
117
|
def rows
|
90
118
|
rows = []
|
91
119
|
each_row_chunk {|chunk|
|
data/lib/trino/client/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trino-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sadayuki Furuhashi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-09-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -190,6 +190,7 @@ files:
|
|
190
190
|
- lib/trino-client.rb
|
191
191
|
- lib/trino/client.rb
|
192
192
|
- lib/trino/client/client.rb
|
193
|
+
- lib/trino/client/column_value_parser.rb
|
193
194
|
- lib/trino/client/errors.rb
|
194
195
|
- lib/trino/client/faraday_client.rb
|
195
196
|
- lib/trino/client/model_versions/0.149.rb
|