@@ -12,7 +12,7 @@ use async_trait::async_trait;
1212use bytes:: Bytes ;
1313use chrono:: Utc ;
1414use dashmap:: DashMap ;
15- use iceberg_rust:: catalog:: commit:: apply_table_updates;
15+ use iceberg_rust:: catalog:: commit:: { TableUpdate as IcebergTableUpdate , apply_table_updates} ;
1616use iceberg_rust_spec:: {
1717 schema:: Schema as IcebergSchema ,
1818 table_metadata:: { FormatVersion , TableMetadataBuilder } ,
@@ -125,6 +125,10 @@ impl InMemoryMetastore {
125125 )
126126 }
127127
128+ fn database_key ( ident : & TableIdent ) -> DatabaseIdent {
129+ ident. database . to_ascii_lowercase ( )
130+ }
131+
128132 fn ensure_volume ( state : & MetastoreState , name : & VolumeIdent ) -> Result < RwObject < Volume > > {
129133 state. volumes . get ( name) . cloned ( ) . ok_or_else ( || {
130134 metastore_error:: VolumeNotFoundSnafu {
@@ -359,12 +363,18 @@ impl Metastore for InMemoryMetastore {
359363
360364 async fn list_schemas ( & self , database : & DatabaseIdent ) -> Result < Vec < RwObject < Schema > > > {
361365 let state = self . state . read ( ) . await ;
362- Ok ( state
366+
367+ let mut items: Vec < RwObject < Schema > > = state
363368 . schemas
364369 . iter ( )
365370 . filter ( |( ( db, _) , _) | db == database)
366371 . map ( |( _, schema) | schema. clone ( ) )
367- . collect ( ) )
372+ . collect ( ) ;
373+
374+ // Sort by schema name
375+ items. sort_by ( |a, b| b. ident . schema . cmp ( & a. ident . schema ) ) ;
376+
377+ Ok ( items)
368378 }
369379
370380 async fn create_schema ( & self , ident : & SchemaIdent , schema : Schema ) -> Result < RwObject < Schema > > {
@@ -467,6 +477,16 @@ impl Metastore for InMemoryMetastore {
467477 . fail ( ) ;
468478 }
469479
480+ if table. volume_ident . is_none ( ) {
481+ let database = state. databases . get ( & ident. database ) . ok_or_else ( || {
482+ metastore_error:: DatabaseNotFoundSnafu {
483+ db : ident. database . clone ( ) ,
484+ }
485+ . build ( )
486+ } ) ?;
487+ table. volume_ident = Some ( database. volume . clone ( ) ) ;
488+ }
489+
470490 let schema_id = * table. schema . schema_id ( ) ;
471491 let mut schemas = HashMap :: new ( ) ;
472492 schemas. insert ( schema_id, table. schema . clone ( ) ) ;
@@ -546,7 +566,7 @@ impl Metastore for InMemoryMetastore {
546566 async fn update_table (
547567 & self ,
548568 ident : & TableIdent ,
549- update : TableUpdate ,
569+ mut update : TableUpdate ,
550570 ) -> Result < RwObject < Table > > {
551571 let object_store = self . table_object_store ( ident) . await ?. ok_or_else ( || {
552572 metastore_error:: TableNotFoundSnafu {
@@ -569,10 +589,13 @@ impl Metastore for InMemoryMetastore {
569589 }
570590 . build ( )
571591 } ) ?;
592+ update
593+ . requirements
594+ . into_iter ( )
595+ . map ( TableRequirementExt :: new)
596+ . try_for_each ( |req| req. assert ( & table_entry. metadata ) ) ?;
572597
573- for requirement in & update. requirements {
574- TableRequirementExt :: new ( requirement. clone ( ) ) . assert ( & table_entry. metadata ) ?;
575- }
598+ convert_add_schema_update_to_lowercase ( & mut update. updates ) ?;
576599
577600 let mut metadata = table_entry. metadata . clone ( ) ;
578601 apply_table_updates ( & mut metadata, update. updates . clone ( ) )
@@ -592,14 +615,8 @@ impl Metastore for InMemoryMetastore {
592615 }
593616
594617 async fn table_object_store ( & self , ident : & TableIdent ) -> Result < Option < Arc < dyn ObjectStore > > > {
595- let state = self . state . read ( ) . await ;
596- let volume_ident = state
597- . tables
598- . get ( & Self :: table_key ( ident) )
599- . and_then ( |table| table. volume_ident . clone ( ) ) ;
600- drop ( state) ;
601- if let Some ( volume_ident) = volume_ident {
602- self . volume_object_store ( & volume_ident) . await
618+ if let Some ( volume) = self . volume_for_table ( ident) . await ? {
619+ self . volume_object_store ( & volume. ident ) . await
603620 } else {
604621 Ok ( None )
605622 }
@@ -635,6 +652,12 @@ impl Metastore for InMemoryMetastore {
635652 . and_then ( |table| table. volume_ident . as_ref ( ) )
636653 {
637654 Ok ( state. volumes . get ( volume_ident) . cloned ( ) )
655+ } else if let Some ( volume_ident) = state
656+ . databases
657+ . get ( & Self :: database_key ( ident) )
658+ . map ( |database| & database. volume )
659+ {
660+ Ok ( state. volumes . get ( volume_ident) . cloned ( ) )
638661 } else {
639662 Ok ( None )
640663 }
@@ -686,3 +709,45 @@ fn max_field_id(schema: &IcebergSchema) -> i32 {
686709
687710 schema. fields ( ) . iter ( ) . map ( recurse) . max ( ) . unwrap_or ( 0 )
688711}
712+
713+ fn convert_add_schema_update_to_lowercase ( updates : & mut Vec < IcebergTableUpdate > ) -> Result < ( ) > {
714+ for update in updates {
715+ if let IcebergTableUpdate :: AddSchema {
716+ schema,
717+ last_column_id,
718+ } = update
719+ {
720+ let schema = convert_schema_fields_to_lowercase ( schema) ?;
721+ * update = IcebergTableUpdate :: AddSchema {
722+ schema,
723+ last_column_id : * last_column_id,
724+ }
725+ }
726+ }
727+ Ok ( ( ) )
728+ }
729+
730+ fn convert_schema_fields_to_lowercase ( schema : & IcebergSchema ) -> Result < IcebergSchema > {
731+ let converted_fields: Vec < StructField > = schema
732+ . fields ( )
733+ . iter ( )
734+ . map ( |field| {
735+ StructField :: new (
736+ field. id ,
737+ & field. name . to_lowercase ( ) ,
738+ field. required ,
739+ field. field_type . clone ( ) ,
740+ field. doc . clone ( ) ,
741+ )
742+ } )
743+ . collect ( ) ;
744+
745+ let mut builder = IcebergSchema :: builder ( ) ;
746+ builder. with_schema_id ( * schema. schema_id ( ) ) ;
747+
748+ for field in converted_fields {
749+ builder. with_struct_field ( field) ;
750+ }
751+
752+ builder. build ( ) . context ( metastore_error:: IcebergSpecSnafu )
753+ }
0 commit comments