Skip to content

Commit

Permalink
rename and add docs
Browse files Browse the repository at this point in the history
Signed-off-by: Bugen Zhao <[email protected]>
  • Loading branch information
BugenZhao committed Nov 21, 2024
1 parent 23c2196 commit 8c0a300
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 26 deletions.
10 changes: 5 additions & 5 deletions src/frontend/src/catalog/system_catalog/pg_catalog/pg_cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use itertools::Itertools;
use risingwave_common::types::{DataType, Fields};
use risingwave_frontend_macro::system_catalog;

use crate::catalog::system_catalog::SysCatalogReaderImpl;
use crate::expr::cast_map_array;
use crate::expr::CAST_TABLE;

/// The catalog `pg_cast` stores data type conversion paths.
/// Ref: [`https://www.postgresql.org/docs/current/catalog-pg-cast.html`]
Expand All @@ -31,12 +32,11 @@ struct PgCast {

#[system_catalog(table, "pg_catalog.pg_cast")]
fn read_pg_cast(_: &SysCatalogReaderImpl) -> Vec<PgCast> {
let mut cast_array = cast_map_array();
cast_array.sort();
cast_array
CAST_TABLE
.iter()
.sorted()
.enumerate()
.map(|(idx, (src, target, ctx))| PgCast {
.map(|(idx, ((src, target), ctx))| PgCast {
oid: idx as i32,
castsource: DataType::try_from(*src).unwrap().to_oid(),
casttarget: DataType::try_from(*target).unwrap().to_oid(),
Expand Down
2 changes: 2 additions & 0 deletions src/frontend/src/expr/function_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@ pub fn is_row_function(expr: &ExprImpl) -> bool {
false
}

/// A stack of error messages for the cast operation.
#[derive(Error, Debug, Box, Macro)]
#[thiserror_ext(newtype(name = CastError), macro(path = "crate::expr::function_call"))]
#[error("{message}")]
Expand All @@ -433,6 +434,7 @@ pub struct CastErrorInner {

pub type CastResult<T = ()> = Result<T, CastError>;

// TODO(error-handling): do not use report string but directly make it a source of `ErrorCode`.
impl From<CastError> for ErrorCode {
fn from(value: CastError) -> Self {
ErrorCode::BindError(value.to_report_string())
Expand Down
4 changes: 2 additions & 2 deletions src/frontend/src/expr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ pub use session_timezone::{SessionTimezone, TimestamptzExprFinder};
pub use subquery::{Subquery, SubqueryKind};
pub use table_function::{TableFunction, TableFunctionType};
pub use type_inference::{
align_types, cast_map_array, cast_ok, cast_sigs, infer_some_all, infer_type, infer_type_name,
infer_type_with_sigmap, CastContext, CastSig, FuncSign,
align_types, cast_ok, cast_sigs, infer_some_all, infer_type, infer_type_name,
infer_type_with_sigmap, CastContext, CastSig, FuncSign, CAST_TABLE,
};
pub use user_defined_function::UserDefinedFunction;
pub use utils::*;
Expand Down
36 changes: 18 additions & 18 deletions src/frontend/src/expr/type_inference/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,17 +115,22 @@ pub fn align_array_and_element(
Ok(array_type)
}

/// Returns `Ok` if `ok` is true, otherwise returns a placeholder [`CastError`] to be further
/// wrapped with a more informative context in [`cast`].
fn canmeh(ok: bool) -> CastResult {
if ok {
Ok(())
} else {
bail_cast_error!()
}
}
/// Equivalent to `canmeh(false)`.
fn cannot() -> CastResult {
canmeh(false)
}

/// Checks whether casting from `source` to `target` is ok in `allows` context.
/// Returns an error if the cast is not possible.
pub fn cast(source: &DataType, target: &DataType, allows: CastContext) -> Result<(), CastError> {
macro_rules! any {
($f:ident) => {
Expand All @@ -134,11 +139,11 @@ pub fn cast(source: &DataType, target: &DataType, allows: CastContext) -> Result
}

if any!(is_struct) {
cast_ok_struct(source, target, allows)
cast_struct(source, target, allows)
} else if any!(is_array) {
cast_ok_array(source, target, allows)
cast_array(source, target, allows)
} else if any!(is_map) {
cast_ok_map(source, target, allows)
cast_map(source, target, allows)
} else {
canmeh(cast_ok_base(source, target, allows))
}
Expand All @@ -154,17 +159,19 @@ pub fn cast(source: &DataType, target: &DataType, allows: CastContext) -> Result
}

/// Checks whether casting from `source` to `target` is ok in `allows` context.
///
/// Equivalent to `cast(..).is_ok()`, but [`cast`] may be preferred for its error messages.
pub fn cast_ok(source: &DataType, target: &DataType, allows: CastContext) -> bool {
cast(source, target, allows).is_ok()
}

/// Checks whether casting from `source` to `target` is ok in `allows` context.
/// Both `source` and `target` must be base types, i.e. not struct or array.
pub fn cast_ok_base(source: &DataType, target: &DataType, allows: CastContext) -> bool {
matches!(CAST_MAP.get(&(source.into(), target.into())), Some(context) if *context <= allows)
matches!(CAST_TABLE.get(&(source.into(), target.into())), Some(context) if *context <= allows)
}

fn cast_ok_struct(source: &DataType, target: &DataType, allows: CastContext) -> CastResult {
fn cast_struct(source: &DataType, target: &DataType, allows: CastContext) -> CastResult {
match (source, target) {
(DataType::Struct(lty), DataType::Struct(rty)) => {
if lty.is_empty() || rty.is_empty() {
Expand Down Expand Up @@ -193,7 +200,7 @@ fn cast_ok_struct(source: &DataType, target: &DataType, allows: CastContext) ->
}
}

fn cast_ok_array(source: &DataType, target: &DataType, allows: CastContext) -> CastResult {
fn cast_array(source: &DataType, target: &DataType, allows: CastContext) -> CastResult {
match (source, target) {
(DataType::List(source_elem), DataType::List(target_elem)) => {
cast(source_elem, target_elem, allows)
Expand All @@ -207,7 +214,7 @@ fn cast_ok_array(source: &DataType, target: &DataType, allows: CastContext) -> C
}
}

fn cast_ok_map(source: &DataType, target: &DataType, allows: CastContext) -> CastResult {
fn cast_map(source: &DataType, target: &DataType, allows: CastContext) -> CastResult {
match (source, target) {
(DataType::Map(source_elem), DataType::Map(target_elem)) => cast(
&source_elem.clone().into_list(),
Expand All @@ -218,13 +225,6 @@ fn cast_ok_map(source: &DataType, target: &DataType, allows: CastContext) -> Cas
}
}

pub fn cast_map_array() -> Vec<(DataTypeName, DataTypeName, CastContext)> {
CAST_MAP
.iter()
.map(|((src, target), ctx)| (*src, *target, *ctx))
.collect_vec()
}

#[derive(Clone, Debug)]
pub struct CastSig {
pub from_type: DataTypeName,
Expand All @@ -245,10 +245,10 @@ pub enum CastContext {
Explicit,
}

pub type CastMap = BTreeMap<(DataTypeName, DataTypeName), CastContext>;
pub type CastTable = BTreeMap<(DataTypeName, DataTypeName), CastContext>;

pub fn cast_sigs() -> impl Iterator<Item = CastSig> {
CAST_MAP
CAST_TABLE
.iter()
.map(|((from_type, to_type), context)| CastSig {
from_type: *from_type,
Expand All @@ -257,7 +257,7 @@ pub fn cast_sigs() -> impl Iterator<Item = CastSig> {
})
}

pub static CAST_MAP: LazyLock<CastMap> = LazyLock::new(|| {
pub static CAST_TABLE: LazyLock<CastTable> = LazyLock::new(|| {
// cast rules:
// 1. implicit cast operations in PG are organized in 3 sequences,
// with the reverse direction being assign cast operations.
Expand Down Expand Up @@ -347,7 +347,7 @@ mod tests {
fn test_cast_ok() {
// With the help of a script we can obtain the 3 expected cast tables from PG. They are
// slightly modified on same-type cast and from-string cast for reasons explained above in
// `build_cast_map`.
// `build_`.

let actual = gen_cast_table(CastContext::Implicit);
assert_eq!(
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/src/expr/type_inference/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@
mod cast;
mod func;
pub use cast::{
align_types, cast_map_array, cast_ok, cast, cast_ok_base, cast_sigs, CastContext, CastSig,
align_types, cast, cast_ok, cast_ok_base, cast_sigs, CastContext, CastSig, CAST_TABLE,
};
pub use func::{infer_some_all, infer_type, infer_type_name, infer_type_with_sigmap, FuncSign};

0 comments on commit 8c0a300

Please sign in to comment.