rb_snowflake_client 1.3.0 → 1.4.0

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: ef7c1798270965128711042d7d218668b318356bf6a3fac8efc2144538c5a246
4
- data.tar.gz: a04c605cfff4659c18deb58ccdca3d49db8a6d85d98825a496ab6d8641030193
3
+ metadata.gz: 9c1581fededb6e083bc1f55249d806fca4a63462fafee98f9277986729dd1107
4
+ data.tar.gz: e810744812f56a65d519d8a30ce96e97d2f1341479ee7aeb2a50766c0f541e90
5
5
  SHA512:
6
- metadata.gz: 3633bc26af9b0912735ad82840795ab81c6178c381b11ae7ade7b6fd2272576a7a9d4f65a7cd22a5786ede9f2d153bc7ccb3a5816fe0263e48cb6f5df448297b
7
- data.tar.gz: 449e2d7140b58c6d629fd17bf4641b3d698a03d10a1fb6df3444fd3bd5bf6fd6da1f146c59d96dcedd3932ddc1f5b4b086524f427385510435e36dc8de052824
6
+ metadata.gz: 7cc78b78f3a5a3d056c826107aab889d23705ea76249800a7c098e43e8515db4fc9f85e11a2fae86cced570b1c5aaa869dded60495467bbb2b52241edd466c2e
7
+ data.tar.gz: 6b57c2a14a03fe96711d86554eb13b86bd5865a1aafa629a30ea02b2c27fc72f743f8942fc0d4d35b590d824cbd110c2ad3efbe6ffc235037c7039213644e97c
@@ -12,9 +12,9 @@ jobs:
12
12
  steps:
13
13
  - uses: actions/checkout@v3
14
14
  - name: Set up Ruby
15
- uses: ruby/setup-ruby@904f3fef85a9c80a3750cbe7d5159268fd5caa9f
15
+ uses: ruby/setup-ruby@v1
16
16
  with:
17
- ruby-version: '3.0.6'
17
+ ruby-version: '3.3'
18
18
  - name: Install dependencies
19
19
  run: bundle install
20
20
  - name: Build gem
@@ -1,5 +1,6 @@
1
1
  name: Release to Github Packages
2
2
  on:
3
+ workflow_dispatch:
3
4
  push:
4
5
  branches:
5
6
  - "master"
@@ -14,9 +15,9 @@ jobs:
14
15
  steps:
15
16
  - uses: actions/checkout@v3
16
17
  - name: Set up Ruby
17
- uses: ruby/setup-ruby@904f3fef85a9c80a3750cbe7d5159268fd5caa9f
18
+ uses: ruby/setup-ruby@v1
18
19
  with:
19
- ruby-version: '3.0.6'
20
+ ruby-version: '3.3'
20
21
  - name: Install dependencies
21
22
  run: bundle install
22
23
  - name: Build gem
@@ -1,5 +1,6 @@
1
1
  name: Release to Rubygems
2
2
  on:
3
+ workflow_dispatch:
3
4
  push:
4
5
  branches:
5
6
  - "master"
@@ -11,9 +12,9 @@ jobs:
11
12
  steps:
12
13
  - uses: actions/checkout@v3
13
14
  - name: Set up Ruby
14
- uses: ruby/setup-ruby@904f3fef85a9c80a3750cbe7d5159268fd5caa9f
15
+ uses: ruby/setup-ruby@v1
15
16
  with:
16
- ruby-version: '3.0.6'
17
+ ruby-version: '3.3'
17
18
  - name: Install dependencies
18
19
  run: bundle install
19
20
  - name: Publish to RubyGems
data/CHANGELOG.md ADDED
@@ -0,0 +1,128 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.4.0] - 2025-05-01
9
+ ### Added
10
+ - Enhanced Row API to implement Enumerable interface
11
+ - Added case-insensitive access to Row columns via both symbol and string keys
12
+ - Added numeric column access to Row (e.g., `row[0]`)
13
+ - Support setting organization or ENV["SNOWFLAKE_ORGANIZATION"] to nil or "" in JWT authentication
14
+ - Added default_role parameter and SNOWFLAKE_DEFAULT_ROLE env variable
15
+
16
+ ## [1.3.0] - 2025-01-03
17
+ ### Changed
18
+ - Bumped gem dependencies to newer versions
19
+ - Added support for role parameter in Client and query method
20
+
21
+ ## [1.2.0] - 2025-01-03
22
+ ### Changed
23
+ - Switched from Oj to JSON gem for parsing
24
+ - Improved performance by utilizing the optimized JSON gem
25
+
26
+ ## [1.1.5] - 2024-12-19
27
+ ### Fixed
28
+ - Parse exception detail OR message for better error handling
29
+
30
+ ## [1.1.4] - 2024-11-05
31
+ ### Fixed
32
+ - Fixed ENV variable issue
33
+
34
+ ## [1.1.3] - 2024-08-09
35
+ ### Added
36
+ - Retry HTTP codes in the 3xx range
37
+
38
+ ## [1.1.2] - 2024-08-06
39
+ ### Fixed
40
+ - CI error fixes
41
+
42
+ ## [1.1.1] - 2024-07-12
43
+ ### Fixed
44
+ - Added 502 to specific list of retryable HTTP error codes
45
+ - Fixed issue with checking string code presence in an array of integer values
46
+
47
+ ## [1.1.0] - 2024-06-05
48
+ ### Added
49
+ - Support for specifying a schema in query method
50
+ - Merged multiple community contributions
51
+
52
+ ## [1.0.6] - 2024-06-05
53
+ ### Added
54
+ - Allow specifying schema in query method
55
+
56
+ ## [1.0.5] - 2024-03-20
57
+ ### Added
58
+ - Added exponential backoff to retryable calls
59
+ - Improved handling of rate limiting (429 responses)
60
+
61
+ ## [1.0.4] - 2024-01-30
62
+ ### Fixed
63
+ - Fixed raise arguments
64
+ - Now properly raising OpenSSL errors to retry them
65
+
66
+ ## [1.0.3] - 2024-01-17
67
+ ### Fixed
68
+ - Now upcasing database and warehouse fields in requests
69
+ - Fixed error where lowercase field names would result in "Unable to run command without specifying database/warehouse"
70
+
71
+ ## [1.0.2] - 2024-01-16
72
+ ### Fixed
73
+ - Fixed typo in key pair memoization
74
+
75
+ ## [1.0.1] - 2024-01-09
76
+ ### Added
77
+ - Added `create_jwt_token` helper method for testing
78
+ - Support for time travel in tests
79
+
80
+ ## [1.0.0] - 2023-12-11
81
+ ### Changed
82
+ - First stable release
83
+ - Fixed markdown links in documentation
84
+
85
+ ## [0.3.0] - 2023-12-08
86
+ ### Added
87
+ - Support for Snowflake polling responses
88
+ - Handle async query execution
89
+
90
+ ## [0.2.0] - 2023-12-07
91
+ ### Added
92
+ - Extracted authentication logic into its own class
93
+ - Improved time handling for various Snowflake date/time types
94
+ - Support for TIME, DATETIME, TIMESTAMP, TIMESTAMP_LTZ, TIMESTAMP_NTZ, TIMESTAMP_TZ
95
+
96
+ ## [0.1.2] - 2023-12-04
97
+ ### Added
98
+ - Support for database parameter in requests
99
+ - Added missing dependencies to gemspec
100
+
101
+ ## [0.1.1] - 2023-12-01
102
+ ### Added
103
+ - Added `fetch` as an alias for `query` for compatibility with other clients
104
+
105
+ ## [0.1.0] - 2023-11-28
106
+ ### Added
107
+ - First minor version release with basic functionality
108
+ - Support for querying Snowflake with the HTTP API
109
+ - Support for streaming results
110
+
111
+ ## [0.0.6] - 2023-11-27
112
+ ### Changed
113
+ - Cleaned up key pair authentication
114
+ - Improved documentation with better setup instructions
115
+
116
+ ## [0.0.5] - 2023-11-27
117
+ ### Fixed
118
+ - Various bug fixes and improvements
119
+
120
+ ## [0.0.4] - 2023-11-22
121
+ ### Changed
122
+ - Fixed type handling for query results
123
+ - All specs now pass
124
+
125
+ ## [0.0.3] - 2023-11-21
126
+ ### Changed
127
+ - Renamed to RubySnowflake namespace
128
+ - Initial gem structure
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rb_snowflake_client (1.3.0)
4
+ rb_snowflake_client (1.4.0)
5
5
  bigdecimal (>= 3.0)
6
6
  concurrent-ruby (>= 1.2)
7
7
  connection_pool (>= 2.4)
@@ -16,15 +16,15 @@ GEM
16
16
  base64 (0.2.0)
17
17
  bigdecimal (3.1.9)
18
18
  coderay (1.1.3)
19
- concurrent-ruby (1.3.4)
20
- connection_pool (2.4.1)
21
- diff-lcs (1.5.1)
22
- dotenv (3.1.7)
23
- json (2.9.1)
19
+ concurrent-ruby (1.3.5)
20
+ connection_pool (2.5.3)
21
+ diff-lcs (1.6.1)
22
+ dotenv (3.1.8)
23
+ json (2.11.3)
24
24
  jwt (2.10.1)
25
25
  base64
26
26
  method_source (1.1.0)
27
- parallel (1.26.3)
27
+ parallel (1.27.0)
28
28
  pry (0.15.2)
29
29
  coderay (~> 1.1)
30
30
  method_source (~> 1.0)
@@ -34,7 +34,7 @@ GEM
34
34
  rspec-core (~> 3.13.0)
35
35
  rspec-expectations (~> 3.13.0)
36
36
  rspec-mocks (~> 3.13.0)
37
- rspec-core (3.13.2)
37
+ rspec-core (3.13.3)
38
38
  rspec-support (~> 3.13.0)
39
39
  rspec-expectations (3.13.3)
40
40
  diff-lcs (>= 1.2.0, < 2.0)
data/README.md CHANGED
@@ -30,11 +30,12 @@ require "rb_snowflake_client"
30
30
  client = RubySnowflake::Client.new(
31
31
  "https://yourinstance.region.snowflakecomputing.com", # insert your URL here
32
32
  File.read("secrets/my_key.pem"), # your private key in PEM format (scroll down for instructions)
33
- "snowflake-organization", # your account name (doesn't match your URL)
33
+ "snowflake-organization", # your account name (doesn't match your URL), using nil may be required depending on your snowflake account
34
34
  "snowflake-account", # typically your subdomain
35
35
  "snowflake-user", # Your snowflake user
36
36
  "some_warehouse", # The name of your warehouse to use by default
37
37
  "some_database", # The name of the database in the context of which the queries will run
38
+ default_role: "some_role", # The name of the role with which the queries will run. A `nil` value uses the primary role of the user.
38
39
  max_connections: 12, # Config options can be passed in
39
40
  connection_timeout: 45, # See below for the full set of options
40
41
  query_timeout: 1200, # how long to wait for queries, in seconds
@@ -48,10 +49,12 @@ Available ENV variables (see below in the config section for details)
48
49
  - `SNOWFLAKE_PRIVATE_KEY_PATH` or `SNOWFLAKE_PRIVATE_KEY`
49
50
  - Use either the key or the path. Key takes precedence if both are provided.
50
51
  - `SNOWFLAKE_ORGANIZATION`
52
+ - Optional, if you leave it off, the library will authenticate with an account name of only SNOWFLAKE_ACCOUNT
51
53
  - `SNOWFLAKE_ACCOUNT`
52
54
  - `SNOWFLAKE_USER`
53
55
  - `SNOWFLAKE_DEFAULT_WAREHOUSE`
54
56
  - `SNOWFLAKE_DEFAULT_DATABASE`
57
+ - `SNOWFLAKE_DEFAULT_ROLE`
55
58
  - `SNOWFLAKE_JWT_TOKEN_TTL`
56
59
  - `SNOWFLAKE_CONNECTION_TIMEOUT`
57
60
  - `SNOWFLAKE_MAX_CONNECTIONS`
@@ -69,9 +72,19 @@ result = client.query("SELECT ID, NAME FROM SOMETABLE")
69
72
 
70
73
  # result is Enumerable
71
74
  result.each do |row|
72
- puts row[:id] # row supports access with symbols
73
- puts row["name"] # or case insensitive strings
74
- puts row.to_h # and can produce a hash with keys/values
75
+ # Row implements Enumerable and provides flexible column access:
76
+ puts row[:id] # access with symbols (case-insensitive)
77
+ puts row["name"] # access with strings (case-insensitive)
78
+ puts row[0] # access with numeric indices
79
+
80
+ # Row has Enumerable methods
81
+ puts row.keys # get all column names
82
+ puts row.values # get all values
83
+ puts row.to_h # convert to Hash with column names as keys
84
+
85
+ # Use all Enumerable methods
86
+ row.each { |column_name, value| puts "#{column_name}: #{value}" }
87
+ filtered = row.select { |column, value| column.start_with?("i") }
75
88
  end
76
89
  ```
77
90
 
@@ -111,6 +124,14 @@ client.query("SELECT * FROM BIGTABLE", warehouse: "FAST_WH")
111
124
  client.query("SELECT * FROM BIGTABLE", schema: "MY_SCHEMA")
112
125
  ```
113
126
 
127
+ ## Specifying role
128
+
129
+ Queries by default use the primary role assigned to the account. If there are multiple roles you can switch between them on a per query basis.
130
+
131
+ ```ruby
132
+ client.query("SELECT * FROM BIGTABLE", role: "MY_ROLE")
133
+ ```
134
+
114
135
  ## Binding parameters
115
136
 
116
137
  Say we have `BIGTABLE` with a `data` column of a type `VARIANT`.
@@ -157,7 +178,9 @@ end
157
178
 
158
179
  1. Does not yet support multiple statements (work around is to wrap in `BEGIN ... END`)
159
180
  2. Only supports key pair authentication
160
- 3. Its faster to work directly with the row value and not call to_h if you don't need to
181
+ 3. It's faster to work directly with the row value and not call to_h if you don't need to
182
+ 4. Rows are Enumerable, providing access to methods like `each`, `map`, `select`, `keys`, and `values`
183
+ 5. Row column access is case-insensitive and supports string keys, symbol keys, and numeric indices
161
184
 
162
185
  # Setting up a user for key pair authentication
163
186
 
@@ -205,7 +228,7 @@ or alternatively, use the client to verify:
205
228
  client = RubySnowflake::Client.new(
206
229
  "https://yourinstance.region.snowflakecomputing.com", # insert your URL here
207
230
  File.read("secrets/my_key.pem"), # path to your private key
208
- "snowflake-organization", # your account name (doesn't match your URL)
231
+ "snowflake-organization", # your account name (doesn't match your URL), using nil may be required depending on your snowflake account
209
232
  "snowflake-account", # typically your subdomain
210
233
  "snowflake-user", # Your snowflake user
211
234
  "some_warehouse", # The name of your warehouse to use by default
@@ -213,6 +236,10 @@ client = RubySnowflake::Client.new(
213
236
  )
214
237
  ```
215
238
 
239
+ # Change Log
240
+
241
+ See [Change Log](CHANGELOG.md)
242
+
216
243
  # Code of conduct
217
244
 
218
245
  See [Code of Coduct](CODE_OF_CONDUCT.md)
@@ -30,8 +30,8 @@ module RubySnowflake
30
30
  private_key = OpenSSL::PKey.read(@private_key_pem)
31
31
 
32
32
  payload = {
33
- :iss => "#{@organization.upcase}-#{@account.upcase}.#{@user.upcase}.#{public_key_fingerprint}",
34
- :sub => "#{@organization.upcase}-#{@account.upcase}.#{@user.upcase}",
33
+ :iss => "#{account_name}.#{@user.upcase}.#{public_key_fingerprint}",
34
+ :sub => "#{account_name}.#{@user.upcase}",
35
35
  :iat => now,
36
36
  :exp => @token_expires_at
37
37
  }
@@ -45,6 +45,14 @@ module RubySnowflake
45
45
  Time.now.to_i > @token_expires_at
46
46
  end
47
47
 
48
+ def account_name
49
+ if @organization == nil || @organization == ""
50
+ @account.upcase
51
+ else
52
+ "#{@organization.upcase}-#{@account.upcase}"
53
+ end
54
+ end
55
+
48
56
  def public_key_fingerprint
49
57
  return @public_key_fingerprint unless @public_key_fingerprint.nil?
50
58
 
@@ -22,22 +22,12 @@ require_relative "streaming_result"
22
22
 
23
23
  module RubySnowflake
24
24
  class Error < StandardError
25
- # This will get pulled through to Sentry, see:
26
- # https://github.com/getsentry/sentry-ruby/blob/11ecd254c0d2cae2b327f0348074e849095aa32d/sentry-ruby/lib/sentry/error_event.rb#L31-L33
27
- attr_reader :sentry_context
28
-
29
25
  def initialize(details)
30
- @sentry_context = details
31
26
  @details = details
32
27
  end
33
28
 
34
29
  def message
35
- if @details == {}
36
- super
37
- else
38
- @details.to_s
39
- end
40
-
30
+ @details.to_s
41
31
  end
42
32
  end
43
33
 
@@ -67,6 +57,8 @@ module RubySnowflake
67
57
  DEFAULT_HTTP_RETRIES = 2
68
58
  # how long to wait to allow a query to complete, in seconds
69
59
  DEFAULT_QUERY_TIMEOUT = 600 # 10 minutes
60
+ # default role to use
61
+ DEFAULT_ROLE = nil
70
62
 
71
63
  JSON_PARSE_OPTIONS = { decimal_class: BigDecimal }.freeze
72
64
  VALID_RESPONSE_CODES = %w(200 202).freeze
@@ -74,7 +66,7 @@ module RubySnowflake
74
66
  POLLING_INTERVAL = 2 # seconds
75
67
 
76
68
  # can't be set after initialization
77
- attr_reader :connection_timeout, :max_connections, :logger, :max_threads_per_query, :thread_scale_factor, :http_retries, :query_timeout
69
+ attr_reader :connection_timeout, :max_connections, :logger, :max_threads_per_query, :thread_scale_factor, :http_retries, :query_timeout, :default_role
78
70
 
79
71
  def self.from_env(logger: DEFAULT_LOGGER,
80
72
  log_level: DEFAULT_LOG_LEVEL,
@@ -84,14 +76,15 @@ module RubySnowflake
84
76
  max_threads_per_query: env_option("SNOWFLAKE_MAX_THREADS_PER_QUERY", DEFAULT_MAX_THREADS_PER_QUERY),
85
77
  thread_scale_factor: env_option("SNOWFLAKE_THREAD_SCALE_FACTOR", DEFAULT_THREAD_SCALE_FACTOR),
86
78
  http_retries: env_option("SNOWFLAKE_HTTP_RETRIES", DEFAULT_HTTP_RETRIES),
87
- query_timeout: env_option("SNOWFLAKE_QUERY_TIMEOUT", DEFAULT_QUERY_TIMEOUT))
79
+ query_timeout: env_option("SNOWFLAKE_QUERY_TIMEOUT", DEFAULT_QUERY_TIMEOUT),
80
+ default_role: env_option("SNOWFLAKE_DEFAULT_ROLE", DEFAULT_ROLE))
88
81
  private_key =
89
82
  if key = ENV["SNOWFLAKE_PRIVATE_KEY"]
90
83
  key
91
84
  elsif path = ENV["SNOWFLAKE_PRIVATE_KEY_PATH"]
92
85
  File.read(path)
93
86
  else
94
- raise MissingConfig.new({}), "Either ENV['SNOWFLAKE_PRIVATE_KEY'] or ENV['SNOWFLAKE_PRIVATE_KEY_PATH'] must be set"
87
+ raise MissingConfig, "Either ENV['SNOWFLAKE_PRIVATE_KEY'] or ENV['SNOWFLAKE_PRIVATE_KEY_PATH'] must be set"
95
88
  end
96
89
 
97
90
  new(
@@ -102,6 +95,7 @@ module RubySnowflake
102
95
  ENV.fetch("SNOWFLAKE_USER"),
103
96
  ENV["SNOWFLAKE_DEFAULT_WAREHOUSE"],
104
97
  ENV["SNOWFLAKE_DEFAULT_DATABASE"],
98
+ default_role: ENV.fetch("SNOWFLAKE_DEFAULT_ROLE", nil),
105
99
  logger: logger,
106
100
  log_level: log_level,
107
101
  jwt_token_ttl: jwt_token_ttl,
@@ -116,6 +110,7 @@ module RubySnowflake
116
110
 
117
111
  def initialize(
118
112
  uri, private_key, organization, account, user, default_warehouse, default_database,
113
+ default_role: nil,
119
114
  logger: DEFAULT_LOGGER,
120
115
  log_level: DEFAULT_LOG_LEVEL,
121
116
  jwt_token_ttl: DEFAULT_JWT_TOKEN_TTL,
@@ -131,6 +126,7 @@ module RubySnowflake
131
126
  KeyPairJwtAuthManager.new(organization, account, user, private_key, jwt_token_ttl)
132
127
  @default_warehouse = default_warehouse
133
128
  @default_database = default_database
129
+ @default_role = default_role
134
130
 
135
131
  # set defaults for config settings
136
132
  @logger = logger
@@ -147,9 +143,10 @@ module RubySnowflake
147
143
  @_enable_polling_queries = false
148
144
  end
149
145
 
150
- def query(query, warehouse: nil, streaming: false, database: nil, schema: nil, bindings: nil)
146
+ def query(query, warehouse: nil, streaming: false, database: nil, schema: nil, bindings: nil, role: nil)
151
147
  warehouse ||= @default_warehouse
152
148
  database ||= @default_database
149
+ role ||= @default_role
153
150
 
154
151
  query_start_time = Time.now.to_i
155
152
  response = nil
@@ -159,7 +156,8 @@ module RubySnowflake
159
156
  "schema" => schema&.upcase,
160
157
  "database" => database&.upcase,
161
158
  "statement" => query,
162
- "bindings" => bindings
159
+ "bindings" => bindings,
160
+ "role" => role
163
161
  }
164
162
 
165
163
  response = request_with_auth_and_headers(
@@ -228,11 +226,11 @@ module RubySnowflake
228
226
 
229
227
  # there are a class of errors we want to retry rather than just giving up
230
228
  if retryable_http_response_code?(response.code)
231
- raise RetryableBadResponseError.new({}),
229
+ raise RetryableBadResponseError,
232
230
  "Retryable bad response! Got code: #{response.code}, w/ message #{response.body}"
233
231
 
234
232
  else # not one we should retry
235
- raise BadResponseError.new({}),
233
+ raise BadResponseError,
236
234
  "Bad response! Got code: #{response.code}, w/ message #{response.body}"
237
235
  end
238
236
  end
@@ -5,6 +5,8 @@ require "time"
5
5
 
6
6
  module RubySnowflake
7
7
  class Row
8
+ include Enumerable
9
+
8
10
  EPOCH_JULIAN_DAY_NUMBER = Date.new(1970,1,1).jd
9
11
  TIME_FORMAT = "%s.%N".freeze
10
12
 
@@ -16,7 +18,13 @@ module RubySnowflake
16
18
 
17
19
  # see: https://docs.snowflake.com/en/developer-guide/sql-api/handling-responses#getting-the-data-from-the-results
18
20
  def [](column)
19
- index = column.is_a?(Numeric) ? Integer(column) : @column_to_index[column]
21
+ index = if column.is_a?(Numeric)
22
+ Integer(column)
23
+ else
24
+ # Handle column names case-insensitively regardless of string or symbol
25
+ @column_to_index[column.to_s.downcase]
26
+ end
27
+
20
28
  return nil if index.nil?
21
29
  return nil if @data[index].nil?
22
30
 
@@ -49,12 +57,24 @@ module RubySnowflake
49
57
  end
50
58
  end
51
59
 
52
- def to_h
53
- output = {}
60
+ def each
61
+ return to_enum __method__ unless block_given?
62
+
54
63
  @column_to_index.each_pair do |name, index|
55
- output[name.downcase] = self[index]
64
+ yield(name, self[index])
56
65
  end
57
- output
66
+
67
+ self
68
+ end
69
+
70
+ def keys
71
+ map { |k, _| k }
72
+ end
73
+
74
+ alias columns keys
75
+
76
+ def values
77
+ map { |_, v| v }
58
78
  end
59
79
 
60
80
  def to_s
@@ -1,3 +1,3 @@
1
1
  module RubySnowflake
2
- VERSION = "1.3.0"
2
+ VERSION = "1.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rb_snowflake_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rinsed
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-01-03 00:00:00.000000000 Z
11
+ date: 2025-05-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bigdecimal
@@ -124,6 +124,7 @@ files:
124
124
  - ".github/workflows/release-gh-packages.yml"
125
125
  - ".github/workflows/release-rubygems.yml"
126
126
  - ".gitignore"
127
+ - CHANGELOG.md
127
128
  - CODE_OF_CONDUCT.md
128
129
  - Gemfile
129
130
  - Gemfile.lock
@@ -146,7 +147,7 @@ homepage: https://github.com/rinsed-org/rb-snowflake-client
146
147
  licenses:
147
148
  - MIT
148
149
  metadata: {}
149
- post_install_message:
150
+ post_install_message:
150
151
  rdoc_options: []
151
152
  require_paths:
152
153
  - lib
@@ -161,8 +162,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
161
162
  - !ruby/object:Gem::Version
162
163
  version: '0'
163
164
  requirements: []
164
- rubygems_version: 3.2.33
165
- signing_key:
165
+ rubygems_version: 3.5.22
166
+ signing_key:
166
167
  specification_version: 4
167
168
  summary: Snowflake connector for Ruby
168
169
  test_files: []