diff options
author | uzhas <uzhas@ydb.tech> | 2022-09-28 21:05:21 +0300 |
---|---|---|
committer | uzhas <uzhas@ydb.tech> | 2022-09-28 21:05:21 +0300 |
commit | f063daeadff3ceacd9cde94a6b6e1f47d4d77edc (patch) | |
tree | 967dc89a4393571562f0d819d9c280eaba10b48c | |
parent | ce67eb7f501987256b2d6fa5dd7dfb79fa5f49c8 (diff) | |
download | ydb-f063daeadff3ceacd9cde94a6b6e1f47d4d77edc.tar.gz |
pg binding: move common logic to separate func
-rw-r--r-- | ydb/library/yql/sql/pg/pg_sql.cpp | 74 | ||||
-rw-r--r-- | ydb/library/yql/sql/settings/partitioning.cpp | 63 | ||||
-rw-r--r-- | ydb/library/yql/sql/settings/partitioning.h | 12 | ||||
-rw-r--r-- | ydb/library/yql/sql/v1/sql.cpp | 76 |
4 files changed, 96 insertions, 129 deletions
diff --git a/ydb/library/yql/sql/pg/pg_sql.cpp b/ydb/library/yql/sql/pg/pg_sql.cpp index 5bec2f4f13e..1766600b424 100644 --- a/ydb/library/yql/sql/pg/pg_sql.cpp +++ b/ydb/library/yql/sql/pg/pg_sql.cpp @@ -1253,82 +1253,30 @@ public: TAstNode* BuildBindingSource(const RangeVar* value) { const TString binding = value->relname; - auto pit = Settings.PrivateBindings.find(binding); - auto sit = Settings.ScopedBindings.find(binding); - - if (pit == Settings.PrivateBindings.end() && sit == Settings.ScopedBindings.end()) { - AddError(TStringBuilder() << "Table binding `" << binding << "` is not defined"); + NSQLTranslation::TBindingInfo bindingInfo; + if (const auto& error = ExtractBindingInfo(Settings, binding, bindingInfo)) { + AddError(error); return nullptr; } - - const auto& bindSettings = (pit != Settings.PrivateBindings.end()) ? pit->second : sit->second; - - // ordered map ensures AST stability - std::map<TString, TString> kvs(bindSettings.Settings.begin(), bindSettings.Settings.end()); - auto pullSettingOrFail = [&](const TString& name, TString& value) -> bool { - auto it = kvs.find(name); - if (it == kvs.end()) { - AddError(TStringBuilder() << name << " is not found for " << binding); - return false; - } - value = it->second; - kvs.erase(it); - return true; - }; - - TString cluster; - TString path; - TString format; - - if (!pullSettingOrFail("cluster", cluster) || - !pullSettingOrFail("path", path) || - !pullSettingOrFail("format", format)) { - return nullptr; - } - TVector<TAstNode*> hints; - if (auto it = kvs.find("schema"); it != kvs.end()) { - auto schema = QA(it->second); + if (bindingInfo.Schema) { + auto schema = QA(bindingInfo.Schema); auto type = L(A("SqlTypeFromYson"), schema); auto columns = L(A("SqlColumnOrderFromYson"), schema); hints.emplace_back(QL(QA("userschema"), type, columns)); - kvs.erase(it); } - if (auto it = kvs.find("partitioned_by"); it != kvs.end()) { - TVector<TString> columns; - if (const TString& error = NSQLTranslation::ParsePartitionedByBinding(it->first, it->second, columns)) { - AddError(error); - } + for (auto& [key, value] : bindingInfo.Attributes) { TVector<TAstNode*> hintValues; - hintValues.push_back(QA("partitionedby")); - for (auto& column : columns) { - hintValues.push_back(QA(column)); + hintValues.push_back(QA(key)); + for (auto& v : value) { + hintValues.push_back(QA(v)); } hints.emplace_back(QVL(hintValues.data(), hintValues.size())); - kvs.erase(it); - } - - // put format back to hints - kvs["format"] = format; - - for (auto& [key, value] : kvs) { - if (!key) { - AddError(TStringBuilder() << "Hint key should not be empty"); - return nullptr; - } - - hints.emplace_back(QL(QA(key), QA(value))); - } - - auto p = Settings.ClusterMapping.FindPtr(cluster); - if (!p) { - AddError(TStringBuilder() << "Unknown cluster: " << cluster); - return nullptr; } - auto source = L(A("DataSource"), QAX(*p), QAX(cluster)); + auto source = L(A("DataSource"), QAX(bindingInfo.ClusterType), QAX(bindingInfo.Cluster)); return L( A("Read!"), A("world"), @@ -1341,7 +1289,7 @@ public: QA("table"), L( A("String"), - QAX(path) + QAX(bindingInfo.Path) ) ) ) diff --git a/ydb/library/yql/sql/settings/partitioning.cpp b/ydb/library/yql/sql/settings/partitioning.cpp index 49e84a855fd..adc65973dba 100644 --- a/ydb/library/yql/sql/settings/partitioning.cpp +++ b/ydb/library/yql/sql/settings/partitioning.cpp @@ -1,8 +1,11 @@ #include "partitioning.h" +#include <ydb/library/yql/providers/common/provider/yql_provider_names.h> #include <library/cpp/json/json_reader.h> +#include <util/generic/is_in.h> #include <util/string/builder.h> namespace NSQLTranslation { +namespace { TString ParsePartitionedByBinding(const TString& name, const TString& value, TVector<TString>& columns) { using namespace NJson; @@ -32,4 +35,64 @@ TString ParsePartitionedByBinding(const TString& name, const TString& value, TVe return {}; } +} + +TString ExtractBindingInfo(const TTranslationSettings& settings, const TString& binding, TBindingInfo& result) { + auto pit = settings.PrivateBindings.find(binding); + auto sit = settings.ScopedBindings.find(binding); + + if (pit == settings.PrivateBindings.end() && sit == settings.ScopedBindings.end()) { + return TStringBuilder() << "Table binding `" << binding << "` is not defined"; + } + + const auto& bindSettings = (pit != settings.PrivateBindings.end()) ? pit->second : sit->second; + + if (!IsIn({NYql::S3ProviderName, NYql::PqProviderName}, bindSettings.ClusterType)) { + return TStringBuilder() << "Cluster type " << bindSettings.ClusterType << " is not supported for table bindings"; + } + result.ClusterType = bindSettings.ClusterType; + + // ordered map ensures AST stability + TMap<TString, TString> kvs(bindSettings.Settings.begin(), bindSettings.Settings.end()); + auto pullSettingOrFail = [&](const TString& name, TString& value) -> TString { + auto it = kvs.find(name); + if (it == kvs.end()) { + return TStringBuilder() << name << " is not found for " << binding; + } + value = it->second; + kvs.erase(it); + return {}; + }; + + if (const auto& error = pullSettingOrFail("cluster", result.Cluster)) { + return error; + } + if (const auto& error = pullSettingOrFail("path", result.Path)) { + return error; + } + + if (auto it = kvs.find("schema"); it != kvs.end()) { + result.Schema = it->second; + kvs.erase(it); + } + + if (auto it = kvs.find("partitioned_by"); it != kvs.end()) { + TVector<TString> columns; + if (const auto& error = ParsePartitionedByBinding(it->first, it->second, columns)) { + return error; + } + result.Attributes.emplace("partitionedby", std::move(columns)); + kvs.erase(it); + } + + for (auto& [key, value] : kvs) { + if (key.empty()) { + return "Attribute should not be empty"; + } + result.Attributes.emplace(key, TVector<TString>{value}); + } + + return {}; +} + } // namespace NSQLTranslation diff --git a/ydb/library/yql/sql/settings/partitioning.h b/ydb/library/yql/sql/settings/partitioning.h index db825aa95ee..082890ae153 100644 --- a/ydb/library/yql/sql/settings/partitioning.h +++ b/ydb/library/yql/sql/settings/partitioning.h @@ -1,9 +1,19 @@ #pragma once +#include "translation_settings.h" +#include <util/generic/map.h> #include <util/generic/string.h> #include <util/generic/vector.h> namespace NSQLTranslation { + struct TBindingInfo { + TString ClusterType; + TString Cluster; + TString Path; + TString Schema; + TMap<TString, TVector<TString>> Attributes; + }; + // returns error message if any - TString ParsePartitionedByBinding(const TString& name, const TString& value, TVector<TString>& columns); + TString ExtractBindingInfo(const TTranslationSettings& settings, const TString& binding, TBindingInfo& result); } // namespace NSQLTranslation diff --git a/ydb/library/yql/sql/v1/sql.cpp b/ydb/library/yql/sql/v1/sql.cpp index fa36b157203..ad5a388a2bf 100644 --- a/ydb/library/yql/sql/v1/sql.cpp +++ b/ydb/library/yql/sql/v1/sql.cpp @@ -1468,88 +1468,34 @@ bool TSqlTranslation::ClusterExpr(const TRule_cluster_expr& node, bool allowWild bool ExprList(TSqlExpression& sqlExpr, TVector<TNodePtr>& exprNodes, const TRule_expr_list& node); bool TSqlTranslation::ApplyTableBinding(const TString& binding, TTableRef& tr, TTableHints& hints) { - const auto& settings = Context().Settings; - auto pit = settings.PrivateBindings.find(binding); - auto sit = settings.ScopedBindings.find(binding); - - if (pit == settings.PrivateBindings.end() && sit == settings.ScopedBindings.end()) { - Ctx.Error() << "Table binding `" << binding << "` is not defined"; + NSQLTranslation::TBindingInfo bindingInfo; + if (const auto& error = ExtractBindingInfo(Context().Settings, binding, bindingInfo)) { + Ctx.Error() << error; return false; } - if (pit != settings.PrivateBindings.end() && sit != settings.ScopedBindings.end()) { - // warn - Ctx.Warning(Ctx.Pos(), - TIssuesIds::YQL_TABLE_BINDING_DUPLICATE) << "Table binding `" << binding << "` is defined both as private and scoped binding"; - } - - const auto& bindSettings = (pit != settings.PrivateBindings.end()) ? pit->second : sit->second; - - if (!IsIn({S3ProviderName, PqProviderName}, bindSettings.ClusterType)) { - Ctx.Error() << "Cluster type " << bindSettings.ClusterType << " is not supported for table bindings"; - return false; - } - - // ordered map ensures AST stability - TMap<TString, TString> kvs(bindSettings.Settings.begin(), bindSettings.Settings.end()); - auto pullSettingOrFail = [&](const TString& name, TString& value) -> bool { - auto it = kvs.find(name); - if (it == kvs.end()) { - Ctx.Error() << name << " is not found for " << binding; - return false; - } - value = it->second; - kvs.erase(it); - return true; - }; - - TString cluster; - TString path; - TString format; - - if (!pullSettingOrFail("cluster", cluster) || - !pullSettingOrFail("path", path) || - !pullSettingOrFail("format", format)) - { - return false; - } - - if (auto it = kvs.find("schema"); it != kvs.end()) { - TNodePtr schema = BuildQuotedAtom(Ctx.Pos(), it->second); + if (bindingInfo.Schema) { + TNodePtr schema = BuildQuotedAtom(Ctx.Pos(), bindingInfo.Schema); TNodePtr type = new TCallNodeImpl(Ctx.Pos(), "SqlTypeFromYson", { schema }); TNodePtr columns = new TCallNodeImpl(Ctx.Pos(), "SqlColumnOrderFromYson", { schema }); hints["user_schema"] = { type, columns }; - kvs.erase(it); } - if (auto it = kvs.find("partitioned_by"); it != kvs.end()) { - TVector<TString> columns; - if (const auto& error = NSQLTranslation::ParsePartitionedByBinding(it->first, it->second, columns)) { - Ctx.Error() << error; - return false; - } + for (auto& [key, values] : bindingInfo.Attributes) { TVector<TNodePtr> hintValue; - for (auto& column : columns) { + for (auto& column : values) { hintValue.push_back(BuildQuotedAtom(Ctx.Pos(), column)); } - hints[it->first] = std::move(hintValue); - kvs.erase(it); + hints[key] = std::move(hintValue); } - tr.Service = bindSettings.ClusterType; - tr.Cluster = TDeferredAtom(Ctx.Pos(), cluster); - // put format back to hints - kvs["format"] = format; - - for (auto& [key, value] : kvs) { - YQL_ENSURE(!key.empty()); - hints[key] = { BuildQuotedAtom(Ctx.Pos(), value) }; - } + tr.Service = bindingInfo.ClusterType; + tr.Cluster = TDeferredAtom(Ctx.Pos(), bindingInfo.Cluster); const TString view = ""; - tr.Keys = BuildTableKey(Ctx.Pos(), tr.Service, tr.Cluster, TDeferredAtom(Ctx.Pos(), path), view); + tr.Keys = BuildTableKey(Ctx.Pos(), tr.Service, tr.Cluster, TDeferredAtom(Ctx.Pos(), bindingInfo.Path), view); return true; } |