@@ -110,6 +110,7 @@ use databend_common_meta_app::schema::SequenceIdent;
110110use databend_common_meta_app:: schema:: SetSecurityPolicyAction ;
111111use databend_common_meta_app:: schema:: SetTableColumnMaskPolicyReq ;
112112use databend_common_meta_app:: schema:: SetTableRowAccessPolicyReq ;
113+ use databend_common_meta_app:: schema:: SnapshotLvtCheck ;
113114use databend_common_meta_app:: schema:: SwapTableReq ;
114115use databend_common_meta_app:: schema:: TableCopiedFileInfo ;
115116use databend_common_meta_app:: schema:: TableCopiedFileNameIdent ;
@@ -2642,6 +2643,7 @@ impl SchemaApiTestSuite {
26422643 mt : & MT ,
26432644 ) -> anyhow:: Result < ( ) > {
26442645 let tenant_name = "tenant1" ;
2646+ let tenant = Tenant :: new_or_err ( tenant_name, func_name ! ( ) ) ?;
26452647 let db_name = "db1" ;
26462648 let tbl_name = "tb2" ;
26472649
@@ -2717,6 +2719,7 @@ impl SchemaApiTestSuite {
27172719 seq : MatchSeq :: Exact ( table_version) ,
27182720 new_table_meta : new_table_meta. clone ( ) ,
27192721 base_snapshot_location : None ,
2722+ lvt_check : None ,
27202723 } ;
27212724
27222725 mt. update_multi_table_meta ( UpdateMultiTableMetaReq {
@@ -2742,6 +2745,7 @@ impl SchemaApiTestSuite {
27422745 seq : MatchSeq :: Exact ( table_version + 1 ) ,
27432746 new_table_meta : new_table_meta. clone ( ) ,
27442747 base_snapshot_location : None ,
2748+ lvt_check : None ,
27452749 } ;
27462750 let res = mt
27472751 . update_multi_table_meta ( UpdateMultiTableMetaReq {
@@ -2768,6 +2772,7 @@ impl SchemaApiTestSuite {
27682772 seq : MatchSeq :: Exact ( table_version) ,
27692773 new_table_meta : new_table_meta. clone ( ) ,
27702774 base_snapshot_location : None ,
2775+ lvt_check : None ,
27712776 } ;
27722777 let res = mt
27732778 . update_multi_table_meta_with_sender (
@@ -2849,6 +2854,7 @@ impl SchemaApiTestSuite {
28492854 seq : MatchSeq :: Exact ( table_version) ,
28502855 new_table_meta : new_table_meta. clone ( ) ,
28512856 base_snapshot_location : None ,
2857+ lvt_check : None ,
28522858 } ;
28532859 mt. update_multi_table_meta ( UpdateMultiTableMetaReq {
28542860 update_table_metas : vec ! [ ( req, table. as_ref( ) . clone( ) ) ] ,
@@ -2899,6 +2905,7 @@ impl SchemaApiTestSuite {
28992905 seq : MatchSeq :: Exact ( table_version) ,
29002906 new_table_meta : new_table_meta. clone ( ) ,
29012907 base_snapshot_location : None ,
2908+ lvt_check : None ,
29022909 } ;
29032910 mt. update_multi_table_meta ( UpdateMultiTableMetaReq {
29042911 update_table_metas : vec ! [ ( req, table. as_ref( ) . clone( ) ) ] ,
@@ -2949,6 +2956,7 @@ impl SchemaApiTestSuite {
29492956 seq : MatchSeq :: Exact ( table_version) ,
29502957 new_table_meta : new_table_meta. clone ( ) ,
29512958 base_snapshot_location : None ,
2959+ lvt_check : None ,
29522960 } ;
29532961 let result = mt
29542962 . update_multi_table_meta ( UpdateMultiTableMetaReq {
@@ -2961,6 +2969,67 @@ impl SchemaApiTestSuite {
29612969 let err = ErrorCode :: from ( err) ;
29622970 assert_eq ! ( ErrorCode :: DUPLICATED_UPSERT_FILES , err. code( ) ) ;
29632971 }
2972+
2973+ info ! ( "--- update table meta, snapshot_ts must respect LVT" ) ;
2974+ {
2975+ let table = util. get_table ( ) . await . unwrap ( ) ;
2976+ let table_id = table. ident . table_id ;
2977+ let lvt_ident = LeastVisibleTimeIdent :: new ( & tenant, table_id) ;
2978+ let lvt_time = DateTime :: < Utc > :: from_timestamp ( 2_000 , 0 ) . unwrap ( ) ;
2979+ mt. set_table_lvt ( & lvt_ident, & LeastVisibleTime :: new ( lvt_time) )
2980+ . await ?;
2981+
2982+ // Snapshot older than LVT should be rejected.
2983+ let mut new_table_meta = table. meta . clone ( ) ;
2984+ new_table_meta. comment = "lvt guard should fail" . to_string ( ) ;
2985+ let bad_snapshot_ts = DateTime :: < Utc > :: from_timestamp ( 1_000 , 0 ) . unwrap ( ) ;
2986+ let req = UpdateTableMetaReq {
2987+ table_id,
2988+ seq : MatchSeq :: Exact ( table. ident . seq ) ,
2989+ new_table_meta : new_table_meta. clone ( ) ,
2990+ base_snapshot_location : None ,
2991+ lvt_check : Some ( SnapshotLvtCheck {
2992+ tenant : tenant. clone ( ) ,
2993+ timestamp : bad_snapshot_ts,
2994+ } ) ,
2995+ } ;
2996+ let err = mt
2997+ . update_multi_table_meta ( UpdateMultiTableMetaReq {
2998+ update_table_metas : vec ! [ ( req, table. as_ref( ) . clone( ) ) ] ,
2999+ ..Default :: default ( )
3000+ } )
3001+ . await
3002+ . unwrap_err ( ) ;
3003+ assert_eq ! (
3004+ ErrorCode :: TABLE_SNAPSHOT_EXPIRED ,
3005+ ErrorCode :: from( err) . code( )
3006+ ) ;
3007+
3008+ // Snapshot newer than LVT should succeed.
3009+ let table = util. get_table ( ) . await . unwrap ( ) ;
3010+ let mut ok_table_meta = table. meta . clone ( ) ;
3011+ ok_table_meta. comment = "lvt guard success" . to_string ( ) ;
3012+ let ok_snapshot_ts = DateTime :: < Utc > :: from_timestamp ( 2_001 , 0 ) . unwrap ( ) ;
3013+ let req = UpdateTableMetaReq {
3014+ table_id,
3015+ seq : MatchSeq :: Exact ( table. ident . seq ) ,
3016+ new_table_meta : ok_table_meta. clone ( ) ,
3017+ base_snapshot_location : None ,
3018+ lvt_check : Some ( SnapshotLvtCheck {
3019+ tenant,
3020+ timestamp : ok_snapshot_ts,
3021+ } ) ,
3022+ } ;
3023+ mt. update_multi_table_meta ( UpdateMultiTableMetaReq {
3024+ update_table_metas : vec ! [ ( req, table. as_ref( ) . clone( ) ) ] ,
3025+ ..Default :: default ( )
3026+ } )
3027+ . await ?
3028+ . unwrap ( ) ;
3029+
3030+ let updated = util. get_table ( ) . await . unwrap ( ) ;
3031+ assert_eq ! ( updated. meta. comment, "lvt guard success" ) ;
3032+ }
29643033 }
29653034 Ok ( ( ) )
29663035 }
@@ -4300,6 +4369,7 @@ impl SchemaApiTestSuite {
43004369 seq : MatchSeq :: Any ,
43014370 new_table_meta : table_meta. clone ( ) ,
43024371 base_snapshot_location : None ,
4372+ lvt_check : None ,
43034373 } ;
43044374
43054375 let table = mt
@@ -4440,6 +4510,7 @@ impl SchemaApiTestSuite {
44404510 seq : MatchSeq :: Any ,
44414511 new_table_meta : create_table_meta. clone ( ) ,
44424512 base_snapshot_location : None ,
4513+ lvt_check : None ,
44434514 } ;
44444515
44454516 let table = mt
@@ -6237,6 +6308,7 @@ impl SchemaApiTestSuite {
62376308 seq : MatchSeq :: Any ,
62386309 new_table_meta : table_meta ( created_on) ,
62396310 base_snapshot_location : None ,
6311+ lvt_check : None ,
62406312 } ;
62416313
62426314 let table = mt
@@ -6288,6 +6360,7 @@ impl SchemaApiTestSuite {
62886360 seq : MatchSeq :: Any ,
62896361 new_table_meta : table_meta ( created_on) ,
62906362 base_snapshot_location : None ,
6363+ lvt_check : None ,
62916364 } ;
62926365
62936366 let table = mt
@@ -7801,6 +7874,7 @@ impl SchemaApiTestSuite {
78017874 seq : MatchSeq :: Any ,
78027875 new_table_meta : table_meta ( created_on) ,
78037876 base_snapshot_location : None ,
7877+ lvt_check : None ,
78047878 } ;
78057879
78067880 let table = mt
@@ -7860,6 +7934,7 @@ impl SchemaApiTestSuite {
78607934 seq : MatchSeq :: Any ,
78617935 new_table_meta : table_meta ( created_on) ,
78627936 base_snapshot_location : None ,
7937+ lvt_check : None ,
78637938 } ;
78647939
78657940 let table = mt
@@ -7916,6 +7991,7 @@ impl SchemaApiTestSuite {
79167991 seq : MatchSeq :: Any ,
79177992 new_table_meta : table_meta ( created_on) ,
79187993 base_snapshot_location : None ,
7994+ lvt_check : None ,
79197995 } ;
79207996
79217997 let table = mt
@@ -8370,6 +8446,7 @@ where MT: SchemaApi + kvapi::KVApi<Error = MetaError>
83708446 seq : MatchSeq :: Any ,
83718447 new_table_meta : self . table_meta ( ) ,
83728448 base_snapshot_location : None ,
8449+ lvt_check : None ,
83738450 } ;
83748451
83758452 let req = UpdateMultiTableMetaReq {
0 commit comments