@@ -10,20 +10,21 @@ use datafusion::arrow::array::{
1010use datafusion:: arrow:: datatypes:: { DataType , Field , SchemaRef } ;
1111use datafusion:: arrow:: ipc:: reader:: FileReader ;
1212use datafusion:: catalog:: streaming:: StreamingTable ;
13- use datafusion:: catalog:: { CatalogProviderList , MemTable , SchemaProvider } ;
13+ use datafusion:: catalog:: { CatalogProviderList , MemTable , SchemaProvider , TableFunctionImpl } ;
1414use datafusion:: common:: utils:: SingleRowListArrayBuilder ;
1515use datafusion:: datasource:: { TableProvider , ViewTable } ;
1616use datafusion:: error:: { DataFusionError , Result } ;
1717use datafusion:: logical_expr:: { ColumnarValue , ScalarUDF , Volatility } ;
1818use datafusion:: physical_plan:: streaming:: PartitionStream ;
19- use datafusion:: prelude:: { create_udf, SessionContext } ;
19+ use datafusion:: prelude:: { create_udf, Expr , SessionContext } ;
2020use postgres_types:: Oid ;
2121use tokio:: sync:: RwLock ;
2222
2323mod pg_attribute;
2424mod pg_class;
2525mod pg_database;
2626mod pg_namespace;
27+ mod pg_settings;
2728
2829const PG_CATALOG_TABLE_PG_AGGREGATE : & str = "pg_aggregate" ;
2930const PG_CATALOG_TABLE_PG_AM : & str = "pg_am" ;
@@ -86,6 +87,7 @@ const PG_CATALOG_TABLE_PG_SUBSCRIPTION_REL: &str = "pg_subscription_rel";
8687const PG_CATALOG_TABLE_PG_TABLESPACE : & str = "pg_tablespace" ;
8788const PG_CATALOG_TABLE_PG_TRIGGER : & str = "pg_trigger" ;
8889const PG_CATALOG_TABLE_PG_USER_MAPPING : & str = "pg_user_mapping" ;
90+ const PG_CATALOG_VIEW_PG_SETTINGS : & str = "pg_settings" ;
8991
9092/// Determine PostgreSQL table type (relkind) from DataFusion TableProvider
9193fn get_table_type ( table : & Arc < dyn TableProvider > ) -> & ' static str {
@@ -180,6 +182,7 @@ pub const PG_CATALOG_TABLES: &[&str] = &[
180182 PG_CATALOG_TABLE_PG_TABLESPACE ,
181183 PG_CATALOG_TABLE_PG_TRIGGER ,
182184 PG_CATALOG_TABLE_PG_USER_MAPPING ,
185+ PG_CATALOG_VIEW_PG_SETTINGS ,
183186] ;
184187
185188#[ derive( Debug , Hash , Eq , PartialEq , PartialOrd , Ord ) ]
@@ -196,7 +199,7 @@ pub struct PgCatalogSchemaProvider {
196199 catalog_list : Arc < dyn CatalogProviderList > ,
197200 oid_counter : Arc < AtomicU32 > ,
198201 oid_cache : Arc < RwLock < HashMap < OidCacheKey , Oid > > > ,
199- static_tables : PgCatalogStaticTables ,
202+ static_tables : Arc < PgCatalogStaticTables > ,
200203}
201204
202205#[ async_trait]
@@ -345,6 +348,10 @@ impl SchemaProvider for PgCatalogSchemaProvider {
345348 StreamingTable :: try_new ( Arc :: clone ( table. schema ( ) ) , vec ! [ table] ) . unwrap ( ) ,
346349 ) ) )
347350 }
351+ PG_CATALOG_VIEW_PG_SETTINGS => {
352+ let table = pg_settings:: PgSettingsView :: try_new ( ) ?;
353+ Ok ( Some ( Arc :: new ( table. try_into_memtable ( ) ?) ) )
354+ }
348355
349356 _ => Ok ( None ) ,
350357 }
@@ -356,12 +363,15 @@ impl SchemaProvider for PgCatalogSchemaProvider {
356363}
357364
358365impl PgCatalogSchemaProvider {
359- pub fn try_new ( catalog_list : Arc < dyn CatalogProviderList > ) -> Result < PgCatalogSchemaProvider > {
366+ pub fn try_new (
367+ catalog_list : Arc < dyn CatalogProviderList > ,
368+ static_tables : Arc < PgCatalogStaticTables > ,
369+ ) -> Result < PgCatalogSchemaProvider > {
360370 Ok ( Self {
361371 catalog_list,
362372 oid_counter : Arc :: new ( AtomicU32 :: new ( 16384 ) ) ,
363373 oid_cache : Arc :: new ( RwLock :: new ( HashMap :: new ( ) ) ) ,
364- static_tables : PgCatalogStaticTables :: try_new ( ) ? ,
374+ static_tables,
365375 } )
366376 }
367377}
@@ -399,10 +409,17 @@ impl ArrowTable {
399409 }
400410}
401411
412+ impl TableFunctionImpl for ArrowTable {
413+ fn call ( & self , _args : & [ Expr ] ) -> Result < Arc < dyn TableProvider > > {
414+ let table = self . clone ( ) . try_into_memtable ( ) ?;
415+ Ok ( Arc :: new ( table) )
416+ }
417+ }
418+
402419/// pg_catalog table as datafusion table provider
403420///
404421/// This implementation only contains static tables
405- #[ derive( Debug ) ]
422+ #[ derive( Debug , Clone ) ]
406423pub struct PgCatalogStaticTables {
407424 pub pg_aggregate : Arc < dyn TableProvider > ,
408425 pub pg_am : Arc < dyn TableProvider > ,
@@ -461,6 +478,8 @@ pub struct PgCatalogStaticTables {
461478 pub pg_tablespace : Arc < dyn TableProvider > ,
462479 pub pg_trigger : Arc < dyn TableProvider > ,
463480 pub pg_user_mapping : Arc < dyn TableProvider > ,
481+
482+ pub pg_get_keywords : Arc < dyn TableFunctionImpl > ,
464483}
465484
466485impl PgCatalogStaticTables {
@@ -647,6 +666,10 @@ impl PgCatalogStaticTables {
647666 pg_user_mapping : Self :: create_arrow_table (
648667 include_bytes ! ( "../../pg_catalog_arrow_exports/pg_user_mapping.feather" ) . to_vec ( ) ,
649668 ) ?,
669+
670+ pg_get_keywords : Self :: create_arrow_table_function (
671+ include_bytes ! ( "../../pg_catalog_arrow_exports/pg_get_keywords.feather" ) . to_vec ( ) ,
672+ ) ?,
650673 } )
651674 }
652675
@@ -656,6 +679,11 @@ impl PgCatalogStaticTables {
656679 let mem_table = table. try_into_memtable ( ) ?;
657680 Ok ( Arc :: new ( mem_table) )
658681 }
682+
683+ fn create_arrow_table_function ( data_bytes : Vec < u8 > ) -> Result < Arc < dyn TableFunctionImpl > > {
684+ let table = ArrowTable :: from_ipc_data ( data_bytes) ?;
685+ Ok ( Arc :: new ( table) )
686+ }
659687}
660688
661689pub fn create_current_schemas_udf ( ) -> ScalarUDF {
@@ -862,7 +890,78 @@ pub fn create_format_type_udf() -> ScalarUDF {
862890
863891 create_udf (
864892 "format_type" ,
865- vec ! [ DataType :: Int32 , DataType :: Int32 ] ,
893+ vec ! [ DataType :: Int64 , DataType :: Int32 ] ,
894+ DataType :: Utf8 ,
895+ Volatility :: Stable ,
896+ Arc :: new ( func) ,
897+ )
898+ }
899+
900+ pub fn create_session_user_udf ( ) -> ScalarUDF {
901+ let func = move |_args : & [ ColumnarValue ] | {
902+ let mut builder = StringBuilder :: new ( ) ;
903+ // TODO: return real user
904+ builder. append_value ( "postgres" ) ;
905+
906+ let array: ArrayRef = Arc :: new ( builder. finish ( ) ) ;
907+
908+ Ok ( ColumnarValue :: Array ( array) )
909+ } ;
910+
911+ create_udf (
912+ "session_user" ,
913+ vec ! [ ] ,
914+ DataType :: Utf8 ,
915+ Volatility :: Stable ,
916+ Arc :: new ( func) ,
917+ )
918+ }
919+
920+ pub fn create_pg_get_expr_udf ( ) -> ScalarUDF {
921+ let func = move |args : & [ ColumnarValue ] | {
922+ let args = ColumnarValue :: values_to_arrays ( args) ?;
923+ let expr = & args[ 0 ] ;
924+ let _oid = & args[ 1 ] ;
925+
926+ // For now, always return true (full access for current user)
927+ let mut builder = StringBuilder :: new ( ) ;
928+ for _ in 0 ..expr. len ( ) {
929+ builder. append_value ( "" ) ;
930+ }
931+
932+ let array: ArrayRef = Arc :: new ( builder. finish ( ) ) ;
933+
934+ Ok ( ColumnarValue :: Array ( array) )
935+ } ;
936+
937+ create_udf (
938+ "pg_catalog.pg_get_expr" ,
939+ vec ! [ DataType :: Utf8 , DataType :: Int32 ] ,
940+ DataType :: Utf8 ,
941+ Volatility :: Stable ,
942+ Arc :: new ( func) ,
943+ )
944+ }
945+
946+ pub fn create_pg_get_partkeydef_udf ( ) -> ScalarUDF {
947+ let func = move |args : & [ ColumnarValue ] | {
948+ let args = ColumnarValue :: values_to_arrays ( args) ?;
949+ let oid = & args[ 0 ] ;
950+
951+ // For now, always return true (full access for current user)
952+ let mut builder = StringBuilder :: new ( ) ;
953+ for _ in 0 ..oid. len ( ) {
954+ builder. append_value ( "" ) ;
955+ }
956+
957+ let array: ArrayRef = Arc :: new ( builder. finish ( ) ) ;
958+
959+ Ok ( ColumnarValue :: Array ( array) )
960+ } ;
961+
962+ create_udf (
963+ "pg_catalog.pg_get_partkeydef" ,
964+ vec ! [ DataType :: Utf8 ] ,
866965 DataType :: Utf8 ,
867966 Volatility :: Stable ,
868967 Arc :: new ( func) ,
@@ -874,8 +973,11 @@ pub fn setup_pg_catalog(
874973 session_context : & SessionContext ,
875974 catalog_name : & str ,
876975) -> Result < ( ) , Box < DataFusionError > > {
877- let pg_catalog =
878- PgCatalogSchemaProvider :: try_new ( session_context. state ( ) . catalog_list ( ) . clone ( ) ) ?;
976+ let static_tables = Arc :: new ( PgCatalogStaticTables :: try_new ( ) ?) ;
977+ let pg_catalog = PgCatalogSchemaProvider :: try_new (
978+ session_context. state ( ) . catalog_list ( ) . clone ( ) ,
979+ static_tables. clone ( ) ,
980+ ) ?;
879981 session_context
880982 . catalog ( catalog_name)
881983 . ok_or_else ( || {
@@ -892,6 +994,10 @@ pub fn setup_pg_catalog(
892994 session_context. register_udf ( create_has_table_privilege_2param_udf ( ) ) ;
893995 session_context. register_udf ( create_pg_table_is_visible ( ) ) ;
894996 session_context. register_udf ( create_format_type_udf ( ) ) ;
997+ session_context. register_udf ( create_session_user_udf ( ) ) ;
998+ session_context. register_udtf ( "pg_get_keywords" , static_tables. pg_get_keywords . clone ( ) ) ;
999+ session_context. register_udf ( create_pg_get_expr_udf ( ) ) ;
1000+ session_context. register_udf ( create_pg_get_partkeydef_udf ( ) ) ;
8951001
8961002 Ok ( ( ) )
8971003}
@@ -1145,5 +1251,9 @@ mod test {
11451251 include_bytes ! ( "../../pg_catalog_arrow_exports/pg_user_mapping.feather" ) . to_vec ( ) ,
11461252 )
11471253 . expect ( "Failed to load ipc data" ) ;
1254+ let _ = ArrowTable :: from_ipc_data (
1255+ include_bytes ! ( "../../pg_catalog_arrow_exports/pg_get_keywords.feather" ) . to_vec ( ) ,
1256+ )
1257+ . expect ( "Failed to load ipc data" ) ;
11481258 }
11491259}
0 commit comments