@@ -13,6 +13,7 @@ use url::Url;
13
13
14
14
use delta_kernel:: schema:: Schema ;
15
15
use delta_kernel:: snapshot:: Snapshot ;
16
+ use delta_kernel:: Version ;
16
17
use delta_kernel:: { DeltaResult , Engine , EngineData , Table } ;
17
18
use delta_kernel_ffi_macros:: handle_descriptor;
18
19
@@ -568,14 +569,31 @@ pub unsafe extern "C" fn snapshot(
568
569
) -> ExternResult < Handle < SharedSnapshot > > {
569
570
let url = unsafe { unwrap_and_parse_path_as_url ( path) } ;
570
571
let engine = unsafe { engine. as_ref ( ) } ;
571
- snapshot_impl ( url, engine) . into_extern_result ( & engine)
572
+ snapshot_impl ( url, engine, None ) . into_extern_result ( & engine)
573
+ }
574
+
575
+ /// Get the snapshot from the specified table at a specific version
576
+ ///
577
+ /// # Safety
578
+ ///
579
+ /// Caller is responsible for passing valid handles and path pointer.
580
+ #[ no_mangle]
581
+ pub unsafe extern "C" fn snapshot_at_version (
582
+ path : KernelStringSlice ,
583
+ engine : Handle < SharedExternEngine > ,
584
+ version : Version ,
585
+ ) -> ExternResult < Handle < SharedSnapshot > > {
586
+ let url = unsafe { unwrap_and_parse_path_as_url ( path) } ;
587
+ let engine = unsafe { engine. as_ref ( ) } ;
588
+ snapshot_impl ( url, engine, version. into ( ) ) . into_extern_result ( & engine)
572
589
}
573
590
574
591
fn snapshot_impl (
575
592
url : DeltaResult < Url > ,
576
593
extern_engine : & dyn ExternEngine ,
594
+ version : Option < Version > ,
577
595
) -> DeltaResult < Handle < SharedSnapshot > > {
578
- let snapshot = Snapshot :: try_new ( url?, extern_engine. engine ( ) . as_ref ( ) , None ) ?;
596
+ let snapshot = Snapshot :: try_new ( url?, extern_engine. engine ( ) . as_ref ( ) , version ) ?;
579
597
Ok ( Arc :: new ( snapshot) . into ( ) )
580
598
}
581
599
@@ -776,6 +794,12 @@ mod tests {
776
794
Some ( ptr)
777
795
}
778
796
797
+ // helper to recover an error from the above
798
+ fn recover_error ( ptr : * mut EngineError ) -> EngineError {
799
+ let ptr = ptr. cast ( ) ;
800
+ * unsafe { Box :: from_raw ( ptr) }
801
+ }
802
+
779
803
// helper to recover a string from the above
780
804
fn recover_string ( ptr : NonNull < c_void > ) -> String {
781
805
let ptr = ptr. as_ptr ( ) . cast ( ) ;
@@ -834,18 +858,40 @@ mod tests {
834
858
let engine = engine_to_handle ( Arc :: new ( engine) , allocate_err) ;
835
859
let path = "memory:///" ;
836
860
837
- let snapshot =
861
+ // Test getting latest snapshot
862
+ let snapshot1 =
838
863
unsafe { ok_or_panic ( snapshot ( kernel_string_slice ! ( path) , engine. shallow_copy ( ) ) ) } ;
864
+ let version1 = unsafe { version ( snapshot1. shallow_copy ( ) ) } ;
865
+ assert_eq ! ( version1, 0 ) ;
866
+
867
+ // Test getting snapshot at version
868
+ let snapshot2 = unsafe {
869
+ ok_or_panic ( snapshot_at_version (
870
+ kernel_string_slice ! ( path) ,
871
+ engine. shallow_copy ( ) ,
872
+ 0 ,
873
+ ) )
874
+ } ;
875
+ let version2 = unsafe { version ( snapshot2. shallow_copy ( ) ) } ;
876
+ assert_eq ! ( version2, 0 ) ;
877
+
878
+ // Test getting non-existent snapshot
879
+ let snapshot_at_non_existent_version =
880
+ unsafe { snapshot_at_version ( kernel_string_slice ! ( path) , engine. shallow_copy ( ) , 1 ) } ;
881
+ assert ! ( snapshot_at_non_existent_version. is_err( ) ) ;
882
+
883
+ // Avoid leaking the error by recovering it
884
+ if let ExternResult :: Err ( e) = snapshot_at_non_existent_version {
885
+ recover_error ( e) ;
886
+ }
839
887
840
- let version = unsafe { version ( snapshot. shallow_copy ( ) ) } ;
841
- assert_eq ! ( version, 0 ) ;
842
-
843
- let table_root = unsafe { snapshot_table_root ( snapshot. shallow_copy ( ) , allocate_str) } ;
888
+ let table_root = unsafe { snapshot_table_root ( snapshot1. shallow_copy ( ) , allocate_str) } ;
844
889
assert ! ( table_root. is_some( ) ) ;
845
890
let s = recover_string ( table_root. unwrap ( ) ) ;
846
891
assert_eq ! ( & s, path) ;
847
892
848
- unsafe { free_snapshot ( snapshot) }
893
+ unsafe { free_snapshot ( snapshot1) }
894
+ unsafe { free_snapshot ( snapshot2) }
849
895
unsafe { free_engine ( engine) }
850
896
Ok ( ( ) )
851
897
}
0 commit comments