@@ -606,6 +606,35 @@ void QueryAnalyzer::evaluateScalarSubqueryIfNeeded(QueryTreeNodePtr & node, Iden
606606 replaceStorageInQueryTree (query_tree, subquery_context, storage);
607607 auto interpreter = std::make_unique<InterpreterSelectQueryAnalyzer>(query_tree, subquery_context, options);
608608
609+ auto wrap_with_nullable_or_tuple = [](Block & block)
610+ {
611+ block = materializeBlock (block);
612+ if (block.columns () == 1 )
613+ {
614+ auto & column = block.getByPosition (0 );
615+ // / Here we wrap type to nullable if we can.
616+ // / It is needed cause if subquery return no rows, it's result will be Null.
617+ // / In case of many columns, do not check it cause tuple can't be nullable.
618+ if (!column.type ->isNullable () && column.type ->canBeInsideNullable ())
619+ {
620+ column.type = makeNullable (column.type );
621+ column.column = makeNullable (column.column );
622+ }
623+ } else
624+ {
625+ /* * Make unique column names for tuple.
626+ *
627+ * Example: SELECT (SELECT 2 AS x, x)
628+ */
629+ makeUniqueColumnNamesInBlock (block);
630+ block = Block ({{
631+ ColumnTuple::create (block.getColumns ()),
632+ std::make_shared<DataTypeTuple>(block.getDataTypes (), block.getNames ()),
633+ " tuple"
634+ }});
635+ }
636+ };
637+
609638 if (only_analyze)
610639 {
611640 // / If query is only analyzed, then constants are not correct.
@@ -619,6 +648,8 @@ void QueryAnalyzer::evaluateScalarSubqueryIfNeeded(QueryTreeNodePtr & node, Iden
619648 column.column = std::move (mut_col);
620649 }
621650 }
651+
652+ wrap_with_nullable_or_tuple (scalar_block);
622653 }
623654 else
624655 {
@@ -668,36 +699,8 @@ void QueryAnalyzer::evaluateScalarSubqueryIfNeeded(QueryTreeNodePtr & node, Iden
668699 if (tmp_block.rows () != 0 )
669700 throw Exception (ErrorCodes::INCORRECT_RESULT_OF_SCALAR_SUBQUERY, " Scalar subquery returned more than one row" );
670701
671- block = materializeBlock (block);
672- size_t columns = block.columns ();
673-
674- if (columns == 1 )
675- {
676- auto & column = block.getByPosition (0 );
677- // / Here we wrap type to nullable if we can.
678- // / It is needed cause if subquery return no rows, it's result will be Null.
679- // / In case of many columns, do not check it cause tuple can't be nullable.
680- if (!column.type ->isNullable () && column.type ->canBeInsideNullable ())
681- {
682- column.type = makeNullable (column.type );
683- column.column = makeNullable (column.column );
684- }
685-
686- scalar_block = block;
687- }
688- else
689- {
690- /* * Make unique column names for tuple.
691- *
692- * Example: SELECT (SELECT 2 AS x, x)
693- */
694- makeUniqueColumnNamesInBlock (block);
695-
696- scalar_block.insert ({
697- ColumnTuple::create (block.getColumns ()),
698- std::make_shared<DataTypeTuple>(block.getDataTypes (), block.getNames ()),
699- " tuple" });
700- }
702+ wrap_with_nullable_or_tuple (block);
703+ scalar_block = std::move (block);
701704 }
702705
703706 logProcessorProfile (context, io.pipeline .getProcessors ());
0 commit comments