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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 50686d406d4aedd29016b8b5cfee3024869e797791cc53e099dbf813f6a7d135
4
- data.tar.gz: d4d2e2762b8eba6ecaf6c2dd07c19f1db37eee5c8d1ebf4c995d88ec768fe62c
3
+ metadata.gz: 887c8e77f79998cb038d93f27879b2ca268d455343cb4628b865306ba894ab1d
4
+ data.tar.gz: 2f28c84bc26e36da9de4f5b3d275d099ecd304341f6640bd75c973fd8d14eded
5
5
  SHA512:
6
- metadata.gz: 203db357ca5034c2000d836667ac1bb92d976300d7299663105af90f284657854eb061625b48756a4cba0d21a4d8342d5006c95a7b6eab7e37ca1abbe832c21d
7
- data.tar.gz: 5566882e00f6edac34ac3d863d78aea8f3358e829b86d7ffff9f51582b42315b7a2b87e0d71a7b22cfd98eea5ac0fb20ab28f1e219991f1ac62e28256cf914ec
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
@@ -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|
@@ -15,6 +15,6 @@
15
15
  #
16
16
  module Trino
17
17
  module Client
18
- VERSION = "2.0.1"
18
+ VERSION = "2.1.0"
19
19
  end
20
20
  end
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.1
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-08-17 00:00:00.000000000 Z
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