risingwave_frontend/optimizer/rule/
table_function_to_postgres_query_rule.rs1use itertools::Itertools;
16use risingwave_common::catalog::{Field, Schema};
17use risingwave_common::types::{DataType, ScalarImpl};
18
19use super::prelude::{PlanRef, *};
20use crate::expr::{Expr, TableFunctionType};
21use crate::optimizer::plan_node::generic::GenericPlanRef;
22use crate::optimizer::plan_node::{LogicalPostgresQuery, LogicalTableFunction};
23
24pub struct TableFunctionToPostgresQueryRule {}
26impl Rule<Logical> for TableFunctionToPostgresQueryRule {
27 fn apply(&self, plan: PlanRef) -> Option<PlanRef> {
28 let logical_table_function: &LogicalTableFunction = plan.as_logical_table_function()?;
29 if logical_table_function.table_function().function_type != TableFunctionType::PostgresQuery
30 {
31 return None;
32 }
33 assert!(!logical_table_function.with_ordinality());
34 let table_function_return_type = logical_table_function.table_function().return_type();
35
36 if let DataType::Struct(st) = table_function_return_type {
37 let fields = st
38 .iter()
39 .map(|(name, data_type)| Field::with_name(data_type.clone(), name.to_owned()))
40 .collect_vec();
41
42 let schema = Schema::new(fields);
43
44 assert!(logical_table_function.table_function().args.len() >= 6);
45 let mut eval_args = vec![];
46 for arg in &logical_table_function.table_function().args {
47 assert_eq!(arg.return_type(), DataType::Varchar);
48 let value = arg.try_fold_const().unwrap().unwrap();
49 match value {
50 Some(ScalarImpl::Utf8(s)) => {
51 eval_args.push(s.to_string());
52 }
53 _ => {
54 unreachable!("must be a varchar")
55 }
56 }
57 }
58 let hostname = eval_args[0].clone();
59 let port = eval_args[1].clone();
60 let username = eval_args[2].clone();
61 let password = eval_args[3].clone();
62 let database = eval_args[4].clone();
63 let query = eval_args[5].clone();
64 let ssl_mode = eval_args.get(6).cloned();
65 let ssl_root_cert = eval_args.get(7).cloned();
66
67 Some(
68 LogicalPostgresQuery::new(
69 logical_table_function.ctx(),
70 schema,
71 hostname,
72 port,
73 username,
74 password,
75 database,
76 query,
77 ssl_mode,
78 ssl_root_cert,
79 )
80 .into(),
81 )
82 } else {
83 unreachable!("TableFunction return type should be struct")
84 }
85 }
86}
87
88impl TableFunctionToPostgresQueryRule {
89 pub fn create() -> BoxedRule {
90 Box::new(TableFunctionToPostgresQueryRule {})
91 }
92}