@@ -22,18 +22,24 @@ use databend_common_expression::types::StringType;
2222use databend_common_expression:: types:: TimestampType ;
2323use databend_common_expression:: DataBlock ;
2424use databend_common_expression:: FromData ;
25+ use databend_common_expression:: Scalar ;
2526use databend_common_expression:: TableDataType ;
2627use databend_common_expression:: TableField ;
2728use databend_common_expression:: TableSchemaRefExt ;
29+ use databend_common_functions:: BUILTIN_FUNCTIONS ;
2830use databend_common_meta_app:: schema:: ListIndexesReq ;
2931use databend_common_meta_app:: schema:: TableIdent ;
3032use databend_common_meta_app:: schema:: TableInfo ;
3133use databend_common_meta_app:: schema:: TableMeta ;
3234use databend_common_storages_fuse:: TableContext ;
35+ use futures:: future:: try_join_all;
3336use log:: warn;
3437
3538use crate :: table:: AsyncOneBlockSystemTable ;
3639use crate :: table:: AsyncSystemTable ;
40+ use crate :: util:: find_eq_or_filter;
41+
42+ const POINT_GET_TABLE_LIMIT : usize = 20 ;
3743
3844pub struct IndexesTable {
3945 table_info : TableInfo ,
@@ -50,19 +56,69 @@ impl AsyncSystemTable for IndexesTable {
5056 async fn get_full_data (
5157 & self ,
5258 ctx : Arc < dyn TableContext > ,
53- _push_downs : Option < PushDownInfo > ,
59+ push_downs : Option < PushDownInfo > ,
5460 ) -> Result < DataBlock > {
61+ let mut filtered_db_names = None ;
62+ let mut filtered_table_names = None ;
63+ let mut invalid_optimize = false ;
64+
65+ if let Some ( filters) = push_downs. and_then ( |info| info. filters ) {
66+ let expr = filters. filter . as_expr ( & BUILTIN_FUNCTIONS ) ;
67+
68+ let mut databases: Vec < String > = Vec :: new ( ) ;
69+ let mut tables: Vec < String > = Vec :: new ( ) ;
70+
71+ invalid_optimize = find_eq_or_filter (
72+ & expr,
73+ & mut |col_name, scalar| {
74+ if col_name == "database" {
75+ if let Scalar :: String ( database) = scalar {
76+ if !databases. contains ( database) {
77+ databases. push ( database. clone ( ) ) ;
78+ }
79+ }
80+ } else if col_name == "table" {
81+ if let Scalar :: String ( table) = scalar {
82+ if !tables. contains ( table) {
83+ tables. push ( table. clone ( ) ) ;
84+ }
85+ }
86+ }
87+ Ok ( ( ) )
88+ } ,
89+ invalid_optimize,
90+ ) ;
91+ if !databases. is_empty ( ) {
92+ filtered_db_names = Some ( databases) ;
93+ }
94+ if !tables. is_empty ( ) {
95+ filtered_table_names = Some ( tables) ;
96+ }
97+ }
98+ if invalid_optimize {
99+ filtered_db_names = None ;
100+ filtered_table_names = None ;
101+ }
102+
55103 let tenant = ctx. get_tenant ( ) ;
56104 let catalog = ctx. get_catalog ( CATALOG_DEFAULT ) . await ?;
57105 let indexes = catalog
58106 . list_indexes ( ListIndexesReq :: new ( & tenant, None ) )
59107 . await ?;
60108
61- let table_index_tables = self . list_table_index_tables ( ctx. clone ( ) ) . await ?;
109+ let table_index_tables = self
110+ . list_table_index_tables (
111+ ctx. clone ( ) ,
112+ filtered_db_names. as_deref ( ) ,
113+ filtered_table_names. as_deref ( ) ,
114+ )
115+ . await ?;
62116
63117 let len = indexes. len ( ) + table_index_tables. len ( ) ;
64118 let mut names = Vec :: with_capacity ( len) ;
65119 let mut types = Vec :: with_capacity ( len) ;
120+ let mut databases = Vec :: with_capacity ( len) ;
121+ let mut tables = Vec :: with_capacity ( len) ;
66122 let mut originals = Vec :: with_capacity ( len) ;
67123 let mut defs = Vec :: with_capacity ( len) ;
68124 let mut created_on = Vec :: with_capacity ( len) ;
@@ -71,6 +127,8 @@ impl AsyncSystemTable for IndexesTable {
71127 for ( _, name, index) in indexes {
72128 names. push ( name. clone ( ) ) ;
73129 types. push ( index. index_type . to_string ( ) ) ;
130+ databases. push ( ctx. get_current_database ( ) ) ;
131+ tables. push ( catalog. get_table_name_by_id ( index. table_id ) . await ?) ;
74132 originals. push ( index. original_query . clone ( ) ) ;
75133 defs. push ( index. query . clone ( ) ) ;
76134 created_on. push ( index. created_on . timestamp_micros ( ) ) ;
@@ -81,6 +139,8 @@ impl AsyncSystemTable for IndexesTable {
81139 for ( name, index) in & table. meta . indexes {
82140 names. push ( name. clone ( ) ) ;
83141 types. push ( index. index_type . to_string ( ) ) ;
142+ databases. push ( table. database_name ( ) ?. to_string ( ) ) ;
143+ tables. push ( Some ( table. name . to_string ( ) ) ) ;
84144 originals. push ( "" . to_string ( ) ) ;
85145
86146 let schema = table. schema ( ) ;
@@ -111,6 +171,8 @@ impl AsyncSystemTable for IndexesTable {
111171 Ok ( DataBlock :: new_from_columns ( vec ! [
112172 StringType :: from_data( names) ,
113173 StringType :: from_data( types) ,
174+ StringType :: from_data( databases) ,
175+ StringType :: from_opt_data( tables) ,
114176 StringType :: from_data( originals) ,
115177 StringType :: from_data( defs) ,
116178 TimestampType :: from_data( created_on) ,
@@ -124,6 +186,11 @@ impl IndexesTable {
124186 let schema = TableSchemaRefExt :: create ( vec ! [
125187 TableField :: new( "name" , TableDataType :: String ) ,
126188 TableField :: new( "type" , TableDataType :: String ) ,
189+ TableField :: new( "database" , TableDataType :: String ) ,
190+ TableField :: new(
191+ "table" ,
192+ TableDataType :: Nullable ( Box :: new( TableDataType :: String ) ) ,
193+ ) ,
127194 TableField :: new( "original" , TableDataType :: String ) ,
128195 TableField :: new( "definition" , TableDataType :: String ) ,
129196 TableField :: new( "created_on" , TableDataType :: Timestamp ) ,
@@ -149,7 +216,12 @@ impl IndexesTable {
149216 AsyncOneBlockSystemTable :: create ( Self { table_info } )
150217 }
151218
152- async fn list_table_index_tables ( & self , ctx : Arc < dyn TableContext > ) -> Result < Vec < TableInfo > > {
219+ async fn list_table_index_tables (
220+ & self ,
221+ ctx : Arc < dyn TableContext > ,
222+ database_names : Option < & [ String ] > ,
223+ table_names : Option < & [ String ] > ,
224+ ) -> Result < Vec < TableInfo > > {
153225 let tenant = ctx. get_tenant ( ) ;
154226 let visibility_checker = ctx. get_visibility_checker ( false ) . await ?;
155227 let catalog = ctx. get_catalog ( CATALOG_DEFAULT ) . await ?;
@@ -180,20 +252,56 @@ impl IndexesTable {
180252 let db_id = db. get_db_info ( ) . database_id . db_id ;
181253 let db_name = db. name ( ) ;
182254
183- let tables = match catalog. list_tables ( & tenant, db_name) . await {
184- Ok ( tables) => tables,
185- Err ( err) => {
186- let msg = format ! ( "Failed to list tables in database: {}, {}" , db_name, err) ;
187- warn ! ( "{}" , msg) ;
188- ctx. push_warning ( msg) ;
255+ if let Some ( database_names) = database_names {
256+ if !database_names. iter ( ) . any ( |name| name == db_name) {
189257 continue ;
190258 }
259+ }
260+ let tables = match (
261+ table_names,
262+ table_names. iter ( ) . len ( ) <= POINT_GET_TABLE_LIMIT ,
263+ ) {
264+ ( Some ( table_names) , true ) => {
265+ match try_join_all ( table_names. iter ( ) . map ( |table_name| async {
266+ db. get_table ( table_name)
267+ . await
268+ . map_err ( |err| ( table_name. to_string ( ) , err) )
269+ } ) )
270+ . await
271+ {
272+ Ok ( tables) => tables,
273+ Err ( ( table_name, err) ) => {
274+ let msg = format ! (
275+ "Failed to get table: {} in database: {}, {}" ,
276+ table_name, db_name, err
277+ ) ;
278+ warn ! ( "{}" , msg) ;
279+ ctx. push_warning ( msg) ;
280+ continue ;
281+ }
282+ }
283+ }
284+ _ => match catalog. list_tables ( & tenant, db_name) . await {
285+ Ok ( tables) => tables,
286+ Err ( err) => {
287+ let msg =
288+ format ! ( "Failed to list tables in database: {}, {}" , db_name, err) ;
289+ warn ! ( "{}" , msg) ;
290+ ctx. push_warning ( msg) ;
291+ continue ;
292+ }
293+ } ,
191294 } ;
192295 for table in tables {
193296 let table_info = table. get_table_info ( ) ;
194297 if table_info. meta . indexes . is_empty ( ) {
195298 continue ;
196299 }
300+ if let Some ( table_names) = table_names {
301+ if !table_names. contains ( & table_info. name ) {
302+ continue ;
303+ }
304+ }
197305 if visibility_checker. check_table_visibility (
198306 & ctl_name,
199307 db_name,
0 commit comments