From 1a058dd468975ab66a00395b26d3822fdaf2729e Mon Sep 17 00:00:00 2001 From: WillyKidd <57129289+WillyKidd@users.noreply.github.com> Date: Thu, 8 Jun 2023 17:19:30 +0800 Subject: [PATCH 1/3] fix(cdc): unique `database.server.name` for dbz mysql connector (#10233) --- e2e_test/source/cdc/cdc.check.slt | 7 ++++++- e2e_test/source/cdc/cdc.load.slt | 18 ++++++++++++++++++ .../source/common/PostgresValidator.java | 6 +++++- .../source/core/SourceHandlerFactory.java | 6 +++++- .../src/main/resources/mysql.properties | 2 +- 5 files changed, 35 insertions(+), 4 deletions(-) diff --git a/e2e_test/source/cdc/cdc.check.slt b/e2e_test/source/cdc/cdc.check.slt index 25dd8835e390..b6b3f7122684 100644 --- a/e2e_test/source/cdc/cdc.check.slt +++ b/e2e_test/source/cdc/cdc.check.slt @@ -27,7 +27,12 @@ select count(*) as cnt from mytable; ---- 4 -query IIII +query VI +select count(*) from orders_2; +---- +3 + +query VII select count(*) from shipments_2; ---- 3 diff --git a/e2e_test/source/cdc/cdc.load.slt b/e2e_test/source/cdc/cdc.load.slt index ee9623f2e402..3a6a0fef24df 100644 --- a/e2e_test/source/cdc/cdc.load.slt +++ b/e2e_test/source/cdc/cdc.load.slt @@ -88,6 +88,24 @@ create table mytable ( server.id = '5087' ); +# Some columns missing and reordered (mysql-cdc) +statement ok +create table orders_2 ( + order_id int, + price decimal, + customer_name string, + PRIMARY KEY (order_id) +) with ( + connector = 'mysql-cdc', + hostname = 'mysql', + port = '3306', + username = 'root', + password = '123456', + database.name = 'mydb', + table.name = 'orders', + server.id = '5088' +); + # Some columns missing and reordered (postgres-cdc) statement ok create table shipments_2 ( diff --git a/java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/PostgresValidator.java b/java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/PostgresValidator.java index 14d5571c103d..7709e5f85165 100644 --- a/java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/PostgresValidator.java +++ b/java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/common/PostgresValidator.java @@ -306,7 +306,11 @@ private void validatePrivileges() throws SQLException { stmt.setString(1, tableOwner); var res = stmt.executeQuery(); while (res.next()) { - String[] users = (String[]) res.getArray("members").getArray(); + var usersArray = res.getArray("members"); + if (usersArray == null) { + break; + } + String[] users = (String[]) usersArray.getArray(); if (null != users && Arrays.asList(users) .contains(userProps.get(DbzConnectorConfig.USER))) { diff --git a/java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/core/SourceHandlerFactory.java b/java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/core/SourceHandlerFactory.java index bebd45f747d7..fbd5e071b757 100644 --- a/java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/core/SourceHandlerFactory.java +++ b/java/connector-node/risingwave-connector-service/src/main/java/com/risingwave/connector/source/core/SourceHandlerFactory.java @@ -17,6 +17,7 @@ import com.risingwave.connector.api.source.SourceHandler; import com.risingwave.connector.api.source.SourceTypeE; import com.risingwave.connector.source.common.DbzConnectorConfig; +import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,7 +27,10 @@ public abstract class SourceHandlerFactory { public static SourceHandler createSourceHandler( SourceTypeE source, long sourceId, String startOffset, Map userProps) { - var config = new DbzConnectorConfig(source, sourceId, startOffset, userProps); + // userProps extracted from grpc request, underlying implementation is UnmodifiableMap + Map modifiableUserProps = new HashMap<>(userProps); + modifiableUserProps.put("source.id", Long.toString(sourceId)); + var config = new DbzConnectorConfig(source, sourceId, startOffset, modifiableUserProps); LOG.info("resolved config for source#{}: {}", sourceId, config.getResolvedDebeziumProps()); return new DbzSourceHandler(config); } diff --git a/java/connector-node/risingwave-connector-service/src/main/resources/mysql.properties b/java/connector-node/risingwave-connector-service/src/main/resources/mysql.properties index d7b9b384ca4b..5d6482617524 100644 --- a/java/connector-node/risingwave-connector-service/src/main/resources/mysql.properties +++ b/java/connector-node/risingwave-connector-service/src/main/resources/mysql.properties @@ -16,6 +16,6 @@ table.include.list=${database.name}.${table.name} # default to disable schema change events include.schema.changes=${debezium.include.schema.changes:-false} database.server.id=${server.id} -database.server.name=RW_CDC_${database.name}.${table.name} +database.server.name=RW_CDC_${database.name}.${table.name}.${source.id} name=${hostname}:${port}:${database.name}.${table.name} From 9688b222d904c3c215a1e921961ccf40da8a294d Mon Sep 17 00:00:00 2001 From: xiangjinwu <17769960+xiangjinwu@users.noreply.github.com> Date: Thu, 8 Jun 2023 17:35:07 +0800 Subject: [PATCH 2/3] refactor(binder): in-place `cast_mut` or `ExprImpl::take` (#10227) --- src/frontend/src/binder/relation/join.rs | 3 +- src/frontend/src/expr/function_call.rs | 54 ++++++++++---------- src/frontend/src/expr/mod.rs | 25 ++++++--- src/frontend/src/expr/type_inference/cast.rs | 9 +--- src/frontend/src/expr/type_inference/func.rs | 31 ++++------- 5 files changed, 60 insertions(+), 62 deletions(-) diff --git a/src/frontend/src/binder/relation/join.rs b/src/frontend/src/binder/relation/join.rs index 5c6f0622336d..d8b8d708025d 100644 --- a/src/frontend/src/binder/relation/join.rs +++ b/src/frontend/src/binder/relation/join.rs @@ -35,8 +35,7 @@ impl RewriteExprsRecursive for BoundJoin { fn rewrite_exprs_recursive(&mut self, rewriter: &mut impl crate::expr::ExprRewriter) { self.left.rewrite_exprs_recursive(rewriter); self.right.rewrite_exprs_recursive(rewriter); - let dummy = ExprImpl::literal_bool(true); - self.cond = rewriter.rewrite_expr(std::mem::replace(&mut self.cond, dummy)); + self.cond = rewriter.rewrite_expr(self.cond.take()); } } diff --git a/src/frontend/src/expr/function_call.rs b/src/frontend/src/expr/function_call.rs index 22f7366c5f1e..ea71e2d515a2 100644 --- a/src/frontend/src/expr/function_call.rs +++ b/src/frontend/src/expr/function_call.rs @@ -110,20 +110,22 @@ impl FunctionCall { } /// Create a cast expr over `child` to `target` type in `allows` context. - pub fn new_cast( - mut child: ExprImpl, + /// The input `child` remains unchanged when this returns an error. + pub fn cast_mut( + child: &mut ExprImpl, target: DataType, allows: CastContext, - ) -> Result { - if let ExprImpl::Parameter(expr) = &mut child && !expr.has_infer() { + ) -> Result<(), CastError> { + if let ExprImpl::Parameter(expr) = child && !expr.has_infer() { + // Always Ok below. Safe to mutate `expr` (from `child`). expr.cast_infer_type(target); - return Ok(child); + return Ok(()); } - if is_row_function(&child) { + if let ExprImpl::FunctionCall(func) = child && func.func_type == ExprType::Row { // Row function will have empty fields in Datatype::Struct at this point. Therefore, // we will need to take some special care to generate the cast types. For normal struct // types, they will be handled in `cast_ok`. - return Self::cast_row_expr(child, target, allows); + return Self::cast_row_expr(func, target, allows); } if child.is_untyped() { // `is_unknown` makes sure `as_literal` and `as_utf8` will never panic. @@ -137,23 +139,27 @@ impl FunctionCall { }) .transpose(); if let Ok(datum) = datum { - return Ok(Literal::new(datum, target).into()); + *child = Literal::new(datum, target).into(); + return Ok(()); } // else when eager parsing fails, just proceed as normal. // Some callers are not ready to handle `'a'::int` error here. } let source = child.return_type(); if source == target { - Ok(child) + Ok(()) // Casting from unknown is allowed in all context. And PostgreSQL actually does the parsing // in frontend. } else if child.is_untyped() || cast_ok(&source, &target, allows) { - Ok(Self { + // Always Ok below. Safe to mutate `child`. + let owned = std::mem::replace(child, ExprImpl::literal_bool(false)); + *child = Self { func_type: ExprType::Cast, return_type: target, - inputs: vec![child], + inputs: vec![owned], } - .into()) + .into(); + Ok(()) } else { Err(CastError(format!( "cannot cast type \"{}\" to \"{}\" in {:?} context", @@ -166,11 +172,10 @@ impl FunctionCall { /// expressions, like `ROW(1)::STRUCT` to `STRUCT`, although an integer /// is castible to VARCHAR. It's to simply the casting rules. fn cast_row_expr( - expr: ExprImpl, + func: &mut FunctionCall, target_type: DataType, allows: CastContext, - ) -> Result { - let func = *expr.into_function_call().unwrap(); + ) -> Result<(), CastError> { let DataType::Struct(t) = &target_type else { return Err(CastError(format!( "cannot cast type \"{}\" to \"{}\" in {:?} context", @@ -179,19 +184,16 @@ impl FunctionCall { allows ))); }; - let (func_type, inputs, _) = func.decompose(); - match t.len().cmp(&inputs.len()) { + match t.len().cmp(&func.inputs.len()) { std::cmp::Ordering::Equal => { - let inputs = inputs - .into_iter() + // FIXME: `func` shall not be in a partially mutated state when one of its fields + // fails to cast. + func.inputs + .iter_mut() .zip_eq_fast(t.types()) - .map(|(e, t)| Self::new_cast(e, t.clone(), allows)) - .collect::, CastError>>()?; - let return_type = DataType::new_struct( - inputs.iter().map(|i| i.return_type()).collect(), - t.names().map(|s| s.to_string()).collect(), - ); - Ok(FunctionCall::new_unchecked(func_type, inputs, return_type).into()) + .try_for_each(|(e, t)| Self::cast_mut(e, t.clone(), allows))?; + func.return_type = target_type; + Ok(()) } std::cmp::Ordering::Less => Err(CastError("Input has too few columns.".to_string())), std::cmp::Ordering::Greater => { diff --git a/src/frontend/src/expr/mod.rs b/src/frontend/src/expr/mod.rs index c12a36f45256..e614be03fb2d 100644 --- a/src/frontend/src/expr/mod.rs +++ b/src/frontend/src/expr/mod.rs @@ -167,6 +167,11 @@ impl ExprImpl { .into() } + /// Takes the expression, leaving a literal null of the same type in its place. + pub fn take(&mut self) -> Self { + std::mem::replace(self, Self::literal_null(self.return_type())) + } + /// A `count(*)` aggregate function. #[inline(always)] pub fn count_star() -> Self { @@ -216,18 +221,26 @@ impl ExprImpl { } /// Shorthand to create cast expr to `target` type in implicit context. - pub fn cast_implicit(self, target: DataType) -> Result { - FunctionCall::new_cast(self, target, CastContext::Implicit) + pub fn cast_implicit(mut self, target: DataType) -> Result { + FunctionCall::cast_mut(&mut self, target, CastContext::Implicit)?; + Ok(self) } /// Shorthand to create cast expr to `target` type in assign context. - pub fn cast_assign(self, target: DataType) -> Result { - FunctionCall::new_cast(self, target, CastContext::Assign) + pub fn cast_assign(mut self, target: DataType) -> Result { + FunctionCall::cast_mut(&mut self, target, CastContext::Assign)?; + Ok(self) } /// Shorthand to create cast expr to `target` type in explicit context. - pub fn cast_explicit(self, target: DataType) -> Result { - FunctionCall::new_cast(self, target, CastContext::Explicit) + pub fn cast_explicit(mut self, target: DataType) -> Result { + FunctionCall::cast_mut(&mut self, target, CastContext::Explicit)?; + Ok(self) + } + + /// Shorthand to inplace cast expr to `target` type in implicit context. + pub fn cast_implicit_mut(&mut self, target: DataType) -> Result<(), CastError> { + FunctionCall::cast_mut(self, target, CastContext::Implicit) } /// Shorthand to enforce implicit cast to boolean diff --git a/src/frontend/src/expr/type_inference/cast.rs b/src/frontend/src/expr/type_inference/cast.rs index 6daaa3533999..b7e3749236f9 100644 --- a/src/frontend/src/expr/type_inference/cast.rs +++ b/src/frontend/src/expr/type_inference/cast.rs @@ -46,8 +46,6 @@ pub fn least_restrictive(lhs: DataType, rhs: DataType) -> std::result::Result( exprs: impl Iterator, ) -> std::result::Result { - use std::mem::swap; - let exprs = exprs.collect_vec(); // Essentially a filter_map followed by a try_reduce, which is unstable. let mut ret_type = None; @@ -62,10 +60,8 @@ pub fn align_types<'a>( } let ret_type = ret_type.unwrap_or(DataType::Varchar); for e in exprs { - let mut dummy = ExprImpl::literal_bool(false); - swap(&mut dummy, e); // unwrap: cast to least_restrictive type always succeeds - *e = dummy.cast_implicit(ret_type.clone()).unwrap(); + e.cast_implicit_mut(ret_type.clone()).unwrap(); } Ok(ret_type) } @@ -106,8 +102,7 @@ pub fn align_array_and_element( let array_type = DataType::List(Box::new(common_element_type)); // elements are already casted by `align_types`, we cast the array argument here - let array_owned = std::mem::replace(&mut inputs[array_idx], ExprImpl::literal_bool(false)); - inputs[array_idx] = array_owned.cast_implicit(array_type.clone())?; + inputs[array_idx].cast_implicit_mut(array_type.clone())?; Ok(array_type) } diff --git a/src/frontend/src/expr/type_inference/func.rs b/src/frontend/src/expr/type_inference/func.rs index a75abdf680f4..1e204aa4e06a 100644 --- a/src/frontend/src/expr/type_inference/func.rs +++ b/src/frontend/src/expr/type_inference/func.rs @@ -93,7 +93,7 @@ pub fn infer_some_all( ) .into()); } - inputs[0] = inputs[0].clone().cast_implicit(sig.inputs_type[0].into())?; + inputs[0].cast_implicit_mut(sig.inputs_type[0].into())?; } if element_type != Some(sig.inputs_type[1]) { if matches!( @@ -104,9 +104,7 @@ pub fn infer_some_all( ErrorCode::BindError("array/struct on left are not supported yet".into()).into(), ); } - inputs[1] = inputs[1] - .clone() - .cast_implicit(DataType::List(Box::new(sig.inputs_type[1].into())))?; + inputs[1].cast_implicit_mut(DataType::List(Box::new(sig.inputs_type[1].into())))?; } let inputs_owned = std::mem::take(inputs); @@ -373,13 +371,13 @@ fn infer_type_for_special( // `null = array[1]` where null should have same type as right side // `null = 1` can use the general rule, but return `Ok(None)` here is less readable (true, false) => { - let owned = std::mem::replace(&mut inputs[0], ExprImpl::literal_bool(true)); - inputs[0] = owned.cast_implicit(inputs[1].return_type())?; + let t = inputs[1].return_type(); + inputs[0].cast_implicit_mut(t)?; return Ok(Some(DataType::Boolean)); } (false, true) => { - let owned = std::mem::replace(&mut inputs[1], ExprImpl::literal_bool(true)); - inputs[1] = owned.cast_implicit(inputs[0].return_type())?; + let t = inputs[0].return_type(); + inputs[1].cast_implicit_mut(t)?; return Ok(Some(DataType::Boolean)); } // Types of both sides are known. Continue. @@ -394,17 +392,10 @@ fn infer_type_for_special( extract_expr_nested_type(&inputs[1])?, )?; if lcast { - let owned0 = - std::mem::replace(&mut inputs[0], ExprImpl::literal_bool(true)); - inputs[0] = - FunctionCall::new_unchecked(ExprType::Cast, vec![owned0], ret.clone()) - .into(); + inputs[0].cast_implicit_mut(ret.clone())?; } if rcast { - let owned1 = - std::mem::replace(&mut inputs[1], ExprImpl::literal_bool(true)); - inputs[1] = - FunctionCall::new_unchecked(ExprType::Cast, vec![owned1], ret).into(); + inputs[1].cast_implicit_mut(ret)?; } true } @@ -561,8 +552,7 @@ fn infer_type_for_special( ExprType::ArrayPosition => { ensure_arity!("array_position", 2 <= | inputs | <= 3); if let Some(start) = inputs.get_mut(2) { - let owned = std::mem::replace(start, ExprImpl::literal_bool(false)); - *start = owned.cast_implicit(DataType::Int32)?; + start.cast_implicit_mut(DataType::Int32)?; } let common_type = align_array_and_element(0, &[1], inputs); match common_type { @@ -639,8 +629,7 @@ fn infer_type_for_special( ExprType::TrimArray => { ensure_arity!("trim_array", | inputs | == 2); - let owned = std::mem::replace(&mut inputs[1], ExprImpl::literal_bool(true)); - inputs[1] = owned.cast_implicit(DataType::Int32)?; + inputs[1].cast_implicit_mut(DataType::Int32)?; match inputs[0].return_type() { DataType::List(typ) => Ok(Some(DataType::List(typ))), From 64ec79ff245ed121e9bddb79e51b2a15dd978081 Mon Sep 17 00:00:00 2001 From: August Date: Thu, 8 Jun 2023 18:03:18 +0800 Subject: [PATCH 3/3] fix: returning text type in pg_type as a workaround (#10237) --- e2e_test/batch/catalog/issue_10177.slt.part | 1 + e2e_test/batch/catalog/pg_cast.slt.part | 168 +++++++++--------- e2e_test/batch/catalog/pg_type.slt.part | 1 + src/common/src/types/postgres_type.rs | 1 + src/expr/src/sig/cast.rs | 4 +- .../system_catalog/pg_catalog/pg_type.rs | 3 + 6 files changed, 93 insertions(+), 85 deletions(-) diff --git a/e2e_test/batch/catalog/issue_10177.slt.part b/e2e_test/batch/catalog/issue_10177.slt.part index dee7cd3baf3c..db1a850ec076 100644 --- a/e2e_test/batch/catalog/issue_10177.slt.part +++ b/e2e_test/batch/catalog/issue_10177.slt.part @@ -54,5 +54,6 @@ pg_catalog 1700 numeric b f NULL pg_catalog 20 int8 b f NULL pg_catalog 21 int2 b f NULL pg_catalog 23 int4 b f NULL +pg_catalog 25 text b f NULL pg_catalog 700 float4 b f NULL pg_catalog 701 float8 b f NULL diff --git a/e2e_test/batch/catalog/pg_cast.slt.part b/e2e_test/batch/catalog/pg_cast.slt.part index 43c8444154db..7d8a24b63faa 100644 --- a/e2e_test/batch/catalog/pg_cast.slt.part +++ b/e2e_test/batch/catalog/pg_cast.slt.part @@ -1,95 +1,95 @@ query IIIT SELECT * FROM pg_catalog.pg_cast; ---- -0 16 23 EXPLICIT -1 16 1043 ASSIGN -2 21 23 IMPLICIT -3 21 20 IMPLICIT -4 21 700 IMPLICIT -5 21 701 IMPLICIT -6 21 1700 IMPLICIT -7 21 1043 ASSIGN -8 21 1301 IMPLICIT -9 23 16 EXPLICIT -10 23 21 ASSIGN -11 23 20 IMPLICIT -12 23 700 IMPLICIT -13 23 701 IMPLICIT -14 23 1700 IMPLICIT -15 23 1043 ASSIGN -16 23 1301 IMPLICIT -17 20 21 ASSIGN -18 20 23 ASSIGN -19 20 700 IMPLICIT -20 20 701 IMPLICIT -21 20 1700 IMPLICIT -22 20 1043 ASSIGN -23 20 1301 IMPLICIT -24 700 21 ASSIGN -25 700 23 ASSIGN -26 700 20 ASSIGN -27 700 701 IMPLICIT -28 700 1700 ASSIGN -29 700 1043 ASSIGN -30 701 21 ASSIGN -31 701 23 ASSIGN -32 701 20 ASSIGN -33 701 700 ASSIGN -34 701 1700 ASSIGN -35 701 1043 ASSIGN -36 1700 21 ASSIGN -37 1700 23 ASSIGN -38 1700 20 ASSIGN -39 1700 700 IMPLICIT -40 1700 701 IMPLICIT -41 1700 1043 ASSIGN -42 1082 1043 ASSIGN -43 1082 1114 IMPLICIT -44 1082 1184 IMPLICIT -45 1043 16 EXPLICIT -46 1043 21 EXPLICIT -47 1043 23 EXPLICIT -48 1043 20 EXPLICIT -49 1043 700 EXPLICIT -50 1043 701 EXPLICIT -51 1043 1700 EXPLICIT -52 1043 1082 EXPLICIT -53 1043 1083 EXPLICIT -54 1043 1114 EXPLICIT -55 1043 1184 EXPLICIT -56 1043 1186 EXPLICIT -57 1043 17 EXPLICIT -58 1043 3802 EXPLICIT -59 1043 1301 EXPLICIT -60 1083 1043 ASSIGN -61 1083 1186 IMPLICIT -62 1114 1082 ASSIGN -63 1114 1043 ASSIGN -64 1114 1083 ASSIGN -65 1114 1184 IMPLICIT -66 1184 1082 ASSIGN -67 1184 1043 ASSIGN -68 1184 1083 ASSIGN -69 1184 1114 ASSIGN -70 1186 1043 ASSIGN -71 1186 1083 ASSIGN -72 17 1043 ASSIGN -73 3802 16 EXPLICIT -74 3802 21 EXPLICIT -75 3802 23 EXPLICIT -76 3802 20 EXPLICIT -77 3802 700 EXPLICIT -78 3802 701 EXPLICIT -79 3802 1700 EXPLICIT -80 3802 1043 ASSIGN -81 1301 701 EXPLICIT -82 1301 1043 ASSIGN +0 16 23 e +1 16 1043 a +2 21 23 i +3 21 20 i +4 21 700 i +5 21 701 i +6 21 1700 i +7 21 1043 a +8 21 1301 i +9 23 16 e +10 23 21 a +11 23 20 i +12 23 700 i +13 23 701 i +14 23 1700 i +15 23 1043 a +16 23 1301 i +17 20 21 a +18 20 23 a +19 20 700 i +20 20 701 i +21 20 1700 i +22 20 1043 a +23 20 1301 i +24 700 21 a +25 700 23 a +26 700 20 a +27 700 701 i +28 700 1700 a +29 700 1043 a +30 701 21 a +31 701 23 a +32 701 20 a +33 701 700 a +34 701 1700 a +35 701 1043 a +36 1700 21 a +37 1700 23 a +38 1700 20 a +39 1700 700 i +40 1700 701 i +41 1700 1043 a +42 1082 1043 a +43 1082 1114 i +44 1082 1184 i +45 1043 16 e +46 1043 21 e +47 1043 23 e +48 1043 20 e +49 1043 700 e +50 1043 701 e +51 1043 1700 e +52 1043 1082 e +53 1043 1083 e +54 1043 1114 e +55 1043 1184 e +56 1043 1186 e +57 1043 17 e +58 1043 3802 e +59 1043 1301 e +60 1083 1043 a +61 1083 1186 i +62 1114 1082 a +63 1114 1043 a +64 1114 1083 a +65 1114 1184 i +66 1184 1082 a +67 1184 1043 a +68 1184 1083 a +69 1184 1114 a +70 1186 1043 a +71 1186 1083 a +72 17 1043 a +73 3802 16 e +74 3802 21 e +75 3802 23 e +76 3802 20 e +77 3802 700 e +78 3802 701 e +79 3802 1700 e +80 3802 1043 a +81 1301 701 e +82 1301 1043 a query TT rowsort SELECT s.typname, t.typname FROM pg_catalog.pg_cast as c, pg_catalog.pg_type as s, pg_catalog.pg_type as t WHERE - castcontext = 'IMPLICIT' + castcontext = 'i' and c.castsource = s.oid and c.casttarget = t.oid; ---- date timestamp diff --git a/e2e_test/batch/catalog/pg_type.slt.part b/e2e_test/batch/catalog/pg_type.slt.part index 0ad8da1a066c..39af08f0fec9 100644 --- a/e2e_test/batch/catalog/pg_type.slt.part +++ b/e2e_test/batch/catalog/pg_type.slt.part @@ -5,6 +5,7 @@ SELECT oid, typname, typelem, typnotnull, typtype FROM pg_catalog.pg_type; 20 int8 0 f b 21 int2 0 f b 23 int4 0 f b +25 text 0 f b 700 float4 0 f b 701 float8 0 f b 1043 varchar 0 f b diff --git a/src/common/src/types/postgres_type.rs b/src/common/src/types/postgres_type.rs index e4de7a4886d2..58b65cec9bd2 100644 --- a/src/common/src/types/postgres_type.rs +++ b/src/common/src/types/postgres_type.rs @@ -52,6 +52,7 @@ impl DataType { 21 => Ok(DataType::Int16), 23 => Ok(DataType::Int32), 20 => Ok(DataType::Int64), + 25 => Ok(DataType::Varchar), // workaround to support text in extended mode. 700 => Ok(DataType::Float32), 701 => Ok(DataType::Float64), 1700 => Ok(DataType::Decimal), diff --git a/src/expr/src/sig/cast.rs b/src/expr/src/sig/cast.rs index 1b272946fc1c..73841a85e303 100644 --- a/src/expr/src/sig/cast.rs +++ b/src/expr/src/sig/cast.rs @@ -29,10 +29,12 @@ pub struct CastSig { /// that allows explicit casts, but not vice versa. See details in /// [PG](https://www.postgresql.org/docs/current/catalog-pg-cast.html). #[derive(Clone, Copy, Debug, Display, Eq, Ord, PartialEq, PartialOrd)] -#[display(style = "UPPERCASE")] pub enum CastContext { + #[display("i")] Implicit, + #[display("a")] Assign, + #[display("e")] Explicit, } diff --git a/src/frontend/src/catalog/system_catalog/pg_catalog/pg_type.rs b/src/frontend/src/catalog/system_catalog/pg_catalog/pg_type.rs index c6c8304b9272..06142e626768 100644 --- a/src/frontend/src/catalog/system_catalog/pg_catalog/pg_type.rs +++ b/src/frontend/src/catalog/system_catalog/pg_catalog/pg_type.rs @@ -56,6 +56,9 @@ pub const PG_TYPE_DATA: &[(i32, &str)] = &[ (20, "int8"), (21, "int2"), (23, "int4"), + // Note: rw doesn't support `text` type, returning it is just a workaround to be compatible + // with PostgreSQL. + (25, "text"), (700, "float4"), (701, "float8"), (1043, "varchar"),