aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorareredify <areredify@yandex-team.com>2023-11-14 11:26:03 +0300
committerareredify <areredify@yandex-team.com>2023-11-14 18:53:11 +0300
commit60b19cde31eefa790f0956b3eb1f2e567dd2ca15 (patch)
treecd5c96222827aff1f4dd74d2219983465a9d3629
parent59c91d9ecf73b46bd8e22a7f78531b93502c0cae (diff)
downloadydb-60b19cde31eefa790f0956b3eb1f2e567dd2ca15.tar.gz
support UNION wihout ALL
-rw-r--r--ydb/docs/en/core/yql/reference/yql-core/syntax/_includes/not_yet_supported.md4
-rw-r--r--ydb/docs/en/core/yql/reference/yql-core/syntax/_includes/select/combining_queries.md21
-rw-r--r--ydb/docs/en/core/yql/reference/yql-core/syntax/_includes/select/union.md13
-rw-r--r--ydb/docs/en/core/yql/reference/yql-core/syntax/select.md4
-rw-r--r--ydb/docs/ru/core/yql/reference/yql-core/syntax/_includes/not_yet_supported.md4
-rw-r--r--ydb/docs/ru/core/yql/reference/yql-core/syntax/_includes/select/combining_queries.md21
-rw-r--r--ydb/docs/ru/core/yql/reference/yql-core/syntax/_includes/select/union.md13
-rw-r--r--ydb/docs/ru/core/yql/reference/yql-core/syntax/_includes/select/union_all.md6
-rw-r--r--ydb/docs/ru/core/yql/reference/yql-core/syntax/select.md4
-rw-r--r--ydb/library/yql/core/common_opt/yql_co_simple1.cpp9
-rw-r--r--ydb/library/yql/core/type_ann/type_ann_core.cpp3
-rw-r--r--ydb/library/yql/sql/v1/format/sql_format_ut.cpp10
-rw-r--r--ydb/library/yql/sql/v1/select.cpp25
-rw-r--r--ydb/library/yql/sql/v1/source.h2
-rw-r--r--ydb/library/yql/sql/v1/sql_select.cpp61
-rw-r--r--ydb/library/yql/sql/v1/sql_ut.cpp33
-rw-r--r--ydb/library/yql/tests/sql/dq_file/part0/canondata/result.json22
-rw-r--r--ydb/library/yql/tests/sql/dq_file/part4/canondata/result.json22
-rw-r--r--ydb/library/yql/tests/sql/dq_file/part6/canondata/result.json22
-rw-r--r--ydb/library/yql/tests/sql/dq_file/part8/canondata/result.json22
-rw-r--r--ydb/library/yql/tests/sql/dq_file/part9/canondata/result.json44
-rw-r--r--ydb/library/yql/tests/sql/sql2yql/canondata/result.json86
-rw-r--r--ydb/library/yql/tests/sql/suites/union/default.cfg1
-rw-r--r--ydb/library/yql/tests/sql/suites/union/input.txt4
-rw-r--r--ydb/library/yql/tests/sql/suites/union/input2.txt4
-rw-r--r--ydb/library/yql/tests/sql/suites/union/union_column_extention.sql16
-rw-r--r--ydb/library/yql/tests/sql/suites/union/union_mix.sql4
-rw-r--r--ydb/library/yql/tests/sql/suites/union/union_multiin.cfg2
-rw-r--r--ydb/library/yql/tests/sql/suites/union/union_multiin.sql4
-rw-r--r--ydb/library/yql/tests/sql/suites/union/union_positional.sql9
-rw-r--r--ydb/library/yql/tests/sql/suites/union/union_positional_mix.sql10
-rw-r--r--ydb/library/yql/tests/sql/suites/union/union_trivial.sql4
-rw-r--r--ydb/library/yql/tests/sql/yt_native_file/part0/canondata/result.json21
-rw-r--r--ydb/library/yql/tests/sql/yt_native_file/part4/canondata/result.json21
-rw-r--r--ydb/library/yql/tests/sql/yt_native_file/part6/canondata/result.json21
-rw-r--r--ydb/library/yql/tests/sql/yt_native_file/part8/canondata/result.json21
-rw-r--r--ydb/library/yql/tests/sql/yt_native_file/part9/canondata/result.json42
37 files changed, 578 insertions, 57 deletions
diff --git a/ydb/docs/en/core/yql/reference/yql-core/syntax/_includes/not_yet_supported.md b/ydb/docs/en/core/yql/reference/yql-core/syntax/_includes/not_yet_supported.md
index eb128a428d..2dae040aa3 100644
--- a/ydb/docs/en/core/yql/reference/yql-core/syntax/_includes/not_yet_supported.md
+++ b/ydb/docs/en/core/yql/reference/yql-core/syntax/_includes/not_yet_supported.md
@@ -4,10 +4,6 @@
A syntactically available alternative is `EXISTS`, but it's not very useful as it doesn't support correlated subqueries. You can also rewrite it using `JOIN`.
-## UNION {#union}
-
-An available alternative is `SELECT DISTINCT` by explicitly listed columns + `UNION ALL` with subqueries (if needed).
-
## NATURAL JOIN {#natural-join}
An alternative is to explicitly list the matching columns on both sides.
diff --git a/ydb/docs/en/core/yql/reference/yql-core/syntax/_includes/select/combining_queries.md b/ydb/docs/en/core/yql/reference/yql-core/syntax/_includes/select/combining_queries.md
new file mode 100644
index 0000000000..8268b9d1f1
--- /dev/null
+++ b/ydb/docs/en/core/yql/reference/yql-core/syntax/_includes/select/combining_queries.md
@@ -0,0 +1,21 @@
+### Combining queries {#combining-queries}
+
+Results of several SELECT statements (or subqueries) can be combined using `UNION` and `UNION ALL` keywords.
+```yql
+query1 UNION [ALL] query2 (UNION [ALL] query3 ...)
+```
+Union of more than two queries is interpreted as a left-associative operation, that is
+
+```yql
+query1 UNION query2 UNION ALL query3
+```
+is interpreted as
+```yql
+(query1 UNION query2) UNION ALL query3
+```
+
+If the underlying queries have one of the `ORDER BY/LIMIT/DISCARD/INTO RESULT` operators, the following rules apply:
+* `ORDER BY/LIMIT/INTO RESULT` is only allowed after the last query;
+* `DISCARD` is only allowed before the first query;
+* the operators apply to the `UNION [ALL]` as a whole, instead of referring to one of the queries;
+* to apply the operator to one of the queries, enclose the query in parantheses
diff --git a/ydb/docs/en/core/yql/reference/yql-core/syntax/_includes/select/union.md b/ydb/docs/en/core/yql/reference/yql-core/syntax/_includes/select/union.md
new file mode 100644
index 0000000000..2c0c0bc634
--- /dev/null
+++ b/ydb/docs/en/core/yql/reference/yql-core/syntax/_includes/select/union.md
@@ -0,0 +1,13 @@
+## UNION {#union}
+
+Union of the results of the underlying queries, with duplicates removed.
+Behavior is identical to using `UNION ALL` followed by `SELECT DISTINCT *`.
+Refer to [UNION ALL](#union-all) for more details.
+
+**Примеры**
+
+```yql
+SELECT key FROM T1
+UNION
+SELECT key FROM T2 -- returns the set of distinct keys in the tables
+```
diff --git a/ydb/docs/en/core/yql/reference/yql-core/syntax/select.md b/ydb/docs/en/core/yql/reference/yql-core/syntax/select.md
index f414f568ca..79f2ecb0b3 100644
--- a/ydb/docs/en/core/yql/reference/yql-core/syntax/select.md
+++ b/ydb/docs/en/core/yql/reference/yql-core/syntax/select.md
@@ -30,8 +30,12 @@
{% include [x](_includes/select/column_order.md) %}
+{% include [x](_includes/select/combining_queries.md) %}
+
{% include [x](_includes/select/union_all.md) %}
+{% include [x](_includes/select/union.md) %}
+
{% include [x](_includes/select/commit.md) %}
{% if feature_bulk_tables %}
diff --git a/ydb/docs/ru/core/yql/reference/yql-core/syntax/_includes/not_yet_supported.md b/ydb/docs/ru/core/yql/reference/yql-core/syntax/_includes/not_yet_supported.md
index 86109cc29d..d8c105463d 100644
--- a/ydb/docs/ru/core/yql/reference/yql-core/syntax/_includes/not_yet_supported.md
+++ b/ydb/docs/ru/core/yql/reference/yql-core/syntax/_includes/not_yet_supported.md
@@ -4,10 +4,6 @@
Доступный альтернативный вариант — `EXISTS` синтаксически доступен, но из-за отсутствия поддержки коррелированных подзапросов не очень полезен. Также можно переписать через `JOIN`.
-## UNION {#union}
-
-Доступный альтернативный вариант — `SELECT DISTINCT` по явно перечисленным колонкам + `UNION ALL`, при необходимости с использованием подзапросов.
-
## NATURAL JOIN {#natural-join}
Доступный альтернативный вариант — явно перечислить совпадающие с обеих сторон колонки.
diff --git a/ydb/docs/ru/core/yql/reference/yql-core/syntax/_includes/select/combining_queries.md b/ydb/docs/ru/core/yql/reference/yql-core/syntax/_includes/select/combining_queries.md
new file mode 100644
index 0000000000..8ee44ba90d
--- /dev/null
+++ b/ydb/docs/ru/core/yql/reference/yql-core/syntax/_includes/select/combining_queries.md
@@ -0,0 +1,21 @@
+### Комбинация запросов {#combining-queries}
+
+Результаты нескольких SELECT (или подзапросов) могут быть объединены с помощью ключевых слов `UNION` и `UNION ALL`.
+```yql
+query1 UNION [ALL] query2 (UNION [ALL] query3 ...)
+```
+Объединение более двух запросов интерпретируется как левоассоциативная операция, то есть
+
+```yql
+query1 UNION query2 UNION ALL query3
+```
+интерпретируется как
+```yql
+(query1 UNION query2) UNION ALL query3
+```
+
+При наличии `ORDER BY/LIMIT/DISCARD/INTO RESULT` в объединяемых подзапросах применяются следующие правила:
+* `ORDER BY/LIMIT/INTO RESULT` допускается только после последнего подзапроса;
+* `DISCARD` допускается только перед первым подзапросом;
+* указанные операторы действуют на результат `UNION [ALL]`, а не на подзапрос;
+* чтобы применить оператор к подзапросу, подзапрос необходимо взять в скобки.
diff --git a/ydb/docs/ru/core/yql/reference/yql-core/syntax/_includes/select/union.md b/ydb/docs/ru/core/yql/reference/yql-core/syntax/_includes/select/union.md
new file mode 100644
index 0000000000..d3f940ef2c
--- /dev/null
+++ b/ydb/docs/ru/core/yql/reference/yql-core/syntax/_includes/select/union.md
@@ -0,0 +1,13 @@
+## UNION {#union}
+
+Объединение результатов нескольких подзапросов с удалением дубликатов.
+Поведение идентично последовательному исполнению `UNION ALL` и `SELECT DISTINCT *`.
+См. [UNION ALL](#union-all) для информации о деталях поведения.
+
+**Примеры**
+
+```yql
+SELECT key FROM T1
+UNION
+SELECT key FROM T2 -- возвращает таблицу различных ключей, лежащих хотя бы в одной из исходных таблиц
+```
diff --git a/ydb/docs/ru/core/yql/reference/yql-core/syntax/_includes/select/union_all.md b/ydb/docs/ru/core/yql/reference/yql-core/syntax/_includes/select/union_all.md
index c7f2ee31e8..1f3e45c79c 100644
--- a/ydb/docs/ru/core/yql/reference/yql-core/syntax/_includes/select/union_all.md
+++ b/ydb/docs/ru/core/yql/reference/yql-core/syntax/_includes/select/union_all.md
@@ -19,12 +19,6 @@
Порядок выходных колонок в этом режиме совпадает с порядком колонок первого входа.
-При наличии `ORDER BY/LIMIT/DISCARD/INTO RESULT` в объединяемых подзапросах применяются следующие правила:
-* `ORDER BY/LIMIT/INTO RESULT` допускается только после последнего подзапроса;
-* `DISCARD` допускается только перед первым подзапросом;
-* указанные операторы действуют на результат `UNION ALL` а на не подзапрос;
-* чтобы применить оператор к подзапросу, подзапрос необходимо взять в скобки.
-
**Примеры**
``` yql
diff --git a/ydb/docs/ru/core/yql/reference/yql-core/syntax/select.md b/ydb/docs/ru/core/yql/reference/yql-core/syntax/select.md
index 692edf672b..eba1eec6cf 100644
--- a/ydb/docs/ru/core/yql/reference/yql-core/syntax/select.md
+++ b/ydb/docs/ru/core/yql/reference/yql-core/syntax/select.md
@@ -32,8 +32,12 @@
{% include [x](_includes/select/column_order.md) %}
+{% include [x](_includes/select/combining_queries.md) %}
+
{% include [x](_includes/select/union_all.md) %}
+{% include [x](_includes/select/union.md) %}
+
{% include [x](_includes/select/commit.md) %}
{% if feature_bulk_tables %}
diff --git a/ydb/library/yql/core/common_opt/yql_co_simple1.cpp b/ydb/library/yql/core/common_opt/yql_co_simple1.cpp
index 042057c32f..df93de9c43 100644
--- a/ydb/library/yql/core/common_opt/yql_co_simple1.cpp
+++ b/ydb/library/yql/core/common_opt/yql_co_simple1.cpp
@@ -4796,6 +4796,10 @@ void RegisterCoSimpleCallables1(TCallableOptimizerMap& map) {
map["UnionAll"] = std::bind(&ExpandUnionAll<false>, _1, _2, _3);
map["UnionMerge"] = std::bind(&ExpandUnionAll<true>, _1, _2, _3);
+ map["Union"] = [](const TExprNode::TPtr& node, TExprContext& ctx, TOptimizeContext& /*optCtx*/) {
+ YQL_CLOG(DEBUG, Core) << node->Content();
+ return ctx.NewCallable(node->Pos(), "SqlAggregateAll", { ctx.NewCallable(node->Pos(), "UnionAll", node->ChildrenList()) });
+ };
map["Aggregate"] = [](const TExprNode::TPtr& node, TExprContext& ctx, TOptimizeContext& /*optCtx*/) {
TCoAggregate self(node);
@@ -6120,6 +6124,11 @@ void RegisterCoSimpleCallables1(TCallableOptimizerMap& map) {
return ExpandPositionalUnionAll(*node, columnOrders, node->ChildrenList(), ctx, optCtx);
};
+ map["UnionPositional"] = [](const TExprNode::TPtr& node, TExprContext& ctx, TOptimizeContext& /*optCtx*/) {
+ YQL_CLOG(DEBUG, Core) << node->Content();
+ return ctx.NewCallable(node->Pos(), "SqlAggregateAll", { ctx.NewCallable(node->Pos(), "UnionAllPositional", node->ChildrenList()) });
+ };
+
map["MapJoinCore"] = [](const TExprNode::TPtr& node, TExprContext& ctx, TOptimizeContext& optCtx) {
if (const auto& inputToCheck = SkipCallables(node->Head(), SkippableCallables); IsEmptyContainer(inputToCheck) || IsEmpty(inputToCheck, *optCtx.Types)) {
YQL_CLOG(DEBUG, Core) << "Empty " << node->Content();
diff --git a/ydb/library/yql/core/type_ann/type_ann_core.cpp b/ydb/library/yql/core/type_ann/type_ann_core.cpp
index ca926a82f0..1ffa1462c8 100644
--- a/ydb/library/yql/core/type_ann/type_ann_core.cpp
+++ b/ydb/library/yql/core/type_ann/type_ann_core.cpp
@@ -11710,6 +11710,7 @@ template <NKikimr::NUdf::EDataSlot DataSlot>
Functions["OrderedExtract"] = &ExtractWrapper;
Functions["UnionAll"] = &UnionAllWrapper;
Functions["UnionMerge"] = &UnionAllWrapper;
+ Functions["Union"] = &UnionAllWrapper;
Functions["ListExtend"] = &ListExtendWrapper<false>;
Functions["ListExtendStrict"] = &ListExtendWrapper<true>;
Functions["ListUnionAll"] = &ListUnionAllWrapper;
@@ -12203,6 +12204,7 @@ template <NKikimr::NUdf::EDataSlot DataSlot>
ExtFunctions["AssumeColumnOrder"] = &AssumeColumnOrderWrapper;
ExtFunctions["AssumeColumnOrderPartial"] = &AssumeColumnOrderWrapper;
ExtFunctions["UnionAllPositional"] = &UnionAllPositionalWrapper;
+ ExtFunctions["UnionPositional"] = &UnionAllPositionalWrapper;
ExtFunctions["SafeCast"] = &CastWrapper<false>;
ExtFunctions["StrictCast"] = &CastWrapper<true>;
@@ -12223,6 +12225,7 @@ template <NKikimr::NUdf::EDataSlot DataSlot>
ColumnOrderFunctions["Merge"] = ColumnOrderFunctions["Extend"] = &OrderForMergeExtend;
ColumnOrderFunctions[RightName] = &OrderFromFirst;
ColumnOrderFunctions["UnionAll"] = &OrderForUnionAll;
+ ColumnOrderFunctions["Union"] = &OrderForUnionAll;
ColumnOrderFunctions["EquiJoin"] = &OrderForEquiJoin;
ColumnOrderFunctions["CalcOverWindow"] = &OrderForCalcOverWindow;
diff --git a/ydb/library/yql/sql/v1/format/sql_format_ut.cpp b/ydb/library/yql/sql/v1/format/sql_format_ut.cpp
index 1699dbf9b5..689e73393f 100644
--- a/ydb/library/yql/sql/v1/format/sql_format_ut.cpp
+++ b/ydb/library/yql/sql/v1/format/sql_format_ut.cpp
@@ -1340,4 +1340,14 @@ FROM Input MATCH_RECOGNIZE (PATTERN (A) DEFINE A AS A);
TSetup setup;
setup.Run(cases);
}
+
+ Y_UNIT_TEST(Union) {
+ TCases cases = {
+ {"select 1 union all select 2 union select 3 union all select 4 union select 5",
+ "SELECT\n\t1\nUNION ALL\nSELECT\n\t2\nUNION\nSELECT\n\t3\nUNION ALL\nSELECT\n\t4\nUNION\nSELECT\n\t5;\n\n"},
+ };
+
+ TSetup setup;
+ setup.Run(cases);
+ }
}
diff --git a/ydb/library/yql/sql/v1/select.cpp b/ydb/library/yql/sql/v1/select.cpp
index 9f4ca93a06..c32307cd64 100644
--- a/ydb/library/yql/sql/v1/select.cpp
+++ b/ydb/library/yql/sql/v1/select.cpp
@@ -2656,11 +2656,12 @@ TSourcePtr BuildSelectCore(
having, std::move(winSpecs), legacyHoppingWindowSpec, std::move(terms), distinct, std::move(without), selectStream, settings, std::move(uniqueSets), std::move(distinctSets));
}
-class TUnionAll: public IRealSource {
+class TUnion: public IRealSource {
public:
- TUnionAll(TPosition pos, TVector<TSourcePtr>&& sources, const TWriteSettings& settings)
+ TUnion(TPosition pos, TVector<TSourcePtr>&& sources, bool quantifierAll, const TWriteSettings& settings)
: IRealSource(pos)
, Sources(std::move(sources))
+ , QuantifierAll(quantifierAll)
, Settings(settings)
{
}
@@ -2695,7 +2696,13 @@ public:
}
TNodePtr Build(TContext& ctx) override {
- auto res = ctx.PositionalUnionAll ? Y("UnionAllPositional") : Y("UnionAll");
+ TPtr res;
+ if (QuantifierAll) {
+ res = ctx.PositionalUnionAll ? Y("UnionAllPositional") : Y("UnionAll");
+ } else {
+ res = ctx.PositionalUnionAll ? Y("UnionPositional") : Y("Union");
+ }
+
for (auto& s: Sources) {
auto input = s->Build(ctx);
if (!input) {
@@ -2717,7 +2724,7 @@ public:
}
TNodePtr DoClone() const final {
- return MakeIntrusive<TUnionAll>(Pos, CloneContainer(Sources), Settings);
+ return MakeIntrusive<TUnion>(Pos, CloneContainer(Sources), QuantifierAll, Settings);
}
bool IsSelect() const override {
@@ -2734,11 +2741,17 @@ public:
private:
TVector<TSourcePtr> Sources;
+ bool QuantifierAll;
const TWriteSettings Settings;
};
-TSourcePtr BuildUnionAll(TPosition pos, TVector<TSourcePtr>&& sources, const TWriteSettings& settings) {
- return new TUnionAll(pos, std::move(sources), settings);
+TSourcePtr BuildUnion(
+ TPosition pos,
+ TVector<TSourcePtr>&& sources,
+ bool quantifierAll,
+ const TWriteSettings& settings
+) {
+ return new TUnion(pos, std::move(sources), quantifierAll, settings);
}
class TOverWindowSource: public IProxySource {
diff --git a/ydb/library/yql/sql/v1/source.h b/ydb/library/yql/sql/v1/source.h
index 3214b95e08..516c93e10a 100644
--- a/ydb/library/yql/sql/v1/source.h
+++ b/ydb/library/yql/sql/v1/source.h
@@ -234,7 +234,7 @@ namespace NSQLTranslationV1 {
TSourcePtr BuildTableSource(TPosition pos, const TTableRef& table, const TString& label = TString());
TSourcePtr BuildInnerSource(TPosition pos, TNodePtr node, const TString& service, const TDeferredAtom& cluster, const TString& label = TString());
TSourcePtr BuildRefColumnSource(TPosition pos, const TString& partExpression);
- TSourcePtr BuildUnionAll(TPosition pos, TVector<TSourcePtr>&& sources, const TWriteSettings& settings);
+ TSourcePtr BuildUnion(TPosition pos, TVector<TSourcePtr>&& sources, bool quantifierAll, const TWriteSettings& settings);
TSourcePtr BuildOverWindowSource(TPosition pos, const TString& windowName, ISource* origSource);
TNodePtr BuildOrderBy(TPosition pos, const TVector<TNodePtr>& keys, const TVector<bool>& order);
diff --git a/ydb/library/yql/sql/v1/sql_select.cpp b/ydb/library/yql/sql/v1/sql_select.cpp
index 79479da0f7..8321d24a70 100644
--- a/ydb/library/yql/sql/v1/sql_select.cpp
+++ b/ydb/library/yql/sql/v1/sql_select.cpp
@@ -1316,18 +1316,25 @@ TSqlSelect::TSelectKindResult TSqlSelect::SelectKind(const TRule_select_kind_par
template<typename TRule>
TSourcePtr TSqlSelect::Build(const TRule& node, TPosition pos, TSelectKindResult&& first) {
- TPosition unionPos = pos; // Position of first select
- TVector<TSourcePtr> sources;
- sources.emplace_back(std::move(first.Source));
+ if (node.GetBlock2().empty()) {
+ return std::move(first.Source);
+ }
+
+ auto blocks = node.GetBlock2();
+ TPosition unionPos = pos; // Position of first select
TVector<TSortSpecificationPtr> orderBy;
- TNodePtr skipTake;
- TWriteSettings settings;
- settings.Discard = first.Settings.Discard;
bool assumeOrderBy = false;
- auto blocks = node.GetBlock2();
+ TNodePtr skipTake;
+ TWriteSettings outermostSettings;
+ outermostSettings.Discard = first.Settings.Discard;
+
+ TVector<TSourcePtr> sources{ std::move(first.Source)};
+ bool currentQuantifier = false;
+
for (int i = 0; i < blocks.size(); ++i) {
auto& b = blocks[i];
+ const bool second = (i == 0);
const bool last = (i + 1 == blocks.size());
TSelectKindPlacement placement;
placement.IsLastInSelectOp = last;
@@ -1341,21 +1348,12 @@ TSourcePtr TSqlSelect::Build(const TRule& node, TPosition pos, TSelectKindResult
orderBy = next.SelectOpOrderBy;
assumeOrderBy = next.SelectOpAssumeOrderBy;
skipTake = next.SelectOpSkipTake;
- settings.Label = next.Settings.Label;
+ outermostSettings.Label = next.Settings.Label;
}
switch (b.GetRule_select_op1().Alt_case()) {
- case TRule_select_op::kAltSelectOp1: {
- const bool isUnionAll = b.GetRule_select_op1().GetAlt_select_op1().HasBlock2();
- if (!isUnionAll) {
- Token(b.GetRule_select_op1().GetAlt_select_op1().GetToken1());
- Ctx.Error() << "UNION without quantifier ALL is not supported yet. Did you mean UNION ALL?";
- return nullptr;
- } else {
- sources.emplace_back(std::move(next.Source));
- }
+ case TRule_select_op::kAltSelectOp1:
break;
- }
case TRule_select_op::kAltSelectOp2:
case TRule_select_op::kAltSelectOp3:
Ctx.Error() << "INTERSECT and EXCEPT are not implemented yet";
@@ -1363,16 +1361,22 @@ TSourcePtr TSqlSelect::Build(const TRule& node, TPosition pos, TSelectKindResult
case TRule_select_op::ALT_NOT_SET:
Y_ABORT("You should change implementation according to grammar changes");
}
- }
- if (sources.size() == 1) {
- return std::move(sources[0]);
+ const bool quantifier = b.GetRule_select_op1().GetAlt_select_op1().HasBlock2();
+
+ if (!second && quantifier != currentQuantifier) {
+ auto source = BuildUnion(pos, std::move(sources), currentQuantifier, {});
+ sources.clear();
+ sources.emplace_back(std::move(source));
+ }
+
+ sources.emplace_back(std::move(next.Source));
+ currentQuantifier = quantifier;
}
- TSourcePtr result;
- if (orderBy) {
- result = BuildUnionAll(unionPos, std::move(sources), {});
+ auto result = BuildUnion(pos, std::move(sources), currentQuantifier, outermostSettings);
+ if (orderBy) {
TVector<TNodePtr> groupByExpr;
TVector<TNodePtr> groupBy;
bool compactGroupBy = false;
@@ -1389,14 +1393,13 @@ TSourcePtr TSqlSelect::Build(const TRule& node, TPosition pos, TSelectKindResult
result = BuildSelectCore(Ctx, unionPos, std::move(result), groupByExpr, groupBy, compactGroupBy, groupBySuffix,
assumeOrderBy, orderBy, having, std::move(winSpecs), legacyHoppingWindowSpec, std::move(terms),
- distinct, std::move(without), stream, settings, {}, {});
- } else {
- result = BuildUnionAll(unionPos, std::move(sources), settings);
- }
+ distinct, std::move(without), stream, outermostSettings, {}, {});
- if (skipTake || orderBy) {
+ result = BuildSelect(unionPos, std::move(result), skipTake);
+ } else if (skipTake) {
result = BuildSelect(unionPos, std::move(result), skipTake);
}
+
return result;
}
diff --git a/ydb/library/yql/sql/v1/sql_ut.cpp b/ydb/library/yql/sql/v1/sql_ut.cpp
index a898fee6e0..6fd2b53cbb 100644
--- a/ydb/library/yql/sql/v1/sql_ut.cpp
+++ b/ydb/library/yql/sql/v1/sql_ut.cpp
@@ -1141,6 +1141,33 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) {
UNIT_ASSERT_VALUES_EQUAL(1, elementStat["UnionAll"]);
}
+ Y_UNIT_TEST(UnionTest) {
+ NYql::TAstParseResult res = SqlToYql("SELECT key FROM plato.Input UNION select subkey FROM plato.Input;");
+ UNIT_ASSERT(res.Root);
+
+ TWordCountHive elementStat = {{TString("Union"), 0}};
+ VerifyProgram(res, elementStat, {});
+ UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Union"]);
+ }
+
+ Y_UNIT_TEST(UnionAggregationTest) {
+ NYql::TAstParseResult res = SqlToYql(R"(
+ SELECT 1
+ UNION ALL
+ SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
+ UNION
+ SELECT 1 UNION SELECT 1 UNION SELECT 1 UNION SELECT 1
+ UNION ALL
+ SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1;
+ )");
+ UNIT_ASSERT(res.Root);
+
+ TWordCountHive elementStat = {{TString("Union"), 0}, {TString("UnionAll"), 0}};
+ VerifyProgram(res, elementStat, {});
+ UNIT_ASSERT_VALUES_EQUAL(2, elementStat["UnionAll"]);
+ UNIT_ASSERT_VALUES_EQUAL(3, elementStat["Union"]);
+ }
+
Y_UNIT_TEST(DeclareDecimalParameter) {
NYql::TAstParseResult res = SqlToYql("declare $value as Decimal(22,9); select $value as cnt;");
UNIT_ASSERT(res.Root);
@@ -3258,12 +3285,6 @@ Y_UNIT_TEST_SUITE(SqlToYQLErrors) {
UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:39: Error: VALUES have 2 columns, UPSERT INTO expects: 3\n");
}
- Y_UNIT_TEST(UnionNotSupported) {
- NYql::TAstParseResult res = SqlToYql("SELECT key FROM plato.Input UNION select subkey FROM plato.Input;");
- UNIT_ASSERT(!res.Root);
- UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:29: Error: UNION without quantifier ALL is not supported yet. Did you mean UNION ALL?\n");
- }
-
Y_UNIT_TEST(GroupingSetByExprWithoutAlias) {
NYql::TAstParseResult res = SqlToYql("SELECT key FROM plato.Input GROUP BY GROUPING SETS (cast(key as uint32), subkey);");
UNIT_ASSERT(!res.Root);
diff --git a/ydb/library/yql/tests/sql/dq_file/part0/canondata/result.json b/ydb/library/yql/tests/sql/dq_file/part0/canondata/result.json
index 6b25797d88..595f7f430f 100644
--- a/ydb/library/yql/tests/sql/dq_file/part0/canondata/result.json
+++ b/ydb/library/yql/tests/sql/dq_file/part0/canondata/result.json
@@ -5659,6 +5659,28 @@
"uri": "file://test.test_udf-wrong_args_fail--Results_/extracted"
}
],
+ "test.test[union-union_multiin--Analyze]": [
+ {
+ "checksum": "7c384bc79aeb667aa92c8aba518cd06e",
+ "size": 5545,
+ "uri": "https://{canondata_backend}/1130705/278b00e80d012b1440a24faff121f276542a077b/resource.tar.gz#test.test_union-union_multiin--Analyze_/plan.txt"
+ }
+ ],
+ "test.test[union-union_multiin--Debug]": [
+ {
+ "checksum": "dd65fa46bf302c6b6579895a9ab83843",
+ "size": 2344,
+ "uri": "https://{canondata_backend}/1130705/278b00e80d012b1440a24faff121f276542a077b/resource.tar.gz#test.test_union-union_multiin--Debug_/opt.yql_patched"
+ }
+ ],
+ "test.test[union-union_multiin--Plan]": [
+ {
+ "checksum": "7c384bc79aeb667aa92c8aba518cd06e",
+ "size": 5545,
+ "uri": "https://{canondata_backend}/1130705/278b00e80d012b1440a24faff121f276542a077b/resource.tar.gz#test.test_union-union_multiin--Plan_/plan.txt"
+ }
+ ],
+ "test.test[union-union_multiin--Results]": [],
"test.test[union_all-union_all_fields-default.txt-Analyze]": [
{
"checksum": "6ed4c6353fe45174ab0983a2262bafe8",
diff --git a/ydb/library/yql/tests/sql/dq_file/part4/canondata/result.json b/ydb/library/yql/tests/sql/dq_file/part4/canondata/result.json
index f9d24e4c82..c917359950 100644
--- a/ydb/library/yql/tests/sql/dq_file/part4/canondata/result.json
+++ b/ydb/library/yql/tests/sql/dq_file/part4/canondata/result.json
@@ -5493,6 +5493,28 @@
}
],
"test.test[udf-python_script--Results]": [],
+ "test.test[union-union_positional_mix-default.txt-Analyze]": [
+ {
+ "checksum": "b4dd508a329723c74293d80f0278c705",
+ "size": 505,
+ "uri": "https://{canondata_backend}/1942415/bc58f4bafc7f7c25e28d8dc76fd80da6616f0b89/resource.tar.gz#test.test_union-union_positional_mix-default.txt-Analyze_/plan.txt"
+ }
+ ],
+ "test.test[union-union_positional_mix-default.txt-Debug]": [
+ {
+ "checksum": "282ee1484f62b665592a016a31f439e0",
+ "size": 448,
+ "uri": "https://{canondata_backend}/1942415/bc58f4bafc7f7c25e28d8dc76fd80da6616f0b89/resource.tar.gz#test.test_union-union_positional_mix-default.txt-Debug_/opt.yql_patched"
+ }
+ ],
+ "test.test[union-union_positional_mix-default.txt-Plan]": [
+ {
+ "checksum": "b4dd508a329723c74293d80f0278c705",
+ "size": 505,
+ "uri": "https://{canondata_backend}/1942415/bc58f4bafc7f7c25e28d8dc76fd80da6616f0b89/resource.tar.gz#test.test_union-union_positional_mix-default.txt-Plan_/plan.txt"
+ }
+ ],
+ "test.test[union-union_positional_mix-default.txt-Results]": [],
"test.test[union_all-inner_union_all_with_limits-default.txt-Analyze]": [
{
"checksum": "b1d15038fdb984e8b1c5ca3c7f219867",
diff --git a/ydb/library/yql/tests/sql/dq_file/part6/canondata/result.json b/ydb/library/yql/tests/sql/dq_file/part6/canondata/result.json
index 26d5254602..f96e188e19 100644
--- a/ydb/library/yql/tests/sql/dq_file/part6/canondata/result.json
+++ b/ydb/library/yql/tests/sql/dq_file/part6/canondata/result.json
@@ -5210,6 +5210,28 @@
}
],
"test.test[udf-udf_result_member--Results]": [],
+ "test.test[union-union_mix-default.txt-Analyze]": [
+ {
+ "checksum": "b4dd508a329723c74293d80f0278c705",
+ "size": 505,
+ "uri": "https://{canondata_backend}/1937001/739f5ccbe8d31f87c515ca8f825e82c32f06f5a1/resource.tar.gz#test.test_union-union_mix-default.txt-Analyze_/plan.txt"
+ }
+ ],
+ "test.test[union-union_mix-default.txt-Debug]": [
+ {
+ "checksum": "a850f418449a697309b143eb2391e238",
+ "size": 432,
+ "uri": "https://{canondata_backend}/1937001/739f5ccbe8d31f87c515ca8f825e82c32f06f5a1/resource.tar.gz#test.test_union-union_mix-default.txt-Debug_/opt.yql_patched"
+ }
+ ],
+ "test.test[union-union_mix-default.txt-Plan]": [
+ {
+ "checksum": "b4dd508a329723c74293d80f0278c705",
+ "size": 505,
+ "uri": "https://{canondata_backend}/1937001/739f5ccbe8d31f87c515ca8f825e82c32f06f5a1/resource.tar.gz#test.test_union-union_mix-default.txt-Plan_/plan.txt"
+ }
+ ],
+ "test.test[union-union_mix-default.txt-Results]": [],
"test.test[union_all-union_all_incompatible-default.txt-Analyze]": [
{
"checksum": "a3b64a2cf9903b3868a2dd88a18fc46e",
diff --git a/ydb/library/yql/tests/sql/dq_file/part8/canondata/result.json b/ydb/library/yql/tests/sql/dq_file/part8/canondata/result.json
index 55ec6bc9ea..572ae715cf 100644
--- a/ydb/library/yql/tests/sql/dq_file/part8/canondata/result.json
+++ b/ydb/library/yql/tests/sql/dq_file/part8/canondata/result.json
@@ -5504,6 +5504,28 @@
}
],
"test.test[udf-udaf_short--Results]": [],
+ "test.test[union-union_column_extention-default.txt-Analyze]": [
+ {
+ "checksum": "b4dd508a329723c74293d80f0278c705",
+ "size": 505,
+ "uri": "https://{canondata_backend}/1925821/5eb8961086ccf3c859505e9d586731aacba51b41/resource.tar.gz#test.test_union-union_column_extention-default.txt-Analyze_/plan.txt"
+ }
+ ],
+ "test.test[union-union_column_extention-default.txt-Debug]": [
+ {
+ "checksum": "6c9c17b4ae2975bc048682706254a70b",
+ "size": 784,
+ "uri": "https://{canondata_backend}/1925821/5eb8961086ccf3c859505e9d586731aacba51b41/resource.tar.gz#test.test_union-union_column_extention-default.txt-Debug_/opt.yql_patched"
+ }
+ ],
+ "test.test[union-union_column_extention-default.txt-Plan]": [
+ {
+ "checksum": "b4dd508a329723c74293d80f0278c705",
+ "size": 505,
+ "uri": "https://{canondata_backend}/1925821/5eb8961086ccf3c859505e9d586731aacba51b41/resource.tar.gz#test.test_union-union_column_extention-default.txt-Plan_/plan.txt"
+ }
+ ],
+ "test.test[union-union_column_extention-default.txt-Results]": [],
"test.test[union_all-infer_3-default.txt-Analyze]": [
{
"checksum": "b4dd508a329723c74293d80f0278c705",
diff --git a/ydb/library/yql/tests/sql/dq_file/part9/canondata/result.json b/ydb/library/yql/tests/sql/dq_file/part9/canondata/result.json
index 80c967672d..93c38b2a7e 100644
--- a/ydb/library/yql/tests/sql/dq_file/part9/canondata/result.json
+++ b/ydb/library/yql/tests/sql/dq_file/part9/canondata/result.json
@@ -5176,6 +5176,50 @@
"uri": "file://test.test_udf-udf_call_with_group_and_limit--Results_/extracted"
}
],
+ "test.test[union-union_positional-default.txt-Analyze]": [
+ {
+ "checksum": "b4dd508a329723c74293d80f0278c705",
+ "size": 505,
+ "uri": "https://{canondata_backend}/1599023/94bc0e579b2dcd1141d79ae81c68cd47cf744693/resource.tar.gz#test.test_union-union_positional-default.txt-Analyze_/plan.txt"
+ }
+ ],
+ "test.test[union-union_positional-default.txt-Debug]": [
+ {
+ "checksum": "1548bc756c3867136c4633dfbae3f547",
+ "size": 427,
+ "uri": "https://{canondata_backend}/1599023/94bc0e579b2dcd1141d79ae81c68cd47cf744693/resource.tar.gz#test.test_union-union_positional-default.txt-Debug_/opt.yql_patched"
+ }
+ ],
+ "test.test[union-union_positional-default.txt-Plan]": [
+ {
+ "checksum": "b4dd508a329723c74293d80f0278c705",
+ "size": 505,
+ "uri": "https://{canondata_backend}/1599023/94bc0e579b2dcd1141d79ae81c68cd47cf744693/resource.tar.gz#test.test_union-union_positional-default.txt-Plan_/plan.txt"
+ }
+ ],
+ "test.test[union-union_positional-default.txt-Results]": [],
+ "test.test[union-union_trivial-default.txt-Analyze]": [
+ {
+ "checksum": "a3d6711e62ffdd325432477d20d241f9",
+ "size": 5262,
+ "uri": "https://{canondata_backend}/1599023/94bc0e579b2dcd1141d79ae81c68cd47cf744693/resource.tar.gz#test.test_union-union_trivial-default.txt-Analyze_/plan.txt"
+ }
+ ],
+ "test.test[union-union_trivial-default.txt-Debug]": [
+ {
+ "checksum": "fa6a7911ad20d797ce4de0c742a30aec",
+ "size": 2030,
+ "uri": "https://{canondata_backend}/1599023/94bc0e579b2dcd1141d79ae81c68cd47cf744693/resource.tar.gz#test.test_union-union_trivial-default.txt-Debug_/opt.yql_patched"
+ }
+ ],
+ "test.test[union-union_trivial-default.txt-Plan]": [
+ {
+ "checksum": "a3d6711e62ffdd325432477d20d241f9",
+ "size": 5262,
+ "uri": "https://{canondata_backend}/1599023/94bc0e579b2dcd1141d79ae81c68cd47cf744693/resource.tar.gz#test.test_union-union_trivial-default.txt-Plan_/plan.txt"
+ }
+ ],
+ "test.test[union-union_trivial-default.txt-Results]": [],
"test.test[union_all-mix_map_and_project--Analyze]": [
{
"checksum": "e8a312a4f10dd45437fcbba8a2b35fb8",
diff --git a/ydb/library/yql/tests/sql/sql2yql/canondata/result.json b/ydb/library/yql/tests/sql/sql2yql/canondata/result.json
index 24c3b32052..4669a50b80 100644
--- a/ydb/library/yql/tests/sql/sql2yql/canondata/result.json
+++ b/ydb/library/yql/tests/sql/sql2yql/canondata/result.json
@@ -10818,7 +10818,7 @@
{
"checksum": "14fe96718c591dd1af1ed6c60f472e29",
"size": 65932,
- "uri": "https://storage.yandex-team.ru/get-devtools/1942100/07ef396fd78c6142ee282f43bd4950f9cadbd86b/resource.tar.gz#test_sql2yql.test_pg-palloc_big_string_/sql.yql"
+ "uri": "https://{canondata_backend}/1942100/07ef396fd78c6142ee282f43bd4950f9cadbd86b/resource.tar.gz#test_sql2yql.test_pg-palloc_big_string_/sql.yql"
}
],
"test_sql2yql.test[pg-parametrized]": [
@@ -15665,6 +15665,48 @@
"uri": "https://{canondata_backend}/1936997/00f46808be87e2ae2d4ac3ac45675b659c5ace45/resource.tar.gz#test_sql2yql.test_udf-wrong_args_fail_/sql.yql"
}
],
+ "test_sql2yql.test[union-union_column_extention]": [
+ {
+ "checksum": "2d2c0fb07abc513cbe802384837991ec",
+ "size": 2934,
+ "uri": "https://{canondata_backend}/1903280/f0c0265b216a7ef70b599283ea3aca04b5590097/resource.tar.gz#test_sql2yql.test_union-union_column_extention_/sql.yql"
+ }
+ ],
+ "test_sql2yql.test[union-union_mix]": [
+ {
+ "checksum": "94c4beb57209551e470052afe191e323",
+ "size": 4082,
+ "uri": "https://{canondata_backend}/1903280/f0c0265b216a7ef70b599283ea3aca04b5590097/resource.tar.gz#test_sql2yql.test_union-union_mix_/sql.yql"
+ }
+ ],
+ "test_sql2yql.test[union-union_multiin]": [
+ {
+ "checksum": "104799b230c982f699a0822cd06c8dd7",
+ "size": 2458,
+ "uri": "https://{canondata_backend}/1903280/f0c0265b216a7ef70b599283ea3aca04b5590097/resource.tar.gz#test_sql2yql.test_union-union_multiin_/sql.yql"
+ }
+ ],
+ "test_sql2yql.test[union-union_positional]": [
+ {
+ "checksum": "a9010a143a43f2ffe5f7e70c376bb348",
+ "size": 1741,
+ "uri": "https://{canondata_backend}/1903280/f0c0265b216a7ef70b599283ea3aca04b5590097/resource.tar.gz#test_sql2yql.test_union-union_positional_/sql.yql"
+ }
+ ],
+ "test_sql2yql.test[union-union_positional_mix]": [
+ {
+ "checksum": "7483ce195c2a3f550bcb4374f7e94502",
+ "size": 2317,
+ "uri": "https://{canondata_backend}/1903280/f0c0265b216a7ef70b599283ea3aca04b5590097/resource.tar.gz#test_sql2yql.test_union-union_positional_mix_/sql.yql"
+ }
+ ],
+ "test_sql2yql.test[union-union_trivial]": [
+ {
+ "checksum": "5c636823089fc3a2acf7328b447297be",
+ "size": 2344,
+ "uri": "https://{canondata_backend}/1903280/f0c0265b216a7ef70b599283ea3aca04b5590097/resource.tar.gz#test_sql2yql.test_union-union_trivial_/sql.yql"
+ }
+ ],
"test_sql2yql.test[union_all-infer_3]": [
{
"checksum": "6d877ca2d26929e9f1ab6b66ed5d8abe",
@@ -30337,6 +30379,48 @@
"uri": "https://{canondata_backend}/1599023/4bd7e6892a9762eec433e60bda88f20cddadc74c/resource.tar.gz#test_sql_format.test_udf-wrong_args_fail_/formatted.sql"
}
],
+ "test_sql_format.test[union-union_column_extention]": [
+ {
+ "checksum": "b370b2b20fa5df6498cfc4a40be821b8",
+ "size": 146,
+ "uri": "https://{canondata_backend}/1903280/f0c0265b216a7ef70b599283ea3aca04b5590097/resource.tar.gz#test_sql_format.test_union-union_column_extention_/formatted.sql"
+ }
+ ],
+ "test_sql_format.test[union-union_mix]": [
+ {
+ "checksum": "7c5c6d49fec0e74f3094cdcf99e664a6",
+ "size": 172,
+ "uri": "https://{canondata_backend}/1903280/f0c0265b216a7ef70b599283ea3aca04b5590097/resource.tar.gz#test_sql_format.test_union-union_mix_/formatted.sql"
+ }
+ ],
+ "test_sql_format.test[union-union_multiin]": [
+ {
+ "checksum": "365c961e02855d888647856c9560d459",
+ "size": 109,
+ "uri": "https://{canondata_backend}/1903280/f0c0265b216a7ef70b599283ea3aca04b5590097/resource.tar.gz#test_sql_format.test_union-union_multiin_/formatted.sql"
+ }
+ ],
+ "test_sql_format.test[union-union_positional]": [
+ {
+ "checksum": "ce3fef08d8e534fdd082a0deb2e01a71",
+ "size": 95,
+ "uri": "https://{canondata_backend}/1903280/f0c0265b216a7ef70b599283ea3aca04b5590097/resource.tar.gz#test_sql_format.test_union-union_positional_/formatted.sql"
+ }
+ ],
+ "test_sql_format.test[union-union_positional_mix]": [
+ {
+ "checksum": "331bfcc32930ed88badb3a7344636b2e",
+ "size": 135,
+ "uri": "https://{canondata_backend}/1903280/f0c0265b216a7ef70b599283ea3aca04b5590097/resource.tar.gz#test_sql_format.test_union-union_positional_mix_/formatted.sql"
+ }
+ ],
+ "test_sql_format.test[union-union_trivial]": [
+ {
+ "checksum": "a28385c703bb2734082b2d8e6566a8fe",
+ "size": 85,
+ "uri": "https://{canondata_backend}/1903280/f0c0265b216a7ef70b599283ea3aca04b5590097/resource.tar.gz#test_sql_format.test_union-union_trivial_/formatted.sql"
+ }
+ ],
"test_sql_format.test[union_all-infer_3]": [
{
"checksum": "9b5988c547a9ea915f1ddc08bcc7180a",
diff --git a/ydb/library/yql/tests/sql/suites/union/default.cfg b/ydb/library/yql/tests/sql/suites/union/default.cfg
new file mode 100644
index 0000000000..58878f8945
--- /dev/null
+++ b/ydb/library/yql/tests/sql/suites/union/default.cfg
@@ -0,0 +1 @@
+in Input input.txt
diff --git a/ydb/library/yql/tests/sql/suites/union/input.txt b/ydb/library/yql/tests/sql/suites/union/input.txt
new file mode 100644
index 0000000000..65949ea745
--- /dev/null
+++ b/ydb/library/yql/tests/sql/suites/union/input.txt
@@ -0,0 +1,4 @@
+{"key"="075";"subkey"="1";"value"="abc"};
+{"key"="800";"subkey"="2";"value"="ddd"};
+{"key"="020";"subkey"="3";"value"="q"};
+{"key"="150";"subkey"="4";"value"="qzz"};
diff --git a/ydb/library/yql/tests/sql/suites/union/input2.txt b/ydb/library/yql/tests/sql/suites/union/input2.txt
new file mode 100644
index 0000000000..252cb6a46d
--- /dev/null
+++ b/ydb/library/yql/tests/sql/suites/union/input2.txt
@@ -0,0 +1,4 @@
+{"key"="075";"subkey"="1";"value"="abc"};
+{"key"="800";"subkey"="2";"value"="ddd"};
+{"key"="020";"subkey"="3";"value"="www"};
+{"key"="150";"subkey"="4";"value"="www"};
diff --git a/ydb/library/yql/tests/sql/suites/union/union_column_extention.sql b/ydb/library/yql/tests/sql/suites/union/union_column_extention.sql
new file mode 100644
index 0000000000..592b6ba780
--- /dev/null
+++ b/ydb/library/yql/tests/sql/suites/union/union_column_extention.sql
@@ -0,0 +1,16 @@
+SELECT
+ 1 as x
+UNION
+SELECT
+ 'a' as y
+UNION
+SELECT
+ 1 as x,
+ 'a' as y
+UNION
+SELECT
+ 1 as x
+UNION
+SELECT
+ 1 as x,
+ 'b' as y;
diff --git a/ydb/library/yql/tests/sql/suites/union/union_mix.sql b/ydb/library/yql/tests/sql/suites/union/union_mix.sql
new file mode 100644
index 0000000000..74e2f9680c
--- /dev/null
+++ b/ydb/library/yql/tests/sql/suites/union/union_mix.sql
@@ -0,0 +1,4 @@
+SELECT 1
+UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 1 UNION ALL SELECT 2
+UNION SELECT 1
+UNION ALL SELECT 1 UNION ALL SELECT 2;
diff --git a/ydb/library/yql/tests/sql/suites/union/union_multiin.cfg b/ydb/library/yql/tests/sql/suites/union/union_multiin.cfg
new file mode 100644
index 0000000000..311e41d04b
--- /dev/null
+++ b/ydb/library/yql/tests/sql/suites/union/union_multiin.cfg
@@ -0,0 +1,2 @@
+in Input input.txt
+in Input2 input2.txt \ No newline at end of file
diff --git a/ydb/library/yql/tests/sql/suites/union/union_multiin.sql b/ydb/library/yql/tests/sql/suites/union/union_multiin.sql
new file mode 100644
index 0000000000..b13293562a
--- /dev/null
+++ b/ydb/library/yql/tests/sql/suites/union/union_multiin.sql
@@ -0,0 +1,4 @@
+SELECT * FROM plato.Input
+UNION
+SELECT * FROM plato.Input2
+ORDER BY key, subkey, value;
diff --git a/ydb/library/yql/tests/sql/suites/union/union_positional.sql b/ydb/library/yql/tests/sql/suites/union/union_positional.sql
new file mode 100644
index 0000000000..3f3a15c1a2
--- /dev/null
+++ b/ydb/library/yql/tests/sql/suites/union/union_positional.sql
@@ -0,0 +1,9 @@
+PRAGMA PositionalUnionAll;
+
+SELECT
+ 1 as y,
+ 2 as x
+UNION
+SELECT
+ 1 as x,
+ 2 as y; \ No newline at end of file
diff --git a/ydb/library/yql/tests/sql/suites/union/union_positional_mix.sql b/ydb/library/yql/tests/sql/suites/union/union_positional_mix.sql
new file mode 100644
index 0000000000..52302030f4
--- /dev/null
+++ b/ydb/library/yql/tests/sql/suites/union/union_positional_mix.sql
@@ -0,0 +1,10 @@
+PRAGMA PositionalUnionAll;
+
+SELECT
+ 1 as y, 2 as x
+UNION
+SELECT
+ 1 as x, 2 as y
+UNION ALL
+SELECT
+ 1 as y, 2 as x; \ No newline at end of file
diff --git a/ydb/library/yql/tests/sql/suites/union/union_trivial.sql b/ydb/library/yql/tests/sql/suites/union/union_trivial.sql
new file mode 100644
index 0000000000..e4112d94ce
--- /dev/null
+++ b/ydb/library/yql/tests/sql/suites/union/union_trivial.sql
@@ -0,0 +1,4 @@
+SELECT * FROM plato.Input
+UNION
+SELECT * FROM plato.Input
+ORDER BY key;
diff --git a/ydb/library/yql/tests/sql/yt_native_file/part0/canondata/result.json b/ydb/library/yql/tests/sql/yt_native_file/part0/canondata/result.json
index 3b3fee54d3..0ba5172cdb 100644
--- a/ydb/library/yql/tests/sql/yt_native_file/part0/canondata/result.json
+++ b/ydb/library/yql/tests/sql/yt_native_file/part0/canondata/result.json
@@ -5122,6 +5122,27 @@
"uri": "file://test.test_udf-wrong_args_fail--Results_/extracted"
}
],
+ "test.test[union-union_multiin--Debug]": [
+ {
+ "checksum": "30e4adcead5240007aa12e272e70b2ec",
+ "size": 2881,
+ "uri": "https://{canondata_backend}/1936273/ce5250cf0582022a95719de2918070497e9a951b/resource.tar.gz#test.test_union-union_multiin--Debug_/opt.yql"
+ }
+ ],
+ "test.test[union-union_multiin--Plan]": [
+ {
+ "checksum": "742f5a64f5191d662380ced1e9a73eca",
+ "size": 7514,
+ "uri": "https://{canondata_backend}/1936273/ce5250cf0582022a95719de2918070497e9a951b/resource.tar.gz#test.test_union-union_multiin--Plan_/plan.txt"
+ }
+ ],
+ "test.test[union-union_multiin--Results]": [
+ {
+ "checksum": "cad773abc2060185d7a6403a5a655c45",
+ "size": 1924,
+ "uri": "https://{canondata_backend}/1936273/ce5250cf0582022a95719de2918070497e9a951b/resource.tar.gz#test.test_union-union_multiin--Results_/results.txt"
+ }
+ ],
"test.test[union_all-union_all_fields-default.txt-Debug]": [
{
"checksum": "780d675c5bbdd951be862dfcaa0be323",
diff --git a/ydb/library/yql/tests/sql/yt_native_file/part4/canondata/result.json b/ydb/library/yql/tests/sql/yt_native_file/part4/canondata/result.json
index 688a99db8e..78255b77b4 100644
--- a/ydb/library/yql/tests/sql/yt_native_file/part4/canondata/result.json
+++ b/ydb/library/yql/tests/sql/yt_native_file/part4/canondata/result.json
@@ -4823,6 +4823,27 @@
"uri": "https://{canondata_backend}/1031349/eb01bd7ff66ea4e3791b69ec15b5a2ac35547ace/resource.tar.gz#test.test_udf-python_script--Results_/results.txt"
}
],
+ "test.test[union-union_positional_mix-default.txt-Debug]": [
+ {
+ "checksum": "6a9a1dee45657e19bc230733da6db58c",
+ "size": 388,
+ "uri": "https://{canondata_backend}/1942415/29ae5077aa130083a199696ee0106585a4af87cf/resource.tar.gz#test.test_union-union_positional_mix-default.txt-Debug_/opt.yql"
+ }
+ ],
+ "test.test[union-union_positional_mix-default.txt-Plan]": [
+ {
+ "checksum": "b4dd508a329723c74293d80f0278c705",
+ "size": 505,
+ "uri": "https://{canondata_backend}/1942415/29ae5077aa130083a199696ee0106585a4af87cf/resource.tar.gz#test.test_union-union_positional_mix-default.txt-Plan_/plan.txt"
+ }
+ ],
+ "test.test[union-union_positional_mix-default.txt-Results]": [
+ {
+ "checksum": "9ff395a6f6ca64aad01d9c666dc2cf41",
+ "size": 1048,
+ "uri": "https://{canondata_backend}/1942415/29ae5077aa130083a199696ee0106585a4af87cf/resource.tar.gz#test.test_union-union_positional_mix-default.txt-Results_/results.txt"
+ }
+ ],
"test.test[union_all-inner_union_all_with_limits-default.txt-Debug]": [
{
"checksum": "abebd3740b5aedc2c401d53247585042",
diff --git a/ydb/library/yql/tests/sql/yt_native_file/part6/canondata/result.json b/ydb/library/yql/tests/sql/yt_native_file/part6/canondata/result.json
index ef43665250..32d4c0e41c 100644
--- a/ydb/library/yql/tests/sql/yt_native_file/part6/canondata/result.json
+++ b/ydb/library/yql/tests/sql/yt_native_file/part6/canondata/result.json
@@ -4469,6 +4469,27 @@
"uri": "https://{canondata_backend}/1936997/a879c594903fb53f2cbc586abd0c0e9fac5dd32a/resource.tar.gz#test.test_udf-udf_result_member--Results_/results.txt"
}
],
+ "test.test[union-union_mix-default.txt-Debug]": [
+ {
+ "checksum": "42b203ba0eeda696fc7effe391946b67",
+ "size": 364,
+ "uri": "https://{canondata_backend}/1599023/4ad9f2bbde6e600e313dfce3ada96dde0aa92f99/resource.tar.gz#test.test_union-union_mix-default.txt-Debug_/opt.yql"
+ }
+ ],
+ "test.test[union-union_mix-default.txt-Plan]": [
+ {
+ "checksum": "b4dd508a329723c74293d80f0278c705",
+ "size": 505,
+ "uri": "https://{canondata_backend}/1599023/4ad9f2bbde6e600e313dfce3ada96dde0aa92f99/resource.tar.gz#test.test_union-union_mix-default.txt-Plan_/plan.txt"
+ }
+ ],
+ "test.test[union-union_mix-default.txt-Results]": [
+ {
+ "checksum": "562cc2d63199bab0d3310c728aeaefb5",
+ "size": 884,
+ "uri": "https://{canondata_backend}/1599023/4ad9f2bbde6e600e313dfce3ada96dde0aa92f99/resource.tar.gz#test.test_union-union_mix-default.txt-Results_/results.txt"
+ }
+ ],
"test.test[union_all-union_all_incompatible-default.txt-Debug]": [
{
"checksum": "ec8f15ddb7b66a35eeadd8ba102d21dc",
diff --git a/ydb/library/yql/tests/sql/yt_native_file/part8/canondata/result.json b/ydb/library/yql/tests/sql/yt_native_file/part8/canondata/result.json
index cdc0424142..3ee2c4d70a 100644
--- a/ydb/library/yql/tests/sql/yt_native_file/part8/canondata/result.json
+++ b/ydb/library/yql/tests/sql/yt_native_file/part8/canondata/result.json
@@ -4866,6 +4866,27 @@
"uri": "https://{canondata_backend}/1900335/4871e48d29e4933514d3ed0c9c5d19de571eda1f/resource.tar.gz#test.test_udf-udaf_short--Results_/results.txt"
}
],
+ "test.test[union-union_column_extention-default.txt-Debug]": [
+ {
+ "checksum": "45125e0670f467720d9be64d9709a1d5",
+ "size": 714,
+ "uri": "https://{canondata_backend}/1942415/7e0189bd894ab6e708de5b9ca24439958027b712/resource.tar.gz#test.test_union-union_column_extention-default.txt-Debug_/opt.yql"
+ }
+ ],
+ "test.test[union-union_column_extention-default.txt-Plan]": [
+ {
+ "checksum": "b4dd508a329723c74293d80f0278c705",
+ "size": 505,
+ "uri": "https://{canondata_backend}/1942415/7e0189bd894ab6e708de5b9ca24439958027b712/resource.tar.gz#test.test_union-union_column_extention-default.txt-Plan_/plan.txt"
+ }
+ ],
+ "test.test[union-union_column_extention-default.txt-Results]": [
+ {
+ "checksum": "84c34350222c426602bbb6f5d2eaf86f",
+ "size": 1857,
+ "uri": "https://{canondata_backend}/1942415/7e0189bd894ab6e708de5b9ca24439958027b712/resource.tar.gz#test.test_union-union_column_extention-default.txt-Results_/results.txt"
+ }
+ ],
"test.test[union_all-infer_3-default.txt-Debug]": [
{
"checksum": "abf4ea22528ff54b64a94af8045294d8",
diff --git a/ydb/library/yql/tests/sql/yt_native_file/part9/canondata/result.json b/ydb/library/yql/tests/sql/yt_native_file/part9/canondata/result.json
index fc67bbc5ac..426d5a9bc2 100644
--- a/ydb/library/yql/tests/sql/yt_native_file/part9/canondata/result.json
+++ b/ydb/library/yql/tests/sql/yt_native_file/part9/canondata/result.json
@@ -4788,6 +4788,48 @@
"uri": "file://test.test_udf-udf_call_with_group_and_limit--Results_/extracted"
}
],
+ "test.test[union-union_positional-default.txt-Debug]": [
+ {
+ "checksum": "ea8e1f91fdd38c45f7ae5a6804fdf7c6",
+ "size": 367,
+ "uri": "https://{canondata_backend}/1937001/5dfe97b7ce28ffb8f959a547a54582d134fcde23/resource.tar.gz#test.test_union-union_positional-default.txt-Debug_/opt.yql"
+ }
+ ],
+ "test.test[union-union_positional-default.txt-Plan]": [
+ {
+ "checksum": "b4dd508a329723c74293d80f0278c705",
+ "size": 505,
+ "uri": "https://{canondata_backend}/1937001/5dfe97b7ce28ffb8f959a547a54582d134fcde23/resource.tar.gz#test.test_union-union_positional-default.txt-Plan_/plan.txt"
+ }
+ ],
+ "test.test[union-union_positional-default.txt-Results]": [
+ {
+ "checksum": "755b9c60568eea73d03c785842c301d5",
+ "size": 946,
+ "uri": "https://{canondata_backend}/1937001/5dfe97b7ce28ffb8f959a547a54582d134fcde23/resource.tar.gz#test.test_union-union_positional-default.txt-Results_/results.txt"
+ }
+ ],
+ "test.test[union-union_trivial-default.txt-Debug]": [
+ {
+ "checksum": "1f733c464cf0f8e7bf495ce1fcd17d70",
+ "size": 2584,
+ "uri": "https://{canondata_backend}/1937001/5dfe97b7ce28ffb8f959a547a54582d134fcde23/resource.tar.gz#test.test_union-union_trivial-default.txt-Debug_/opt.yql"
+ }
+ ],
+ "test.test[union-union_trivial-default.txt-Plan]": [
+ {
+ "checksum": "1a82dfc02d0f56fc44cc72879fe511fa",
+ "size": 6197,
+ "uri": "https://{canondata_backend}/1937001/5dfe97b7ce28ffb8f959a547a54582d134fcde23/resource.tar.gz#test.test_union-union_trivial-default.txt-Plan_/plan.txt"
+ }
+ ],
+ "test.test[union-union_trivial-default.txt-Results]": [
+ {
+ "checksum": "8f6b9bc71c918891f4dce07adf6ff408",
+ "size": 1654,
+ "uri": "https://{canondata_backend}/1937001/5dfe97b7ce28ffb8f959a547a54582d134fcde23/resource.tar.gz#test.test_union-union_trivial-default.txt-Results_/results.txt"
+ }
+ ],
"test.test[union_all-mix_map_and_project--Debug]": [
{
"checksum": "b018e83210bb4f0be0496d4f3f90863d",