datafusion_python/expr/
create_function.rs1use std::fmt::{self, Display, Formatter};
19use std::sync::Arc;
20
21use datafusion::logical_expr::{
22 CreateFunction, CreateFunctionBody, OperateFunctionArg, Volatility,
23};
24use pyo3::IntoPyObjectExt;
25use pyo3::prelude::*;
26
27use super::PyExpr;
28use super::logical_node::LogicalNode;
29use crate::common::data_type::PyDataType;
30use crate::common::df_schema::PyDFSchema;
31use crate::sql::logical::PyLogicalPlan;
32
33#[pyclass(
34 from_py_object,
35 frozen,
36 name = "CreateFunction",
37 module = "datafusion.expr",
38 subclass
39)]
40#[derive(Clone)]
41pub struct PyCreateFunction {
42 create: CreateFunction,
43}
44
45impl From<PyCreateFunction> for CreateFunction {
46 fn from(create: PyCreateFunction) -> Self {
47 create.create
48 }
49}
50
51impl From<CreateFunction> for PyCreateFunction {
52 fn from(create: CreateFunction) -> PyCreateFunction {
53 PyCreateFunction { create }
54 }
55}
56
57impl Display for PyCreateFunction {
58 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
59 write!(f, "CreateFunction: name {:?}", self.create.name)
60 }
61}
62
63#[pyclass(
64 from_py_object,
65 frozen,
66 name = "OperateFunctionArg",
67 module = "datafusion.expr",
68 subclass
69)]
70#[derive(Clone)]
71pub struct PyOperateFunctionArg {
72 arg: OperateFunctionArg,
73}
74
75#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
76#[pyclass(
77 from_py_object,
78 frozen,
79 eq,
80 eq_int,
81 name = "Volatility",
82 module = "datafusion.expr"
83)]
84pub enum PyVolatility {
85 Immutable,
86 Stable,
87 Volatile,
88}
89
90#[pyclass(
91 from_py_object,
92 frozen,
93 name = "CreateFunctionBody",
94 module = "datafusion.expr",
95 subclass
96)]
97#[derive(Clone)]
98pub struct PyCreateFunctionBody {
99 body: CreateFunctionBody,
100}
101
102#[pymethods]
103impl PyCreateFunctionBody {
104 pub fn language(&self) -> Option<String> {
105 self.body
106 .language
107 .as_ref()
108 .map(|language| language.to_string())
109 }
110
111 pub fn behavior(&self) -> Option<PyVolatility> {
112 self.body.behavior.as_ref().map(|behavior| match behavior {
113 Volatility::Immutable => PyVolatility::Immutable,
114 Volatility::Stable => PyVolatility::Stable,
115 Volatility::Volatile => PyVolatility::Volatile,
116 })
117 }
118
119 pub fn function_body(&self) -> Option<PyExpr> {
120 self.body
121 .function_body
122 .as_ref()
123 .map(|function_body| function_body.clone().into())
124 }
125}
126
127#[pymethods]
128impl PyCreateFunction {
129 #[new]
130 #[pyo3(signature = (or_replace, temporary, name, params, schema, return_type=None, args=None))]
131 pub fn new(
132 or_replace: bool,
133 temporary: bool,
134 name: String,
135 params: PyCreateFunctionBody,
136 schema: PyDFSchema,
137 return_type: Option<PyDataType>,
138 args: Option<Vec<PyOperateFunctionArg>>,
139 ) -> Self {
140 PyCreateFunction {
141 create: CreateFunction {
142 or_replace,
143 temporary,
144 name,
145 args: args.map(|args| args.into_iter().map(|arg| arg.arg).collect()),
146 return_type: return_type.map(|return_type| return_type.data_type),
147 params: params.body,
148 schema: Arc::new(schema.into()),
149 },
150 }
151 }
152
153 pub fn or_replace(&self) -> bool {
154 self.create.or_replace
155 }
156
157 pub fn temporary(&self) -> bool {
158 self.create.temporary
159 }
160
161 pub fn name(&self) -> String {
162 self.create.name.clone()
163 }
164
165 pub fn params(&self) -> PyCreateFunctionBody {
166 PyCreateFunctionBody {
167 body: self.create.params.clone(),
168 }
169 }
170
171 pub fn schema(&self) -> PyDFSchema {
172 (*self.create.schema).clone().into()
173 }
174
175 pub fn return_type(&self) -> Option<PyDataType> {
176 self.create
177 .return_type
178 .as_ref()
179 .map(|return_type| return_type.clone().into())
180 }
181
182 pub fn args(&self) -> Option<Vec<PyOperateFunctionArg>> {
183 self.create.args.as_ref().map(|args| {
184 args.iter()
185 .map(|arg| PyOperateFunctionArg { arg: arg.clone() })
186 .collect()
187 })
188 }
189
190 fn __repr__(&self) -> PyResult<String> {
191 Ok(format!("CreateFunction({self})"))
192 }
193
194 fn __name__(&self) -> PyResult<String> {
195 Ok("CreateFunction".to_string())
196 }
197}
198
199impl LogicalNode for PyCreateFunction {
200 fn inputs(&self) -> Vec<PyLogicalPlan> {
201 vec![]
202 }
203
204 fn to_variant<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
205 self.clone().into_bound_py_any(py)
206 }
207}