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.
@@ -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
+ }
@@ -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, Value};
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::utils::*;
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: RbArrowType<ArrowArrayStreamReader>,
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().clone())?;
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().with_schema(table_schema.clone())?;
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.table.read().unwrap().metadata().format_version() {
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.table.read().unwrap().metadata().uuid().to_string()
164
+ self.metadata.uuid().to_string()
120
165
  }
121
166
 
122
167
  pub fn location(&self) -> String {
123
- self.table.read().unwrap().metadata().location().to_string()
168
+ self.metadata.location().to_string()
124
169
  }
125
170
 
126
171
  pub fn last_sequence_number(&self) -> i64 {
127
- self.table.read().unwrap().metadata().last_sequence_number()
172
+ self.metadata.last_sequence_number()
128
173
  }
129
174
 
130
175
  pub fn next_sequence_number(&self) -> i64 {
131
- self.table.read().unwrap().metadata().next_sequence_number()
176
+ self.metadata.next_sequence_number()
132
177
  }
133
178
 
134
179
  pub fn last_column_id(&self) -> i32 {
135
- self.table.read().unwrap().metadata().last_column_id()
180
+ self.metadata.last_column_id()
136
181
  }
137
182
 
138
183
  pub fn last_partition_id(&self) -> i32 {
139
- self.table.read().unwrap().metadata().last_partition_id()
184
+ self.metadata.last_partition_id()
140
185
  }
141
186
 
142
187
  pub fn last_updated_ms(&self) -> i64 {
143
- self.table.read().unwrap().metadata().last_updated_ms()
188
+ self.metadata.last_updated_ms()
144
189
  }
145
190
 
146
- pub fn schemas(ruby: &Ruby, rb_self: &Self) -> RbResult<RArray> {
147
- let schemas = ruby.ary_new();
148
- for s in rb_self.table.read().unwrap().metadata().schemas_iter() {
149
- schemas.push(rb_schema(ruby, s)?)?;
150
- }
151
- Ok(schemas)
152
- }
153
-
154
- pub fn schema_by_id(ruby: &Ruby, rb_self: &Self, schema_id: i32) -> RbResult<Option<Value>> {
155
- let schema = match rb_self
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.table.read().unwrap().metadata().current_schema_id()
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 partition_spec_by_id(&self, partition_spec_id: i32) -> RbResult<Option<Value>> {
194
- let partition_spec = match self
195
- .table
196
- .read()
197
- .unwrap()
198
- .metadata()
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.table
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) -> RbResult<RArray> {
226
- let snapshots = ruby.ary_new();
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
- ruby: &Ruby,
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 current_snapshot(ruby: &Ruby, rb_self: &Self) -> RbResult<Option<Value>> {
277
- let snapshot = match rb_self.table.read().unwrap().metadata().current_snapshot() {
278
- Some(s) => Some(rb_snapshot(ruby, s)?),
279
- None => None,
280
- };
281
- Ok(snapshot)
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.table.read().unwrap().metadata().current_snapshot_id()
263
+ self.metadata.current_snapshot_id()
286
264
  }
287
265
 
288
- pub fn snapshot_for_ref(
289
- ruby: &Ruby,
290
- rb_self: &Self,
291
- ref_name: String,
292
- ) -> RbResult<Option<Value>> {
293
- let snapshot = match rb_self
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) -> RbResult<Option<Value>> {
315
- let sort_order = match self
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) -> RbResult<Value> {
329
- rb_sort_order(self.table.read().unwrap().metadata().default_sort_order())
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.table
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.table.read().unwrap().metadata().properties().clone()
289
+ self.metadata.properties().clone()
342
290
  }
343
291
 
344
- pub fn statistics(ruby: &Ruby, rb_self: &Self) -> RbResult<RArray> {
345
- let statistics = ruby.ary_new();
346
- for s in rb_self.table.read().unwrap().metadata().statistics_iter() {
347
- statistics.push(rb_statistics_file(s)?)?;
348
- }
349
- Ok(statistics)
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 statistics_for_snapshot(&self, snapshot_id: i64) -> RbResult<Option<Value>> {
367
- let statistics = match self
368
- .table
369
- .read()
370
- .unwrap()
371
- .metadata()
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
- Some(s) => Some(rb_statistics_file(s)?),
375
- None => None,
376
- };
377
- Ok(statistics)
378
- }
379
-
380
- pub fn partition_statistics_for_snapshot(&self, snapshot_id: i64) -> RbResult<Option<Value>> {
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 encryption_key(&self, key_id: String) -> RbResult<Option<Value>> {
409
- let key = match self
410
- .table
411
- .read()
412
- .unwrap()
413
- .metadata()
414
- .encryption_key(&key_id)
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 from_metadata_file(location: String) -> RbResult<Self> {
423
- let file_io = FileIO::new_with_fs();
424
- let table_ident = TableIdent::from_strs(["static-table", &location]).unwrap();
425
- let static_table = runtime()
426
- .block_on(StaticTable::from_metadata_file(
427
- &location,
428
- table_ident,
429
- file_io,
430
- ))
431
- .map_err(to_rb_err)?;
432
- Ok(Self {
433
- table: static_table.into_table().into(),
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
  }