@@ -674,6 +674,10 @@ TEST_P(SubfieldTest, overAggregation) {
674674}
675675
676676TEST_P (SubfieldTest, blackbox) {
677+ registerGenieUdfs ();
678+ if (GetParam () == 3 ) {
679+ optimizerOptions_.allMapsAsStruct = true ;
680+ }
677681 auto data = makeRowVector (
678682 {" id" , " m" },
679683 {
@@ -686,7 +690,8 @@ TEST_P(SubfieldTest, blackbox) {
686690
687691 lp::PlanBuilder::Context ctx (kHiveConnectorId );
688692 ctx.hook = [](const auto & name, const auto & args) -> lp::ExprPtr {
689- if (name == " map_row_from_map" ) {
693+ if (name == " map_row_from_map" || name == " make_row_from_map" ||
694+ name == " padded_make_row_from_map" ) {
690695 VELOX_CHECK (args.at (2 )->isConstant ());
691696 auto names = args.at (2 )
692697 ->template as <lp::ConstantExpr>()
@@ -723,6 +728,82 @@ TEST_P(SubfieldTest, blackbox) {
723728 .build ();
724729
725730 ASSERT_NO_THROW (toSingleNodePlan (logicalPlan));
731+
732+ logicalPlan =
733+ lp::PlanBuilder (ctx)
734+ .tableScan (" t" )
735+ .project (
736+ {" make_row_from_map(m, array[1, 2, 3], array['f1', 'f2', 'f3']) as m" })
737+ .build ();
738+
739+ auto plan = toSingleNodePlan (logicalPlan);
740+
741+ verifyRequiredSubfields (
742+ plan, {{" m" , {subfield (" 1" ), subfield (" 2" ), subfield (" 3" )}}});
743+
744+ if (GetParam () == 1 ) {
745+ auto matcher =
746+ core::PlanMatcherBuilder ()
747+ .tableScan ()
748+ .project (
749+ {" row_constructor(subscript(m_4,1),subscript(m_4,2),subscript(m_4,3))" })
750+ .build ();
751+
752+ ASSERT_TRUE (matcher->match (plan));
753+ } else {
754+ auto matcher =
755+ core::PlanMatcherBuilder ().tableScan ().project ().project ().build ();
756+
757+ ASSERT_TRUE (matcher->match (plan));
758+ }
759+
760+ logicalPlan =
761+ lp::PlanBuilder (ctx, true )
762+ .tableScan (" t" )
763+ .project (
764+ {" identity(make_row_from_map(m, array[1, 2, 3], array['f1', 'f2', 'f3'])) as m" })
765+ .project (
766+ {" if (m.f1 < 0, ceil(m.f1), floor(m.f1)) as f1b" ,
767+ " if (m.f2 < 0, 1 + floor(m.f2), ceil(m.f2) + 1) as f2b" })
768+ .project ({" f1b + 1 as f1b1" , " f1b * 2 as f1b2b" , " f2b * 3 as f2b3" })
769+ .build ();
770+
771+ // Enable parallel project for the remainder of this test. This is reset in
772+ // SetUp().
773+ optimizerOptions_.parallelProjectWidth = 2 ;
774+ plan = toSingleNodePlan (logicalPlan);
775+
776+ verifyRequiredSubfields (
777+ plan, {{" m" , {subfield (" 1" ), subfield (" 2" ), subfield (" 3" )}}});
778+
779+ if (GetParam () == 1 ) {
780+ auto matcher =
781+ core::PlanMatcherBuilder ()
782+ .tableScan ()
783+ .parallelProject ()
784+ .parallelProject (
785+ {" identity(row_constructor(subscript(m_7,1),subscript(m_7,2),subscript(m_7,3)))" })
786+ .parallelProject ()
787+ .parallelProject ()
788+ .project ()
789+ .build ();
790+
791+ ASSERT_TRUE (matcher->match (plan));
792+ }
793+
794+ logicalPlan =
795+ lp::PlanBuilder (ctx, true )
796+ .tableScan (" t" )
797+ .project (
798+ {" make_row_from_map(m, array[1, 2, 3], array['f1', 'f2', 'f3']) as m" })
799+ .project (
800+ {" if (coalesce(m.f1, 1::REAL) < 0, ceil(coalesce(m.f1, 1::REAL)), floor(coalesce(m.f1, 1::REAL))) as f1b" ,
801+ " if (coalesce(m.f2, 1::REAL) < 0, 1 + floor(coalesce(m.f2, 2::real)), ceil(coalesce(m.f2, 3::REAL)) + 1) as f2b" })
802+ .project ({" f1b + 1 as f1b1" , " f1b * 2 as f1b2b" , " f2b * 3 as f2b3" })
803+ .build ();
804+
805+ plan = toSingleNodePlan (logicalPlan);
806+ std::cout << plan->toString (true , true );
726807}
727808
728809VELOX_INSTANTIATE_TEST_SUITE_P (
0 commit comments