altertable-lakehouse 0.7.0 → 0.8.1
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 +4 -4
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +20 -0
- data/Gemfile.lock +1 -1
- data/README.md +2 -1
- data/lib/altertable/lakehouse/client.rb +39 -7
- data/lib/altertable/lakehouse/errors.rb +21 -0
- data/lib/altertable/lakehouse/models.rb +4 -2
- data/lib/altertable/lakehouse/version.rb +1 -1
- data/rbi/altertable/lakehouse.rbi +27 -2
- data/sig/altertable/lakehouse/errors.rbs +16 -0
- data/sig/altertable/lakehouse/models.rbs +3 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c92cf2b0a1bf2f44a8d3b2e7934a5b9f3399293409333cbd19e5749158272176
|
|
4
|
+
data.tar.gz: 44e709abf74aa54c03345afd11ddfb15be5aec1fff1f76722fad1d05a7c9499d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3a01c990cd7454973a878bf9a7835e9bf19b1795ba44209aa9d844e88188af31b36712b4fbcfa4ce7de503401bc5faaa3d266324da944f17d1f52b05de217d55
|
|
7
|
+
data.tar.gz: 75b2e70e21eec5de857922989fbbb3aee671905298dd1645e8da56d26791eb41ee29112769f03aafc08d6903d0b1f578eb7561e37bf6d3dc9095de36cf2b20a1
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## Unreleased
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
* Support named and positional bind values through `QueryRequest#params`.
|
|
10
|
+
|
|
11
|
+
## [0.8.1](https://github.com/altertable-ai/altertable-lakehouse-ruby/compare/altertable-lakehouse/v0.8.0...altertable-lakehouse/v0.8.1) (2026-10-07)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
* **error:** implement proper query error parsing ([#54](https://github.com/altertable-ai/altertable-lakehouse-ruby/issues/54)) ([86f6512](https://github.com/altertable-ai/altertable-lakehouse-ruby/commit/86f6512cfc6c58822981d0ac4824b7479dd1f2f4))
|
|
17
|
+
|
|
18
|
+
## [0.8.0](https://github.com/altertable-ai/altertable-lakehouse-ruby/compare/altertable-lakehouse/v0.7.0...altertable-lakehouse/v0.8.0) (2026-10-07)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### Features
|
|
22
|
+
|
|
23
|
+
* **query:** support bind parameters ([#52](https://github.com/altertable-ai/altertable-lakehouse-ruby/issues/52)) ([33b2fb3](https://github.com/altertable-ai/altertable-lakehouse-ruby/commit/33b2fb38d82714a344263e1d77e4552e152b9aaa))
|
|
24
|
+
|
|
5
25
|
## [0.7.0](https://github.com/altertable-ai/altertable-lakehouse-ruby/compare/altertable-lakehouse/v0.6.0...altertable-lakehouse/v0.7.0) (2026-08-26)
|
|
6
26
|
|
|
7
27
|
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -40,7 +40,8 @@ client.append(
|
|
|
40
40
|
|
|
41
41
|
# Query data
|
|
42
42
|
result = client.query_all(
|
|
43
|
-
statement: "SELECT * FROM main.public.events
|
|
43
|
+
statement: "SELECT * FROM main.public.events WHERE age >= $min_age",
|
|
44
|
+
params: { "min_age" => 25 }
|
|
44
45
|
)
|
|
45
46
|
result[:rows].each { |row| puts row }
|
|
46
47
|
```
|
|
@@ -282,7 +282,7 @@ module Altertable
|
|
|
282
282
|
include Enumerable
|
|
283
283
|
|
|
284
284
|
# metadata: the stream header object (first NDJSON line)
|
|
285
|
-
# columns: array of column
|
|
285
|
+
# columns: array of column names or typed column descriptors (second NDJSON line)
|
|
286
286
|
attr_reader :metadata, :columns
|
|
287
287
|
|
|
288
288
|
def initialize(enum)
|
|
@@ -292,19 +292,29 @@ module Altertable
|
|
|
292
292
|
end
|
|
293
293
|
|
|
294
294
|
def each(&block)
|
|
295
|
-
# The
|
|
296
|
-
# line 1:
|
|
297
|
-
# line 2:
|
|
298
|
-
# line 3+:
|
|
299
|
-
#
|
|
295
|
+
# The mock streams NDJSON:
|
|
296
|
+
# line 1: metadata object
|
|
297
|
+
# line 2: column descriptors, or { "error": string }
|
|
298
|
+
# line 3+: row arrays, or { "error": string }
|
|
299
|
+
# Row arrays are zipped with column names into hashes.
|
|
300
300
|
line_index = 0
|
|
301
301
|
|
|
302
302
|
@enum.each do |item|
|
|
303
|
+
if line_index.positive? && (message = stream_error_message(item))
|
|
304
|
+
raise QueryError.new(
|
|
305
|
+
message,
|
|
306
|
+
line_index: line_index,
|
|
307
|
+
operation: "query",
|
|
308
|
+
http_method: "POST",
|
|
309
|
+
http_path: "/query"
|
|
310
|
+
)
|
|
311
|
+
end
|
|
312
|
+
|
|
303
313
|
case line_index
|
|
304
314
|
when 0
|
|
305
315
|
@metadata = item
|
|
306
316
|
when 1
|
|
307
|
-
@columns = item
|
|
317
|
+
@columns = normalize_columns(item)
|
|
308
318
|
else
|
|
309
319
|
if @columns.is_a?(Array) && item.is_a?(Array)
|
|
310
320
|
block.call(@columns.zip(item).to_h)
|
|
@@ -315,6 +325,28 @@ module Altertable
|
|
|
315
325
|
line_index += 1
|
|
316
326
|
end
|
|
317
327
|
end
|
|
328
|
+
|
|
329
|
+
private
|
|
330
|
+
|
|
331
|
+
# A post-metadata JSON object with an `error` string is a stream failure,
|
|
332
|
+
# not column schema or a row.
|
|
333
|
+
def stream_error_message(item)
|
|
334
|
+
return unless item.is_a?(Hash)
|
|
335
|
+
|
|
336
|
+
message = item["error"]
|
|
337
|
+
message if message.is_a?(String)
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
# The query service emits typed column descriptors, such as
|
|
341
|
+
# { "name" => "id", "type" => "INTEGER" }. Keep the public result
|
|
342
|
+
# shape stable by exposing names and using them as row keys.
|
|
343
|
+
def normalize_columns(columns)
|
|
344
|
+
return columns unless columns.is_a?(Array)
|
|
345
|
+
|
|
346
|
+
columns.map do |column|
|
|
347
|
+
column.is_a?(Hash) && column.key?("name") ? column["name"] : column
|
|
348
|
+
end
|
|
349
|
+
end
|
|
318
350
|
end
|
|
319
351
|
|
|
320
352
|
end
|
|
@@ -21,6 +21,27 @@ module Altertable
|
|
|
21
21
|
class TimeoutError < Error; end
|
|
22
22
|
class SerializationError < Error; end
|
|
23
23
|
class ParseError < Error; end
|
|
24
|
+
|
|
25
|
+
# Backend-emitted `{ "error": string }` line in a /query NDJSON stream.
|
|
26
|
+
# `line_index` is the zero-based index of that line.
|
|
27
|
+
class QueryError < Error
|
|
28
|
+
attr_reader :line_index
|
|
29
|
+
|
|
30
|
+
def initialize(message, line_index:, operation: nil, http_method: nil, http_path: nil, status_code: nil, retriable: false, request_id: nil, cause: nil)
|
|
31
|
+
super(
|
|
32
|
+
message,
|
|
33
|
+
operation: operation,
|
|
34
|
+
http_method: http_method,
|
|
35
|
+
http_path: http_path,
|
|
36
|
+
status_code: status_code,
|
|
37
|
+
retriable: retriable,
|
|
38
|
+
request_id: request_id,
|
|
39
|
+
cause: cause
|
|
40
|
+
)
|
|
41
|
+
@line_index = line_index
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
24
45
|
class ApiError < Error; end
|
|
25
46
|
class ConfigurationError < Error; end
|
|
26
47
|
end
|
|
@@ -54,9 +54,9 @@ module Altertable
|
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
class QueryRequest < Request
|
|
57
|
-
attr_reader :statement, :catalog, :schema, :session_id, :compute_size, :sanitize, :limit, :offset, :timezone, :ephemeral, :visible, :requested_by, :query_id, :cache
|
|
57
|
+
attr_reader :statement, :catalog, :schema, :session_id, :compute_size, :sanitize, :limit, :offset, :timezone, :ephemeral, :visible, :requested_by, :query_id, :cache, :params
|
|
58
58
|
|
|
59
|
-
def initialize(statement:, catalog: nil, schema: nil, session_id: nil, compute_size: nil, sanitize: nil, limit: nil, offset: nil, timezone: nil, ephemeral: nil, visible: nil, requested_by: nil, query_id: nil, cache: nil)
|
|
59
|
+
def initialize(statement:, catalog: nil, schema: nil, session_id: nil, compute_size: nil, sanitize: nil, limit: nil, offset: nil, timezone: nil, ephemeral: nil, visible: nil, requested_by: nil, query_id: nil, cache: nil, params: nil)
|
|
60
60
|
@statement = statement
|
|
61
61
|
@catalog = catalog
|
|
62
62
|
@schema = schema
|
|
@@ -71,6 +71,7 @@ module Altertable
|
|
|
71
71
|
@requested_by = requested_by
|
|
72
72
|
@query_id = query_id
|
|
73
73
|
@cache = cache
|
|
74
|
+
@params = params
|
|
74
75
|
end
|
|
75
76
|
|
|
76
77
|
def to_h
|
|
@@ -88,6 +89,7 @@ module Altertable
|
|
|
88
89
|
h[:requested_by] = @requested_by if @requested_by
|
|
89
90
|
h[:query_id] = @query_id if @query_id
|
|
90
91
|
h[:cache] = @cache unless @cache.nil?
|
|
92
|
+
h[:params] = @params unless @params.nil?
|
|
91
93
|
h
|
|
92
94
|
end
|
|
93
95
|
end
|
|
@@ -47,6 +47,27 @@ module Altertable
|
|
|
47
47
|
class TimeoutError < Error; end
|
|
48
48
|
class SerializationError < Error; end
|
|
49
49
|
class ParseError < Error; end
|
|
50
|
+
|
|
51
|
+
class QueryError < Error
|
|
52
|
+
sig { returns(Integer) }
|
|
53
|
+
def line_index; end
|
|
54
|
+
|
|
55
|
+
sig do
|
|
56
|
+
params(
|
|
57
|
+
message: String,
|
|
58
|
+
line_index: Integer,
|
|
59
|
+
operation: T.nilable(String),
|
|
60
|
+
http_method: T.nilable(String),
|
|
61
|
+
http_path: T.nilable(String),
|
|
62
|
+
status_code: T.nilable(Integer),
|
|
63
|
+
retriable: T::Boolean,
|
|
64
|
+
request_id: T.nilable(String),
|
|
65
|
+
cause: T.nilable(Exception)
|
|
66
|
+
).void
|
|
67
|
+
end
|
|
68
|
+
def initialize(message, line_index:, operation: nil, http_method: nil, http_path: nil, status_code: nil, retriable: false, request_id: nil, cause: nil); end
|
|
69
|
+
end
|
|
70
|
+
|
|
50
71
|
class ApiError < Error; end
|
|
51
72
|
class ConfigurationError < Error; end
|
|
52
73
|
|
|
@@ -300,6 +321,9 @@ module Altertable
|
|
|
300
321
|
sig { returns(T.nilable(T::Boolean)) }
|
|
301
322
|
def cache; end
|
|
302
323
|
|
|
324
|
+
sig { returns(T.nilable(T.any(T::Hash[String, T.untyped], T::Array[T.untyped]))) }
|
|
325
|
+
def params; end
|
|
326
|
+
|
|
303
327
|
sig do
|
|
304
328
|
params(
|
|
305
329
|
statement: String,
|
|
@@ -315,10 +339,11 @@ module Altertable
|
|
|
315
339
|
visible: T.nilable(T::Boolean),
|
|
316
340
|
requested_by: T.nilable(String),
|
|
317
341
|
query_id: T.nilable(String),
|
|
318
|
-
cache: T.nilable(T::Boolean)
|
|
342
|
+
cache: T.nilable(T::Boolean),
|
|
343
|
+
params: T.nilable(T.any(T::Hash[String, T.untyped], T::Array[T.untyped]))
|
|
319
344
|
).void
|
|
320
345
|
end
|
|
321
|
-
def initialize(statement:, catalog: nil, schema: nil, session_id: nil, compute_size: nil, sanitize: nil, limit: nil, offset: nil, timezone: nil, ephemeral: nil, visible: nil, requested_by: nil, query_id: nil, cache: nil); end
|
|
346
|
+
def initialize(statement:, catalog: nil, schema: nil, session_id: nil, compute_size: nil, sanitize: nil, limit: nil, offset: nil, timezone: nil, ephemeral: nil, visible: nil, requested_by: nil, query_id: nil, cache: nil, params: nil); end
|
|
322
347
|
|
|
323
348
|
sig { returns(T::Hash[Symbol, T.untyped]) }
|
|
324
349
|
def to_h; end
|
|
@@ -39,6 +39,22 @@ module Altertable
|
|
|
39
39
|
class ParseError < Error
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
+
class QueryError < Error
|
|
43
|
+
attr_reader line_index: Integer
|
|
44
|
+
|
|
45
|
+
def initialize: (
|
|
46
|
+
String message,
|
|
47
|
+
line_index: Integer,
|
|
48
|
+
?operation: String?,
|
|
49
|
+
?http_method: String?,
|
|
50
|
+
?http_path: String?,
|
|
51
|
+
?status_code: Integer?,
|
|
52
|
+
?retriable: bool,
|
|
53
|
+
?request_id: String?,
|
|
54
|
+
?cause: Exception?
|
|
55
|
+
) -> void
|
|
56
|
+
end
|
|
57
|
+
|
|
42
58
|
class ApiError < Error
|
|
43
59
|
end
|
|
44
60
|
|
|
@@ -45,6 +45,7 @@ module Altertable
|
|
|
45
45
|
attr_reader requested_by: String?
|
|
46
46
|
attr_reader query_id: String?
|
|
47
47
|
attr_reader cache: bool?
|
|
48
|
+
attr_reader params: (::Hash[String, untyped] | ::Array[untyped])?
|
|
48
49
|
|
|
49
50
|
def initialize: (
|
|
50
51
|
statement: String,
|
|
@@ -60,7 +61,8 @@ module Altertable
|
|
|
60
61
|
?visible: bool?,
|
|
61
62
|
?requested_by: String?,
|
|
62
63
|
?query_id: String?,
|
|
63
|
-
?cache: bool
|
|
64
|
+
?cache: bool?,
|
|
65
|
+
?params: (::Hash[String, untyped] | ::Array[untyped])?
|
|
64
66
|
) -> void
|
|
65
67
|
|
|
66
68
|
def to_h: () -> ::Hash[Symbol, untyped]
|