sql_exists.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #pragma once
  2. #include "resource.h"
  3. #include "compile_path.h"
  4. #include <yql/essentials/public/udf/udf_type_builder.h>
  5. #include <yql/essentials/public/udf/udf_value.h>
  6. #include <yql/essentials/public/udf/udf_helpers.h>
  7. #include <util/generic/yexception.h>
  8. namespace NJson2Udf {
  9. using namespace NKikimr;
  10. using namespace NUdf;
  11. using namespace NYql;
  12. using namespace NJsonPath;
  13. template <EDataSlot InputType, bool ThrowException>
  14. class TSqlExists: public TBoxedValue {
  15. public:
  16. explicit TSqlExists(TSourcePosition pos)
  17. : Pos_(pos)
  18. {
  19. }
  20. static TStringRef Name();
  21. static bool DeclareSignature(
  22. const TStringRef& name,
  23. TType* userType,
  24. IFunctionTypeInfoBuilder& builder,
  25. bool typesOnly) {
  26. Y_UNUSED(userType);
  27. if (name != Name()) {
  28. return false;
  29. }
  30. auto jsonType = builder.Resource(JSON_NODE_RESOURCE_NAME);
  31. TType* inputType = nullptr;
  32. if constexpr (InputType == EDataSlot::JsonDocument) {
  33. inputType = builder.SimpleType<TJsonDocument>();
  34. } else {
  35. inputType = jsonType;
  36. }
  37. auto inputOptionalType = builder.Optional()->Item(inputType).Build();
  38. auto jsonPathType = builder.Resource(JSONPATH_RESOURCE_NAME);
  39. auto dictType = builder.Dict()->Key<TUtf8>().Value(jsonType).Build();
  40. auto optionalBoolType = builder.Optional()->Item<bool>().Build();
  41. if constexpr (ThrowException) {
  42. builder.Args()
  43. ->Add(inputOptionalType)
  44. .Add(jsonPathType)
  45. .Add(dictType)
  46. .Done()
  47. .Returns(optionalBoolType);
  48. } else {
  49. builder.Args()
  50. ->Add(inputOptionalType)
  51. .Add(jsonPathType)
  52. .Add(dictType)
  53. .Add(optionalBoolType)
  54. .Done()
  55. .Returns(optionalBoolType);
  56. }
  57. if (!typesOnly) {
  58. builder.Implementation(new TSqlExists(builder.GetSourcePosition()));
  59. }
  60. if constexpr (!ThrowException) {
  61. builder.IsStrict();
  62. }
  63. return true;
  64. }
  65. private:
  66. TUnboxedValue Run(
  67. const IValueBuilder* valueBuilder,
  68. const TUnboxedValuePod* args) const final {
  69. Y_UNUSED(valueBuilder);
  70. try {
  71. if (!args[0].HasValue()) {
  72. return TUnboxedValuePod();
  73. }
  74. TValue jsonDom;
  75. if constexpr (InputType == EDataSlot::JsonDocument) {
  76. jsonDom = TValue(NBinaryJson::TBinaryJsonReader::Make(args[0].AsStringRef())->GetRootCursor());
  77. } else {
  78. jsonDom = TValue(args[0]);
  79. }
  80. auto* jsonPathResource = static_cast<TJsonPathResource*>(args[1].AsBoxed().Get());
  81. const auto& jsonPath = *jsonPathResource->Get();
  82. const auto variables = DictToVariables(args[2]);
  83. const auto result = ExecuteJsonPath(jsonPath, jsonDom, variables, valueBuilder);
  84. if (result.IsError()) {
  85. if constexpr (ThrowException) {
  86. ythrow yexception() << "Error executing jsonpath:" << Endl << result.GetError() << Endl;
  87. } else {
  88. return args[3];
  89. }
  90. }
  91. return TUnboxedValuePod(!result.GetNodes().empty());
  92. } catch (const std::exception& e) {
  93. UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).data());
  94. }
  95. }
  96. TSourcePosition Pos_;
  97. };
  98. template <>
  99. TStringRef TSqlExists<EDataSlot::Json, false>::Name() {
  100. return "SqlExists";
  101. }
  102. template <>
  103. TStringRef TSqlExists<EDataSlot::Json, true>::Name() {
  104. return "SqlTryExists";
  105. }
  106. template <>
  107. TStringRef TSqlExists<EDataSlot::JsonDocument, false>::Name() {
  108. return "JsonDocumentSqlExists";
  109. }
  110. template <>
  111. TStringRef TSqlExists<EDataSlot::JsonDocument, true>::Name() {
  112. return "JsonDocumentSqlTryExists";
  113. }
  114. }