| 1151 | } |
| 1152 | |
| 1153 | static std::unique_ptr<FunctionBindData> castBindFunc(ScalarBindFuncInput input) { |
| 1154 | DASSERT(input.arguments.size() == 2); |
| 1155 | // Bind target type. |
| 1156 | if (input.arguments[1]->expressionType != ExpressionType::LITERAL) { |
| 1157 | throw BinderException(std::format("Second parameter of CAST function must be a literal.")); |
| 1158 | } |
| 1159 | auto literalExpr = input.arguments[1]->constPtrCast<LiteralExpression>(); |
| 1160 | auto targetTypeStr = literalExpr->getValue().getValue<std::string>(); |
| 1161 | auto func = input.definition->ptrCast<ScalarFunction>(); |
| 1162 | func->name = "CAST_TO_" + targetTypeStr; |
| 1163 | auto targetType = LogicalType::convertFromString(targetTypeStr, input.context); |
| 1164 | if (!LogicalType::isBuiltInType(targetTypeStr)) { |
| 1165 | std::vector<LogicalType> typeVec; |
| 1166 | typeVec.push_back(input.arguments[0]->getDataType().copy()); |
| 1167 | try { |
| 1168 | auto entry = |
| 1169 | catalog::Catalog::Get(*input.context) |
| 1170 | ->getFunctionEntry(transaction::Transaction::Get(*input.context), func->name); |
| 1171 | auto match = BuiltInFunctionsUtils::matchFunction(func->name, typeVec, |
| 1172 | entry->ptrCast<catalog::FunctionCatalogEntry>()); |
| 1173 | func->execFunc = match->constPtrCast<ScalarFunction>()->execFunc; |
| 1174 | return std::make_unique<function::CastFunctionBindData>(targetType.copy()); |
| 1175 | } catch (...) { // NOLINT |
| 1176 | // If there's no user defined casting function for the corresponding user defined type, |
| 1177 | // we use the default casting function. |
| 1178 | } |
| 1179 | } |
| 1180 | // For STRUCT type, we will need to check its field name in later stage |
| 1181 | // Otherwise, there will be bug for: RETURN cast({'a': 12, 'b': 12} AS struct(c int64, d |
| 1182 | // int64)); being allowed. |
| 1183 | if (targetType == input.arguments[0]->getDataType() && |
| 1184 | targetType.getLogicalTypeID() != LogicalTypeID::STRUCT) { // No need to cast. |
| 1185 | return nullptr; |
| 1186 | } |
| 1187 | if (ExpressionUtil::canCastStatically(*input.arguments[0], targetType) && |
| 1188 | targetType.getLogicalTypeID() != LogicalTypeID::STRUCT) { |
| 1189 | input.arguments[0]->cast(targetType); |
| 1190 | return nullptr; |
| 1191 | } |
| 1192 | // TODO(Xiyang): Can we unify the binding of casting function with other scalar functions? |
| 1193 | auto res = |
| 1194 | CastFunction::bindCastFunction(func->name, input.arguments[0]->getDataType(), targetType); |
| 1195 | func->execFunc = res->execFunc; |
| 1196 | if (res->bindFunc) { |
| 1197 | return res->bindFunc(input); |
| 1198 | } |
| 1199 | return std::make_unique<function::CastFunctionBindData>(targetType.copy()); |
| 1200 | } |
| 1201 | |
| 1202 | function_set CastAnyFunction::getFunctionSet() { |
| 1203 | function_set result; |
nothing calls this directly
no test coverage detected