partitioning.cpp 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #include "partitioning.h"
  2. #include <yql/essentials/providers/common/provider/yql_provider_names.h>
  3. #include <library/cpp/json/json_reader.h>
  4. #include <util/generic/is_in.h>
  5. #include <util/string/builder.h>
  6. namespace NSQLTranslation {
  7. namespace {
  8. TString ParsePartitionedByBinding(const TString& name, const TString& value, TVector<TString>& columns) {
  9. using namespace NJson;
  10. TJsonValue json;
  11. bool throwOnError = false;
  12. if (!ReadJsonTree(value, &json, throwOnError)) {
  13. return TStringBuilder() << "Binding setting " << name << " is not a valid JSON";
  14. }
  15. const TJsonValue::TArray* arr = nullptr;
  16. if (!json.GetArrayPointer(&arr)) {
  17. return TStringBuilder() << "Binding setting " << name << ": expecting array";
  18. }
  19. if (arr->empty()) {
  20. return TStringBuilder() << "Binding setting " << name << ": expecting non-empty array";
  21. }
  22. for (auto& item : *arr) {
  23. TString str;
  24. if (!item.GetString(&str)) {
  25. return TStringBuilder() << "Binding setting " << name << ": expecting non-empty array of strings";
  26. }
  27. columns.push_back(std::move(str));
  28. }
  29. return {};
  30. }
  31. }
  32. TString ExtractBindingInfo(const TTranslationSettings& settings, const TString& binding, TBindingInfo& result) {
  33. auto pit = settings.Bindings.find(binding);
  34. if (pit == settings.Bindings.end()) {
  35. return TStringBuilder() << "Table binding `" << binding << "` is not defined";
  36. }
  37. const auto& bindSettings = pit->second;
  38. if (!IsIn({NYql::S3ProviderName, NYql::PqProviderName}, bindSettings.ClusterType)) {
  39. return TStringBuilder() << "Cluster type " << bindSettings.ClusterType << " is not supported for table bindings";
  40. }
  41. result.ClusterType = bindSettings.ClusterType;
  42. // ordered map ensures AST stability
  43. TMap<TString, TString> kvs(bindSettings.Settings.begin(), bindSettings.Settings.end());
  44. auto pullSettingOrFail = [&](const TString& name, TString& value) -> TString {
  45. auto it = kvs.find(name);
  46. if (it == kvs.end()) {
  47. return TStringBuilder() << name << " is not found for " << binding;
  48. }
  49. value = it->second;
  50. kvs.erase(it);
  51. return {};
  52. };
  53. if (const auto& error = pullSettingOrFail("cluster", result.Cluster)) {
  54. return error;
  55. }
  56. if (const auto& error = pullSettingOrFail("path", result.Path)) {
  57. return error;
  58. }
  59. if (auto it = kvs.find("schema"); it != kvs.end()) {
  60. result.Schema = it->second;
  61. kvs.erase(it);
  62. }
  63. if (auto it = kvs.find("partitioned_by"); it != kvs.end()) {
  64. TVector<TString> columns;
  65. if (const auto& error = ParsePartitionedByBinding(it->first, it->second, columns)) {
  66. return error;
  67. }
  68. result.Attributes.emplace("partitionedby", std::move(columns));
  69. kvs.erase(it);
  70. }
  71. for (auto& [key, value] : kvs) {
  72. if (key.empty()) {
  73. return "Attribute should not be empty";
  74. }
  75. result.Attributes.emplace(key, TVector<TString>{value});
  76. }
  77. return {};
  78. }
  79. } // namespace NSQLTranslation