iceberg 0.12.0 → 0.12.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.
data/README.md CHANGED
@@ -31,10 +31,17 @@ catalog.create_namespace("main")
31
31
  Create a table
32
32
 
33
33
  ```ruby
34
- catalog.create_table("events") do |t|
35
- t.bigint "id"
36
- t.float "value"
37
- end
34
+ table =
35
+ catalog.create_table("events") do |t|
36
+ t.bigint "id"
37
+ t.float "value"
38
+ end
39
+ ```
40
+
41
+ Append data
42
+
43
+ ```ruby
44
+ table.append([{"id" => 1, "value" => 3.0}, {"id" => 2, "value" => 4.0}])
38
45
  ```
39
46
 
40
47
  Or with [Polars](https://github.com/ankane/ruby-polars)
@@ -45,6 +52,18 @@ table = catalog.create_table("events", schema: df.schema)
45
52
  table.append(df)
46
53
  ```
47
54
 
55
+ Or with [Nanoarrow](https://github.com/ankane/nanoarrow-ruby)
56
+
57
+ ```ruby
58
+ arr =
59
+ Nanoarrow::Array.new(
60
+ [{"id" => 1, "value" => 3.0}, {"id" => 2, "value" => 4.0}],
61
+ Nanoarrow.struct({"a" => Nanoarrow.int64, "b" => Nanoarrow.string})
62
+ )
63
+ table = catalog.create_table("events", schema: arr.schema)
64
+ table.append(arr)
65
+ ```
66
+
48
67
  Load a table
49
68
 
50
69
  ```ruby
@@ -54,7 +73,11 @@ table = catalog.load_table("events")
54
73
  Query a table
55
74
 
56
75
  ```ruby
76
+ table.to_a
77
+ # or
57
78
  table.to_polars.collect
79
+ # or
80
+ table.scan.to_arrow
58
81
  ```
59
82
 
60
83
  ## Catalog Types
@@ -69,8 +92,6 @@ Iceberg::RestCatalog.new(
69
92
 
70
93
  ### S3 Tables
71
94
 
72
- [unreleased]
73
-
74
95
  ```ruby
75
96
  Iceberg::S3TablesCatalog.new(
76
97
  arn: "arn:aws:s3tables:..."
@@ -79,8 +100,6 @@ Iceberg::S3TablesCatalog.new(
79
100
 
80
101
  ### Glue
81
102
 
82
- [unreleased]
83
-
84
103
  ```ruby
85
104
  Iceberg::GlueCatalog.new(
86
105
  warehouse: "s3://my-bucket"
@@ -228,4 +247,10 @@ bundle exec rake test:rest
228
247
  # SQL catalog
229
248
  createdb iceberg_ruby_test
230
249
  bundle exec rake test:sql
250
+
251
+ # S3 Tables catalog
252
+ bundle exec rake test:s3tables
253
+
254
+ # Glue catalog
255
+ bundle exec rake test:glue
231
256
  ```
@@ -1,10 +1,10 @@
1
1
  [package]
2
2
  name = "iceberg-ruby"
3
- version = "0.12.0"
3
+ version = "0.12.1"
4
4
  license = "Apache-2.0"
5
5
  authors = ["Andrew Kane <andrew@ankane.org>"]
6
6
  edition = "2024"
7
- rust-version = "1.94"
7
+ rust-version = "1.95"
8
8
  publish = false
9
9
 
10
10
  [lib]
@@ -12,23 +12,23 @@ name = "iceberg"
12
12
  crate-type = ["cdylib"]
13
13
 
14
14
  [dependencies]
15
- arrow = "58"
16
- arrow-array = { version = "58", features = ["ffi"] }
17
- arrow-cast = "58"
18
- arrow-schema = "58"
19
- datafusion = { version = "53", optional = true }
15
+ arrow = "58.4"
16
+ arrow-array = { version = "58.4", features = ["ffi"] }
17
+ arrow-cast = "58.4"
18
+ arrow-schema = "58.4"
19
+ datafusion = { version = "54", optional = true }
20
20
  futures = "0.3"
21
- iceberg = "=0.10.0"
22
- iceberg-catalog-glue = { version = "=0.10.0", optional = true }
23
- iceberg-catalog-rest = { version = "=0.10.0", optional = true }
24
- iceberg-catalog-s3tables = { version = "=0.10.0", optional = true }
25
- iceberg-catalog-sql = { version = "=0.10.0", optional = true }
26
- iceberg-datafusion = { version = "=0.10.0", optional = true }
27
- iceberg-storage-opendal = "=0.10.0"
28
- magnus = "0.8"
29
- parquet = "58"
21
+ iceberg = "=0.11.0"
22
+ iceberg-catalog-glue = { version = "=0.11.0", optional = true }
23
+ iceberg-catalog-rest = { version = "=0.11.0", optional = true }
24
+ iceberg-catalog-s3tables = { version = "=0.11.0", optional = true }
25
+ iceberg-catalog-sql = { version = "=0.11.0", optional = true }
26
+ iceberg-datafusion = { version = "=0.11.0", optional = true }
27
+ iceberg-storage-opendal = "=0.11.0"
28
+ magnus = "0.9"
29
+ parquet = "58.4"
30
30
  rb-sys = "0.9"
31
- sqlx = { version = "0.8", features = ["postgres", "runtime-tokio", "sqlite"], default-features = false, optional = true }
31
+ sqlx = { version = "0.8", features = ["postgres", "runtime-tokio", "sqlite", "tls-rustls-aws-lc-rs"], default-features = false, optional = true }
32
32
  tokio = { version = "1", features = ["rt-multi-thread"] }
33
33
  uuid = { version = "1", features = ["v4"] }
34
34
 
@@ -316,21 +316,18 @@ impl RbCatalog {
316
316
  partition_spec: Option<&RbPartitionSpec>,
317
317
  sort_order: Option<&RbSortOrder>,
318
318
  properties: HashMap<String, String>,
319
+ format_version: u8,
319
320
  ) -> RbResult<RbTable> {
320
- let format_version = if let Some(v) = properties.get("format-version") {
321
- match v.as_str() {
322
- "1" => FormatVersion::V1,
323
- "2" => FormatVersion::V2,
324
- "3" => FormatVersion::V3,
325
- _ => {
326
- return Err(RbErr::new(
327
- ruby.exception_arg_error(),
328
- "Unsupported format version",
329
- ));
330
- }
321
+ let format_version = match format_version {
322
+ 1 => FormatVersion::V1,
323
+ 2 => FormatVersion::V2,
324
+ 3 => FormatVersion::V3,
325
+ _ => {
326
+ return Err(RbErr::new(
327
+ ruby.exception_arg_error(),
328
+ "Unsupported format version",
329
+ ));
331
330
  }
332
- } else {
333
- FormatVersion::V2
334
331
  };
335
332
  let creation = TableCreation::builder()
336
333
  .name(name.0.name)
@@ -1,3 +1,5 @@
1
+ use std::error::Error as _;
2
+
1
3
  use iceberg::{Error, ErrorKind};
2
4
  use magnus::{Error as RbErr, RModule, Ruby, prelude::*};
3
5
 
@@ -14,7 +16,18 @@ pub fn to_rb_err(err: Error) -> RbErr {
14
16
 
15
17
  // no way to get context separately
16
18
  // https://github.com/apache/iceberg-rust/issues/1071
17
- let message = err.message().to_string();
19
+ let mut message = err.message().to_string();
20
+
21
+ let mut source = err.source();
22
+ while let Some(s) = source {
23
+ let m = s.to_string();
24
+ if message.contains(&m) {
25
+ break;
26
+ }
27
+ message.push_str(": ");
28
+ message.push_str(&m);
29
+ source = s.source();
30
+ }
18
31
 
19
32
  if class_name == "Error" {
20
33
  let s = err.to_string();
@@ -58,7 +58,7 @@ fn init(ruby: &Ruby) -> RbResult<()> {
58
58
  class.define_method("update_namespace", method!(RbCatalog::update_namespace, 2))?;
59
59
  class.define_method("drop_namespace", method!(RbCatalog::drop_namespace, 1))?;
60
60
  class.define_method("list_tables", method!(RbCatalog::list_tables, 1))?;
61
- class.define_method("create_table", method!(RbCatalog::create_table, 6))?;
61
+ class.define_method("create_table", method!(RbCatalog::create_table, 7))?;
62
62
  class.define_method("load_table", method!(RbCatalog::load_table, 1))?;
63
63
  class.define_method("drop_table", method!(RbCatalog::drop_table, 1))?;
64
64
  class.define_method("purge_table", method!(RbCatalog::purge_table, 1))?;
@@ -82,15 +82,15 @@ impl RbTableScan {
82
82
  impl RbFileScanTask {
83
83
  pub fn file(&self) -> RbDataFile {
84
84
  RbDataFile {
85
- file_path: self.scan.data_file_path.clone(),
86
- record_count: self.scan.record_count,
87
- file_size_in_bytes: self.scan.file_size_in_bytes,
85
+ file_path: self.scan.data_file_path().to_string(),
86
+ record_count: self.scan.record_count(),
87
+ file_size_in_bytes: self.scan.file_size_in_bytes(),
88
88
  equality_ids: None,
89
89
  }
90
90
  }
91
91
 
92
92
  pub fn delete_files(ruby: &Ruby, rb_self: &Self) -> RArray {
93
- ruby.ary_from_iter(rb_self.scan.deletes.iter().map(|v| RbDataFile {
93
+ ruby.ary_from_iter(rb_self.scan.deletes().iter().map(|v| RbDataFile {
94
94
  file_path: v.file_path.clone(),
95
95
  record_count: None,
96
96
  file_size_in_bytes: v.file_size_in_bytes,
@@ -10,7 +10,7 @@ use magnus::{
10
10
 
11
11
  use crate::RbResult;
12
12
  use crate::capsule::RbCapsule;
13
- use crate::error::to_rb_err;
13
+ use crate::error::{to_rb_err, todo_error};
14
14
  use crate::utils::{Wrap, default_value, rb_literal};
15
15
 
16
16
  #[magnus::wrap(class = "Iceberg::Schema")]
@@ -252,6 +252,7 @@ impl RbNestedField {
252
252
  RbNestedField::from(&ty.key_field),
253
253
  RbNestedField::from(&ty.value_field),
254
254
  ))?,
255
+ Type::Variant(_) => return Err(todo_error(field_type)),
255
256
  };
256
257
  Ok(v)
257
258
  }
@@ -160,6 +160,7 @@ pub fn default_value(ob: Value, field_type: &Type) -> RbResult<Option<Literal>>
160
160
  Type::Struct(_) => return Err(todo_error(field_type)),
161
161
  Type::List(_) => return Err(todo_error(field_type)),
162
162
  Type::Map(_) => return Err(todo_error(field_type)),
163
+ Type::Variant(_) => return Err(todo_error(field_type)),
163
164
  };
164
165
  Ok(Some(lit))
165
166
  }
@@ -66,7 +66,12 @@ module Iceberg
66
66
  schema = Schema.new
67
67
  end
68
68
 
69
- Table.new(@catalog.create_table(with_namespace(table_name), schema, location, partition_spec, sort_order, properties), @catalog)
69
+ format_version = (properties["format-version"] || 2).to_i
70
+ if properties["format-version"] && (is_a?(MemoryCatalog) || is_a?(SqlCatalog))
71
+ properties = properties.except("format-version")
72
+ end
73
+
74
+ Table.new(@catalog.create_table(with_namespace(table_name), schema, location, partition_spec, sort_order, properties, format_version), @catalog)
70
75
  end
71
76
 
72
77
  def load_table(table_name)
@@ -1,3 +1,3 @@
1
1
  module Iceberg
2
- VERSION = "0.12.0"
2
+ VERSION = "0.12.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iceberg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.12.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
@@ -88,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  requirements: []
91
- rubygems_version: 4.0.14
91
+ rubygems_version: 4.0.20
92
92
  specification_version: 4
93
93
  summary: Apache Iceberg for Ruby
94
94
  test_files: []