trino-client 2.0.1 → 2.2.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 +7 -0
- data/README.md +13 -0
- data/lib/trino/client/column_value_parser.rb +115 -0
- data/lib/trino/client/query.rb +31 -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: a9ecbdf7d017c29ac4e645d54564a701538724367f8ae62551c5e5dce705f91f
|
4
|
+
data.tar.gz: 78f07db77b0c6231c563c4a39a74e07d186c93b0b0ad03327439c9781e5d577d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c6c3b16e146d2141df38a4bd10e873cedcb18d3a0f6cb8908122382ac2cc44b471a27a4c243981ff9783da450f497ef4219d6bf4a4cc1c4e94a7d2a6ab084f2
|
7
|
+
data.tar.gz: 71bf6ac5e65dada7e5f02f03f7abf13132a81849520720a41641acc2041ef2bfbd4f8000de476d968dfec3c5666cf94c6acff52ec2771aaabb924bfddd228d44
|
data/ChangeLog.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
trino-client-ruby
|
2
2
|
====
|
3
|
+
## 2.2.0
|
4
|
+
- Add transform_row and scalar_parser documentation and make them easier to use ([#118](https://github.com/treasure-data/trino-client-ruby/issues/118)) [[41ffca7](https://github.com/treasure-data/trino-client-ruby/commit/41ffca7)]
|
5
|
+
|
6
|
+
## 2.1.0
|
7
|
+
- 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)]
|
8
|
+
- 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)]
|
9
|
+
|
3
10
|
## 2.0.1
|
4
11
|
- 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
12
|
- 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)]
|
data/README.md
CHANGED
@@ -64,6 +64,19 @@ query = client.query("select * from sys.node")
|
|
64
64
|
query_id = query.query_info.query_id
|
65
65
|
query.each_row {|row| ... } # when a thread is processing the query,
|
66
66
|
client.kill(query_id) # another thread / process can kill the query.
|
67
|
+
|
68
|
+
# Use Query#transform_row to parse Trino ROW types into Ruby Hashes.
|
69
|
+
# You can also set a scalar_parser to parse scalars how you'd like them.
|
70
|
+
scalar_parser = -> (data, type) { (type === 'json') ? JSON.parse(data) : data }
|
71
|
+
client.query("select * from sys.node") do |q|
|
72
|
+
q.scalar_parser = scalar_parser
|
73
|
+
|
74
|
+
# get query results. it feeds more rows until
|
75
|
+
# query execution finishes:
|
76
|
+
q.each_row {|row|
|
77
|
+
p q.transform_row(row)
|
78
|
+
}
|
79
|
+
end
|
67
80
|
```
|
68
81
|
|
69
82
|
## Build models
|
@@ -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,21 @@ 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
|
+
|
61
|
+
attr_accessor :scalar_parser
|
62
|
+
|
47
63
|
def initialize(api)
|
48
64
|
@api = api
|
49
65
|
end
|
@@ -86,6 +102,21 @@ module Trino::Client
|
|
86
102
|
return @api.current_results.columns
|
87
103
|
end
|
88
104
|
|
105
|
+
def column_value_parsers
|
106
|
+
@column_value_parsers ||= {}
|
107
|
+
@column_value_parsers[scalar_parser] ||= columns.map {|column|
|
108
|
+
ColumnValueParser.new(column, scalar_parser)
|
109
|
+
}
|
110
|
+
end
|
111
|
+
|
112
|
+
def transform_rows
|
113
|
+
rows.map { |row| transform_row(row) }
|
114
|
+
end
|
115
|
+
|
116
|
+
def transform_row(row)
|
117
|
+
self.class.transform_row(column_value_parsers, row)
|
118
|
+
end
|
119
|
+
|
89
120
|
def rows
|
90
121
|
rows = []
|
91
122
|
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.2.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-28 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
|