#pragma once #include #include #include namespace NYql { namespace NUdf { template std::unique_ptr MakeTupleArrowTraitsImpl(bool isOptional, TVector>&& children, const TType* type, TArgs&&... args) { if (isOptional) { if constexpr (TTraits::PassType) { return std::make_unique>(std::move(children), type, std::forward(args)...); } else { return std::make_unique>(std::move(children), std::forward(args)...); } } else { if constexpr (TTraits::PassType) { return std::make_unique>(std::move(children), type, std::forward(args)...); } else { return std::make_unique>(std::move(children), std::forward(args)...); } } } template std::unique_ptr MakeFixedSizeArrowTraitsImpl(bool isOptional, const TType* type, TArgs&&... args) { if (isOptional) { if constexpr (TTraits::PassType) { return std::make_unique>(type, std::forward(args)...); } else { return std::make_unique>(std::forward(args)...); } } else { if constexpr (TTraits::PassType) { return std::make_unique>(type, std::forward(args)...); } else { return std::make_unique>(std::forward(args)...); } } } template std::unique_ptr MakeStringArrowTraitsImpl(bool isOptional, const TType* type, TArgs&&... args) { if (isOptional) { if constexpr (TTraits::PassType) { return std::make_unique>(type, std::forward(args)...); } else { return std::make_unique>(std::forward(args)...); } } else { if constexpr (TTraits::PassType) { return std::make_unique>(type, std::forward(args)...); } else { return std::make_unique>(std::forward(args)...); } } } template std::unique_ptr MakeTzDateArrowTraitsImpl(bool isOptional, const TType* type, TArgs&&... args) { if constexpr (TTraits::PassType) { return TTraits::template MakeTzDate(isOptional, type, std::forward(args)...); } else { return TTraits::template MakeTzDate(isOptional, std::forward(args)...); } } template concept CanInstantiateArrowTraitsForDecimal = requires { typename TTraits::template TFixedSize; }; template std::unique_ptr DispatchByArrowTraits(const ITypeInfoHelper& typeInfoHelper, const TType* type, const IPgBuilder* pgBuilder, TArgs&&... args) { const TType* unpacked = type; TOptionalTypeInspector typeOpt(typeInfoHelper, type); bool isOptional = false; if (typeOpt) { unpacked = typeOpt.GetItemType(); isOptional = true; } TOptionalTypeInspector unpackedOpt(typeInfoHelper, unpacked); TPgTypeInspector unpackedPg(typeInfoHelper, unpacked); if (unpackedOpt || typeOpt && unpackedPg) { // at least 2 levels of optionals ui32 nestLevel = 0; auto currentType = type; auto previousType = type; TVector types; for (;;) { ++nestLevel; previousType = currentType; types.push_back(currentType); TOptionalTypeInspector currentOpt(typeInfoHelper, currentType); currentType = currentOpt.GetItemType(); TOptionalTypeInspector nexOpt(typeInfoHelper, currentType); if (!nexOpt) { break; } } if (TPgTypeInspector(typeInfoHelper, currentType)) { previousType = currentType; ++nestLevel; } auto reader = DispatchByArrowTraits(typeInfoHelper, previousType, pgBuilder, std::forward(args)...); for (ui32 i = 1; i < nestLevel; ++i) { if constexpr (TTraits::PassType) { reader = std::make_unique(std::move(reader), types[nestLevel - 1 - i], std::forward(args)...); } else { reader = std::make_unique(std::move(reader), std::forward(args)...); } } return reader; } else { type = unpacked; } TStructTypeInspector typeStruct(typeInfoHelper, type); if (typeStruct) { TVector> members; for (ui32 i = 0; i < typeStruct.GetMembersCount(); i++) { members.emplace_back(DispatchByArrowTraits(typeInfoHelper, typeStruct.GetMemberType(i), pgBuilder, std::forward(args)...)); } // XXX: Use Tuple block reader for Struct. return MakeTupleArrowTraitsImpl(isOptional, std::move(members), type, std::forward(args)...); } TTupleTypeInspector typeTuple(typeInfoHelper, type); if (typeTuple) { TVector> children; for (ui32 i = 0; i < typeTuple.GetElementsCount(); ++i) { children.emplace_back(DispatchByArrowTraits(typeInfoHelper, typeTuple.GetElementType(i), pgBuilder, std::forward(args)...)); } return MakeTupleArrowTraitsImpl(isOptional, std::move(children), type, std::forward(args)...); } TDataTypeInspector typeData(typeInfoHelper, type); if (typeData) { auto typeId = typeData.GetTypeId(); switch (GetDataSlot(typeId)) { case NUdf::EDataSlot::Int8: return MakeFixedSizeArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::Bool: case NUdf::EDataSlot::Uint8: return MakeFixedSizeArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::Int16: return MakeFixedSizeArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::Uint16: case NUdf::EDataSlot::Date: return MakeFixedSizeArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::Int32: case NUdf::EDataSlot::Date32: return MakeFixedSizeArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::Uint32: case NUdf::EDataSlot::Datetime: return MakeFixedSizeArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::Int64: case NUdf::EDataSlot::Interval: case NUdf::EDataSlot::Interval64: case NUdf::EDataSlot::Datetime64: case NUdf::EDataSlot::Timestamp64: return MakeFixedSizeArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::Uint64: case NUdf::EDataSlot::Timestamp: return MakeFixedSizeArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::Float: return MakeFixedSizeArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::Double: return MakeFixedSizeArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::String: return MakeStringArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::Yson: return MakeStringArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::JsonDocument: return MakeStringArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::Utf8: return MakeStringArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::Json: return MakeStringArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::TzDate: return MakeTzDateArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::TzDatetime: return MakeTzDateArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::TzTimestamp: return MakeTzDateArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::TzDate32: return MakeTzDateArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::TzDatetime64: return MakeTzDateArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::TzTimestamp64: return MakeTzDateArrowTraitsImpl(isOptional, type, std::forward(args)...); case NUdf::EDataSlot::Decimal: { if constexpr (CanInstantiateArrowTraitsForDecimal) { return MakeFixedSizeArrowTraitsImpl(isOptional, type, std::forward(args)...); } else { Y_ENSURE(false, "Unsupported data slot"); } } case NUdf::EDataSlot::Uuid: case NUdf::EDataSlot::DyNumber: Y_ENSURE(false, "Unsupported data slot"); } } TResourceTypeInspector resource(typeInfoHelper, type); if (resource) { if constexpr (TTraits::PassType) { return TTraits::MakeResource(isOptional, type, std::forward(args)...); } else { return TTraits::MakeResource(isOptional, std::forward(args)...); } } TPgTypeInspector typePg(typeInfoHelper, type); if (typePg) { auto desc = typeInfoHelper.FindPgTypeDescription(typePg.GetTypeId()); if constexpr (TTraits::PassType) { return TTraits::MakePg(*desc, pgBuilder, type, std::forward(args)...); } else { return TTraits::MakePg(*desc, pgBuilder, std::forward(args)...); } } Y_ENSURE(false, "Unsupported type"); } } }