diff options
author | vvvv <vvvv@yandex-team.com> | 2025-02-21 21:51:34 +0300 |
---|---|---|
committer | vvvv <vvvv@yandex-team.com> | 2025-02-21 22:33:18 +0300 |
commit | a3da80a1d278964b44086f8b500ed09bad0f165f (patch) | |
tree | 368b6985119a89ba99279100dbb8adf7f4bda951 /yql | |
parent | 005b8a9fd31e325164fdaad9ccde51222d9dc1c7 (diff) | |
download | ydb-a3da80a1d278964b44086f8b500ed09bad0f165f.tar.gz |
YQL-19129 soft WITHOUT
commit_hash:563aebc32ae87bc18e5e3e38babc034e5e89e2c1
Diffstat (limited to 'yql')
-rw-r--r-- | yql/essentials/docs/en/syntax/select/without.md | 3 | ||||
-rw-r--r-- | yql/essentials/docs/ru/syntax/select/without.md | 3 | ||||
-rw-r--r-- | yql/essentials/sql/v1/SQLv1.g.in | 2 | ||||
-rw-r--r-- | yql/essentials/sql/v1/SQLv1Antlr4.g.in | 2 | ||||
-rw-r--r-- | yql/essentials/sql/v1/format/sql_format_ut.h | 2 | ||||
-rw-r--r-- | yql/essentials/sql/v1/select.cpp | 17 | ||||
-rw-r--r-- | yql/essentials/sql/v1/source.h | 1 | ||||
-rw-r--r-- | yql/essentials/sql/v1/sql_select.cpp | 9 | ||||
-rw-r--r-- | yql/essentials/tests/sql/minirun/part0/canondata/result.json | 14 | ||||
-rw-r--r-- | yql/essentials/tests/sql/sql2yql/canondata/result.json | 12 | ||||
-rw-r--r-- | yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_select-without_if_exists_/formatted.sql | 19 | ||||
-rw-r--r-- | yql/essentials/tests/sql/suites/select/without_if_exists.sql | 13 |
12 files changed, 84 insertions, 13 deletions
diff --git a/yql/essentials/docs/en/syntax/select/without.md b/yql/essentials/docs/en/syntax/select/without.md index 7f85fab3bc..00a7e519bf 100644 --- a/yql/essentials/docs/en/syntax/select/without.md +++ b/yql/essentials/docs/en/syntax/select/without.md @@ -1,11 +1,12 @@ # WITHOUT -Excluding columns from the result of `SELECT *`. +Excluding columns from the result of `SELECT *`. The `IF EXISTS` modifier does not throw an error for missing columns. ## Examples ```yql SELECT * WITHOUT foo, bar FROM my_table; +SELECT * WITHOUT IF EXISTS foo, bar FROM my_table; ``` ```yql diff --git a/yql/essentials/docs/ru/syntax/select/without.md b/yql/essentials/docs/ru/syntax/select/without.md index 1f0f47146f..9a9b3a36c4 100644 --- a/yql/essentials/docs/ru/syntax/select/without.md +++ b/yql/essentials/docs/ru/syntax/select/without.md @@ -1,11 +1,12 @@ # WITHOUT -Исключение столбцов из результата запроса `SELECT *`. +Исключение столбцов из результата запроса `SELECT *`. С модификатором `IF EXISTS` не выдается ошибки для отсуствующих столбцов. ## Примеры ```yql SELECT * WITHOUT foo, bar FROM my_table; +SELECT * WITHOUT IF EXISTS foo, bar FROM my_table; ``` ```yql diff --git a/yql/essentials/sql/v1/SQLv1.g.in b/yql/essentials/sql/v1/SQLv1.g.in index 0168dbab95..1d7dca5185 100644 --- a/yql/essentials/sql/v1/SQLv1.g.in +++ b/yql/essentials/sql/v1/SQLv1.g.in @@ -397,7 +397,7 @@ reduce_core: opt_set_quantifier: (ALL | DISTINCT)?; select_core: - (FROM join_source)? SELECT STREAM? opt_set_quantifier result_column (COMMA result_column)* COMMA? (WITHOUT without_column_list)? (FROM join_source)? (WHERE expr)? + (FROM join_source)? SELECT STREAM? opt_set_quantifier result_column (COMMA result_column)* COMMA? (WITHOUT (IF EXISTS)? without_column_list)? (FROM join_source)? (WHERE expr)? group_by_clause? (HAVING expr)? window_clause? ext_order_by_clause? ; diff --git a/yql/essentials/sql/v1/SQLv1Antlr4.g.in b/yql/essentials/sql/v1/SQLv1Antlr4.g.in index 0edf273094..8aff2bb89a 100644 --- a/yql/essentials/sql/v1/SQLv1Antlr4.g.in +++ b/yql/essentials/sql/v1/SQLv1Antlr4.g.in @@ -396,7 +396,7 @@ reduce_core: opt_set_quantifier: (ALL | DISTINCT)?; select_core: - (FROM join_source)? SELECT STREAM? opt_set_quantifier result_column (COMMA result_column)* COMMA? (WITHOUT without_column_list)? (FROM join_source)? (WHERE expr)? + (FROM join_source)? SELECT STREAM? opt_set_quantifier result_column (COMMA result_column)* COMMA? (WITHOUT (IF EXISTS)? without_column_list)? (FROM join_source)? (WHERE expr)? group_by_clause? (HAVING expr)? window_clause? ext_order_by_clause? ; diff --git a/yql/essentials/sql/v1/format/sql_format_ut.h b/yql/essentials/sql/v1/format/sql_format_ut.h index d92393008f..2747ce2871 100644 --- a/yql/essentials/sql/v1/format/sql_format_ut.h +++ b/yql/essentials/sql/v1/format/sql_format_ut.h @@ -858,6 +858,8 @@ Y_UNIT_TEST(Select) { "SELECT\n\t*\nWITHOUT\n\ta,\n\tb\n;\n"}, {"select * without a,", "SELECT\n\t*\nWITHOUT\n\ta,\n;\n"}, + {"select * without if exists a", + "SELECT\n\t*\nWITHOUT IF EXISTS\n\ta\n;\n"}, {"select 1 from user", "SELECT\n\t1\nFROM\n\tuser\n;\n"}, {"select 1 from plato.user", diff --git a/yql/essentials/sql/v1/select.cpp b/yql/essentials/sql/v1/select.cpp index f44e328ba2..98029daa51 100644 --- a/yql/essentials/sql/v1/select.cpp +++ b/yql/essentials/sql/v1/select.cpp @@ -1489,6 +1489,7 @@ public: const TVector<TNodePtr>& terms, bool distinct, const TVector<TNodePtr>& without, + bool forceWithout, bool selectStream, const TWriteSettings& settings, TColumnsSets&& uniqueSets, @@ -1506,6 +1507,7 @@ public: , WinSpecs(winSpecs) , Terms(terms) , Without(without) + , ForceWithout(forceWithout) , Distinct(distinct) , LegacyHoppingWindowSpec(legacyHoppingWindowSpec) , SelectStream(selectStream) @@ -1924,7 +1926,7 @@ public: if (Source && Source->GetJoin()) { name = DotJoin(*without->GetSourceName(), name); } - terms = L(terms, Y("let", "row", Y("RemoveMember", "row", Q(name)))); + terms = L(terms, Y("let", "row", Y(ForceWithout ? "ForceRemoveMember" : "RemoveMember", "row", Q(name)))); } } @@ -1941,7 +1943,7 @@ public: return new TSelectCore(Pos, Source->CloneSource(), CloneContainer(GroupByExpr), CloneContainer(GroupBy), CompactGroupBy, GroupBySuffix, AssumeSorted, CloneContainer(OrderBy), SafeClone(Having), CloneContainer(WinSpecs), SafeClone(LegacyHoppingWindowSpec), - CloneContainer(Terms), Distinct, Without, SelectStream, Settings, TColumnsSets(UniqueSets), TColumnsSets(DistinctSets)); + CloneContainer(Terms), Distinct, Without, ForceWithout, SelectStream, Settings, TColumnsSets(UniqueSets), TColumnsSets(DistinctSets)); } private: @@ -2301,6 +2303,7 @@ private: TNodePtr CompositeTerms; TVector<TNodePtr> Terms; TVector<TNodePtr> Without; + const bool ForceWithout; const bool Distinct; bool OrderByInit = false; TLegacyHoppingWindowSpecPtr LegacyHoppingWindowSpec; @@ -2715,6 +2718,7 @@ TSourcePtr DoBuildSelectCore( TVector<TNodePtr>&& terms, bool distinct, TVector<TNodePtr>&& without, + bool forceWithout, bool selectStream, const TWriteSettings& settings, TColumnsSets&& uniqueSets, @@ -2722,7 +2726,7 @@ TSourcePtr DoBuildSelectCore( ) { if (groupBy.empty() || !groupBy.front()->ContentListPtr()) { return new TSelectCore(pos, std::move(source), groupByExpr, groupBy, compactGroupBy, groupBySuffix, assumeSorted, - orderBy, having, winSpecs, legacyHoppingWindowSpec, terms, distinct, without, selectStream, settings, std::move(uniqueSets), std::move(distinctSets)); + orderBy, having, winSpecs, legacyHoppingWindowSpec, terms, distinct, without, forceWithout, selectStream, settings, std::move(uniqueSets), std::move(distinctSets)); } if (groupBy.size() == 1) { /// actualy no big idea to use grouping function in this case (result allways 0) @@ -2730,7 +2734,7 @@ TSourcePtr DoBuildSelectCore( source = new TNestedProxySource(pos, *contentPtr, source); return DoBuildSelectCore(ctx, pos, originalSource, source, groupByExpr, *contentPtr, compactGroupBy, groupBySuffix, assumeSorted, orderBy, having, std::move(winSpecs), - legacyHoppingWindowSpec, std::move(terms), distinct, std::move(without), selectStream, settings, std::move(uniqueSets), std::move(distinctSets)); + legacyHoppingWindowSpec, std::move(terms), distinct, std::move(without), forceWithout, selectStream, settings, std::move(uniqueSets), std::move(distinctSets)); } /// \todo some smart merge logic, generalize common part of grouping (expr, flatten, etc)? TIntrusivePtr<TCompositeSelect> compositeSelect = new TCompositeSelect(pos, std::move(source), originalSource->CloneSource(), settings); @@ -2757,7 +2761,7 @@ TSourcePtr DoBuildSelectCore( totalGroups += contentPtr->size(); TSelectCore* selectCore = new TSelectCore(pos, std::move(proxySource), CloneContainer(groupByExpr), CloneContainer(*contentPtr), compactGroupBy, groupBySuffix, assumeSorted, orderBy, SafeClone(having), CloneContainer(winSpecs), - legacyHoppingWindowSpec, terms, distinct, without, selectStream, settings, TColumnsSets(uniqueSets), TColumnsSets(distinctSets)); + legacyHoppingWindowSpec, terms, distinct, without, forceWithout, selectStream, settings, TColumnsSets(uniqueSets), TColumnsSets(distinctSets)); subselects.emplace_back(selectCore); } if (totalGroups > ctx.PragmaGroupByLimit) { @@ -2786,6 +2790,7 @@ TSourcePtr BuildSelectCore( TVector<TNodePtr>&& terms, bool distinct, TVector<TNodePtr>&& without, + bool forceWithout, bool selectStream, const TWriteSettings& settings, TColumnsSets&& uniqueSets, @@ -2793,7 +2798,7 @@ TSourcePtr BuildSelectCore( ) { return DoBuildSelectCore(ctx, pos, source, source, groupByExpr, groupBy, compactGroupBy, groupBySuffix, assumeSorted, orderBy, - having, std::move(winSpecs), legacyHoppingWindowSpec, std::move(terms), distinct, std::move(without), selectStream, settings, std::move(uniqueSets), std::move(distinctSets)); + having, std::move(winSpecs), legacyHoppingWindowSpec, std::move(terms), distinct, std::move(without), forceWithout, selectStream, settings, std::move(uniqueSets), std::move(distinctSets)); } class TUnion: public IRealSource { diff --git a/yql/essentials/sql/v1/source.h b/yql/essentials/sql/v1/source.h index f5855f50d1..f89be5dd98 100644 --- a/yql/essentials/sql/v1/source.h +++ b/yql/essentials/sql/v1/source.h @@ -269,6 +269,7 @@ namespace NSQLTranslationV1 { TVector<TNodePtr>&& terms, bool distinct, TVector<TNodePtr>&& without, + bool forceWithout, bool selectStream, const TWriteSettings& settings, TColumnsSets&& uniqueSets, diff --git a/yql/essentials/sql/v1/sql_select.cpp b/yql/essentials/sql/v1/sql_select.cpp index c27aa8f126..52dd399a99 100644 --- a/yql/essentials/sql/v1/sql_select.cpp +++ b/yql/essentials/sql/v1/sql_select.cpp @@ -1027,8 +1027,10 @@ TSourcePtr TSqlSelect::SelectCore(const TRule_select_core& node, const TWriteSet const bool selectStream = node.HasBlock3(); TVector<TNodePtr> without; + bool forceWithout = false; if (node.HasBlock8()) { - if (!ColumnList(without, node.GetBlock8().GetRule_without_column_list2())) { + forceWithout = node.GetBlock8().HasBlock2(); + if (!ColumnList(without, node.GetBlock8().GetRule_without_column_list3())) { return nullptr; } } @@ -1167,7 +1169,7 @@ TSourcePtr TSqlSelect::SelectCore(const TRule_select_core& node, const TWriteSet return nullptr; } return BuildSelectCore(Ctx, startPos, std::move(source), groupByExpr, groupBy, compactGroupBy, groupBySuffix, assumeSorted, orderBy, having, - std::move(windowSpec), legacyHoppingWindowSpec, std::move(terms), distinct, std::move(without), selectStream, settings, std::move(uniqueSets), std::move(distinctSets)); + std::move(windowSpec), legacyHoppingWindowSpec, std::move(terms), distinct, std::move(without), forceWithout, selectStream, settings, std::move(uniqueSets), std::move(distinctSets)); } bool TSqlSelect::WindowDefinition(const TRule_window_definition& rule, TWinSpecs& winSpecs) { @@ -1421,6 +1423,7 @@ TSourcePtr TSqlSelect::Build(const TRule& node, TPosition pos, TSelectKindResult TLegacyHoppingWindowSpecPtr legacyHoppingWindowSpec; bool distinct = false; TVector<TNodePtr> without; + bool forceWithout = false; bool stream = false; TVector<TNodePtr> terms; @@ -1428,7 +1431,7 @@ 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, outermostSettings, {}, {}); + distinct, std::move(without), forceWithout, stream, outermostSettings, {}, {}); result = BuildSelect(unionPos, std::move(result), skipTake); } else if (skipTake) { diff --git a/yql/essentials/tests/sql/minirun/part0/canondata/result.json b/yql/essentials/tests/sql/minirun/part0/canondata/result.json index d90bfc7598..4b2f711ac2 100644 --- a/yql/essentials/tests/sql/minirun/part0/canondata/result.json +++ b/yql/essentials/tests/sql/minirun/part0/canondata/result.json @@ -1345,6 +1345,20 @@ "uri": "https://{canondata_backend}/1946324/42941f53c7bc2748dcbf9469a617a6dd3e805076/resource.tar.gz#test.test_select-id_xor-default.txt-Results_/results.txt" } ], + "test.test[select-without_if_exists-default.txt-Debug]": [ + { + "checksum": "ea7d283945e2e1b87cb08073282a19e7", + "size": 301, + "uri": "https://{canondata_backend}/1809005/3d9ba2209e199d535bc6bbb3c259c9d955a3f50c/resource.tar.gz#test.test_select-without_if_exists-default.txt-Debug_/opt.yql" + } + ], + "test.test[select-without_if_exists-default.txt-Results]": [ + { + "checksum": "54766486c34ebb7876ebb3d362dc96f9", + "size": 1663, + "uri": "https://{canondata_backend}/1809005/3d9ba2209e199d535bc6bbb3c259c9d955a3f50c/resource.tar.gz#test.test_select-without_if_exists-default.txt-Results_/results.txt" + } + ], "test.test[udf-udf_with_settings--Debug]": [ { "checksum": "a7b364b692c35af7b468f42ab6a7b43f", diff --git a/yql/essentials/tests/sql/sql2yql/canondata/result.json b/yql/essentials/tests/sql/sql2yql/canondata/result.json index 1db06fe887..1bdda7b12b 100644 --- a/yql/essentials/tests/sql/sql2yql/canondata/result.json +++ b/yql/essentials/tests/sql/sql2yql/canondata/result.json @@ -6922,6 +6922,13 @@ "uri": "https://{canondata_backend}/1903280/03a80e4eaf2d24e0b4fad2e65ee62b19b904eb3c/resource.tar.gz#test_sql2yql.test_select-values_/sql.yql" } ], + "test_sql2yql.test[select-without_if_exists]": [ + { + "checksum": "698deee923ae5f88185130a30121b741", + "size": 3065, + "uri": "https://{canondata_backend}/1937492/efb17561a1a79f7d31fb758358c23c28314c8d60/resource.tar.gz#test_sql2yql.test_select-without_if_exists_/sql.yql" + } + ], "test_sql2yql.test[seq_mode-shared_named_expr]": [ { "checksum": "7f16d29d01ed38006249f8a6df896d89", @@ -10755,6 +10762,11 @@ "uri": "file://test_sql_format.test_select-values_/formatted.sql" } ], + "test_sql_format.test[select-without_if_exists]": [ + { + "uri": "file://test_sql_format.test_select-without_if_exists_/formatted.sql" + } + ], "test_sql_format.test[seq_mode-shared_named_expr]": [ { "uri": "file://test_sql_format.test_seq_mode-shared_named_expr_/formatted.sql" diff --git a/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_select-without_if_exists_/formatted.sql b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_select-without_if_exists_/formatted.sql new file mode 100644 index 0000000000..8cca65ae81 --- /dev/null +++ b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_select-without_if_exists_/formatted.sql @@ -0,0 +1,19 @@ +SELECT + * +WITHOUT IF EXISTS + x +FROM ( + SELECT + 1 AS x, + 2 AS z +); + +SELECT + * +WITHOUT IF EXISTS + y +FROM ( + SELECT + 1 AS x, + 2 AS z +); diff --git a/yql/essentials/tests/sql/suites/select/without_if_exists.sql b/yql/essentials/tests/sql/suites/select/without_if_exists.sql new file mode 100644 index 0000000000..c62b81747d --- /dev/null +++ b/yql/essentials/tests/sql/suites/select/without_if_exists.sql @@ -0,0 +1,13 @@ + +SELECT + * + without if exists x +FROM (select 1 as x,2 as z); + + +SELECT + * + without if exists y +FROM (select 1 as x, 2 as z); + + |