diff options
| author | vvvv <[email protected]> | 2024-12-12 18:16:33 +0300 |
|---|---|---|
| committer | vvvv <[email protected]> | 2024-12-12 19:16:09 +0300 |
| commit | 06977e9655c2ebeaa6535bf9018691f5d98a48f7 (patch) | |
| tree | a13cbf824b2158d68cc8d0ca622276ed7d09ad6e | |
| parent | fab222fd8176d00eee5ddafc6bce8cb95a6e3ab0 (diff) | |
Better diagnostics for scalar context usages
init
commit_hash:12f8e607ccf54d241b69dbb1903cf36a1930295f
| -rw-r--r-- | yql/essentials/sql/v1/node.cpp | 8 | ||||
| -rw-r--r-- | yql/essentials/sql/v1/node.h | 3 | ||||
| -rw-r--r-- | yql/essentials/sql/v1/select.cpp | 8 | ||||
| -rw-r--r-- | yql/essentials/sql/v1/sql_expression.cpp | 7 | ||||
| -rw-r--r-- | yql/essentials/sql/v1/sql_into_tables.cpp | 1 | ||||
| -rw-r--r-- | yql/essentials/sql/v1/sql_ut.cpp | 39 | ||||
| -rw-r--r-- | yql/essentials/sql/v1/sql_ut_antlr4.cpp | 39 | ||||
| -rw-r--r-- | yql/essentials/tests/sql/sql2yql/canondata/result.json | 12 |
8 files changed, 110 insertions, 7 deletions
diff --git a/yql/essentials/sql/v1/node.cpp b/yql/essentials/sql/v1/node.cpp index 31d72385ca7..2339fa894e7 100644 --- a/yql/essentials/sql/v1/node.cpp +++ b/yql/essentials/sql/v1/node.cpp @@ -91,6 +91,14 @@ void INode::MarkImplicitLabel(bool isImplicitLabel) { ImplicitLabel = isImplicitLabel; } +void INode::SetRefPos(TPosition pos) { + RefPos = pos; +} + +TMaybe<TPosition> INode::GetRefPos() const { + return RefPos; +} + void INode::SetCountHint(bool isCount) { State.Set(ENodeState::CountHint, isCount); } diff --git a/yql/essentials/sql/v1/node.h b/yql/essentials/sql/v1/node.h index c2c46c60775..ba14584543c 100644 --- a/yql/essentials/sql/v1/node.h +++ b/yql/essentials/sql/v1/node.h @@ -140,6 +140,8 @@ namespace NSQLTranslationV1 { void SetLabel(const TString& label, TMaybe<TPosition> pos = {}); bool IsImplicitLabel() const; void MarkImplicitLabel(bool isImplicitLabel); + void SetRefPos(TPosition pos); + TMaybe<TPosition> GetRefPos() const; void SetCountHint(bool isCount); bool GetCountHint() const; @@ -276,6 +278,7 @@ namespace NSQLTranslationV1 { TString Label; TMaybe<TPosition> LabelPos; bool ImplicitLabel = false; + TMaybe<TPosition> RefPos; mutable TNodeState State; bool AsInner = false; bool DisableSort_ = false; diff --git a/yql/essentials/sql/v1/select.cpp b/yql/essentials/sql/v1/select.cpp index d2e4c0a8749..1442215e15c 100644 --- a/yql/essentials/sql/v1/select.cpp +++ b/yql/essentials/sql/v1/select.cpp @@ -124,6 +124,10 @@ public: Node = Y("SingleMember", Y("SqlAccess", Q("dict"), Y("Take", Node, Y("Uint64", Q("1"))), Y("Uint64", Q("0")))); } else { ctx.Error(Pos) << "Source used in expression should contain one concrete column"; + if (RefPos) { + ctx.Error(*RefPos) << "Source is used here"; + } + return false; } } @@ -565,6 +569,10 @@ public: Node = Y("SingleMember", Y("SqlAccess", Q("dict"), Y("Take", Node, Y("Uint64", Q("1"))), Y("Uint64", Q("0")))); } else { ctx.Error(Pos) << "Source used in expression should contain one concrete column"; + if (RefPos) { + ctx.Error(*RefPos) << "Source is used here"; + } + return false; } } diff --git a/yql/essentials/sql/v1/sql_expression.cpp b/yql/essentials/sql/v1/sql_expression.cpp index 1f506991a2c..675d36ed464 100644 --- a/yql/essentials/sql/v1/sql_expression.cpp +++ b/yql/essentials/sql/v1/sql_expression.cpp @@ -1152,7 +1152,12 @@ TNodePtr TSqlExpression::BindParameterRule(const TRule_bind_parameter& rule, con return {}; } Ctx.IncrementMonCounter("sql_features", "NamedNodeUseAtom"); - return GetNamedNode(namedArg); + auto ret = GetNamedNode(namedArg); + if (ret) { + ret->SetRefPos(Ctx.Pos()); + } + + return ret; } TNodePtr TSqlExpression::LambdaRule(const TRule_lambda& rule) { diff --git a/yql/essentials/sql/v1/sql_into_tables.cpp b/yql/essentials/sql/v1/sql_into_tables.cpp index 43cc08de0d7..ac9ce53061a 100644 --- a/yql/essentials/sql/v1/sql_into_tables.cpp +++ b/yql/essentials/sql/v1/sql_into_tables.cpp @@ -124,6 +124,7 @@ TNodePtr TSqlIntoTable::Build(const TRule_into_table_stmt& node) { return nullptr; } + named->SetRefPos(Ctx.Pos()); if (cluster.Empty()) { Ctx.Error() << "No cluster name given and no default cluster is selected"; return nullptr; diff --git a/yql/essentials/sql/v1/sql_ut.cpp b/yql/essentials/sql/v1/sql_ut.cpp index 3ef964fa0d4..0cb626f5b03 100644 --- a/yql/essentials/sql/v1/sql_ut.cpp +++ b/yql/essentials/sql/v1/sql_ut.cpp @@ -5040,6 +5040,45 @@ select FormatType($f()); )"; ExpectFailWithError(query, "<main>:2:33: Error: Aggregation function Min requires exactly 1 argument(s), given: 2\n"); } + + Y_UNIT_TEST(ScalarContextUsage1) { + TString query = R"( + $a = (select 1 as x, 2 as y); + select 1 + $a; + )"; + ExpectFailWithError(query, "<main>:2:39: Error: Source used in expression should contain one concrete column\n" + "<main>:3:24: Error: Source is used here\n"); + } + + Y_UNIT_TEST(ScalarContextUsage2) { + TString query = R"( + use plato; + $a = (select 1 as x, 2 as y); + select * from concat($a); + )"; + ExpectFailWithError(query, "<main>:3:39: Error: Source used in expression should contain one concrete column\n" + "<main>:4:34: Error: Source is used here\n"); + } + + Y_UNIT_TEST(ScalarContextUsage3) { + TString query = R"( + use plato; + $a = (select 1 as x, 2 as y); + select * from range($a); + )"; + ExpectFailWithError(query, "<main>:3:39: Error: Source used in expression should contain one concrete column\n" + "<main>:4:33: Error: Source is used here\n"); + } + + Y_UNIT_TEST(ScalarContextUsage4) { + TString query = R"( + use plato; + $a = (select 1 as x, 2 as y); + insert into $a select 1; + )"; + ExpectFailWithError(query, "<main>:3:39: Error: Source used in expression should contain one concrete column\n" + "<main>:4:25: Error: Source is used here\n"); + } } void CheckUnused(const TString& req, const TString& symbol, unsigned row, unsigned col) { diff --git a/yql/essentials/sql/v1/sql_ut_antlr4.cpp b/yql/essentials/sql/v1/sql_ut_antlr4.cpp index c3c5f9c9833..ae2ef947592 100644 --- a/yql/essentials/sql/v1/sql_ut_antlr4.cpp +++ b/yql/essentials/sql/v1/sql_ut_antlr4.cpp @@ -5037,6 +5037,45 @@ select FormatType($f()); )"; ExpectFailWithError(query, "<main>:2:33: Error: Aggregation function Min requires exactly 1 argument(s), given: 2\n"); } + + Y_UNIT_TEST(ScalarContextUsage1) { + TString query = R"( + $a = (select 1 as x, 2 as y); + select 1 + $a; + )"; + ExpectFailWithError(query, "<main>:2:39: Error: Source used in expression should contain one concrete column\n" + "<main>:3:24: Error: Source is used here\n"); + } + + Y_UNIT_TEST(ScalarContextUsage2) { + TString query = R"( + use plato; + $a = (select 1 as x, 2 as y); + select * from concat($a); + )"; + ExpectFailWithError(query, "<main>:3:39: Error: Source used in expression should contain one concrete column\n" + "<main>:4:34: Error: Source is used here\n"); + } + + Y_UNIT_TEST(ScalarContextUsage3) { + TString query = R"( + use plato; + $a = (select 1 as x, 2 as y); + select * from range($a); + )"; + ExpectFailWithError(query, "<main>:3:39: Error: Source used in expression should contain one concrete column\n" + "<main>:4:33: Error: Source is used here\n"); + } + + Y_UNIT_TEST(ScalarContextUsage4) { + TString query = R"( + use plato; + $a = (select 1 as x, 2 as y); + insert into $a select 1; + )"; + ExpectFailWithError(query, "<main>:3:39: Error: Source used in expression should contain one concrete column\n" + "<main>:4:25: Error: Source is used here\n"); + } } void CheckUnused(const TString& req, const TString& symbol, unsigned row, unsigned col) { diff --git a/yql/essentials/tests/sql/sql2yql/canondata/result.json b/yql/essentials/tests/sql/sql2yql/canondata/result.json index e73aa91e9e2..817b47972c0 100644 --- a/yql/essentials/tests/sql/sql2yql/canondata/result.json +++ b/yql/essentials/tests/sql/sql2yql/canondata/result.json @@ -32262,9 +32262,9 @@ ], "test_sql_negative.test[select-autoextract_source_value_in_where-default.txt]": [ { - "checksum": "0a04f9617e0bd69931c6f09f4579ad25", - "size": 237, - "uri": "https://{canondata_backend}/1937429/434276f26b2857be3c5ad3fdbbf877d2bf775ac5/resource.tar.gz#test_sql_negative.test_select-autoextract_source_value_in_where-default.txt_/err_file.out" + "checksum": "8dae30c2b591ac52d6135d1fdc127b81", + "size": 347, + "uri": "https://{canondata_backend}/1889210/2ddfda0b16ee484b8c32025195f554d885acf48d/resource.tar.gz#test_sql_negative.test_select-autoextract_source_value_in_where-default.txt_/err_file.out" } ], "test_sql_negative.test[select-normalize_name-default.txt]": [ @@ -32290,9 +32290,9 @@ ], "test_sql_negative.test[select-use_subrequest_as_table-default.txt]": [ { - "checksum": "b487c7081e29ca693370513c4786c0b5", - "size": 134, - "uri": "https://{canondata_backend}/1937429/434276f26b2857be3c5ad3fdbbf877d2bf775ac5/resource.tar.gz#test_sql_negative.test_select-use_subrequest_as_table-default.txt_/err_file.out" + "checksum": "e0ce66df53204c1c27e622ecb103c627", + "size": 289, + "uri": "https://{canondata_backend}/1889210/2ddfda0b16ee484b8c32025195f554d885acf48d/resource.tar.gz#test_sql_negative.test_select-use_subrequest_as_table-default.txt_/err_file.out" } ], "test_sql_negative.test[udf-named_args_for_script_with_wrong_order-default.txt]": [ |
