From bdd64eb994cbb5bfc2e592c1cbdc4fd0353124a4 Mon Sep 17 00:00:00 2001 From: Michael Xu Date: Fri, 12 Jan 2024 20:41:39 -0500 Subject: [PATCH] feat(catalog): add function catalog Signed-off-by: Michael Xu --- .gitignore | 1 + src/binder/create_function.rs | 56 +++++++++++++++++++++++++++++++++++ src/binder/mod.rs | 9 ++++++ src/catalog/function.rs | 42 ++++++++++++++++++++++++++ src/catalog/mod.rs | 1 + src/catalog/schema.rs | 8 +++++ src/planner/explain.rs | 4 +++ src/planner/mod.rs | 3 +- 8 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 src/binder/create_function.rs create mode 100644 src/catalog/function.rs diff --git a/.gitignore b/.gitignore index 302dee2fe..cb7bfc198 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ /.vscode .gdb_history risinglight +/.DS_Store diff --git a/src/binder/create_function.rs b/src/binder/create_function.rs new file mode 100644 index 000000000..50272ff52 --- /dev/null +++ b/src/binder/create_function.rs @@ -0,0 +1,56 @@ +// Copyright 2024 RisingLight Project Authors. Licensed under Apache-2.0. + +use std::fmt; +use std::str::FromStr; + +use pretty_xmlish::helper::delegate_fmt; +use pretty_xmlish::Pretty; +use serde::{Deserialize, Serialize}; + +use super::*; + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Serialize, Deserialize)] +pub struct CreateFunction { + name: String, + arg_types: Vec, + return_types: DataType, + language: String, + body: String, +} + +impl fmt::Display for CreateFunction { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let explainer = Pretty::childless_record("CreateFunction", self.pretty_function()); + delegate_fmt(&explainer, f, String::with_capacity(1000)) + } +} + +impl FromStr for CreateFunction { + type Err = (); + + fn from_str(_s: &str) -> std::result::Result { + Err(()) + } +} + +impl CreateFunction { + pub fn pretty_function<'a>(&self) -> Vec<(&'a str, Pretty<'a>)> { + vec![ + ("name", Pretty::display(&self.name)), + ("language", Pretty::display(&self.language)), + ("body", Pretty::display(&self.body)), + ] + } +} + +impl Binder { + pub(super) fn bind_create_function( + &mut self, + _name: ObjectName, + _args: Option>, + _return_type: Option, + _params: CreateFunctionBody, + ) -> Result { + todo!() + } +} diff --git a/src/binder/mod.rs b/src/binder/mod.rs index 04f01258e..d7abaabd8 100644 --- a/src/binder/mod.rs +++ b/src/binder/mod.rs @@ -15,6 +15,7 @@ use crate::planner::{Expr as Node, RecExpr, TypeError, TypeSchemaAnalysis}; use crate::types::{DataTypeKind, DataValue}; pub mod copy; +mod create_function; mod create_table; mod delete; mod drop; @@ -23,6 +24,7 @@ mod insert; mod select; mod table; +pub use self::create_function::*; pub use self::create_table::*; pub use self::drop::*; @@ -154,6 +156,13 @@ impl Binder { constraints, .. } => self.bind_create_table(name, &columns, &constraints), + Statement::CreateFunction { + name, + args, + return_type, + params, + .. + } => self.bind_create_function(name, args, return_type, params), Statement::Drop { object_type, if_exists, diff --git a/src/catalog/function.rs b/src/catalog/function.rs new file mode 100644 index 000000000..cb57256ed --- /dev/null +++ b/src/catalog/function.rs @@ -0,0 +1,42 @@ +// Copyright 2024 RisingLight Project Authors. Licensed under Apache-2.0. + +use crate::types::DataType; + +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub struct FunctionCatalog { + name: String, + arg_types: Vec, + return_type: DataType, + language: String, + body: String, +} + +impl FunctionCatalog { + pub fn new( + name: String, + arg_types: Vec, + return_type: DataType, + language: String, + body: String, + ) -> Self { + Self { + name, + arg_types, + return_type, + language, + body, + } + } + + pub fn body(&self) -> String { + self.body.clone() + } + + pub fn name(&self) -> String { + self.name.clone() + } + + pub fn language(&self) -> String { + self.language.clone() + } +} diff --git a/src/catalog/mod.rs b/src/catalog/mod.rs index 99f4f21db..59f76f39b 100644 --- a/src/catalog/mod.rs +++ b/src/catalog/mod.rs @@ -18,6 +18,7 @@ static CONTRIBUTORS_TABLE_NAME: &str = "contributors"; pub const CONTRIBUTORS_TABLE_ID: TableId = 0; mod column; +mod function; mod root; mod schema; mod table; diff --git a/src/catalog/schema.rs b/src/catalog/schema.rs index 3418a34df..615aabb4e 100644 --- a/src/catalog/schema.rs +++ b/src/catalog/schema.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; use std::sync::Arc; +use super::function::FunctionCatalog; use super::*; /// The catalog of a schema. @@ -13,6 +14,8 @@ pub struct SchemaCatalog { table_idxs: HashMap, tables: HashMap>, next_table_id: TableId, + /// Currently indexed by function name + functions: HashMap>, } impl SchemaCatalog { @@ -23,6 +26,7 @@ impl SchemaCatalog { table_idxs: HashMap::new(), tables: HashMap::new(), next_table_id: 0, + functions: HashMap::new(), } } @@ -81,6 +85,10 @@ impl SchemaCatalog { pub fn id(&self) -> SchemaId { self.id } + + pub fn get_function_by_name(&self, name: &str) -> Option> { + self.functions.get(name).cloned() + } } #[cfg(test)] diff --git a/src/planner/explain.rs b/src/planner/explain.rs index 4777a4409..b9dc879fe 100644 --- a/src/planner/explain.rs +++ b/src/planner/explain.rs @@ -341,6 +341,10 @@ impl<'a> Explain<'a> { let fields = t.pretty_table().with(cost, rows); Pretty::childless_record("CreateTable", fields) } + CreateFunction(f) => { + let v = f.pretty_function(); + Pretty::childless_record("CreateFunction", v) + } Drop(t) => { let fields = t.pretty_table().with(cost, rows); Pretty::childless_record("Drop", fields) diff --git a/src/planner/mod.rs b/src/planner/mod.rs index 046fab28b..3580b5748 100644 --- a/src/planner/mod.rs +++ b/src/planner/mod.rs @@ -3,7 +3,7 @@ use egg::{define_language, Id, Symbol}; use crate::binder::copy::ExtSource; -use crate::binder::{BoundDrop, CreateTable}; +use crate::binder::{BoundDrop, CreateFunction, CreateTable}; use crate::catalog::{ColumnRefId, TableRefId}; use crate::parser::{BinaryOperator, UnaryOperator}; use crate::types::{ColumnIndex, DataTypeKind, DataValue, DateTimeField}; @@ -117,6 +117,7 @@ define_language! { "window" = Window([Id; 2]), // (window [over..] child) // output = child || exprs CreateTable(CreateTable), + CreateFunction(CreateFunction), Drop(BoundDrop), "insert" = Insert([Id; 3]), // (insert table [column..] child) "delete" = Delete([Id; 2]), // (delete table child)