summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvvvv <[email protected]>2024-12-12 18:16:33 +0300
committervvvv <[email protected]>2024-12-12 19:16:09 +0300
commit06977e9655c2ebeaa6535bf9018691f5d98a48f7 (patch)
treea13cbf824b2158d68cc8d0ca622276ed7d09ad6e
parentfab222fd8176d00eee5ddafc6bce8cb95a6e3ab0 (diff)
Better diagnostics for scalar context usages
init commit_hash:12f8e607ccf54d241b69dbb1903cf36a1930295f
-rw-r--r--yql/essentials/sql/v1/node.cpp8
-rw-r--r--yql/essentials/sql/v1/node.h3
-rw-r--r--yql/essentials/sql/v1/select.cpp8
-rw-r--r--yql/essentials/sql/v1/sql_expression.cpp7
-rw-r--r--yql/essentials/sql/v1/sql_into_tables.cpp1
-rw-r--r--yql/essentials/sql/v1/sql_ut.cpp39
-rw-r--r--yql/essentials/sql/v1/sql_ut_antlr4.cpp39
-rw-r--r--yql/essentials/tests/sql/sql2yql/canondata/result.json12
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]": [