@@ -587,7 +587,7 @@ mod tests {
587587 async fn test_update_field_metadata_sets_unenforced_primary_key ( ) {
588588 let mut dataset = test_dataset_for_pk ( ) . await ;
589589
590- // Set the boolean primary key metadata on the "id" field
590+ // Legacy boolean flag should map to position 0.
591591 dataset
592592 . update_field_metadata ( )
593593 . update ( "id" , [ ( "lance-schema:unenforced-primary-key" , "true" ) ] )
@@ -605,21 +605,13 @@ mod tests {
605605 Some ( 0 ) ,
606606 "Legacy boolean flag should map to position 0"
607607 ) ;
608- }
609608
610- #[ tokio:: test]
611- async fn test_update_field_metadata_sets_unenforced_primary_key_position ( ) {
612- let mut dataset = test_dataset_for_pk ( ) . await ;
613-
614- // Set both the boolean flag and explicit position
609+ // Explicit position should override the legacy flag.
615610 dataset
616611 . update_field_metadata ( )
617612 . update (
618613 "id" ,
619- [
620- ( "lance-schema:unenforced-primary-key" , "true" ) ,
621- ( "lance-schema:unenforced-primary-key:position" , "2" ) ,
622- ] ,
614+ [ ( "lance-schema:unenforced-primary-key:position" , "2" ) ] ,
623615 )
624616 . unwrap ( )
625617 . await
@@ -630,137 +622,7 @@ mod tests {
630622 assert_eq ! (
631623 field. unenforced_primary_key_position,
632624 Some ( 2 ) ,
633- "Explicit position should take precedence over boolean flag"
634- ) ;
635- }
636-
637- #[ tokio:: test]
638- async fn test_update_field_metadata_removes_unenforced_primary_key ( ) {
639- let mut dataset = test_dataset_for_pk ( ) . await ;
640-
641- // First, set the primary key
642- dataset
643- . update_field_metadata ( )
644- . update ( "id" , [ ( "lance-schema:unenforced-primary-key" , "true" ) ] )
645- . unwrap ( )
646- . await
647- . unwrap ( ) ;
648- assert ! (
649- dataset
650- . schema( )
651- . field( "id" )
652- . unwrap( )
653- . is_unenforced_primary_key( )
654- ) ;
655-
656- // Now remove it by setting value to None (delete the key)
657- dataset
658- . update_field_metadata ( )
659- . update (
660- "id" ,
661- [ ( "lance-schema:unenforced-primary-key" , Option :: < & str > :: None ) ] ,
662- )
663- . unwrap ( )
664- . await
665- . unwrap ( ) ;
666-
667- let field = dataset. schema ( ) . field ( "id" ) . unwrap ( ) ;
668- assert ! (
669- !field. is_unenforced_primary_key( ) ,
670- "Field should no longer be a primary key after removing the metadata key"
671- ) ;
672- assert_eq ! ( field. unenforced_primary_key_position, None ) ;
673- }
674-
675- #[ tokio:: test]
676- async fn test_update_field_metadata_replace_clears_unenforced_primary_key ( ) {
677- let mut dataset = test_dataset_for_pk ( ) . await ;
678-
679- // First, set the primary key
680- dataset
681- . update_field_metadata ( )
682- . update ( "id" , [ ( "lance-schema:unenforced-primary-key" , "true" ) ] )
683- . unwrap ( )
684- . await
685- . unwrap ( ) ;
686- assert ! (
687- dataset
688- . schema( )
689- . field( "id" )
690- . unwrap( )
691- . is_unenforced_primary_key( )
692- ) ;
693-
694- // Replace all metadata with unrelated keys — PK metadata should be cleared
695- dataset
696- . update_field_metadata ( )
697- . replace ( "id" , [ ( "some-other-key" , "some-value" ) ] )
698- . unwrap ( )
699- . await
700- . unwrap ( ) ;
701-
702- let field = dataset. schema ( ) . field ( "id" ) . unwrap ( ) ;
703- assert ! (
704- !field. is_unenforced_primary_key( ) ,
705- "Primary key status should be cleared after replacing metadata without PK keys"
706- ) ;
707- assert_eq ! ( field. unenforced_primary_key_position, None ) ;
708- }
709-
710- #[ tokio:: test]
711- async fn test_update_field_metadata_primary_key_roundtrip ( ) {
712- use lance_core:: utils:: tempfile:: TempDir ;
713-
714- let dir = TempDir :: default ( ) ;
715- let uri = dir. path_str ( ) ;
716-
717- let schema = Arc :: new ( ArrowSchema :: new ( vec ! [
718- ArrowField :: new( "id" , DataType :: Int32 , false ) ,
719- ArrowField :: new( "value" , DataType :: Utf8 , true ) ,
720- ] ) ) ;
721-
722- let batch = RecordBatch :: try_new (
723- schema. clone ( ) ,
724- vec ! [
725- Arc :: new( Int32Array :: from( vec![ 1 , 2 , 3 ] ) ) ,
726- Arc :: new( arrow_array:: StringArray :: from( vec![ "a" , "b" , "c" ] ) ) ,
727- ] ,
728- )
729- . unwrap ( ) ;
730-
731- let mut dataset = Dataset :: write (
732- RecordBatchIterator :: new ( vec ! [ Ok ( batch) ] , schema. clone ( ) ) ,
733- & uri,
734- None ,
735- )
736- . await
737- . unwrap ( ) ;
738-
739- // Set PK metadata via update
740- dataset
741- . update_field_metadata ( )
742- . update (
743- "id" ,
744- [
745- ( "lance-schema:unenforced-primary-key" , "true" ) ,
746- ( "lance-schema:unenforced-primary-key:position" , "1" ) ,
747- ] ,
748- )
749- . unwrap ( )
750- . await
751- . unwrap ( ) ;
752-
753- // Reload the dataset from storage to verify protobuf round-trip
754- let reloaded = Dataset :: open ( & uri) . await . unwrap ( ) ;
755- let field = reloaded. schema ( ) . field ( "id" ) . unwrap ( ) ;
756- assert ! (
757- field. is_unenforced_primary_key( ) ,
758- "Primary key should survive protobuf round-trip after metadata update"
759- ) ;
760- assert_eq ! (
761- field. unenforced_primary_key_position,
762- Some ( 1 ) ,
763- "Primary key position should survive protobuf round-trip"
625+ "Explicit position should take precedence over the legacy boolean flag"
764626 ) ;
765627 }
766628
@@ -838,61 +700,4 @@ mod tests {
838700 ]
839701 ) ;
840702 }
841-
842- #[ tokio:: test]
843- async fn test_update_field_metadata_invalid_pk_position_returns_error ( ) {
844- let mut dataset = test_dataset_for_pk ( ) . await ;
845-
846- let result = dataset
847- . update_field_metadata ( )
848- . update (
849- "id" ,
850- [ ( "lance-schema:unenforced-primary-key:position" , "abc" ) ] ,
851- )
852- . unwrap ( )
853- . await ;
854-
855- assert ! ( result. is_err( ) , "Non-numeric position should return error" ) ;
856- assert ! ( matches!( result. unwrap_err( ) , Error :: InvalidInput { .. } ) ) ;
857- }
858-
859- #[ tokio:: test]
860- async fn test_update_field_metadata_negative_pk_position_returns_error ( ) {
861- let mut dataset = test_dataset_for_pk ( ) . await ;
862-
863- let result = dataset
864- . update_field_metadata ( )
865- . update (
866- "id" ,
867- [ ( "lance-schema:unenforced-primary-key:position" , "-1" ) ] ,
868- )
869- . unwrap ( )
870- . await ;
871-
872- assert ! ( result. is_err( ) , "Negative position should return error" ) ;
873- assert ! ( matches!( result. unwrap_err( ) , Error :: InvalidInput { .. } ) ) ;
874- }
875-
876- #[ tokio:: test]
877- async fn test_update_field_metadata_overflow_pk_position_returns_error ( ) {
878- let mut dataset = test_dataset_for_pk ( ) . await ;
879-
880- let result = dataset
881- . update_field_metadata ( )
882- . update (
883- "id" ,
884- [ (
885- "lance-schema:unenforced-primary-key:position" ,
886- "99999999999" ,
887- ) ] ,
888- )
889- . unwrap ( )
890- . await ;
891-
892- assert ! (
893- result. is_err( ) ,
894- "Overflowing u32 position should return error"
895- ) ;
896- assert ! ( matches!( result. unwrap_err( ) , Error :: InvalidInput { .. } ) ) ;
897- }
898703}
0 commit comments