jsonpath.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #include "jsonpath.h"
  2. #include "binary.h"
  3. #include "ast_builder.h"
  4. #include "executor.h"
  5. #include "type_check.h"
  6. #include "value.h"
  7. #include <yql/essentials/core/issue/protos/issue_id.pb.h>
  8. #include <yql/essentials/parser/proto_ast/gen/jsonpath/JsonPathLexer.h>
  9. #include <yql/essentials/parser/proto_ast/gen/jsonpath/JsonPathParser.h>
  10. #include <yql/essentials/parser/proto_ast/gen/jsonpath/JsonPathParser.pb.h>
  11. #include <yql/essentials/parser/proto_ast/antlr3/proto_ast_antlr3.h>
  12. #include <google/protobuf/message.h>
  13. #include <util/string/strip.h>
  14. #if defined(_tsan_enabled_)
  15. #include <util/system/mutex.h>
  16. #endif
  17. using namespace NYql;
  18. using namespace NYql::NUdf;
  19. using namespace NJson;
  20. namespace {
  21. #if defined(_tsan_enabled_)
  22. TMutex SanitizerJsonPathTranslationMutex;
  23. #endif
  24. class TParseErrorsCollector : public NProtoAST::IErrorCollector {
  25. public:
  26. TParseErrorsCollector(TIssues& issues, size_t maxErrors)
  27. : IErrorCollector(maxErrors)
  28. , Issues(issues)
  29. {
  30. }
  31. private:
  32. void AddError(ui32 line, ui32 column, const TString& message) override {
  33. Issues.AddIssue(TPosition(column, line, "jsonpath"), StripString(message));
  34. Issues.back().SetCode(TIssuesIds::JSONPATH_PARSE_ERROR, TSeverityIds::S_ERROR);
  35. }
  36. TIssues& Issues;
  37. };
  38. }
  39. namespace NYql::NJsonPath {
  40. const TAstNodePtr ParseJsonPathAst(const TStringBuf path, TIssues& issues, size_t maxParseErrors) {
  41. if (!IsUtf(path)) {
  42. issues.AddIssue(TPosition(1, 1, "jsonpath"), "JsonPath must be UTF-8 encoded string");
  43. issues.back().SetCode(TIssuesIds::JSONPATH_PARSE_ERROR, TSeverityIds::S_ERROR);
  44. return {};
  45. }
  46. google::protobuf::Arena arena;
  47. const google::protobuf::Message* rawAst = nullptr;
  48. {
  49. #if defined(_tsan_enabled_)
  50. TGuard<TMutex> guard(SanitizerJsonPathTranslationMutex);
  51. #endif
  52. NProtoAST::TProtoASTBuilder3<NALP::JsonPathParser, NALP::JsonPathLexer> builder(path, "JsonPath", &arena);
  53. TParseErrorsCollector collector(issues, maxParseErrors);
  54. rawAst = builder.BuildAST(collector);
  55. }
  56. if (rawAst == nullptr) {
  57. return nullptr;
  58. }
  59. const google::protobuf::Descriptor* descriptor = rawAst->GetDescriptor();
  60. if (descriptor && descriptor->name() != "TJsonPathParserAST") {
  61. return nullptr;
  62. }
  63. const auto* protoAst = static_cast<const NJsonPathGenerated::TJsonPathParserAST*>(rawAst);
  64. TAstBuilder astBuilder(issues);
  65. TAstNodePtr ast = astBuilder.Build(*protoAst);
  66. if (!issues.Empty()) {
  67. return nullptr;
  68. }
  69. // At this point AST is guaranteed to be valid. We return it even if
  70. // type checker finds some logical errors.
  71. TJsonPathTypeChecker checker(issues);
  72. ast->Accept(checker);
  73. return ast;
  74. }
  75. const TJsonPathPtr PackBinaryJsonPath(const TAstNodePtr ast) {
  76. TJsonPathBuilder builder;
  77. ast->Accept(builder);
  78. return builder.ShrinkAndGetResult();
  79. }
  80. const TJsonPathPtr ParseJsonPath(const TStringBuf path, TIssues& issues, size_t maxParseErrors) {
  81. const auto ast = ParseJsonPathAst(path, issues, maxParseErrors);
  82. if (!issues.Empty()) {
  83. return {};
  84. }
  85. return PackBinaryJsonPath(ast);
  86. }
  87. TResult ExecuteJsonPath(
  88. const TJsonPathPtr jsonPath,
  89. const TValue& json,
  90. const TVariablesMap& variables,
  91. const NUdf::IValueBuilder* valueBuilder) {
  92. TExecutor executor(jsonPath, {json}, variables, valueBuilder);
  93. return executor.Execute();
  94. }
  95. TVariablesMap DictToVariables(const NUdf::TUnboxedValue& dict) {
  96. TVariablesMap variables;
  97. TUnboxedValue key;
  98. TUnboxedValue payload;
  99. auto it = dict.GetDictIterator();
  100. while (it.NextPair(key, payload)) {
  101. variables[key.AsStringRef()] = TValue(payload);
  102. }
  103. return variables;
  104. }
  105. }