yql_dispatch.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #include "yql_dispatch.h"
  2. #include <yql/essentials/core/yql_expr_type_annotation.h>
  3. #include <yql/essentials/ast/yql_expr.h>
  4. #include <yql/essentials/utils/log/log.h>
  5. #include <library/cpp/string_utils/levenshtein_diff/levenshtein_diff.h>
  6. #include <util/string/split.h>
  7. #include <util/random/random.h>
  8. #include <util/datetime/base.h>
  9. namespace NYql {
  10. namespace NPrivate {
  11. template <>
  12. TParser<TString> GetDefaultParser<TString>() {
  13. return [] (const TString& str) {
  14. return str;
  15. };
  16. }
  17. template<>
  18. TParser<bool> GetDefaultParser<bool>() {
  19. // Special handle of empty value to properly set setting for empty pragmas like yt.UseFeautre;
  20. return [] (const TString& str) {
  21. return str ? FromString<bool>(str) : true;
  22. };
  23. }
  24. template <>
  25. TParser<TGUID> GetDefaultParser<TGUID>() {
  26. return [] (const TString& str) {
  27. TGUID guid;
  28. if (!GetGuid(str, guid)) {
  29. throw yexception() << "Bad GUID format";
  30. }
  31. return guid;
  32. };
  33. }
  34. template<>
  35. TParser<NSize::TSize> GetDefaultParser<NSize::TSize>() {
  36. return [] (const TString& str) -> NSize::TSize {
  37. return NSize::ParseSize(str); // Support suffixes k, m, g, ...
  38. };
  39. }
  40. template<>
  41. TParser<TInstant> GetDefaultParser<TInstant>() {
  42. return [] (const TString& str) {
  43. TInstant val;
  44. if (!TInstant::TryParseIso8601(str, val)
  45. && !TInstant::TryParseRfc822(str, val)
  46. && !TInstant::TryParseHttp(str, val)
  47. && !TInstant::TryParseX509(str, val)
  48. ) {
  49. throw yexception() << "Bad date/time format";
  50. }
  51. return val;
  52. };
  53. }
  54. #define YQL_DEFINE_PRIMITIVE_SETTING_PARSER(type) \
  55. template<> \
  56. TParser<type> GetDefaultParser<type>() { \
  57. return [] (const TString& s) { return FromString<type>(s); }; \
  58. }
  59. #define YQL_DEFINE_CONTAINER_SETTING_PARSER(type) \
  60. template <> \
  61. TParser<type> GetDefaultParser<type>() { \
  62. return [] (const TString& str) { \
  63. type res; \
  64. StringSplitter(str).SplitBySet(",;| ").AddTo(&res); \
  65. for (auto& s: res) { \
  66. if (s.empty()) { \
  67. throw yexception() << "Empty value item"; \
  68. } \
  69. } \
  70. return res; \
  71. }; \
  72. }
  73. YQL_PRIMITIVE_SETTING_PARSER_TYPES(YQL_DEFINE_PRIMITIVE_SETTING_PARSER)
  74. YQL_CONTAINER_SETTING_PARSER_TYPES(YQL_DEFINE_CONTAINER_SETTING_PARSER)
  75. } // NPrivate
  76. namespace NCommon {
  77. bool TSettingDispatcher::IsRuntime(const TString& name) {
  78. auto normalizedName = NormalizeName(name);
  79. if (auto handler = Handlers.Value(normalizedName, TSettingHandler::TPtr())) {
  80. return handler->IsRuntime();
  81. }
  82. return false;
  83. }
  84. bool TSettingDispatcher::Dispatch(const TString& cluster, const TString& name, const TMaybe<TString>& value, EStage stage, const TErrorCallback& errorCallback) {
  85. auto normalizedName = NormalizeName(name);
  86. if (auto handler = Handlers.Value(normalizedName, TSettingHandler::TPtr())) {
  87. if (cluster != ALL_CLUSTERS) {
  88. if (!handler->IsRuntime()) {
  89. return errorCallback(TStringBuilder() << "Static setting " << name.Quote() << " cannot be set for specific cluster", true);
  90. }
  91. if (!ValidClusters.contains(cluster)) {
  92. TStringBuilder nearClusterMsg;
  93. for (auto& item: ValidClusters) {
  94. if (NLevenshtein::Distance(cluster, item) < DefaultMistypeDistance) {
  95. nearClusterMsg << ", did you mean " << item.Quote() << '?';
  96. break;
  97. }
  98. }
  99. return errorCallback(TStringBuilder() << "Unknown cluster name " << cluster.Quote()
  100. << " for setting " << name.Quote() << nearClusterMsg, true);
  101. }
  102. }
  103. if (!value && !handler->IsRuntime()) {
  104. return errorCallback(TStringBuilder() << "Static setting " << name.Quote() << " cannot be reset to default", true);
  105. }
  106. bool validateOnly = true;
  107. switch (stage) {
  108. case EStage::RUNTIME:
  109. validateOnly = !handler->IsRuntime();
  110. break;
  111. case EStage::STATIC:
  112. validateOnly = handler->IsRuntime();
  113. break;
  114. case EStage::CONFIG:
  115. validateOnly = false;
  116. break;
  117. }
  118. return handler->Handle(cluster, value, validateOnly, errorCallback);
  119. } else {
  120. // ignore unknown names in config
  121. if (stage == EStage::CONFIG) {
  122. return true;
  123. }
  124. TStringBuilder nearHandlerMsg;
  125. for (auto& item: Handlers) {
  126. if (NLevenshtein::Distance(normalizedName, item.first) < DefaultMistypeDistance) {
  127. nearHandlerMsg << ", did you mean " << item.second->GetDisplayName().Quote() << '?';
  128. break;
  129. }
  130. }
  131. return errorCallback(TStringBuilder() << "Unknown setting name " << name.Quote() << nearHandlerMsg, true);
  132. }
  133. }
  134. void TSettingDispatcher::FreezeDefaults() {
  135. for (auto& item: Handlers) {
  136. item.second->FreezeDefault();
  137. }
  138. }
  139. void TSettingDispatcher::Restore() {
  140. for (auto& item: Handlers) {
  141. item.second->Restore(ALL_CLUSTERS);
  142. }
  143. }
  144. TSettingDispatcher::TErrorCallback TSettingDispatcher::GetDefaultErrorCallback() {
  145. return [] (const TString& msg, bool isError) -> bool {
  146. if (isError) {
  147. YQL_LOG(ERROR) << msg;
  148. throw yexception() << msg;
  149. }
  150. YQL_LOG(WARN) << msg;
  151. return true;
  152. };
  153. }
  154. TSettingDispatcher::TErrorCallback TSettingDispatcher::GetErrorCallback(TPositionHandle pos, TExprContext& ctx) {
  155. return [pos, &ctx](const TString& msg, bool isError) -> bool {
  156. if (isError) {
  157. ctx.AddError(YqlIssue(ctx.GetPosition(pos), TIssuesIds::DEFAULT_ERROR, msg));
  158. return false;
  159. } else {
  160. return ctx.AddWarning(YqlIssue(ctx.GetPosition(pos), TIssuesIds::YQL_PRAGMA_WARNING_MSG, msg));
  161. }
  162. };
  163. }
  164. } // NCommon
  165. } // NYql