iceberg 0.11.2-aarch64-linux → 0.12.0-aarch64-linux
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/CHANGELOG.md +11 -0
- data/Cargo.lock +799 -270
- data/Cargo.toml +7 -0
- data/LICENSE-THIRD-PARTY.txt +38549 -16342
- data/NOTICE.txt +2 -2
- data/README.md +32 -12
- data/lib/iceberg/3.3/iceberg.so +0 -0
- data/lib/iceberg/3.4/iceberg.so +0 -0
- data/lib/iceberg/4.0/iceberg.so +0 -0
- data/lib/iceberg/catalog.rb +54 -35
- data/lib/iceberg/glue_catalog.rb +5 -2
- data/lib/iceberg/memory_catalog.rb +5 -2
- data/lib/iceberg/rest_catalog.rb +5 -2
- data/lib/iceberg/result.rb +22 -0
- data/lib/iceberg/s3_tables_catalog.rb +5 -2
- data/lib/iceberg/sql_catalog.rb +5 -2
- data/lib/iceberg/table.rb +87 -21
- data/lib/iceberg/table_definition.rb +49 -7
- data/lib/iceberg/table_scan.rb +14 -0
- data/lib/iceberg/transforms.rb +64 -0
- data/lib/iceberg/types.rb +137 -0
- data/lib/iceberg/version.rb +1 -1
- data/lib/iceberg.rb +10 -5
- metadata +5 -3
- data/lib/iceberg/schema.rb +0 -10
data/NOTICE.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
Apache Iceberg
|
|
3
|
-
Copyright 2017-
|
|
3
|
+
Copyright 2017-2026 The Apache Software Foundation
|
|
4
4
|
|
|
5
5
|
This product includes software developed at
|
|
6
6
|
The Apache Software Foundation (http://www.apache.org/).
|
|
@@ -8,7 +8,7 @@ The Apache Software Foundation (http://www.apache.org/).
|
|
|
8
8
|
--------------------------------------------------------------------------------
|
|
9
9
|
|
|
10
10
|
Apache Iceberg Rust
|
|
11
|
-
Copyright 2023-
|
|
11
|
+
Copyright 2023-2026 The Apache Software Foundation
|
|
12
12
|
|
|
13
13
|
This product includes software developed at
|
|
14
14
|
The Apache Software Foundation (http://www.apache.org/).
|
data/README.md
CHANGED
|
@@ -19,10 +19,10 @@ gem "iceberg"
|
|
|
19
19
|
Create a client for an Iceberg catalog
|
|
20
20
|
|
|
21
21
|
```ruby
|
|
22
|
-
catalog = Iceberg::RestCatalog.new(uri: "http://localhost:8181")
|
|
22
|
+
catalog = Iceberg::RestCatalog.new(uri: "http://localhost:8181", default_namespace: "main")
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
Create a namespace
|
|
25
|
+
Create a namespace if needed
|
|
26
26
|
|
|
27
27
|
```ruby
|
|
28
28
|
catalog.create_namespace("main")
|
|
@@ -31,7 +31,7 @@ catalog.create_namespace("main")
|
|
|
31
31
|
Create a table
|
|
32
32
|
|
|
33
33
|
```ruby
|
|
34
|
-
catalog.create_table("
|
|
34
|
+
catalog.create_table("events") do |t|
|
|
35
35
|
t.bigint "id"
|
|
36
36
|
t.float "value"
|
|
37
37
|
end
|
|
@@ -41,14 +41,14 @@ Or with [Polars](https://github.com/ankane/ruby-polars)
|
|
|
41
41
|
|
|
42
42
|
```ruby
|
|
43
43
|
df = Polars::DataFrame.new({"id" => [1, 2], "value" => [3.0, 4.0]})
|
|
44
|
-
table = catalog.create_table("
|
|
44
|
+
table = catalog.create_table("events", schema: df.schema)
|
|
45
45
|
table.append(df)
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
Load a table
|
|
49
49
|
|
|
50
50
|
```ruby
|
|
51
|
-
table = catalog.load_table("
|
|
51
|
+
table = catalog.load_table("events")
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
Query a table
|
|
@@ -67,6 +67,26 @@ Iceberg::RestCatalog.new(
|
|
|
67
67
|
)
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
+
### S3 Tables
|
|
71
|
+
|
|
72
|
+
[unreleased]
|
|
73
|
+
|
|
74
|
+
```ruby
|
|
75
|
+
Iceberg::S3TablesCatalog.new(
|
|
76
|
+
arn: "arn:aws:s3tables:..."
|
|
77
|
+
)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Glue
|
|
81
|
+
|
|
82
|
+
[unreleased]
|
|
83
|
+
|
|
84
|
+
```ruby
|
|
85
|
+
Iceberg::GlueCatalog.new(
|
|
86
|
+
warehouse: "s3://my-bucket"
|
|
87
|
+
)
|
|
88
|
+
```
|
|
89
|
+
|
|
70
90
|
### SQL
|
|
71
91
|
|
|
72
92
|
```ruby
|
|
@@ -133,7 +153,7 @@ catalog.list_tables("main")
|
|
|
133
153
|
Create a table
|
|
134
154
|
|
|
135
155
|
```ruby
|
|
136
|
-
catalog.create_table("
|
|
156
|
+
catalog.create_table("events") do |t|
|
|
137
157
|
t.integer "id"
|
|
138
158
|
t.float "value"
|
|
139
159
|
end
|
|
@@ -142,31 +162,31 @@ end
|
|
|
142
162
|
Load a table
|
|
143
163
|
|
|
144
164
|
```ruby
|
|
145
|
-
catalog.load_table("
|
|
165
|
+
catalog.load_table("events")
|
|
146
166
|
```
|
|
147
167
|
|
|
148
168
|
Check if a table exists
|
|
149
169
|
|
|
150
170
|
```ruby
|
|
151
|
-
catalog.table_exists?("
|
|
171
|
+
catalog.table_exists?("events")
|
|
152
172
|
```
|
|
153
173
|
|
|
154
174
|
Rename a table
|
|
155
175
|
|
|
156
176
|
```ruby
|
|
157
|
-
catalog.rename_table("
|
|
177
|
+
catalog.rename_table("events", "events2")
|
|
158
178
|
```
|
|
159
179
|
|
|
160
180
|
Register a table
|
|
161
181
|
|
|
162
182
|
```ruby
|
|
163
|
-
catalog.register_table("
|
|
183
|
+
catalog.register_table("events", "metadata.json")
|
|
164
184
|
```
|
|
165
185
|
|
|
166
186
|
Drop a table
|
|
167
187
|
|
|
168
188
|
```ruby
|
|
169
|
-
catalog.drop_table("
|
|
189
|
+
catalog.drop_table("events")
|
|
170
190
|
```
|
|
171
191
|
|
|
172
192
|
## Static Tables
|
|
@@ -196,7 +216,7 @@ To get started with development:
|
|
|
196
216
|
git clone https://github.com/ankane/iceberg-ruby.git
|
|
197
217
|
cd iceberg-ruby
|
|
198
218
|
bundle install
|
|
199
|
-
bundle exec rake compile
|
|
219
|
+
bundle exec rake compile:dev
|
|
200
220
|
|
|
201
221
|
# memory catalog
|
|
202
222
|
bundle exec rake test:memory
|
data/lib/iceberg/3.3/iceberg.so
CHANGED
|
Binary file
|
data/lib/iceberg/3.4/iceberg.so
CHANGED
|
Binary file
|
data/lib/iceberg/4.0/iceberg.so
CHANGED
|
Binary file
|
data/lib/iceberg/catalog.rb
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
module Iceberg
|
|
2
2
|
class Catalog
|
|
3
|
+
def _initialize(catalog, default_namespace:)
|
|
4
|
+
@catalog = catalog
|
|
5
|
+
@default_namespace = default_namespace
|
|
6
|
+
end
|
|
7
|
+
|
|
3
8
|
def list_namespaces(parent = nil)
|
|
4
9
|
@catalog.list_namespaces(parent)
|
|
5
10
|
end
|
|
6
11
|
|
|
7
12
|
def create_namespace(namespace, properties: {}, if_not_exists: nil)
|
|
8
13
|
@catalog.create_namespace(namespace, properties)
|
|
9
|
-
rescue
|
|
10
|
-
|
|
11
|
-
if !if_not_exists || (e.message != "Cannot create namespace" && !e.message.include?("already exists"))
|
|
14
|
+
rescue NamespaceAlreadyExistsError => e
|
|
15
|
+
if !if_not_exists
|
|
12
16
|
raise e
|
|
13
17
|
end
|
|
14
18
|
nil
|
|
@@ -28,19 +32,18 @@ module Iceberg
|
|
|
28
32
|
|
|
29
33
|
def drop_namespace(namespace, if_exists: nil)
|
|
30
34
|
@catalog.drop_namespace(namespace)
|
|
31
|
-
rescue
|
|
32
|
-
|
|
33
|
-
if !if_exists || (e.message != "Tried to drop a namespace that does not exist" && !e.message.include?("No such namespace") && !e.message.include?("The specified namespace does not exist") && !e.message.include?("not found"))
|
|
35
|
+
rescue NoSuchNamespaceError => e
|
|
36
|
+
if !if_exists
|
|
34
37
|
raise e
|
|
35
38
|
end
|
|
36
39
|
nil
|
|
37
40
|
end
|
|
38
41
|
|
|
39
|
-
def list_tables(namespace)
|
|
40
|
-
@catalog.list_tables(namespace)
|
|
42
|
+
def list_tables(namespace = nil)
|
|
43
|
+
@catalog.list_tables(namespace || @default_namespace)
|
|
41
44
|
end
|
|
42
45
|
|
|
43
|
-
def create_table(table_name, schema: nil, location: nil)
|
|
46
|
+
def create_table(table_name, schema: nil, location: nil, partition_spec: nil, sort_order: nil, properties: {})
|
|
44
47
|
if !schema.nil? && block_given?
|
|
45
48
|
raise ArgumentError, "Must pass schema or block"
|
|
46
49
|
end
|
|
@@ -48,63 +51,79 @@ module Iceberg
|
|
|
48
51
|
if block_given?
|
|
49
52
|
table_definition = TableDefinition.new
|
|
50
53
|
yield table_definition
|
|
51
|
-
schema = Schema.new(table_definition.fields)
|
|
52
|
-
elsif schema.is_a?(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
schema = Schema.new(fields)
|
|
54
|
+
schema = Schema.new(*table_definition.fields)
|
|
55
|
+
elsif schema.is_a?(Schema)
|
|
56
|
+
# do nothing
|
|
57
|
+
elsif schema.respond_to?(:arrow_c_schema)
|
|
58
|
+
schema = Schema.new(schema)
|
|
59
|
+
elsif schema.is_a?(Hash)
|
|
60
|
+
table_definition = TableDefinition.new
|
|
61
|
+
schema.each do |k, v|
|
|
62
|
+
table_definition.column(k, v)
|
|
63
|
+
end
|
|
64
|
+
schema = Schema.new(*table_definition.fields)
|
|
63
65
|
elsif schema.nil?
|
|
64
|
-
schema = Schema.new
|
|
66
|
+
schema = Schema.new
|
|
65
67
|
end
|
|
66
68
|
|
|
67
|
-
Table.new(@catalog.create_table(table_name, schema, location), @catalog)
|
|
69
|
+
Table.new(@catalog.create_table(with_namespace(table_name), schema, location, partition_spec, sort_order, properties), @catalog)
|
|
68
70
|
end
|
|
69
71
|
|
|
70
72
|
def load_table(table_name)
|
|
71
|
-
Table.new(@catalog.load_table(table_name), @catalog)
|
|
73
|
+
Table.new(@catalog.load_table(with_namespace(table_name)), @catalog)
|
|
72
74
|
end
|
|
73
75
|
|
|
74
76
|
def drop_table(table_name, if_exists: nil)
|
|
75
|
-
@catalog.drop_table(table_name)
|
|
76
|
-
rescue
|
|
77
|
-
|
|
78
|
-
if !if_exists || (e.message != "Tried to drop a table that does not exist" && !e.message.include?("No such table") && !e.message.include?("The specified table does not exist") && !e.message.include?("not found"))
|
|
77
|
+
@catalog.drop_table(with_namespace(table_name))
|
|
78
|
+
rescue NoSuchTableError => e
|
|
79
|
+
if !if_exists
|
|
79
80
|
raise e
|
|
80
81
|
end
|
|
81
82
|
nil
|
|
82
83
|
end
|
|
83
84
|
|
|
85
|
+
def purge_table(table_name)
|
|
86
|
+
@catalog.purge_table(with_namespace(table_name))
|
|
87
|
+
end
|
|
88
|
+
|
|
84
89
|
def table_exists?(table_name)
|
|
85
|
-
@catalog.table_exists?(table_name)
|
|
86
|
-
rescue
|
|
90
|
+
@catalog.table_exists?(with_namespace(table_name))
|
|
91
|
+
rescue NoSuchNamespaceError
|
|
87
92
|
false
|
|
88
93
|
end
|
|
89
94
|
|
|
90
95
|
def rename_table(table_name, new_name)
|
|
91
|
-
@catalog.rename_table(table_name, new_name)
|
|
96
|
+
@catalog.rename_table(with_namespace(table_name), with_namespace(new_name))
|
|
92
97
|
end
|
|
93
98
|
|
|
94
99
|
def register_table(table_name, metadata_location)
|
|
95
|
-
@catalog.register_table(table_name, metadata_location)
|
|
100
|
+
@catalog.register_table(with_namespace(table_name), metadata_location)
|
|
96
101
|
end
|
|
97
102
|
|
|
98
|
-
def sql(sql)
|
|
103
|
+
def sql(sql, params = [])
|
|
99
104
|
# requires datafusion feature
|
|
100
|
-
raise Todo unless @catalog.respond_to?(:
|
|
105
|
+
raise Todo unless @catalog.respond_to?(:session_context)
|
|
101
106
|
|
|
102
|
-
|
|
107
|
+
session_context.sql(sql, params)
|
|
103
108
|
end
|
|
104
109
|
|
|
105
110
|
# hide internal state
|
|
106
111
|
def inspect
|
|
107
112
|
to_s
|
|
108
113
|
end
|
|
114
|
+
|
|
115
|
+
private
|
|
116
|
+
|
|
117
|
+
def with_namespace(table_name)
|
|
118
|
+
if @default_namespace && table_name.is_a?(String) && !table_name.include?(".")
|
|
119
|
+
[@default_namespace, table_name]
|
|
120
|
+
else
|
|
121
|
+
table_name
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def session_context
|
|
126
|
+
@session_context ||= @catalog.session_context(@default_namespace)
|
|
127
|
+
end
|
|
109
128
|
end
|
|
110
129
|
end
|
data/lib/iceberg/glue_catalog.rb
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
module Iceberg
|
|
2
2
|
class GlueCatalog < Catalog
|
|
3
3
|
# warehouse is URI of S3 storage bucket
|
|
4
|
-
def initialize(warehouse:)
|
|
5
|
-
|
|
4
|
+
def initialize(warehouse:, default_namespace: nil)
|
|
5
|
+
_initialize(
|
|
6
|
+
RbCatalog.new_glue(warehouse),
|
|
7
|
+
default_namespace:
|
|
8
|
+
)
|
|
6
9
|
end
|
|
7
10
|
end
|
|
8
11
|
end
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
module Iceberg
|
|
2
2
|
class MemoryCatalog < Catalog
|
|
3
3
|
# warehouse is default storage location
|
|
4
|
-
def initialize(warehouse: nil)
|
|
5
|
-
|
|
4
|
+
def initialize(warehouse: nil, default_namespace: nil)
|
|
5
|
+
_initialize(
|
|
6
|
+
RbCatalog.new_memory(warehouse),
|
|
7
|
+
default_namespace:
|
|
8
|
+
)
|
|
6
9
|
end
|
|
7
10
|
end
|
|
8
11
|
end
|
data/lib/iceberg/rest_catalog.rb
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
module Iceberg
|
|
2
2
|
class RestCatalog < Catalog
|
|
3
3
|
# warehouse is passed to REST server
|
|
4
|
-
def initialize(uri:, warehouse: nil, properties: {})
|
|
5
|
-
|
|
4
|
+
def initialize(uri:, warehouse: nil, properties: {}, default_namespace: nil)
|
|
5
|
+
_initialize(
|
|
6
|
+
RbCatalog.new_rest(uri, warehouse, properties),
|
|
7
|
+
default_namespace:
|
|
8
|
+
)
|
|
6
9
|
end
|
|
7
10
|
end
|
|
8
11
|
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Iceberg
|
|
2
|
+
class Result
|
|
3
|
+
include Enumerable
|
|
4
|
+
|
|
5
|
+
attr_reader :columns, :rows
|
|
6
|
+
|
|
7
|
+
def initialize(columns, rows)
|
|
8
|
+
@columns = columns
|
|
9
|
+
@rows = rows
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def each
|
|
13
|
+
@rows.each do |row|
|
|
14
|
+
yield @columns.zip(row).to_h
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def empty?
|
|
19
|
+
rows.empty?
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/iceberg/sql_catalog.rb
CHANGED
|
@@ -2,8 +2,11 @@ module Iceberg
|
|
|
2
2
|
class SqlCatalog < Catalog
|
|
3
3
|
# warehouse is default storage location
|
|
4
4
|
# name is stored in SQL table
|
|
5
|
-
def initialize(uri:, warehouse:, name: "main", properties: {})
|
|
6
|
-
|
|
5
|
+
def initialize(uri:, warehouse:, name: "main", properties: {}, default_namespace: nil)
|
|
6
|
+
_initialize(
|
|
7
|
+
RbCatalog.new_sql(uri, warehouse, name, properties),
|
|
8
|
+
default_namespace:
|
|
9
|
+
)
|
|
7
10
|
end
|
|
8
11
|
end
|
|
9
12
|
end
|
data/lib/iceberg/table.rb
CHANGED
|
@@ -5,93 +5,154 @@ module Iceberg
|
|
|
5
5
|
@catalog = catalog
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
+
def refresh
|
|
9
|
+
@table = @catalog.load_table(@table.identifier)
|
|
10
|
+
end
|
|
11
|
+
|
|
8
12
|
def format_version
|
|
9
|
-
|
|
13
|
+
metadata.format_version
|
|
10
14
|
end
|
|
11
15
|
|
|
12
16
|
def uuid
|
|
13
|
-
|
|
17
|
+
metadata.uuid
|
|
14
18
|
end
|
|
15
19
|
|
|
16
20
|
def location
|
|
17
|
-
|
|
21
|
+
metadata.location
|
|
18
22
|
end
|
|
19
23
|
|
|
20
24
|
def last_sequence_number
|
|
21
|
-
|
|
25
|
+
metadata.last_sequence_number
|
|
22
26
|
end
|
|
23
27
|
|
|
24
28
|
def next_sequence_number
|
|
25
|
-
|
|
29
|
+
metadata.next_sequence_number
|
|
26
30
|
end
|
|
27
31
|
|
|
28
32
|
def last_column_id
|
|
29
|
-
|
|
33
|
+
metadata.last_column_id
|
|
30
34
|
end
|
|
31
35
|
|
|
32
36
|
def last_partition_id
|
|
33
|
-
|
|
37
|
+
metadata.last_partition_id
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def last_updated_at
|
|
41
|
+
ms = metadata.last_updated_ms
|
|
42
|
+
Time.at(ms / 1000, ms % 1000, :millisecond)
|
|
34
43
|
end
|
|
35
44
|
|
|
36
45
|
def schemas
|
|
37
|
-
|
|
46
|
+
metadata.schemas
|
|
38
47
|
end
|
|
39
48
|
|
|
40
49
|
def schema_by_id(schema_id)
|
|
41
|
-
|
|
50
|
+
metadata.schema_by_id(schema_id)
|
|
42
51
|
end
|
|
43
52
|
|
|
44
53
|
def current_schema
|
|
45
|
-
|
|
54
|
+
metadata.current_schema
|
|
46
55
|
end
|
|
47
56
|
alias_method :schema, :current_schema
|
|
48
57
|
|
|
49
58
|
def current_schema_id
|
|
50
|
-
|
|
59
|
+
metadata.current_schema_id
|
|
51
60
|
end
|
|
52
61
|
alias_method :schema_id, :current_schema_id
|
|
53
62
|
|
|
63
|
+
def partition_specs
|
|
64
|
+
metadata.partition_specs
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def partition_spec_by_id(partition_spec_id)
|
|
68
|
+
metadata.partition_spec_by_id(partition_spec_id)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def default_partition_spec
|
|
72
|
+
metadata.default_partition_spec
|
|
73
|
+
end
|
|
74
|
+
|
|
54
75
|
def default_partition_spec_id
|
|
55
|
-
|
|
76
|
+
metadata.default_partition_spec_id
|
|
56
77
|
end
|
|
57
78
|
|
|
58
79
|
def snapshots
|
|
59
|
-
|
|
80
|
+
metadata.snapshots
|
|
60
81
|
end
|
|
61
82
|
|
|
62
83
|
def snapshot_by_id(snapshot_id)
|
|
63
|
-
|
|
84
|
+
metadata.snapshot_by_id(snapshot_id)
|
|
64
85
|
end
|
|
65
86
|
|
|
66
87
|
def history
|
|
67
|
-
|
|
88
|
+
metadata.history
|
|
68
89
|
end
|
|
69
90
|
|
|
70
91
|
def metadata_log
|
|
71
|
-
|
|
92
|
+
metadata.metadata_log
|
|
72
93
|
end
|
|
73
94
|
|
|
74
95
|
def current_snapshot
|
|
75
|
-
|
|
96
|
+
metadata.current_snapshot
|
|
76
97
|
end
|
|
77
98
|
|
|
78
99
|
def current_snapshot_id
|
|
79
|
-
|
|
100
|
+
metadata.current_snapshot_id
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def sort_orders
|
|
104
|
+
metadata.sort_orders
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def default_sort_order
|
|
108
|
+
metadata.default_sort_order
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def default_sort_order_id
|
|
112
|
+
metadata.default_sort_order_id
|
|
80
113
|
end
|
|
81
114
|
|
|
82
115
|
def properties
|
|
83
|
-
|
|
116
|
+
metadata.properties
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def statistics
|
|
120
|
+
metadata.statistics
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def partition_statistics
|
|
124
|
+
metadata.partition_statistics
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def statistics_for_snapshot(snapshot_id)
|
|
128
|
+
metadata.statistics_for_snapshot(snapshot_id)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def partition_statistics_for_snapshot(snapshot_id)
|
|
132
|
+
metadata.partition_statistics_for_snapshot(snapshot_id)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def encryption_keys
|
|
136
|
+
metadata.encryption_keys
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def next_row_id
|
|
140
|
+
metadata.next_row_id
|
|
84
141
|
end
|
|
85
142
|
|
|
86
143
|
def scan(snapshot_id: nil)
|
|
87
144
|
TableScan.new(@table.scan(snapshot_id), self)
|
|
88
145
|
end
|
|
89
146
|
|
|
147
|
+
def to_a(snapshot_id: nil)
|
|
148
|
+
scan(snapshot_id: snapshot_id).to_a
|
|
149
|
+
end
|
|
150
|
+
|
|
90
151
|
def to_polars(snapshot_id: nil, storage_options: nil)
|
|
91
152
|
require "polars-df"
|
|
92
153
|
|
|
93
|
-
if Gem::Version.new(Polars::VERSION) < Gem::Version.new("0.
|
|
94
|
-
raise "Requires polars-df >= 0.
|
|
154
|
+
if Gem::Version.new(Polars::VERSION) < Gem::Version.new("0.26.1")
|
|
155
|
+
raise "Requires polars-df >= 0.26.1"
|
|
95
156
|
end
|
|
96
157
|
|
|
97
158
|
Polars.scan_iceberg(self, snapshot_id:, storage_options:)
|
|
@@ -99,6 +160,7 @@ module Iceberg
|
|
|
99
160
|
|
|
100
161
|
def append(df)
|
|
101
162
|
check_catalog
|
|
163
|
+
df = ArrowRecordBatch.new(df, schema.arrow_c_schema) if df.is_a?(Array)
|
|
102
164
|
@table = @table.append(df.arrow_c_stream, @catalog)
|
|
103
165
|
nil
|
|
104
166
|
end
|
|
@@ -110,6 +172,10 @@ module Iceberg
|
|
|
110
172
|
|
|
111
173
|
private
|
|
112
174
|
|
|
175
|
+
def metadata
|
|
176
|
+
@table.metadata
|
|
177
|
+
end
|
|
178
|
+
|
|
113
179
|
def check_catalog
|
|
114
180
|
raise Error, "Read-only table" if @catalog.nil?
|
|
115
181
|
end
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
module Iceberg
|
|
2
2
|
class TableDefinition
|
|
3
3
|
TYPES = %w[
|
|
4
|
-
boolean int long float double date
|
|
4
|
+
boolean int long float double decimal date time
|
|
5
|
+
timestamp timestamptz timestamp_nano timestamptz_nano
|
|
6
|
+
string uuid fixed binary
|
|
5
7
|
]
|
|
6
8
|
|
|
7
9
|
TYPE_ALIASES = {
|
|
@@ -21,17 +23,57 @@ module Iceberg
|
|
|
21
23
|
end
|
|
22
24
|
end
|
|
23
25
|
|
|
24
|
-
def column(name, type, null: true, default: nil, comment: nil)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
def column(name, type, null: true, default: nil, comment: nil, limit: nil, precision: nil, scale: nil)
|
|
27
|
+
unless type.is_a?(Type)
|
|
28
|
+
type = type.to_s
|
|
29
|
+
type =
|
|
30
|
+
case TYPE_ALIASES.fetch(type, type)
|
|
31
|
+
when "boolean"
|
|
32
|
+
BooleanType.new
|
|
33
|
+
when "int"
|
|
34
|
+
IntType.new
|
|
35
|
+
when "long"
|
|
36
|
+
LongType.new
|
|
37
|
+
when "float"
|
|
38
|
+
FloatType.new
|
|
39
|
+
when "double"
|
|
40
|
+
DoubleType.new
|
|
41
|
+
when "decimal"
|
|
42
|
+
DecimalType.new(precision, scale)
|
|
43
|
+
when "date"
|
|
44
|
+
DateType.new
|
|
45
|
+
when "time"
|
|
46
|
+
TimeType.new
|
|
47
|
+
when "timestamp"
|
|
48
|
+
TimestampType.new
|
|
49
|
+
when "timestamptz"
|
|
50
|
+
TimestamptzType.new
|
|
51
|
+
when "timestamp_nano"
|
|
52
|
+
TimestampNanoType.new
|
|
53
|
+
when "timestamptz_nano"
|
|
54
|
+
TimestamptzNanoType.new
|
|
55
|
+
when "string"
|
|
56
|
+
StringType.new
|
|
57
|
+
when "uuid"
|
|
58
|
+
UUIDType.new
|
|
59
|
+
when "fixed"
|
|
60
|
+
FixedType.new(limit)
|
|
61
|
+
when "binary"
|
|
62
|
+
BinaryType.new
|
|
63
|
+
else
|
|
64
|
+
type
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
@fields << NestedField.new(
|
|
69
|
+
field_id: @fields.size + 1,
|
|
28
70
|
name: name.to_s,
|
|
29
|
-
|
|
71
|
+
field_type: type,
|
|
30
72
|
required: !null,
|
|
31
73
|
doc: comment,
|
|
32
74
|
# no need for initial default (and not supported until v3)
|
|
33
75
|
write_default: default
|
|
34
|
-
|
|
76
|
+
)
|
|
35
77
|
end
|
|
36
78
|
end
|
|
37
79
|
end
|
data/lib/iceberg/table_scan.rb
CHANGED