aboutsummaryrefslogtreecommitdiffstats
path: root/yql
diff options
context:
space:
mode:
authorvvvv <vvvv@yandex-team.com>2025-02-21 21:51:34 +0300
committervvvv <vvvv@yandex-team.com>2025-02-21 22:33:18 +0300
commita3da80a1d278964b44086f8b500ed09bad0f165f (patch)
tree368b6985119a89ba99279100dbb8adf7f4bda951 /yql
parent005b8a9fd31e325164fdaad9ccde51222d9dc1c7 (diff)
downloadydb-a3da80a1d278964b44086f8b500ed09bad0f165f.tar.gz
YQL-19129 soft WITHOUT
commit_hash:563aebc32ae87bc18e5e3e38babc034e5e89e2c1
Diffstat (limited to 'yql')
-rw-r--r--yql/essentials/docs/en/syntax/select/without.md3
-rw-r--r--yql/essentials/docs/ru/syntax/select/without.md3
-rw-r--r--yql/essentials/sql/v1/SQLv1.g.in2
-rw-r--r--yql/essentials/sql/v1/SQLv1Antlr4.g.in2
-rw-r--r--yql/essentials/sql/v1/format/sql_format_ut.h2
-rw-r--r--yql/essentials/sql/v1/select.cpp17
-rw-r--r--yql/essentials/sql/v1/source.h1
-rw-r--r--yql/essentials/sql/v1/sql_select.cpp9
-rw-r--r--yql/essentials/tests/sql/minirun/part0/canondata/result.json14
-rw-r--r--yql/essentials/tests/sql/sql2yql/canondata/result.json12
-rw-r--r--yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_select-without_if_exists_/formatted.sql19
-rw-r--r--yql/essentials/tests/sql/suites/select/without_if_exists.sql13
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);
+
+