iceberg 0.11.2 → 0.12.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 +4 -4
- data/CHANGELOG.md +11 -0
- data/Cargo.lock +799 -270
- data/Cargo.toml +7 -0
- data/NOTICE.txt +2 -2
- data/README.md +32 -12
- data/ext/iceberg/Cargo.toml +16 -13
- data/ext/iceberg/src/arrow.rs +22 -7
- data/ext/iceberg/src/batch.rs +174 -0
- data/ext/iceberg/src/capsule.rs +24 -0
- data/ext/iceberg/src/catalog.rs +160 -33
- data/ext/iceberg/src/encryption.rs +32 -0
- data/ext/iceberg/src/error.rs +50 -23
- data/ext/iceberg/src/lib.rs +264 -41
- data/ext/iceberg/src/partitioning.rs +102 -0
- data/ext/iceberg/src/result.rs +201 -0
- data/ext/iceberg/src/runtime.rs +5 -1
- data/ext/iceberg/src/scan.rs +106 -26
- data/ext/iceberg/src/schema.rs +305 -0
- data/ext/iceberg/src/snapshot.rs +85 -0
- data/ext/iceberg/src/sorting.rs +122 -0
- data/ext/iceberg/src/statistics.rs +71 -0
- data/ext/iceberg/src/table.rs +213 -265
- data/ext/iceberg/src/utils.rs +222 -164
- 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 +14 -3
- data/lib/iceberg/schema.rb +0 -10
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
use iceberg::spec::{PartitionStatisticsFile, StatisticsFile};
|
|
2
|
+
use magnus::{IntoValue, Ruby, value::ReprValue};
|
|
3
|
+
|
|
4
|
+
#[magnus::wrap(class = "Iceberg::StatisticsFile")]
|
|
5
|
+
pub struct RbStatisticsFile {
|
|
6
|
+
pub(crate) file: StatisticsFile,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
#[magnus::wrap(class = "Iceberg::PartitionStatisticsFile")]
|
|
10
|
+
pub struct RbPartitionStatisticsFile {
|
|
11
|
+
pub(crate) file: PartitionStatisticsFile,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
impl RbStatisticsFile {
|
|
15
|
+
pub fn snapshot_id(&self) -> i64 {
|
|
16
|
+
self.file.snapshot_id
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
pub fn statistics_path(&self) -> &str {
|
|
20
|
+
&self.file.statistics_path
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
pub fn file_size_in_bytes(&self) -> i64 {
|
|
24
|
+
self.file.file_size_in_bytes
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
pub fn file_footer_size_in_bytes(&self) -> i64 {
|
|
28
|
+
self.file.file_footer_size_in_bytes
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
pub fn key_metadata(&self) -> Option<&str> {
|
|
32
|
+
self.file.key_metadata.as_deref()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
pub fn inspect(ruby: &Ruby, rb_self: &Self) -> String {
|
|
36
|
+
format!(
|
|
37
|
+
"#<Iceberg::StatisticsFile snapshot_id={}, statistics_path={}, file_size_in_bytes={}, file_footer_size_in_bytes={}, key_metadata={}>",
|
|
38
|
+
rb_self.snapshot_id().into_value_with(ruby).inspect(),
|
|
39
|
+
rb_self.statistics_path().into_value_with(ruby).inspect(),
|
|
40
|
+
rb_self.file_size_in_bytes().into_value_with(ruby).inspect(),
|
|
41
|
+
rb_self
|
|
42
|
+
.file_footer_size_in_bytes()
|
|
43
|
+
.into_value_with(ruby)
|
|
44
|
+
.inspect(),
|
|
45
|
+
rb_self.key_metadata().into_value_with(ruby).inspect(),
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
impl RbPartitionStatisticsFile {
|
|
51
|
+
pub fn snapshot_id(&self) -> i64 {
|
|
52
|
+
self.file.snapshot_id
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
pub fn statistics_path(&self) -> &str {
|
|
56
|
+
&self.file.statistics_path
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
pub fn file_size_in_bytes(&self) -> i64 {
|
|
60
|
+
self.file.file_size_in_bytes
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
pub fn inspect(ruby: &Ruby, rb_self: &Self) -> String {
|
|
64
|
+
format!(
|
|
65
|
+
"#<Iceberg::PartitionStatisticsFile snapshot_id={}, statistics_path={}, file_size_in_bytes={}>",
|
|
66
|
+
rb_self.snapshot_id().into_value_with(ruby).inspect(),
|
|
67
|
+
rb_self.statistics_path().into_value_with(ruby).inspect(),
|
|
68
|
+
rb_self.file_size_in_bytes().into_value_with(ruby).inspect(),
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
}
|
data/ext/iceberg/src/table.rs
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
use std::collections::HashMap;
|
|
2
|
+
use std::sync::{Arc, RwLock};
|
|
3
|
+
|
|
4
|
+
use arrow_array::RecordBatch;
|
|
1
5
|
use arrow_array::ffi_stream::ArrowArrayStreamReader;
|
|
6
|
+
use arrow_cast::cast;
|
|
7
|
+
use arrow_schema::{ArrowError, DataType, Field, Schema};
|
|
2
8
|
use iceberg::TableIdent;
|
|
3
9
|
use iceberg::io::FileIO;
|
|
4
|
-
use iceberg::spec::FormatVersion;
|
|
10
|
+
use iceberg::spec::{FormatVersion, TableMetadata};
|
|
5
11
|
use iceberg::table::{StaticTable, Table};
|
|
6
12
|
use iceberg::transaction::{ApplyTransactionAction, Transaction};
|
|
7
13
|
use iceberg::writer::base_writer::data_file_writer::DataFileWriterBuilder;
|
|
@@ -11,20 +17,23 @@ use iceberg::writer::file_writer::location_generator::{
|
|
|
11
17
|
};
|
|
12
18
|
use iceberg::writer::file_writer::rolling_writer::RollingFileWriterBuilder;
|
|
13
19
|
use iceberg::writer::{IcebergWriter, IcebergWriterBuilder};
|
|
14
|
-
use magnus::{RArray, Ruby
|
|
20
|
+
use magnus::{RArray, Ruby};
|
|
15
21
|
use parquet::file::properties::WriterProperties;
|
|
16
|
-
use std::collections::HashMap;
|
|
17
|
-
use std::sync::{Arc, RwLock};
|
|
18
22
|
use uuid::Uuid;
|
|
19
23
|
|
|
20
24
|
use crate::RbResult;
|
|
21
|
-
use crate::arrow::RbArrowType;
|
|
22
25
|
use crate::catalog::RbCatalog;
|
|
26
|
+
use crate::encryption::RbEncryptedKey;
|
|
23
27
|
use crate::error::to_rb_err;
|
|
28
|
+
use crate::partitioning::RbPartitionSpec;
|
|
24
29
|
use crate::ruby::GvlExt;
|
|
25
30
|
use crate::runtime::runtime;
|
|
26
31
|
use crate::scan::RbTableScan;
|
|
27
|
-
use crate::
|
|
32
|
+
use crate::schema::RbSchema;
|
|
33
|
+
use crate::snapshot::{RbMetadataLogEntry, RbSnapshot, RbSnapshotLogEntry};
|
|
34
|
+
use crate::sorting::RbSortOrder;
|
|
35
|
+
use crate::statistics::{RbPartitionStatisticsFile, RbStatisticsFile};
|
|
36
|
+
use crate::utils::Wrap;
|
|
28
37
|
|
|
29
38
|
#[magnus::wrap(class = "Iceberg::RbTable")]
|
|
30
39
|
pub struct RbTable {
|
|
@@ -32,6 +41,14 @@ pub struct RbTable {
|
|
|
32
41
|
}
|
|
33
42
|
|
|
34
43
|
impl RbTable {
|
|
44
|
+
pub fn identifier(&self) -> Vec<String> {
|
|
45
|
+
let table = self.table.read().unwrap();
|
|
46
|
+
let ident = table.identifier();
|
|
47
|
+
let mut vec = ident.namespace.clone().inner();
|
|
48
|
+
vec.push(ident.name.clone());
|
|
49
|
+
vec
|
|
50
|
+
}
|
|
51
|
+
|
|
35
52
|
pub fn scan(&self, snapshot_id: Option<i64>) -> RbResult<RbTableScan> {
|
|
36
53
|
let table = self.table.read().unwrap();
|
|
37
54
|
let mut builder = table.scan();
|
|
@@ -45,7 +62,7 @@ impl RbTable {
|
|
|
45
62
|
pub fn append(
|
|
46
63
|
ruby: &Ruby,
|
|
47
64
|
rb_self: &Self,
|
|
48
|
-
data:
|
|
65
|
+
data: Wrap<ArrowArrayStreamReader>,
|
|
49
66
|
catalog: &RbCatalog,
|
|
50
67
|
) -> RbResult<RbTable> {
|
|
51
68
|
let table = ruby
|
|
@@ -63,7 +80,7 @@ impl RbTable {
|
|
|
63
80
|
.unwrap(),
|
|
64
81
|
);
|
|
65
82
|
|
|
66
|
-
let location_generator = DefaultLocationGenerator::new(table.metadata()
|
|
83
|
+
let location_generator = DefaultLocationGenerator::new(table.metadata())?;
|
|
67
84
|
let file_name_generator = DefaultFileNameGenerator::new(
|
|
68
85
|
// TODO move task id to suffix to match Python and Java
|
|
69
86
|
"0".to_string(),
|
|
@@ -88,7 +105,7 @@ impl RbTable {
|
|
|
88
105
|
runtime.block_on(data_file_writer_builder.build(None))?;
|
|
89
106
|
|
|
90
107
|
for batch in data.0 {
|
|
91
|
-
let batch = batch.unwrap()
|
|
108
|
+
let batch = cast_batch(batch.unwrap(), table_schema.clone())?;
|
|
92
109
|
runtime.block_on(data_file_writer.write(batch))?;
|
|
93
110
|
}
|
|
94
111
|
|
|
@@ -107,8 +124,36 @@ impl RbTable {
|
|
|
107
124
|
})
|
|
108
125
|
}
|
|
109
126
|
|
|
127
|
+
pub fn metadata(&self) -> RbTableMetadata {
|
|
128
|
+
RbTableMetadata {
|
|
129
|
+
metadata: self.table.read().unwrap().metadata().clone(),
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
pub fn from_metadata_file(location: String) -> RbResult<Self> {
|
|
134
|
+
let file_io = FileIO::new_with_fs();
|
|
135
|
+
let table_ident = TableIdent::from_strs(["static-table", &location]).unwrap();
|
|
136
|
+
let static_table = runtime()
|
|
137
|
+
.block_on(StaticTable::from_metadata_file(
|
|
138
|
+
&location,
|
|
139
|
+
table_ident,
|
|
140
|
+
file_io,
|
|
141
|
+
))
|
|
142
|
+
.map_err(to_rb_err)?;
|
|
143
|
+
Ok(Self {
|
|
144
|
+
table: static_table.into_table().into(),
|
|
145
|
+
})
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
#[magnus::wrap(class = "Iceberg::TableMetadata")]
|
|
150
|
+
pub struct RbTableMetadata {
|
|
151
|
+
pub metadata: TableMetadata,
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
impl RbTableMetadata {
|
|
110
155
|
pub fn format_version(&self) -> i32 {
|
|
111
|
-
match self.
|
|
156
|
+
match self.metadata.format_version() {
|
|
112
157
|
FormatVersion::V1 => 1,
|
|
113
158
|
FormatVersion::V2 => 2,
|
|
114
159
|
FormatVersion::V3 => 3,
|
|
@@ -116,321 +161,224 @@ impl RbTable {
|
|
|
116
161
|
}
|
|
117
162
|
|
|
118
163
|
pub fn uuid(&self) -> String {
|
|
119
|
-
self.
|
|
164
|
+
self.metadata.uuid().to_string()
|
|
120
165
|
}
|
|
121
166
|
|
|
122
167
|
pub fn location(&self) -> String {
|
|
123
|
-
self.
|
|
168
|
+
self.metadata.location().to_string()
|
|
124
169
|
}
|
|
125
170
|
|
|
126
171
|
pub fn last_sequence_number(&self) -> i64 {
|
|
127
|
-
self.
|
|
172
|
+
self.metadata.last_sequence_number()
|
|
128
173
|
}
|
|
129
174
|
|
|
130
175
|
pub fn next_sequence_number(&self) -> i64 {
|
|
131
|
-
self.
|
|
176
|
+
self.metadata.next_sequence_number()
|
|
132
177
|
}
|
|
133
178
|
|
|
134
179
|
pub fn last_column_id(&self) -> i32 {
|
|
135
|
-
self.
|
|
180
|
+
self.metadata.last_column_id()
|
|
136
181
|
}
|
|
137
182
|
|
|
138
183
|
pub fn last_partition_id(&self) -> i32 {
|
|
139
|
-
self.
|
|
184
|
+
self.metadata.last_partition_id()
|
|
140
185
|
}
|
|
141
186
|
|
|
142
187
|
pub fn last_updated_ms(&self) -> i64 {
|
|
143
|
-
self.
|
|
188
|
+
self.metadata.last_updated_ms()
|
|
144
189
|
}
|
|
145
190
|
|
|
146
|
-
pub fn schemas(ruby: &Ruby, rb_self: &Self) ->
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
pub fn
|
|
155
|
-
|
|
156
|
-
.table
|
|
157
|
-
.read()
|
|
158
|
-
.unwrap()
|
|
159
|
-
.metadata()
|
|
160
|
-
.schema_by_id(schema_id)
|
|
161
|
-
{
|
|
162
|
-
Some(s) => Some(rb_schema(ruby, s)?),
|
|
163
|
-
None => None,
|
|
164
|
-
};
|
|
165
|
-
Ok(schema)
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
pub fn current_schema(ruby: &Ruby, rb_self: &Self) -> RbResult<Value> {
|
|
169
|
-
rb_schema(
|
|
170
|
-
ruby,
|
|
171
|
-
rb_self.table.read().unwrap().metadata().current_schema(),
|
|
172
|
-
)
|
|
191
|
+
pub fn schemas(ruby: &Ruby, rb_self: &Self) -> RArray {
|
|
192
|
+
ruby.ary_from_iter(rb_self.metadata.schemas_iter().map(RbSchema::from))
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
pub fn schema_by_id(&self, schema_id: i32) -> Option<RbSchema> {
|
|
196
|
+
self.metadata.schema_by_id(schema_id).map(|v| v.into())
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
pub fn current_schema(&self) -> RbSchema {
|
|
200
|
+
self.metadata.current_schema().into()
|
|
173
201
|
}
|
|
174
202
|
|
|
175
203
|
pub fn current_schema_id(&self) -> i32 {
|
|
176
|
-
self.
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
pub fn partition_specs(ruby: &Ruby, rb_self: &Self) -> RbResult<RArray> {
|
|
180
|
-
let partition_specs = ruby.ary_new();
|
|
181
|
-
for s in rb_self
|
|
182
|
-
.table
|
|
183
|
-
.read()
|
|
184
|
-
.unwrap()
|
|
185
|
-
.metadata()
|
|
186
|
-
.partition_specs_iter()
|
|
187
|
-
{
|
|
188
|
-
partition_specs.push(rb_partition_spec(s)?)?;
|
|
189
|
-
}
|
|
190
|
-
Ok(partition_specs)
|
|
204
|
+
self.metadata.current_schema_id()
|
|
191
205
|
}
|
|
192
206
|
|
|
193
|
-
pub fn
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
.partition_spec_by_id(partition_spec_id)
|
|
200
|
-
{
|
|
201
|
-
Some(s) => Some(rb_partition_spec(s)?),
|
|
202
|
-
None => None,
|
|
203
|
-
};
|
|
204
|
-
Ok(partition_spec)
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
pub fn default_partition_spec(&self) -> RbResult<Value> {
|
|
208
|
-
rb_partition_spec(
|
|
209
|
-
self.table
|
|
210
|
-
.read()
|
|
211
|
-
.unwrap()
|
|
212
|
-
.metadata()
|
|
213
|
-
.default_partition_spec(),
|
|
207
|
+
pub fn partition_specs(ruby: &Ruby, rb_self: &Self) -> RArray {
|
|
208
|
+
ruby.ary_from_iter(
|
|
209
|
+
rb_self
|
|
210
|
+
.metadata
|
|
211
|
+
.partition_specs_iter()
|
|
212
|
+
.map(RbPartitionSpec::from),
|
|
214
213
|
)
|
|
215
214
|
}
|
|
216
215
|
|
|
216
|
+
pub fn partition_spec_by_id(&self, partition_spec_id: i32) -> Option<RbPartitionSpec> {
|
|
217
|
+
self.metadata
|
|
218
|
+
.partition_spec_by_id(partition_spec_id)
|
|
219
|
+
.map(|v| v.into())
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
pub fn default_partition_spec(&self) -> RbPartitionSpec {
|
|
223
|
+
self.metadata.default_partition_spec().into()
|
|
224
|
+
}
|
|
225
|
+
|
|
217
226
|
pub fn default_partition_spec_id(&self) -> i32 {
|
|
218
|
-
self.
|
|
219
|
-
.read()
|
|
220
|
-
.unwrap()
|
|
221
|
-
.metadata()
|
|
222
|
-
.default_partition_spec_id()
|
|
227
|
+
self.metadata.default_partition_spec_id()
|
|
223
228
|
}
|
|
224
229
|
|
|
225
|
-
pub fn snapshots(ruby: &Ruby, rb_self: &Self) ->
|
|
226
|
-
|
|
227
|
-
for s in rb_self.table.read().unwrap().metadata().snapshots() {
|
|
228
|
-
snapshots.push(rb_snapshot(ruby, s)?)?;
|
|
229
|
-
}
|
|
230
|
-
Ok(snapshots)
|
|
230
|
+
pub fn snapshots(ruby: &Ruby, rb_self: &Self) -> RArray {
|
|
231
|
+
ruby.ary_from_iter(rb_self.metadata.snapshots().map(RbSnapshot::from))
|
|
231
232
|
}
|
|
232
233
|
|
|
233
|
-
pub fn snapshot_by_id(
|
|
234
|
-
|
|
235
|
-
rb_self: &Self,
|
|
236
|
-
snapshot_id: i64,
|
|
237
|
-
) -> RbResult<Option<Value>> {
|
|
238
|
-
let snapshot = match rb_self
|
|
239
|
-
.table
|
|
240
|
-
.read()
|
|
241
|
-
.unwrap()
|
|
242
|
-
.metadata()
|
|
243
|
-
.snapshot_by_id(snapshot_id)
|
|
244
|
-
{
|
|
245
|
-
Some(s) => Some(rb_snapshot(ruby, s)?),
|
|
246
|
-
None => None,
|
|
247
|
-
};
|
|
248
|
-
Ok(snapshot)
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
pub fn history(ruby: &Ruby, rb_self: &Self) -> RbResult<RArray> {
|
|
252
|
-
let history = ruby.ary_new();
|
|
253
|
-
for s in rb_self.table.read().unwrap().metadata().history() {
|
|
254
|
-
let snapshot_log = ruby.hash_new();
|
|
255
|
-
snapshot_log.aset(ruby.to_symbol("snapshot_id"), s.snapshot_id)?;
|
|
256
|
-
// TODO timestamp
|
|
257
|
-
history.push(snapshot_log)?;
|
|
258
|
-
}
|
|
259
|
-
Ok(history)
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
pub fn metadata_log(ruby: &Ruby, rb_self: &Self) -> RbResult<RArray> {
|
|
263
|
-
let metadata_logs = ruby.ary_new();
|
|
264
|
-
for s in rb_self.table.read().unwrap().metadata().metadata_log() {
|
|
265
|
-
let metadata_log = ruby.hash_new();
|
|
266
|
-
metadata_log.aset(
|
|
267
|
-
ruby.to_symbol("metadata_file"),
|
|
268
|
-
ruby.str_new(&s.metadata_file),
|
|
269
|
-
)?;
|
|
270
|
-
// TODO timestamp
|
|
271
|
-
metadata_logs.push(metadata_log)?;
|
|
272
|
-
}
|
|
273
|
-
Ok(metadata_logs)
|
|
234
|
+
pub fn snapshot_by_id(&self, snapshot_id: i64) -> Option<RbSnapshot> {
|
|
235
|
+
self.metadata.snapshot_by_id(snapshot_id).map(|v| v.into())
|
|
274
236
|
}
|
|
275
237
|
|
|
276
|
-
pub fn
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
238
|
+
pub fn history(ruby: &Ruby, rb_self: &Self) -> RArray {
|
|
239
|
+
ruby.ary_from_iter(
|
|
240
|
+
rb_self
|
|
241
|
+
.metadata
|
|
242
|
+
.history()
|
|
243
|
+
.iter()
|
|
244
|
+
.map(RbSnapshotLogEntry::from),
|
|
245
|
+
)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
pub fn metadata_log(ruby: &Ruby, rb_self: &Self) -> RArray {
|
|
249
|
+
ruby.ary_from_iter(
|
|
250
|
+
rb_self
|
|
251
|
+
.metadata
|
|
252
|
+
.metadata_log()
|
|
253
|
+
.iter()
|
|
254
|
+
.map(RbMetadataLogEntry::from),
|
|
255
|
+
)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
pub fn current_snapshot(&self) -> Option<RbSnapshot> {
|
|
259
|
+
self.metadata.current_snapshot().map(|v| v.into())
|
|
282
260
|
}
|
|
283
261
|
|
|
284
262
|
pub fn current_snapshot_id(&self) -> Option<i64> {
|
|
285
|
-
self.
|
|
263
|
+
self.metadata.current_snapshot_id()
|
|
286
264
|
}
|
|
287
265
|
|
|
288
|
-
pub fn snapshot_for_ref(
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
) ->
|
|
293
|
-
|
|
294
|
-
.table
|
|
295
|
-
.read()
|
|
296
|
-
.unwrap()
|
|
297
|
-
.metadata()
|
|
298
|
-
.snapshot_for_ref(&ref_name)
|
|
299
|
-
{
|
|
300
|
-
Some(s) => Some(rb_snapshot(ruby, s)?),
|
|
301
|
-
None => None,
|
|
302
|
-
};
|
|
303
|
-
Ok(snapshot)
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
pub fn sort_orders(ruby: &Ruby, rb_self: &Self) -> RbResult<RArray> {
|
|
307
|
-
let sort_orders = ruby.ary_new();
|
|
308
|
-
for s in rb_self.table.read().unwrap().metadata().sort_orders_iter() {
|
|
309
|
-
sort_orders.push(rb_sort_order(s)?)?;
|
|
310
|
-
}
|
|
311
|
-
Ok(sort_orders)
|
|
266
|
+
pub fn snapshot_for_ref(&self, ref_name: String) -> Option<RbSnapshot> {
|
|
267
|
+
self.metadata.snapshot_for_ref(&ref_name).map(|v| v.into())
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
pub fn sort_orders(ruby: &Ruby, rb_self: &Self) -> RArray {
|
|
271
|
+
ruby.ary_from_iter(rb_self.metadata.sort_orders_iter().map(RbSortOrder::from))
|
|
312
272
|
}
|
|
313
273
|
|
|
314
|
-
pub fn sort_order_by_id(&self, sort_order_id: i64) ->
|
|
315
|
-
|
|
316
|
-
.table
|
|
317
|
-
.read()
|
|
318
|
-
.unwrap()
|
|
319
|
-
.metadata()
|
|
274
|
+
pub fn sort_order_by_id(&self, sort_order_id: i64) -> Option<RbSortOrder> {
|
|
275
|
+
self.metadata
|
|
320
276
|
.sort_order_by_id(sort_order_id)
|
|
321
|
-
|
|
322
|
-
Some(s) => Some(rb_sort_order(s)?),
|
|
323
|
-
None => None,
|
|
324
|
-
};
|
|
325
|
-
Ok(sort_order)
|
|
277
|
+
.map(|v| v.into())
|
|
326
278
|
}
|
|
327
279
|
|
|
328
|
-
pub fn default_sort_order(&self) ->
|
|
329
|
-
|
|
280
|
+
pub fn default_sort_order(&self) -> RbSortOrder {
|
|
281
|
+
self.metadata.default_sort_order().into()
|
|
330
282
|
}
|
|
331
283
|
|
|
332
284
|
pub fn default_sort_order_id(&self) -> i64 {
|
|
333
|
-
self.
|
|
334
|
-
.read()
|
|
335
|
-
.unwrap()
|
|
336
|
-
.metadata()
|
|
337
|
-
.default_sort_order_id()
|
|
285
|
+
self.metadata.default_sort_order_id()
|
|
338
286
|
}
|
|
339
287
|
|
|
340
288
|
pub fn properties(&self) -> HashMap<String, String> {
|
|
341
|
-
self.
|
|
289
|
+
self.metadata.properties().clone()
|
|
342
290
|
}
|
|
343
291
|
|
|
344
|
-
pub fn statistics(ruby: &Ruby, rb_self: &Self) ->
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
pub fn partition_statistics(ruby: &Ruby, rb_self: &Self) -> RbResult<RArray> {
|
|
353
|
-
let statistics = ruby.ary_new();
|
|
354
|
-
for s in rb_self
|
|
355
|
-
.table
|
|
356
|
-
.read()
|
|
357
|
-
.unwrap()
|
|
358
|
-
.metadata()
|
|
359
|
-
.partition_statistics_iter()
|
|
360
|
-
{
|
|
361
|
-
statistics.push(rb_partition_statistics_file(s)?)?;
|
|
362
|
-
}
|
|
363
|
-
Ok(statistics)
|
|
292
|
+
pub fn statistics(ruby: &Ruby, rb_self: &Self) -> RArray {
|
|
293
|
+
ruby.ary_from_iter(
|
|
294
|
+
rb_self
|
|
295
|
+
.metadata
|
|
296
|
+
.statistics_iter()
|
|
297
|
+
.map(RbStatisticsFile::from),
|
|
298
|
+
)
|
|
364
299
|
}
|
|
365
300
|
|
|
366
|
-
pub fn
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
301
|
+
pub fn partition_statistics(ruby: &Ruby, rb_self: &Self) -> RArray {
|
|
302
|
+
ruby.ary_from_iter(
|
|
303
|
+
rb_self
|
|
304
|
+
.metadata
|
|
305
|
+
.partition_statistics_iter()
|
|
306
|
+
.map(RbPartitionStatisticsFile::from),
|
|
307
|
+
)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
pub fn statistics_for_snapshot(&self, snapshot_id: i64) -> Option<RbStatisticsFile> {
|
|
311
|
+
self.metadata
|
|
372
312
|
.statistics_for_snapshot(snapshot_id)
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
let statistics = match self
|
|
382
|
-
.table
|
|
383
|
-
.read()
|
|
384
|
-
.unwrap()
|
|
385
|
-
.metadata()
|
|
313
|
+
.map(|v| v.into())
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
pub fn partition_statistics_for_snapshot(
|
|
317
|
+
&self,
|
|
318
|
+
snapshot_id: i64,
|
|
319
|
+
) -> Option<RbPartitionStatisticsFile> {
|
|
320
|
+
self.metadata
|
|
386
321
|
.partition_statistics_for_snapshot(snapshot_id)
|
|
387
|
-
|
|
388
|
-
Some(s) => Some(rb_partition_statistics_file(s)?),
|
|
389
|
-
None => None,
|
|
390
|
-
};
|
|
391
|
-
Ok(statistics)
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
pub fn encryption_keys(ruby: &Ruby, rb_self: &Self) -> RbResult<RArray> {
|
|
395
|
-
let encryption_keys = ruby.ary_new();
|
|
396
|
-
for k in rb_self
|
|
397
|
-
.table
|
|
398
|
-
.read()
|
|
399
|
-
.unwrap()
|
|
400
|
-
.metadata()
|
|
401
|
-
.encryption_keys_iter()
|
|
402
|
-
{
|
|
403
|
-
encryption_keys.push(rb_encrypted_key(k)?)?;
|
|
404
|
-
}
|
|
405
|
-
Ok(encryption_keys)
|
|
322
|
+
.map(|v| v.into())
|
|
406
323
|
}
|
|
407
324
|
|
|
408
|
-
pub fn
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
{
|
|
416
|
-
Some(k) => Some(rb_encrypted_key(k)?),
|
|
417
|
-
None => None,
|
|
418
|
-
};
|
|
419
|
-
Ok(key)
|
|
325
|
+
pub fn encryption_keys(ruby: &Ruby, rb_self: &Self) -> RArray {
|
|
326
|
+
ruby.ary_from_iter(
|
|
327
|
+
rb_self
|
|
328
|
+
.metadata
|
|
329
|
+
.encryption_keys_iter()
|
|
330
|
+
.map(RbEncryptedKey::from),
|
|
331
|
+
)
|
|
420
332
|
}
|
|
421
333
|
|
|
422
|
-
pub fn
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
334
|
+
pub fn encryption_key(&self, key_id: String) -> Option<RbEncryptedKey> {
|
|
335
|
+
self.metadata.encryption_key(&key_id).map(|v| v.into())
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
pub fn next_row_id(&self) -> u64 {
|
|
339
|
+
self.metadata.next_row_id()
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
fn cast_batch(batch: RecordBatch, table_schema: Arc<Schema>) -> Result<RecordBatch, ArrowError> {
|
|
344
|
+
let mut fields = Vec::new();
|
|
345
|
+
let mut columns = Vec::new();
|
|
346
|
+
for (field, column) in batch.schema().fields.iter().zip(batch.columns()) {
|
|
347
|
+
match field.data_type() {
|
|
348
|
+
DataType::Utf8View => {
|
|
349
|
+
fields.push(Arc::new(Field::new(
|
|
350
|
+
field.name(),
|
|
351
|
+
DataType::Utf8,
|
|
352
|
+
field.is_nullable(),
|
|
353
|
+
)));
|
|
354
|
+
columns.push(cast(column, &DataType::Utf8)?);
|
|
355
|
+
}
|
|
356
|
+
DataType::BinaryView => {
|
|
357
|
+
// TODO convert to FixedSizeBinary if needed
|
|
358
|
+
fields.push(Arc::new(Field::new(
|
|
359
|
+
field.name(),
|
|
360
|
+
DataType::LargeBinary,
|
|
361
|
+
field.is_nullable(),
|
|
362
|
+
)));
|
|
363
|
+
columns.push(cast(column, &DataType::LargeBinary)?);
|
|
364
|
+
}
|
|
365
|
+
DataType::Timestamp(time_unit, Some(_)) => {
|
|
366
|
+
fields.push(Arc::new(Field::new(
|
|
367
|
+
field.name(),
|
|
368
|
+
DataType::Timestamp(*time_unit, Some("+00:00".into())),
|
|
369
|
+
field.is_nullable(),
|
|
370
|
+
)));
|
|
371
|
+
columns.push(cast(
|
|
372
|
+
column,
|
|
373
|
+
&DataType::Timestamp(*time_unit, Some("+00:00".into())),
|
|
374
|
+
)?);
|
|
375
|
+
}
|
|
376
|
+
_ => {
|
|
377
|
+
// cloning Arc is cheap
|
|
378
|
+
fields.push(field.clone());
|
|
379
|
+
columns.push(column.clone());
|
|
380
|
+
}
|
|
381
|
+
}
|
|
435
382
|
}
|
|
383
|
+
RecordBatch::try_new(Arc::new(Schema::new(fields)), columns)?.with_schema(table_schema)
|
|
436
384
|
}
|