align_output_schema.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #include "align_output_schema.h"
  2. #include <yql/essentials/public/purecalc/common/names.h>
  3. #include <yql/essentials/public/purecalc/common/type_from_schema.h>
  4. #include <yql/essentials/public/purecalc/common/transformations/utils.h>
  5. #include <yql/essentials/core/yql_expr_type_annotation.h>
  6. using namespace NYql;
  7. using namespace NYql::NPureCalc;
  8. namespace {
  9. class TOutputAligner : public TSyncTransformerBase {
  10. private:
  11. const TTypeAnnotationNode* OutputStruct_;
  12. bool AcceptsBlocks_;
  13. EProcessorMode ProcessorMode_;
  14. public:
  15. explicit TOutputAligner(
  16. const TTypeAnnotationNode* outputStruct,
  17. bool acceptsBlocks,
  18. EProcessorMode processorMode
  19. )
  20. : OutputStruct_(outputStruct)
  21. , AcceptsBlocks_(acceptsBlocks)
  22. , ProcessorMode_(processorMode)
  23. {
  24. }
  25. public:
  26. TStatus DoTransform(TExprNode::TPtr input, TExprNode::TPtr& output, TExprContext& ctx) final {
  27. output = input;
  28. const auto* expectedType = MakeExpectedType(ctx);
  29. const auto* expectedItemType = MakeExpectedItemType();
  30. const auto* actualType = MakeActualType(input);
  31. const auto* actualItemType = MakeActualItemType(input);
  32. // XXX: Tweak the obtained expression type, is the spec supports blocks:
  33. // 1. Remove "_yql_block_length" attribute, since it's for internal usage.
  34. // 2. Strip block container from the type to store its internal type.
  35. if (AcceptsBlocks_) {
  36. Y_ENSURE(actualItemType->GetKind() == ETypeAnnotationKind::Struct);
  37. actualItemType = UnwrapBlockStruct(actualItemType->Cast<TStructExprType>(), ctx);
  38. if (ProcessorMode_ == EProcessorMode::PullList) {
  39. actualType = ctx.MakeType<TListExprType>(actualItemType);
  40. } else {
  41. actualType = ctx.MakeType<TStreamExprType>(actualItemType);
  42. }
  43. }
  44. if (!ValidateOutputType(actualItemType, expectedItemType, ctx)) {
  45. return TStatus::Error;
  46. }
  47. if (!expectedType) {
  48. return TStatus::Ok;
  49. }
  50. auto status = TryConvertTo(output, *actualType, *expectedType, ctx);
  51. if (status.Level == IGraphTransformer::TStatus::Repeat) {
  52. status = IGraphTransformer::TStatus(IGraphTransformer::TStatus::Repeat, true);
  53. }
  54. return status;
  55. }
  56. void Rewind() final {
  57. }
  58. private:
  59. const TTypeAnnotationNode* MakeExpectedType(TExprContext& ctx) {
  60. if (!OutputStruct_) {
  61. return nullptr;
  62. }
  63. switch (ProcessorMode_) {
  64. case EProcessorMode::PullList:
  65. return ctx.MakeType<TListExprType>(OutputStruct_);
  66. case EProcessorMode::PullStream:
  67. case EProcessorMode::PushStream:
  68. return ctx.MakeType<TStreamExprType>(OutputStruct_);
  69. }
  70. Y_ABORT("Unexpected");
  71. }
  72. const TTypeAnnotationNode* MakeExpectedItemType() {
  73. return OutputStruct_;
  74. }
  75. const TTypeAnnotationNode* MakeActualType(TExprNode::TPtr& input) {
  76. return input->GetTypeAnn();
  77. }
  78. const TTypeAnnotationNode* MakeActualItemType(TExprNode::TPtr& input) {
  79. auto actualType = MakeActualType(input);
  80. switch (actualType->GetKind()) {
  81. case ETypeAnnotationKind::Stream:
  82. Y_ENSURE(ProcessorMode_ != EProcessorMode::PullList,
  83. "processor mode mismatches the actual container type");
  84. return actualType->Cast<TStreamExprType>()->GetItemType();
  85. case ETypeAnnotationKind::List:
  86. Y_ENSURE(ProcessorMode_ == EProcessorMode::PullList,
  87. "processor mode mismatches the actual container type");
  88. return actualType->Cast<TListExprType>()->GetItemType();
  89. default:
  90. Y_ABORT("unexpected return type");
  91. }
  92. }
  93. };
  94. }
  95. TAutoPtr<IGraphTransformer> NYql::NPureCalc::MakeOutputAligner(
  96. const TTypeAnnotationNode* outputStruct,
  97. bool acceptsBlocks,
  98. EProcessorMode processorMode
  99. ) {
  100. return new TOutputAligner(outputStruct, acceptsBlocks, processorMode);
  101. }