1
- use std:: cell:: OnceCell ;
2
- use std:: collections:: HashMap ;
3
- use std:: sync:: Arc ;
4
-
1
+ use crate :: data_type:: EncodedType ;
2
+ use crate :: ipc:: SlotStream ;
5
3
use ahash:: AHashMap ;
6
- use datafusion:: arrow:: datatypes:: DataType ;
7
- use datafusion:: arrow:: datatypes:: SchemaRef ;
8
- use datafusion:: common:: DFSchemaRef ;
9
- use datafusion:: common:: ScalarValue ;
4
+ use anyhow:: Result ;
5
+ use datafusion:: arrow:: datatypes:: { DataType , Field , Schema , SchemaRef } ;
10
6
use datafusion:: config:: ConfigOptions ;
11
7
use datafusion:: error:: DataFusionError ;
12
8
use datafusion:: error:: Result as DataFusionResult ;
@@ -16,34 +12,22 @@ use datafusion::functions_aggregate::all_default_aggregate_functions;
16
12
use datafusion:: functions_window:: all_default_window_functions;
17
13
use datafusion:: logical_expr:: planner:: ContextProvider ;
18
14
use datafusion:: logical_expr:: planner:: ExprPlanner ;
19
- use datafusion:: logical_expr:: { AggregateUDF , LogicalPlan , ScalarUDF , TableSource , WindowUDF } ;
20
- use datafusion_sql:: planner:: SqlToRel ;
21
- use datafusion_sql:: sqlparser:: dialect:: PostgreSqlDialect ;
22
- use datafusion_sql:: sqlparser:: parser:: Parser ;
15
+ use datafusion:: logical_expr:: { AggregateUDF , ScalarUDF , TableSource , WindowUDF } ;
23
16
use datafusion_sql:: TableReference ;
17
+ use once_cell:: sync:: Lazy ;
24
18
use pgrx:: pg_sys:: Oid ;
19
+ use rmp:: decode:: read_array_len;
20
+ use rmp:: decode:: read_bool;
21
+ use rmp:: decode:: read_str_len;
22
+ use rmp:: decode:: { read_u32, read_u8} ;
25
23
use smol_str:: SmolStr ;
24
+ use std:: collections:: HashMap ;
25
+ use std:: str:: from_utf8;
26
+ use std:: sync:: Arc ;
26
27
27
- // fn sql_to_logical_plan(
28
- // sql: &str,
29
- // params: Vec<ScalarValue>,
30
- // ) -> Result<LogicalPlan, DataFusionError> {
31
- // let dialect = PostgreSqlDialect {};
32
- // let ast = Parser::parse_sql(&dialect, sql).map_err(|e| DataFusionError::SQL(e, None))?;
33
- // assert_eq!(ast.len(), 1);
34
- // let statement = ast.into_iter().next().expect("ast is not empty");
35
- //
36
- // // Cash metadata provider in a static variable to avoid re-allocation on each query.
37
- // let base_plan = CATALOG.with(|catalog| {
38
- // let catalog = catalog.get_or_init(Builtin::new);
39
- // let sql_to_rel = SqlToRel::new(catalog);
40
- // sql_to_rel.sql_statement_to_plan(statement)
41
- // })?;
42
- // let plan = base_plan.with_param_values(params)?;
43
- //
44
- // Ok(plan)
45
- // }
28
+ static BUILDIN : Lazy < Arc < Builtin > > = Lazy :: new ( || Arc :: new ( Builtin :: new ( ) ) ) ;
46
29
30
+ #[ derive( PartialEq , Eq , Hash ) ]
47
31
pub ( crate ) struct Table {
48
32
oid : Oid ,
49
33
schema : SchemaRef ,
@@ -92,36 +76,86 @@ impl Builtin {
92
76
}
93
77
}
94
78
95
- struct Catalog {
79
+ pub ( crate ) struct Catalog {
96
80
builtin : Arc < Builtin > ,
97
- tables : AHashMap < SmolStr , Arc < dyn TableSource > > ,
81
+ tables : AHashMap < TableReference , Arc < dyn TableSource > > ,
82
+ }
83
+
84
+ impl Catalog {
85
+ pub ( crate ) fn from_stream ( stream : & mut SlotStream ) -> Result < Self > {
86
+ // The header should be consumed before calling this function.
87
+ let table_num = read_array_len ( stream) ?;
88
+ let mut tables = AHashMap :: with_capacity ( table_num as usize ) ;
89
+ for _ in 0 ..table_num {
90
+ let oid = read_u32 ( stream) ?;
91
+ let ns_len = read_str_len ( stream) ?;
92
+ let ns_bytes = stream. look_ahead ( ns_len as usize ) ?;
93
+ let schema = SmolStr :: from ( from_utf8 ( ns_bytes) ?) ;
94
+ stream. rewind ( ns_len as usize ) ?;
95
+ let name_len = read_str_len ( stream) ?;
96
+ let name_bytes = stream. look_ahead ( name_len as usize ) ?;
97
+ let name = from_utf8 ( name_bytes) ?;
98
+ let table_ref = TableReference :: partial ( schema. as_str ( ) , name) ;
99
+ stream. rewind ( name_len as usize ) ?;
100
+ let column_num = read_array_len ( stream) ?;
101
+ let mut fields = Vec :: with_capacity ( column_num as usize ) ;
102
+ for _ in 0 ..column_num {
103
+ let elem_num = read_array_len ( stream) ?;
104
+ assert_eq ! ( elem_num, 3 ) ;
105
+ let etype = read_u8 ( stream) ?;
106
+ let df_type = EncodedType :: try_from ( etype) ?. to_arrow ( ) ;
107
+ let is_nullable = read_bool ( stream) ?;
108
+ let name_len = read_str_len ( stream) ?;
109
+ let name_bytes = stream. look_ahead ( name_len as usize ) ?;
110
+ let name = from_utf8 ( name_bytes) ?;
111
+ let field = Field :: new ( name, df_type, is_nullable) ;
112
+ fields. push ( field) ;
113
+ }
114
+ let schema = Schema :: new ( fields) ;
115
+ let table = Table {
116
+ oid : Oid :: from ( oid) ,
117
+ schema : Arc :: new ( schema) ,
118
+ } ;
119
+ tables. insert ( table_ref, Arc :: new ( table) as Arc < dyn TableSource > ) ;
120
+ }
121
+ Ok ( Self {
122
+ builtin : Arc :: clone ( & * BUILDIN ) ,
123
+ tables,
124
+ } )
125
+ }
98
126
}
99
127
100
128
impl ContextProvider for Catalog {
101
- fn get_table_source ( & self , name : TableReference ) -> DataFusionResult < Arc < dyn TableSource > > {
102
- match self . tables . get ( name . table ( ) ) {
129
+ fn get_table_source ( & self , table : TableReference ) -> DataFusionResult < Arc < dyn TableSource > > {
130
+ match self . tables . get ( & table) {
103
131
Some ( table) => Ok ( Arc :: clone ( table) ) ,
104
- _ => Err ( DataFusionError :: Plan ( format ! (
105
- "Table not found: {}" ,
106
- name. table( )
107
- ) ) ) ,
132
+ _ => {
133
+ let schema = match table. schema ( ) {
134
+ Some ( schema) => & format ! ( "{schema}." ) ,
135
+ _ => table. table ( ) ,
136
+ } ;
137
+ Err ( DataFusionError :: Plan ( format ! (
138
+ "Table not found: {schema}{}" ,
139
+ table. table( )
140
+ ) ) )
141
+ }
108
142
}
109
143
}
110
144
111
145
fn get_function_meta ( & self , name : & str ) -> Option < Arc < ScalarUDF > > {
112
- self . builtin . scalar_udf . get ( name) . map ( |f| Arc :: clone ( f ) )
146
+ self . builtin . scalar_udf . get ( name) . map ( Arc :: clone)
113
147
}
114
148
115
149
fn get_aggregate_meta ( & self , name : & str ) -> Option < Arc < AggregateUDF > > {
116
- self . builtin . agg_udf . get ( name) . map ( |f| Arc :: clone ( f ) )
150
+ self . builtin . agg_udf . get ( name) . map ( Arc :: clone)
117
151
}
118
152
119
153
fn get_variable_type ( & self , _variable_names : & [ String ] ) -> Option < DataType > {
120
154
None
121
155
}
122
156
123
157
fn get_window_meta ( & self , name : & str ) -> Option < Arc < WindowUDF > > {
124
- self . builtin . window_udf . get ( name) . map ( |f| Arc :: clone ( f ) )
158
+ self . builtin . window_udf . get ( name) . map ( Arc :: clone)
125
159
}
126
160
127
161
fn options ( & self ) -> & ConfigOptions {
0 commit comments