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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 730648db52f373495553ad9179f698b55a1bc309e5e5465a3e39733bc4659ab4
4
- data.tar.gz: 0adb085fa50da366e377cb1b847273c0020ef058b871a143866b4c2d1558e106
3
+ metadata.gz: c92cf2b0a1bf2f44a8d3b2e7934a5b9f3399293409333cbd19e5749158272176
4
+ data.tar.gz: 44e709abf74aa54c03345afd11ddfb15be5aec1fff1f76722fad1d05a7c9499d
5
5
  SHA512:
6
- metadata.gz: 1cde4636923e138c259a738f96d84305ff6a8aa929dc12e49f792989da2ee0a2394db20f2a37f80dcda21b304ebb7c3860122bd46b6cc4a01ca0ddadd805bc38
7
- data.tar.gz: baffcdd22da74b9006f153f41b87703f93ba0351f3edcc2082576472b3ef52451656ee0bdc2afe72e79ff6835d10a1049ccc6555bc92c1bf23b82184e65cd54a
6
+ metadata.gz: 3a01c990cd7454973a878bf9a7835e9bf19b1795ba44209aa9d844e88188af31b36712b4fbcfa4ce7de503401bc5faaa3d266324da944f17d1f52b05de217d55
7
+ data.tar.gz: 75b2e70e21eec5de857922989fbbb3aee671905298dd1645e8da56d26791eb41ee29112769f03aafc08d6903d0b1f578eb7561e37bf6d3dc9095de36cf2b20a1
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "0.7.0"
2
+ ".": "0.8.1"
3
3
  }
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- altertable-lakehouse (0.7.0)
4
+ altertable-lakehouse (0.8.1)
5
5
  base64
6
6
 
7
7
  GEM
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 LIMIT 10"
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 name strings (second NDJSON line)
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 real mock streams:
296
- # line 1: { "statement":…, "session_id":…, … } (header object)
297
- # line 2: ["col1", "col2", …] (column names array)
298
- # line 3+: [val1, val2, …] (row value arrays)
299
- # We zip each row array with the column names to produce a Hash.
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
@@ -1,5 +1,5 @@
1
1
  module Altertable
2
2
  module Lakehouse
3
- VERSION = "0.7.0"
3
+ VERSION = "0.8.1"
4
4
  end
5
5
  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]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: altertable-lakehouse
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Altertable AI