@@ -53,6 +53,30 @@ impl MemoryCatalog {
53
53
warehouse_location,
54
54
}
55
55
}
56
+
57
+ fn new_metadata_location ( & self , location : & str ) -> String {
58
+ format ! ( "{}/metadata/{}.metadata.json" , location, Uuid :: new_v4( ) )
59
+ }
60
+
61
+ async fn commit_table (
62
+ & self ,
63
+ table_ident : & TableIdent ,
64
+ next_metadata : TableMetadata ,
65
+ ) -> Result < ( ) > {
66
+ let mut root_namespace_state = self . root_namespace_state . lock ( ) . await ;
67
+
68
+ let table_metadata_dir =
69
+ root_namespace_state. get_existing_table_metadata_dir ( table_ident) ?;
70
+ let metadata_location = self . new_metadata_location ( table_metadata_dir) ;
71
+ self . file_io
72
+ . new_output ( & metadata_location) ?
73
+ . write ( serde_json:: to_vec ( & next_metadata) ?. into ( ) )
74
+ . await ?;
75
+
76
+ root_namespace_state. update_table ( table_ident, metadata_location) ?;
77
+
78
+ Ok ( ( ) )
79
+ }
56
80
}
57
81
58
82
#[ async_trait]
@@ -197,19 +221,14 @@ impl Catalog for MemoryCatalog {
197
221
let metadata = TableMetadataBuilder :: from_table_creation ( table_creation) ?
198
222
. build ( ) ?
199
223
. metadata ;
200
- let metadata_location = format ! (
201
- "{}/metadata/{}-{}.metadata.json" ,
202
- & location,
203
- 0 ,
204
- Uuid :: new_v4( )
205
- ) ;
224
+ let metadata_location = self . new_metadata_location ( & location) ;
206
225
207
226
self . file_io
208
227
. new_output ( & metadata_location) ?
209
228
. write ( serde_json:: to_vec ( & metadata) ?. into ( ) )
210
229
. await ?;
211
230
212
- root_namespace_state. insert_new_table ( & table_ident, metadata_location. clone ( ) ) ?;
231
+ root_namespace_state. insert_new_table ( & table_ident, location , metadata_location. clone ( ) ) ?;
213
232
214
233
Table :: builder ( )
215
234
. file_io ( self . file_io . clone ( ) )
@@ -263,19 +282,39 @@ impl Catalog for MemoryCatalog {
263
282
let metadata_location = new_root_namespace_state
264
283
. get_existing_table_location ( src_table_ident) ?
265
284
. clone ( ) ;
285
+ let metadata_dir = new_root_namespace_state
286
+ . get_existing_table_metadata_dir ( src_table_ident) ?
287
+ . clone ( ) ;
266
288
new_root_namespace_state. remove_existing_table ( src_table_ident) ?;
267
- new_root_namespace_state. insert_new_table ( dst_table_ident, metadata_location) ?;
289
+ new_root_namespace_state. insert_new_table (
290
+ dst_table_ident,
291
+ metadata_dir,
292
+ metadata_location,
293
+ ) ?;
268
294
* root_namespace_state = new_root_namespace_state;
269
295
270
296
Ok ( ( ) )
271
297
}
272
298
273
299
/// Update a table to the catalog.
274
- async fn update_table ( & self , _commit : TableCommit ) -> Result < Table > {
275
- Err ( Error :: new (
276
- ErrorKind :: FeatureUnsupported ,
277
- "MemoryCatalog does not currently support updating tables." ,
278
- ) )
300
+ async fn update_table ( & self , mut commit : TableCommit ) -> Result < Table > {
301
+ // Apply the update to get the new metadata.
302
+ let table = self . load_table ( commit. identifier ( ) ) . await ?;
303
+ let requirements = commit. take_requirements ( ) ;
304
+ let updates = commit. take_updates ( ) ;
305
+ let metadata = table. metadata ( ) . clone ( ) ;
306
+ for requirement in requirements {
307
+ requirement. check ( Some ( & metadata) ) ?;
308
+ }
309
+ let mut metadata_builder = metadata. into_builder ( None ) ;
310
+ for update in updates {
311
+ metadata_builder = update. apply ( metadata_builder) ?;
312
+ }
313
+
314
+ self . commit_table ( commit. identifier ( ) , metadata_builder. build ( ) ?. metadata )
315
+ . await ?;
316
+
317
+ self . load_table ( commit. identifier ( ) ) . await
279
318
}
280
319
}
281
320
@@ -287,6 +326,7 @@ mod tests {
287
326
288
327
use iceberg:: io:: FileIOBuilder ;
289
328
use iceberg:: spec:: { NestedField , PartitionSpec , PrimitiveType , Schema , SortOrder , Type } ;
329
+ use iceberg:: transaction:: Transaction ;
290
330
use regex:: Regex ;
291
331
use tempfile:: TempDir ;
292
332
@@ -1035,7 +1075,7 @@ mod tests {
1035
1075
let table_name = "tbl1" ;
1036
1076
let expected_table_ident = TableIdent :: new ( namespace_ident. clone ( ) , table_name. into ( ) ) ;
1037
1077
let expected_table_metadata_location_regex = format ! (
1038
- "^{}/tbl1/metadata/0- {}.metadata.json$" ,
1078
+ "^{}/tbl1/metadata/{}.metadata.json$" ,
1039
1079
namespace_location, UUID_REGEX_STR ,
1040
1080
) ;
1041
1081
@@ -1088,7 +1128,7 @@ mod tests {
1088
1128
let expected_table_ident =
1089
1129
TableIdent :: new ( nested_namespace_ident. clone ( ) , table_name. into ( ) ) ;
1090
1130
let expected_table_metadata_location_regex = format ! (
1091
- "^{}/tbl1/metadata/0- {}.metadata.json$" ,
1131
+ "^{}/tbl1/metadata/{}.metadata.json$" ,
1092
1132
nested_namespace_location, UUID_REGEX_STR ,
1093
1133
) ;
1094
1134
@@ -1129,7 +1169,7 @@ mod tests {
1129
1169
let table_name = "tbl1" ;
1130
1170
let expected_table_ident = TableIdent :: new ( namespace_ident. clone ( ) , table_name. into ( ) ) ;
1131
1171
let expected_table_metadata_location_regex = format ! (
1132
- "^{}/a/tbl1/metadata/0- {}.metadata.json$" ,
1172
+ "^{}/a/tbl1/metadata/{}.metadata.json$" ,
1133
1173
warehouse_location, UUID_REGEX_STR
1134
1174
) ;
1135
1175
@@ -1177,7 +1217,7 @@ mod tests {
1177
1217
let expected_table_ident =
1178
1218
TableIdent :: new ( nested_namespace_ident. clone ( ) , table_name. into ( ) ) ;
1179
1219
let expected_table_metadata_location_regex = format ! (
1180
- "^{}/a/b/tbl1/metadata/0- {}.metadata.json$" ,
1220
+ "^{}/a/b/tbl1/metadata/{}.metadata.json$" ,
1181
1221
warehouse_location, UUID_REGEX_STR
1182
1222
) ;
1183
1223
@@ -1678,4 +1718,71 @@ mod tests {
1678
1718
) ,
1679
1719
) ;
1680
1720
}
1721
+
1722
+ #[ tokio:: test]
1723
+ async fn test_update_table ( ) {
1724
+ let catalog = new_memory_catalog ( ) ;
1725
+ let namespace_ident = NamespaceIdent :: new ( "n1" . into ( ) ) ;
1726
+ create_namespace ( & catalog, & namespace_ident) . await ;
1727
+ let table_ident = TableIdent :: new ( namespace_ident. clone ( ) , "tbl1" . into ( ) ) ;
1728
+ create_table ( & catalog, & table_ident) . await ;
1729
+
1730
+ let table = catalog. load_table ( & table_ident) . await . unwrap ( ) ;
1731
+ assert ! ( table. metadata( ) . properties( ) . is_empty( ) ) ;
1732
+
1733
+ let transaction = Transaction :: new ( & table) ;
1734
+ let transaction = transaction
1735
+ . set_properties ( HashMap :: from_iter ( vec ! [ ( "k" . to_string( ) , "v" . to_string( ) ) ] ) )
1736
+ . unwrap ( ) ;
1737
+ transaction. commit ( & catalog) . await . unwrap ( ) ;
1738
+
1739
+ let table = catalog. load_table ( & table_ident) . await . unwrap ( ) ;
1740
+ assert_eq ! (
1741
+ table. metadata( ) . properties( ) ,
1742
+ & HashMap :: from_iter( vec![ ( "k" . to_string( ) , "v" . to_string( ) ) ] )
1743
+ ) ;
1744
+ }
1745
+
1746
+ #[ tokio:: test]
1747
+ async fn test_update_rename_table ( ) {
1748
+ let catalog = new_memory_catalog ( ) ;
1749
+ let namespace_ident = NamespaceIdent :: new ( "n1" . into ( ) ) ;
1750
+ create_namespace ( & catalog, & namespace_ident) . await ;
1751
+ let table_ident = TableIdent :: new ( namespace_ident. clone ( ) , "tbl1" . into ( ) ) ;
1752
+ create_table ( & catalog, & table_ident) . await ;
1753
+
1754
+ let table = catalog. load_table ( & table_ident) . await . unwrap ( ) ;
1755
+ assert ! ( table. metadata( ) . properties( ) . is_empty( ) ) ;
1756
+
1757
+ let transaction = Transaction :: new ( & table) ;
1758
+ let transaction = transaction
1759
+ . set_properties ( HashMap :: from_iter ( vec ! [ ( "k" . to_string( ) , "v" . to_string( ) ) ] ) )
1760
+ . unwrap ( ) ;
1761
+ transaction. commit ( & catalog) . await . unwrap ( ) ;
1762
+
1763
+ let dst_table_ident = TableIdent :: new ( namespace_ident. clone ( ) , "tbl2" . into ( ) ) ;
1764
+ catalog
1765
+ . rename_table ( & table_ident, & dst_table_ident)
1766
+ . await
1767
+ . unwrap ( ) ;
1768
+
1769
+ let table = catalog. load_table ( & dst_table_ident) . await . unwrap ( ) ;
1770
+ let transaction = Transaction :: new ( & table) ;
1771
+ let transaction = transaction
1772
+ . set_properties ( HashMap :: from_iter ( vec ! [ (
1773
+ "k1" . to_string( ) ,
1774
+ "v2" . to_string( ) ,
1775
+ ) ] ) )
1776
+ . unwrap ( ) ;
1777
+ transaction. commit ( & catalog) . await . unwrap ( ) ;
1778
+
1779
+ let table = catalog. load_table ( & dst_table_ident) . await . unwrap ( ) ;
1780
+ assert_eq ! (
1781
+ table. metadata( ) . properties( ) ,
1782
+ & HashMap :: from_iter( vec![
1783
+ ( "k" . to_string( ) , "v" . to_string( ) ) ,
1784
+ ( "k1" . to_string( ) , "v2" . to_string( ) )
1785
+ ] )
1786
+ ) ;
1787
+ }
1681
1788
}
0 commit comments