@@ -2151,6 +2151,77 @@ public void testDorisTableCacheMissReloadsPaimonCatalogOnce() throws Exception {
21512151 }
21522152 }
21532153
2154+ @ Test
2155+ public void testRefreshTableInvalidatesPaimonCatalogCacheAfterExternalDrop () throws Exception {
2156+ java .io .File warehouse = temporaryFolder .newFolder ("refresh_after_external_drop" );
2157+ Map <String , String > properties = new HashMap <>();
2158+ properties .put ("type" , "paimon" );
2159+ properties .put (PaimonExternalCatalog .PAIMON_CATALOG_TYPE ,
2160+ PaimonExternalCatalog .PAIMON_FILESYSTEM );
2161+ properties .put ("warehouse" , warehouse .toURI ().toString ());
2162+ long catalogId = 94L ;
2163+ PaimonExternalCatalog dorisCatalog = new PaimonExternalCatalog (
2164+ catalogId , "paimon_refresh_test" , null , properties , "" );
2165+ dorisCatalog .makeSureInitialized ();
2166+ dorisCatalog .catalog .createDatabase ("db" , false );
2167+ Identifier identifier = Identifier .create ("db" , "table" );
2168+ Schema schema = Schema .newBuilder ()
2169+ .column ("id" , DataTypes .INT ())
2170+ .build ();
2171+ dorisCatalog .catalog .createTable (identifier , schema , false );
2172+
2173+ Map <String , String > externalProperties = new HashMap <>(properties );
2174+ externalProperties .put ("paimon.cache-enabled" , "false" );
2175+ PaimonExternalCatalog externalCatalog = new PaimonExternalCatalog (
2176+ 95L , "external_paimon" , null , externalProperties , "" );
2177+ externalCatalog .makeSureInitialized ();
2178+
2179+ CatalogMgr catalogMgr = Mockito .mock (CatalogMgr .class );
2180+ Env env = Mockito .mock (Env .class );
2181+ Mockito .when (env .getCatalogMgr ()).thenReturn (catalogMgr );
2182+ Mockito .doReturn (dorisCatalog ).when (catalogMgr )
2183+ .getCatalogOrException (Mockito .eq (catalogId ), Mockito .any ());
2184+ ExecutorService executor = Executors .newSingleThreadExecutor ();
2185+ try (MockedStatic <Env > mockedEnv = Mockito .mockStatic (Env .class )) {
2186+ mockedEnv .when (Env ::getCurrentEnv ).thenReturn (env );
2187+ PaimonExternalMetaCache cache = new PaimonExternalMetaCache (executor );
2188+ cache .initCatalog (catalogId , Collections .emptyMap ());
2189+ NameMapping nameMapping = new NameMapping (catalogId , "db" , "table" , "db" , "table" );
2190+ Table staleTable = cache .getPaimonTable (nameMapping );
2191+
2192+ externalCatalog .catalog .dropTable (identifier , false );
2193+ Assert .assertSame (staleTable , cache .getPaimonTable (nameMapping ));
2194+
2195+ cache .invalidateTable (catalogId , "db" , "table" );
2196+ assertPaimonTableMissing (cache , nameMapping );
2197+
2198+ externalCatalog .catalog .createTable (identifier , schema , false );
2199+ cache .getPaimonTable (nameMapping );
2200+ externalCatalog .catalog .dropTable (identifier , false );
2201+ cache .invalidateDb (catalogId , "db" );
2202+ assertPaimonTableMissing (cache , nameMapping );
2203+
2204+ externalCatalog .catalog .createTable (identifier , schema , false );
2205+ cache .getPaimonTable (nameMapping );
2206+ externalCatalog .catalog .dropTable (identifier , false );
2207+ cache .invalidateCatalogEntries (catalogId );
2208+ assertPaimonTableMissing (cache , nameMapping );
2209+ } finally {
2210+ executor .shutdownNow ();
2211+ dorisCatalog .catalog .close ();
2212+ externalCatalog .catalog .close ();
2213+ }
2214+ }
2215+
2216+ private void assertPaimonTableMissing (PaimonExternalMetaCache cache , NameMapping nameMapping ) {
2217+ try {
2218+ cache .getPaimonTable (nameMapping );
2219+ Assert .fail ("the externally dropped table must not remain visible after refresh" );
2220+ } catch (CacheException e ) {
2221+ Assert .assertTrue (e .getMessage ().contains ("failed to load paimon table" ));
2222+ }
2223+ }
2224+
21542225 @ Test
21552226 public void testPartitionProjectionRejectsUnsafeEffectiveTableBeforeEnumeration () throws Exception {
21562227 FileStoreTable unsafeTable = newPartitionedTable (
@@ -2557,7 +2628,7 @@ private Object readField(Object target, Class<?> owner, String fieldName) throws
25572628 }
25582629
25592630 @ Test
2560- public void testInvalidateTablePrecise () {
2631+ public void testInvalidateTablePrecise () throws Exception {
25612632 ExecutorService executor = Executors .newSingleThreadExecutor ();
25622633 try {
25632634 PaimonExternalMetaCache cache = new PaimonExternalMetaCache (executor );
@@ -2582,8 +2653,19 @@ public void testInvalidateTablePrecise() {
25822653 snapshotEntry .put (snapshotKey , new PaimonSnapshotCacheValue (
25832654 PaimonPartitionInfo .EMPTY , new PaimonSnapshot (1L , 2L , null )));
25842655
2585- cache .invalidateTable (catalogId , "db1" , "tbl1" );
2656+ PaimonExternalCatalog dorisCatalog = Mockito .mock (PaimonExternalCatalog .class );
2657+ CatalogMgr catalogMgr = Mockito .mock (CatalogMgr .class );
2658+ Env env = Mockito .mock (Env .class );
2659+ Mockito .when (env .getCatalogMgr ()).thenReturn (catalogMgr );
2660+ Mockito .doReturn (dorisCatalog ).when (catalogMgr )
2661+ .getCatalogOrException (Mockito .eq (catalogId ), Mockito .any ());
2662+ try (MockedStatic <Env > mockedEnv = Mockito .mockStatic (Env .class )) {
2663+ mockedEnv .when (Env ::getCurrentEnv ).thenReturn (env );
2664+ cache .invalidateTable (catalogId , "db1" , "tbl1" );
2665+ }
25862666
2667+ Mockito .verify (dorisCatalog ).invalidatePaimonTable (t1 );
2668+ Mockito .verify (dorisCatalog , Mockito .never ()).invalidatePaimonTable (t2 );
25872669 Assert .assertNull (tableEntry .getIfPresent (t1 ));
25882670 Assert .assertNotNull (tableEntry .getIfPresent (t2 ));
25892671 Assert .assertNull (snapshotEntry .getIfPresent (snapshotKey ));
@@ -2593,7 +2675,7 @@ public void testInvalidateTablePrecise() {
25932675 }
25942676
25952677 @ Test
2596- public void testInvalidateDbAndStats () {
2678+ public void testInvalidateDbAndStats () throws Exception {
25972679 ExecutorService executor = Executors .newSingleThreadExecutor ();
25982680 try {
25992681 PaimonExternalMetaCache cache = new PaimonExternalMetaCache (executor );
@@ -2618,8 +2700,19 @@ public void testInvalidateDbAndStats() {
26182700 schemaEntry .put (db1Schema , new SchemaCacheValue (Collections .emptyList ()));
26192701 schemaEntry .put (db2Schema , new SchemaCacheValue (Collections .emptyList ()));
26202702
2621- cache .invalidateDb (catalogId , "db1" );
2703+ PaimonExternalCatalog dorisCatalog = Mockito .mock (PaimonExternalCatalog .class );
2704+ CatalogMgr catalogMgr = Mockito .mock (CatalogMgr .class );
2705+ Env env = Mockito .mock (Env .class );
2706+ Mockito .when (env .getCatalogMgr ()).thenReturn (catalogMgr );
2707+ Mockito .doReturn (dorisCatalog ).when (catalogMgr )
2708+ .getCatalogOrException (Mockito .eq (catalogId ), Mockito .any ());
2709+ try (MockedStatic <Env > mockedEnv = Mockito .mockStatic (Env .class )) {
2710+ mockedEnv .when (Env ::getCurrentEnv ).thenReturn (env );
2711+ cache .invalidateDb (catalogId , "db1" );
2712+ }
26222713
2714+ Mockito .verify (dorisCatalog ).invalidatePaimonTable (db1Table );
2715+ Mockito .verify (dorisCatalog , Mockito .never ()).invalidatePaimonTable (db2Table );
26232716 Assert .assertNull (tableEntry .getIfPresent (db1Table ));
26242717 Assert .assertNotNull (tableEntry .getIfPresent (db2Table ));
26252718 Assert .assertNull (schemaEntry .getIfPresent (db1Schema ));
0 commit comments