Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions velox/expression/CastExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "velox/expression/ScopedVarSetter.h"
#include "velox/external/tzdb/time_zone.h"
#include "velox/functions/lib/RowsTranslationUtil.h"
#include "velox/type/CastRegistry.h"
#include "velox/type/Type.h"
#include "velox/type/tz/TimeZoneMap.h"
#include "velox/vector/ComplexVector.h"
Expand Down Expand Up @@ -782,13 +783,12 @@ void CastExpr::applyPeeled(
const TypePtr& toType,
VectorPtr& result) {
auto castFromOperator = getCastOperator(fromType);
if (castFromOperator && !castFromOperator->isSupportedToType(toType)) {
VELOX_USER_FAIL(
"Cannot cast {} to {}.", fromType->toString(), toType->toString());
}

auto castToOperator = getCastOperator(toType);
if (castToOperator && !castToOperator->isSupportedFromType(fromType)) {

// CastRulesRegistry is the source of truth for all custom type cast
// validation, including container types (e.g., ARRAY<T> → JSON).
if ((castFromOperator || castToOperator) &&
!CastRulesRegistry::instance().canCast(fromType, toType)) {
VELOX_USER_FAIL(
"Cannot cast {} to {}.", fromType->toString(), toType->toString());
}
Expand Down
18 changes: 12 additions & 6 deletions velox/expression/CastExpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,19 @@ class CastOperator {
public:
virtual ~CastOperator() = default;

/// Determines whether the cast operator supports casting to the custom type
/// from the other type.
virtual bool isSupportedFromType(const TypePtr& other) const = 0;
/// Deprecated: cast validation is now handled entirely by
/// CastRulesRegistry. This method is no longer called by CastExpr.
/// Register cast rules via registerCastRules() instead of overriding.
virtual bool isSupportedFromType(const TypePtr&) const {
return true;
}

/// Determines whether the cast operator supports casting from the custom type
/// to the other type.
virtual bool isSupportedToType(const TypePtr& other) const = 0;
/// Deprecated: cast validation is now handled entirely by
/// CastRulesRegistry. This method is no longer called by CastExpr.
/// Register cast rules via registerCastRules() instead of overriding.
virtual bool isSupportedToType(const TypePtr&) const {
return true;
}

/// Casts an input vector to the custom type. This function should not throw
/// when processing input rows, but report errors via context.setError().
Expand Down
2 changes: 1 addition & 1 deletion velox/expression/SignatureBinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ bool SignatureBinderBase::tryBind(
const auto& baseName = typeSignature.baseName();
auto typeName = boost::algorithm::to_upper_copy(baseName);
if (!boost::algorithm::iequals(typeName, actualType->name())) {
if (allowCoercion) {
if (allowCoercion && typeSignature.parameters().empty()) {
if (auto availableCoercion =
TypeCoercer::coerceTypeBase(actualType, typeName)) {
coercion = availableCoercion.value();
Expand Down
34 changes: 23 additions & 11 deletions velox/functions/prestosql/types/BigintEnumRegistration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "velox/functions/prestosql/types/BigintEnumRegistration.h"
#include "velox/expression/CastExpr.h"
#include "velox/functions/prestosql/types/BigintEnumType.h"
#include "velox/type/CastRegistry.h"

namespace facebook::velox {
namespace {
Expand All @@ -29,17 +30,6 @@ class BigintEnumCastOperator : public exec::CastOperator {
return kInstance;
}

// Casting is supported from all integer types.
bool isSupportedFromType(const TypePtr& other) const override {
return BIGINT()->equivalent(*other) || TINYINT()->equivalent(*other) ||
SMALLINT()->equivalent(*other) || INTEGER()->equivalent(*other);
}

// Casting is only supported to BIGINT type.
bool isSupportedToType(const TypePtr& other) const override {
return BIGINT()->equivalent(*other);
}

void castTo(
const BaseVector& input,
exec::EvalCtx& context,
Expand Down Expand Up @@ -133,5 +123,27 @@ class BigintEnumTypeFactory : public CustomTypeFactory {
void registerBigintEnumType() {
registerCustomType(
"bigint_enum", std::make_unique<const BigintEnumTypeFactory>());
registerCastRules({
{.fromType = "TINYINT",
.toType = "BIGINT_ENUM",
.implicitAllowed = false,
.validator = {}},
{.fromType = "SMALLINT",
.toType = "BIGINT_ENUM",
.implicitAllowed = false,
.validator = {}},
{.fromType = "INTEGER",
.toType = "BIGINT_ENUM",
.implicitAllowed = false,
.validator = {}},
{.fromType = "BIGINT",
.toType = "BIGINT_ENUM",
.implicitAllowed = false,
.validator = {}},
{.fromType = "BIGINT_ENUM",
.toType = "BIGINT",
.implicitAllowed = false,
.validator = {}},
});
}
} // namespace facebook::velox
29 changes: 11 additions & 18 deletions velox/functions/prestosql/types/BingTileRegistration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "velox/common/fuzzer/ConstrainedGenerators.h"
#include "velox/expression/CastExpr.h"
#include "velox/functions/prestosql/types/BingTileType.h"
#include "velox/type/CastRegistry.h"

namespace facebook::velox {

Expand All @@ -33,24 +34,6 @@ class BingTileCastOperator final : public exec::CastOperator {
return {std::shared_ptr<const CastOperator>{}, &kInstance};
}

bool isSupportedFromType(const TypePtr& other) const override {
switch (other->kind()) {
case TypeKind::BIGINT:
return true;
default:
return false;
}
}

bool isSupportedToType(const TypePtr& other) const override {
switch (other->kind()) {
case TypeKind::BIGINT:
return true;
default:
return false;
}
}

void castTo(
const BaseVector& input,
exec::EvalCtx& context,
Expand Down Expand Up @@ -138,6 +121,16 @@ class BingTileTypeFactory : public CustomTypeFactory {

void registerBingTileType() {
registerCustomType("bingtile", std::make_unique<const BingTileTypeFactory>());
registerCastRules({
{.fromType = "BIGINT",
.toType = "BINGTILE",
.implicitAllowed = false,
.validator = {}},
{.fromType = "BINGTILE",
.toType = "BIGINT",
.implicitAllowed = false,
.validator = {}},
});
}

} // namespace facebook::velox
57 changes: 27 additions & 30 deletions velox/functions/prestosql/types/IPAddressRegistration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,41 +22,12 @@
#include "velox/expression/CastExpr.h"
#include "velox/functions/prestosql/types/IPAddressType.h"
#include "velox/functions/prestosql/types/IPPrefixType.h"
#include "velox/type/CastRegistry.h"

namespace facebook::velox {
namespace {
class IPAddressCastOperator : public exec::CastOperator {
public:
bool isSupportedFromType(const TypePtr& other) const override {
switch (other->kind()) {
case TypeKind::VARBINARY:
case TypeKind::VARCHAR:
return true;
case TypeKind::ROW:
if (isIPPrefixType(other)) {
return true;
}
[[fallthrough]];
default:
return false;
}
}

bool isSupportedToType(const TypePtr& other) const override {
switch (other->kind()) {
case TypeKind::VARBINARY:
case TypeKind::VARCHAR:
return true;
case TypeKind::ROW:
if (isIPPrefixType(other)) {
return true;
}
[[fallthrough]];
default:
return false;
}
}

void castTo(
const BaseVector& input,
exec::EvalCtx& context,
Expand Down Expand Up @@ -274,5 +245,31 @@ class IPAddressTypeFactory : public CustomTypeFactory {
void registerIPAddressType() {
registerCustomType(
"ipaddress", std::make_unique<const IPAddressTypeFactory>());
registerCastRules({
{.fromType = "VARCHAR",
.toType = "IPADDRESS",
.implicitAllowed = false,
.validator = {}},
{.fromType = "VARBINARY",
.toType = "IPADDRESS",
.implicitAllowed = false,
.validator = {}},
{.fromType = "IPPREFIX",
.toType = "IPADDRESS",
.implicitAllowed = false,
.validator = {}},
{.fromType = "IPADDRESS",
.toType = "VARCHAR",
.implicitAllowed = false,
.validator = {}},
{.fromType = "IPADDRESS",
.toType = "VARBINARY",
.implicitAllowed = false,
.validator = {}},
{.fromType = "IPADDRESS",
.toType = "IPPREFIX",
.implicitAllowed = false,
.validator = {}},
});
}
} // namespace facebook::velox
41 changes: 19 additions & 22 deletions velox/functions/prestosql/types/IPPrefixRegistration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,12 @@
#include "velox/common/fuzzer/ConstrainedGenerators.h"
#include "velox/expression/CastExpr.h"
#include "velox/functions/prestosql/types/IPPrefixType.h"
#include "velox/type/CastRegistry.h"

namespace facebook::velox {
namespace {
class IPPrefixCastOperator : public exec::CastOperator {
public:
bool isSupportedFromType(const TypePtr& other) const override {
switch (other->kind()) {
case TypeKind::VARCHAR:
return true;
case TypeKind::HUGEINT:
return isIPAddressType(other);
default:
return false;
}
}

bool isSupportedToType(const TypePtr& other) const override {
switch (other->kind()) {
case TypeKind::VARCHAR:
return true;
case TypeKind::HUGEINT:
return isIPAddressType(other);
default:
return false;
}
}

void castTo(
const BaseVector& input,
exec::EvalCtx& context,
Expand Down Expand Up @@ -192,5 +171,23 @@ class IPPrefixTypeFactory : public CustomTypeFactory {

void registerIPPrefixType() {
registerCustomType("ipprefix", std::make_unique<const IPPrefixTypeFactory>());
registerCastRules({
{.fromType = "VARCHAR",
.toType = "IPPREFIX",
.implicitAllowed = false,
.validator = {}},
{.fromType = "IPADDRESS",
.toType = "IPPREFIX",
.implicitAllowed = false,
.validator = {}},
{.fromType = "IPPREFIX",
.toType = "VARCHAR",
.implicitAllowed = false,
.validator = {}},
{.fromType = "IPPREFIX",
.toType = "IPADDRESS",
.implicitAllowed = false,
.validator = {}},
});
}
} // namespace facebook::velox
79 changes: 0 additions & 79 deletions velox/functions/prestosql/types/JsonCastOperator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1169,58 +1169,8 @@ simdjson::error_code castFromJsonOneRow(
return simdjson::SUCCESS;
}

bool isSupportedBasicType(const TypePtr& type) {
switch (type->kind()) {
case TypeKind::BOOLEAN:
case TypeKind::BIGINT:
case TypeKind::INTEGER:
case TypeKind::SMALLINT:
case TypeKind::TINYINT:
case TypeKind::DOUBLE:
case TypeKind::REAL:
case TypeKind::VARCHAR:
return true;
default:
return false;
}
}
} // namespace

bool JsonCastOperator::isSupportedFromType(const TypePtr& other) const {
if (isSupportedBasicType(other)) {
return true;
}

switch (other->kind()) {
case TypeKind::UNKNOWN:
case TypeKind::TIMESTAMP:
return true;
case TypeKind::ARRAY:
return isSupportedFromType(other->childAt(0));
case TypeKind::ROW:
for (const auto& child : other->as<TypeKind::ROW>().children()) {
if (!isSupportedFromType(child)) {
return false;
}
}
return true;
case TypeKind::MAP:
if (other->childAt(1)->isUnknown()) {
if (other->childAt(0)->isUnknown()) {
return true;
}
return isSupportedBasicType(other->childAt(0)) &&
!isJsonType(other->childAt(0));
}

return (
isSupportedBasicType(other->childAt(0)) &&
isSupportedFromType(other->childAt(1)));
default:
return false;
}
}

template <TypeKind kind>
void JsonCastOperator::castFromJson(
const BaseVector& input,
Expand Down Expand Up @@ -1264,35 +1214,6 @@ void JsonCastOperator::castFromJson(
writer.finish();
}

bool JsonCastOperator::isSupportedToType(const TypePtr& other) const {
if (other->isDate()) {
return false;
}

if (isSupportedBasicType(other)) {
return true;
}

switch (other->kind()) {
case TypeKind::ARRAY:
return isSupportedToType(other->childAt(0));
case TypeKind::ROW:
for (const auto& child : other->as<TypeKind::ROW>().children()) {
if (!isSupportedToType(child)) {
return false;
}
}
return true;
case TypeKind::MAP:
return (
isSupportedBasicType(other->childAt(0)) &&
isSupportedToType(other->childAt(1)) &&
!isJsonType(other->childAt(0)));
default:
return false;
}
}

/// Converts an input vector of a supported type to Json type. The
/// implementation follows the structure below.
/// JsonOperator::castTo: type dispatch for castToJson
Expand Down
Loading
Loading