aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Neporada <neporada@gmail.com>2022-06-22 19:34:10 +0300
committerAndrey Neporada <neporada@gmail.com>2022-06-22 19:34:10 +0300
commit4b9d2ea716d05932ca6522ca66141e75cf6fc325 (patch)
tree846644d43c10df9d5396396df68ce30bc1dde2be
parentfe06d3c7d1c04f99c1a239707c2a377cd95e20a4 (diff)
downloadydb-4b9d2ea716d05932ca6522ca66141e75cf6fc325.tar.gz
[YQL-15020] Support external declares in TTranslationSettings. Fix declare overrides (last one should win)
ref:34fd8a027e547703ce6c5f880436eaca8c56ac0b
-rw-r--r--ydb/library/yql/sql/settings/translation_settings.h5
-rw-r--r--ydb/library/yql/sql/sql.cpp6
-rw-r--r--ydb/library/yql/sql/v1/context.cpp2
-rw-r--r--ydb/library/yql/sql/v1/sql.cpp25
-rw-r--r--ydb/library/yql/sql/v1/sql_ut.cpp49
5 files changed, 86 insertions, 1 deletions
diff --git a/ydb/library/yql/sql/settings/translation_settings.h b/ydb/library/yql/sql/settings/translation_settings.h
index 0b9194a249..ca898ce5bf 100644
--- a/ydb/library/yql/sql/settings/translation_settings.h
+++ b/ydb/library/yql/sql/settings/translation_settings.h
@@ -2,6 +2,7 @@
#include <util/generic/hash.h>
#include <util/generic/hash_set.h>
+#include <util/generic/map.h>
namespace google::protobuf {
class Arena;
@@ -65,6 +66,10 @@ namespace NSQLTranslation {
THashMap<TString, TTableBindingSettings> PrivateBindings;
THashMap<TString, TTableBindingSettings> ScopedBindings;
+ // each (name, type) entry in this map is equivalent to
+ // DECLARE $name AS type;
+ TMap<TString, TString> DeclaredNamedExprs;
+
ESqlMode Mode;
TString DefaultCluster;
TIncrementMonCounterFunction IncrementCounter;
diff --git a/ydb/library/yql/sql/sql.cpp b/ydb/library/yql/sql/sql.cpp
index 5a99fbf00f..79b62215b3 100644
--- a/ydb/library/yql/sql/sql.cpp
+++ b/ydb/library/yql/sql/sql.cpp
@@ -32,6 +32,12 @@ namespace NSQLTranslation {
*actualSyntaxVersion = parsedSettings.SyntaxVersion;
}
+ if (!parsedSettings.DeclaredNamedExprs.empty() && (parsedSettings.PgParser || parsedSettings.SyntaxVersion != 1)) {
+ result.Issues.AddIssue(NYql::YqlIssue(NYql::TPosition(), NYql::TIssuesIds::DEFAULT_ERROR,
+ "Externally declared named expressions are only supported in V1 syntax"));
+ return result;
+ }
+
if (parsedSettings.PgParser) {
return NSQLTranslationPG::PGToYql(query, parsedSettings);
}
diff --git a/ydb/library/yql/sql/v1/context.cpp b/ydb/library/yql/sql/v1/context.cpp
index a46d7e3fcc..6107645e71 100644
--- a/ydb/library/yql/sql/v1/context.cpp
+++ b/ydb/library/yql/sql/v1/context.cpp
@@ -282,7 +282,7 @@ TNodePtr TContext::UniversalAlias(const TString& baseName, TNodePtr&& node) {
}
void TContext::DeclareVariable(const TString& varName, const TNodePtr& typeNode) {
- Variables.emplace(varName, typeNode);
+ Variables[varName] = typeNode;
}
bool TContext::AddExport(TPosition pos, const TString& name) {
diff --git a/ydb/library/yql/sql/v1/sql.cpp b/ydb/library/yql/sql/v1/sql.cpp
index f666435356..bc9bf6b951 100644
--- a/ydb/library/yql/sql/v1/sql.cpp
+++ b/ydb/library/yql/sql/v1/sql.cpp
@@ -10076,6 +10076,31 @@ TSourcePtr TSqlQuery::Build(const TRule_multiple_column_assignment& stmt) {
}
TNodePtr TSqlQuery::Build(const TSQLv1ParserAST& ast) {
+ if (Mode == NSQLTranslation::ESqlMode::QUERY) {
+ // inject externally declared named expressions
+ for (auto [name, type] : Ctx.Settings.DeclaredNamedExprs) {
+ if (name.empty()) {
+ Error() << "Empty names for externally declared expressions are not allowed";
+ return nullptr;
+ }
+ TString varName = "$" + name;
+ if (IsAnonymousName(varName)) {
+ Error() << "Externally declared name '" << name << "' is anonymous";
+ return nullptr;
+ }
+
+ auto parsed = ParseType(type, *Ctx.Pool, Ctx.Issues, Ctx.Pos());
+ if (!parsed) {
+ Error() << "Failed to parse type for externally declared name '" << name << "'";
+ return nullptr;
+ }
+
+ TNodePtr typeNode = BuildBuiltinFunc(Ctx, Ctx.Pos(), "ParseType", { BuildLiteralRawString(Ctx.Pos(), type) });
+ varName = PushNamedAtom(Ctx.Pos(), varName);
+ Ctx.DeclareVariable(varName, typeNode);
+ }
+ }
+
const auto& query = ast.GetRule_sql_query();
TVector<TNodePtr> blocks;
if (query.Alt_case() == TRule_sql_query::kAltSqlQuery1) {
diff --git a/ydb/library/yql/sql/v1/sql_ut.cpp b/ydb/library/yql/sql/v1/sql_ut.cpp
index c287f696e8..a8300b3624 100644
--- a/ydb/library/yql/sql/v1/sql_ut.cpp
+++ b/ydb/library/yql/sql/v1/sql_ut.cpp
@@ -4276,3 +4276,52 @@ Y_UNIT_TEST_SUITE(FlexibleTypes) {
UNIT_ASSERT(SqlToYql(q).IsOk());
}
}
+
+Y_UNIT_TEST_SUITE(ExternalDeclares) {
+ Y_UNIT_TEST(BasicUsage) {
+ NSQLTranslation::TTranslationSettings settings;
+ settings.DeclaredNamedExprs["foo"] = "String";
+ auto res = SqlToYqlWithSettings("select $foo;", settings);
+ UNIT_ASSERT(res.IsOk());
+ UNIT_ASSERT(res.Issues.Size() == 0);
+
+ TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) {
+ if (word == "declare") {
+ UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"__((declare $foo (DataType 'String)))__"));
+ }
+ };
+
+ TWordCountHive elementStat = {{TString("declare"), 0}};
+ VerifyProgram(res, elementStat, verifyLine);
+
+ UNIT_ASSERT_VALUES_EQUAL(1, elementStat["declare"]);
+ }
+
+ Y_UNIT_TEST(DeclareOverridesExteralDeclares) {
+ NSQLTranslation::TTranslationSettings settings;
+ settings.DeclaredNamedExprs["foo"] = "String";
+ auto res = SqlToYqlWithSettings("declare $foo as Int32; select $foo;", settings);
+ UNIT_ASSERT(res.IsOk());
+
+ TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) {
+ if (word == "declare") {
+ UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"__((declare $foo (DataType 'Int32)))__"));
+ }
+ };
+
+ TWordCountHive elementStat = {{TString("declare"), 0}};
+ VerifyProgram(res, elementStat, verifyLine);
+
+ UNIT_ASSERT_VALUES_EQUAL(1, elementStat["declare"]);
+ }
+
+ Y_UNIT_TEST(DeclaresWithInvalidTypesFails) {
+ NSQLTranslation::TTranslationSettings settings;
+ settings.DeclaredNamedExprs["foo"] = "List<BadType>";
+ auto res = SqlToYqlWithSettings("select 1;", settings);
+ UNIT_ASSERT(!res.Root);
+ UNIT_ASSERT_NO_DIFF(Err2Str(res),
+ "<main>:0:5: Error: Unknown type: 'BadType'\n"
+ "<main>: Error: Failed to parse type for externally declared name 'foo'\n");
+ }
+}