summaryrefslogtreecommitdiffstats
path: root/yql/essentials/udfs/common/json2
diff options
context:
space:
mode:
authorvvvv <[email protected]>2025-10-06 13:26:25 +0300
committervvvv <[email protected]>2025-10-06 14:06:25 +0300
commiteca8ce9cb1613d5c983185c4e43c20651a9638aa (patch)
tree61ee5ae779948e61af9a7691d19eaa2c09869121 /yql/essentials/udfs/common/json2
parent4adf7eecae16a9b228b28cc5f64c27ef69ad5ec2 (diff)
YQL-20086 udfs
init commit_hash:f9684778bf1ea956965f2360b80b91edb7d4ffbe
Diffstat (limited to 'yql/essentials/udfs/common/json2')
-rw-r--r--yql/essentials/udfs/common/json2/as_json_node.h171
-rw-r--r--yql/essentials/udfs/common/json2/compile_path.h101
-rw-r--r--yql/essentials/udfs/common/json2/json2_udf.cpp60
-rw-r--r--yql/essentials/udfs/common/json2/parse.h91
-rw-r--r--yql/essentials/udfs/common/json2/resource.h17
-rw-r--r--yql/essentials/udfs/common/json2/serialize.h127
-rw-r--r--yql/essentials/udfs/common/json2/sql_exists.h205
-rw-r--r--yql/essentials/udfs/common/json2/sql_query.h281
-rw-r--r--yql/essentials/udfs/common/json2/sql_value.h472
-rw-r--r--yql/essentials/udfs/common/json2/ya.make2
10 files changed, 761 insertions, 766 deletions
diff --git a/yql/essentials/udfs/common/json2/as_json_node.h b/yql/essentials/udfs/common/json2/as_json_node.h
index 6060f03bea8..82c51802433 100644
--- a/yql/essentials/udfs/common/json2/as_json_node.h
+++ b/yql/essentials/udfs/common/json2/as_json_node.h
@@ -8,108 +8,107 @@
#include <yql/essentials/minikql/dom/json.h>
namespace NJson2Udf {
- using namespace NKikimr;
- using namespace NUdf;
- using namespace NYql;
- using namespace NDom;
-
- template <typename TSource>
- class TAsJsonNode: public TBoxedValue {
- public:
- TAsJsonNode(TSourcePosition pos)
- : Pos_(pos)
- {
+using namespace NKikimr;
+using namespace NUdf;
+using namespace NYql;
+using namespace NDom;
+
+template <typename TSource>
+class TAsJsonNode: public TBoxedValue {
+public:
+ TAsJsonNode(TSourcePosition pos)
+ : Pos_(pos)
+ {
+ }
+
+ static TStringRef Name();
+
+ static bool DeclareSignature(
+ const TStringRef& name,
+ TType* userType,
+ IFunctionTypeInfoBuilder& builder,
+ bool typesOnly) {
+ Y_UNUSED(userType);
+ if (name != Name()) {
+ return false;
}
- static TStringRef Name();
+ auto optionalSourceType = builder.Optional()->Item<TSource>().Build();
+ auto resourceType = builder.Resource(JSON_NODE_RESOURCE_NAME);
+ builder.Args()
+ ->Add(optionalSourceType)
+ .Done()
+ .Returns(resourceType);
- static bool DeclareSignature(
- const TStringRef& name,
- TType* userType,
- IFunctionTypeInfoBuilder& builder,
- bool typesOnly) {
- Y_UNUSED(userType);
- if (name != Name()) {
- return false;
- }
+ if (!typesOnly) {
+ builder.Implementation(new TAsJsonNode<TSource>(builder.GetSourcePosition()));
+ }
- auto optionalSourceType = builder.Optional()->Item<TSource>().Build();
- auto resourceType = builder.Resource(JSON_NODE_RESOURCE_NAME);
- builder.Args()
- ->Add(optionalSourceType)
- .Done()
- .Returns(resourceType);
+ builder.IsStrict();
+ return true;
+ }
- if (!typesOnly) {
- builder.Implementation(new TAsJsonNode<TSource>(builder.GetSourcePosition()));
- }
+private:
+ const size_t MaxParseErrors_ = 10;
- builder.IsStrict();
- return true;
- }
+ static TUnboxedValue Interpret(const TUnboxedValue& sourceValue, const IValueBuilder* valueBuilder);
- private:
- const size_t MaxParseErrors_ = 10;
-
- static TUnboxedValue Interpret(const TUnboxedValue& sourceValue, const IValueBuilder* valueBuilder);
-
- TUnboxedValue Run(
- const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const final {
- Y_UNUSED(valueBuilder);
- try {
- if (!args[0].HasValue()) {
- return MakeEntity();
- }
- return Interpret(args[0], valueBuilder);
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).c_str());
+ TUnboxedValue Run(
+ const IValueBuilder* valueBuilder,
+ const TUnboxedValuePod* args) const final {
+ Y_UNUSED(valueBuilder);
+ try {
+ if (!args[0].HasValue()) {
+ return MakeEntity();
}
+ return Interpret(args[0], valueBuilder);
+ } catch (const std::exception& e) {
+ UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).c_str());
}
-
- TSourcePosition Pos_;
- };
-
- template <>
- TStringRef TAsJsonNode<TUtf8>::Name() {
- return TStringRef::Of("Utf8AsJsonNode");
}
- template <>
- TUnboxedValue TAsJsonNode<TUtf8>::Interpret(const TUnboxedValue& sourceValue, const IValueBuilder* valueBuilder) {
- return MakeString(sourceValue.AsStringRef(), valueBuilder);
- }
+ TSourcePosition Pos_;
+};
- template <>
- TStringRef TAsJsonNode<double>::Name() {
- return TStringRef::Of("DoubleAsJsonNode");
- }
+template <>
+TStringRef TAsJsonNode<TUtf8>::Name() {
+ return TStringRef::Of("Utf8AsJsonNode");
+}
- template <>
- TUnboxedValue TAsJsonNode<double>::Interpret(const TUnboxedValue& sourceValue, const IValueBuilder* valueBuilder) {
- Y_UNUSED(valueBuilder);
- return MakeDouble(sourceValue.Get<double>());
- }
+template <>
+TUnboxedValue TAsJsonNode<TUtf8>::Interpret(const TUnboxedValue& sourceValue, const IValueBuilder* valueBuilder) {
+ return MakeString(sourceValue.AsStringRef(), valueBuilder);
+}
- template <>
- TStringRef TAsJsonNode<bool>::Name() {
- return TStringRef::Of("BoolAsJsonNode");
- }
+template <>
+TStringRef TAsJsonNode<double>::Name() {
+ return TStringRef::Of("DoubleAsJsonNode");
+}
- template <>
- TUnboxedValue TAsJsonNode<bool>::Interpret(const TUnboxedValue& sourceValue, const IValueBuilder* valueBuilder) {
- Y_UNUSED(valueBuilder);
- return MakeBool(sourceValue.Get<bool>());
- }
+template <>
+TUnboxedValue TAsJsonNode<double>::Interpret(const TUnboxedValue& sourceValue, const IValueBuilder* valueBuilder) {
+ Y_UNUSED(valueBuilder);
+ return MakeDouble(sourceValue.Get<double>());
+}
- template <>
- TStringRef TAsJsonNode<TJson>::Name() {
- return TStringRef::Of("JsonAsJsonNode");
- }
+template <>
+TStringRef TAsJsonNode<bool>::Name() {
+ return TStringRef::Of("BoolAsJsonNode");
+}
- template <>
- TUnboxedValue TAsJsonNode<TJson>::Interpret(const TUnboxedValue& sourceValue, const IValueBuilder* valueBuilder) {
- return TryParseJsonDom(sourceValue.AsStringRef(), valueBuilder);
- }
+template <>
+TUnboxedValue TAsJsonNode<bool>::Interpret(const TUnboxedValue& sourceValue, const IValueBuilder* valueBuilder) {
+ Y_UNUSED(valueBuilder);
+ return MakeBool(sourceValue.Get<bool>());
}
+template <>
+TStringRef TAsJsonNode<TJson>::Name() {
+ return TStringRef::Of("JsonAsJsonNode");
+}
+
+template <>
+TUnboxedValue TAsJsonNode<TJson>::Interpret(const TUnboxedValue& sourceValue, const IValueBuilder* valueBuilder) {
+ return TryParseJsonDom(sourceValue.AsStringRef(), valueBuilder);
+}
+} // namespace NJson2Udf
diff --git a/yql/essentials/udfs/common/json2/compile_path.h b/yql/essentials/udfs/common/json2/compile_path.h
index 220bd4fbaf6..f932c6df60c 100644
--- a/yql/essentials/udfs/common/json2/compile_path.h
+++ b/yql/essentials/udfs/common/json2/compile_path.h
@@ -6,65 +6,64 @@
#include <yql/essentials/public/udf/udf_helpers.h>
namespace NJson2Udf {
- using namespace NKikimr;
- using namespace NUdf;
- using namespace NYql;
+using namespace NKikimr;
+using namespace NUdf;
+using namespace NYql;
- class TCompilePath: public TBoxedValue {
- public:
- TCompilePath(TSourcePosition pos)
- : Pos_(pos)
- {
- }
+class TCompilePath: public TBoxedValue {
+public:
+ TCompilePath(TSourcePosition pos)
+ : Pos_(pos)
+ {
+ }
- static const TStringRef& Name() {
- static auto name = TStringRef::Of("CompilePath");
- return name;
- }
+ static const TStringRef& Name() {
+ static auto name = TStringRef::Of("CompilePath");
+ return name;
+ }
- static bool DeclareSignature(
- const TStringRef& name,
- TType* userType,
- IFunctionTypeInfoBuilder& builder,
- bool typesOnly) {
- Y_UNUSED(userType);
- if (name != Name()) {
- return false;
- }
+ static bool DeclareSignature(
+ const TStringRef& name,
+ TType* userType,
+ IFunctionTypeInfoBuilder& builder,
+ bool typesOnly) {
+ Y_UNUSED(userType);
+ if (name != Name()) {
+ return false;
+ }
- auto resourceType = builder.Resource(JSONPATH_RESOURCE_NAME);
- builder.Args()
- ->Add<NUdf::TUtf8>()
- .Done()
- .Returns(resourceType);
+ auto resourceType = builder.Resource(JSONPATH_RESOURCE_NAME);
+ builder.Args()
+ ->Add<NUdf::TUtf8>()
+ .Done()
+ .Returns(resourceType);
- if (!typesOnly) {
- builder.Implementation(new TCompilePath(builder.GetSourcePosition()));
- }
- return true;
+ if (!typesOnly) {
+ builder.Implementation(new TCompilePath(builder.GetSourcePosition()));
}
+ return true;
+ }
- private:
- const size_t MaxParseErrors_ = 10;
-
- TUnboxedValue Run(
- const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const final {
- Y_UNUSED(valueBuilder);
- try {
- TIssues issues;
- const auto jsonPath = NJsonPath::ParseJsonPath(args[0].AsStringRef(), issues, MaxParseErrors_);
- if (!issues.Empty()) {
- ythrow yexception() << "Error parsing jsonpath:" << Endl << issues.ToString();
- }
+private:
+ const size_t MaxParseErrors_ = 10;
- return TUnboxedValuePod(new TJsonPathResource(jsonPath));
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).c_str());
+ TUnboxedValue Run(
+ const IValueBuilder* valueBuilder,
+ const TUnboxedValuePod* args) const final {
+ Y_UNUSED(valueBuilder);
+ try {
+ TIssues issues;
+ const auto jsonPath = NJsonPath::ParseJsonPath(args[0].AsStringRef(), issues, MaxParseErrors_);
+ if (!issues.Empty()) {
+ ythrow yexception() << "Error parsing jsonpath:" << Endl << issues.ToString();
}
- }
- TSourcePosition Pos_;
- };
-}
+ return TUnboxedValuePod(new TJsonPathResource(jsonPath));
+ } catch (const std::exception& e) {
+ UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).c_str());
+ }
+ }
+ TSourcePosition Pos_;
+};
+} // namespace NJson2Udf
diff --git a/yql/essentials/udfs/common/json2/json2_udf.cpp b/yql/essentials/udfs/common/json2/json2_udf.cpp
index 96ef6ccf00b..76c4ef786db 100644
--- a/yql/essentials/udfs/common/json2/json2_udf.cpp
+++ b/yql/essentials/udfs/common/json2/json2_udf.cpp
@@ -9,35 +9,35 @@
#include <yql/essentials/public/udf/udf_helpers.h>
namespace NJson2Udf {
- SIMPLE_MODULE(TJson2Module,
- TParse,
- TSerialize<EDataSlot::Json>,
- TSerialize<EDataSlot::JsonDocument>,
- TCompilePath,
- TSqlValue<EDataSlot::Json, TUtf8>,
- TSqlValue<EDataSlot::Json, TUtf8, true>,
- TSqlValue<EDataSlot::Json, i64>,
- TSqlValue<EDataSlot::Json, double>,
- TSqlValue<EDataSlot::Json, bool>,
- TSqlValue<EDataSlot::JsonDocument, TUtf8>,
- TSqlValue<EDataSlot::JsonDocument, TUtf8, true>,
- TSqlValue<EDataSlot::JsonDocument, i64>,
- TSqlValue<EDataSlot::JsonDocument, double>,
- TSqlValue<EDataSlot::JsonDocument, bool>,
- TSqlExists<EDataSlot::Json, false>,
- TSqlExists<EDataSlot::Json, true>,
- TSqlExists<EDataSlot::JsonDocument, false>,
- TSqlExists<EDataSlot::JsonDocument, true>,
- TSqlQuery<EDataSlot::Json, EJsonQueryWrap::NoWrap>,
- TSqlQuery<EDataSlot::Json, EJsonQueryWrap::Wrap>,
- TSqlQuery<EDataSlot::Json, EJsonQueryWrap::ConditionalWrap>,
- TSqlQuery<EDataSlot::JsonDocument, EJsonQueryWrap::NoWrap>,
- TSqlQuery<EDataSlot::JsonDocument, EJsonQueryWrap::Wrap>,
- TSqlQuery<EDataSlot::JsonDocument, EJsonQueryWrap::ConditionalWrap>,
- TAsJsonNode<TUtf8>,
- TAsJsonNode<double>,
- TAsJsonNode<bool>,
- TAsJsonNode<TJson>)
-}
+SIMPLE_MODULE(TJson2Module,
+ TParse,
+ TSerialize<EDataSlot::Json>,
+ TSerialize<EDataSlot::JsonDocument>,
+ TCompilePath,
+ TSqlValue<EDataSlot::Json, TUtf8>,
+ TSqlValue<EDataSlot::Json, TUtf8, true>,
+ TSqlValue<EDataSlot::Json, i64>,
+ TSqlValue<EDataSlot::Json, double>,
+ TSqlValue<EDataSlot::Json, bool>,
+ TSqlValue<EDataSlot::JsonDocument, TUtf8>,
+ TSqlValue<EDataSlot::JsonDocument, TUtf8, true>,
+ TSqlValue<EDataSlot::JsonDocument, i64>,
+ TSqlValue<EDataSlot::JsonDocument, double>,
+ TSqlValue<EDataSlot::JsonDocument, bool>,
+ TSqlExists<EDataSlot::Json, false>,
+ TSqlExists<EDataSlot::Json, true>,
+ TSqlExists<EDataSlot::JsonDocument, false>,
+ TSqlExists<EDataSlot::JsonDocument, true>,
+ TSqlQuery<EDataSlot::Json, EJsonQueryWrap::NoWrap>,
+ TSqlQuery<EDataSlot::Json, EJsonQueryWrap::Wrap>,
+ TSqlQuery<EDataSlot::Json, EJsonQueryWrap::ConditionalWrap>,
+ TSqlQuery<EDataSlot::JsonDocument, EJsonQueryWrap::NoWrap>,
+ TSqlQuery<EDataSlot::JsonDocument, EJsonQueryWrap::Wrap>,
+ TSqlQuery<EDataSlot::JsonDocument, EJsonQueryWrap::ConditionalWrap>,
+ TAsJsonNode<TUtf8>,
+ TAsJsonNode<double>,
+ TAsJsonNode<bool>,
+ TAsJsonNode<TJson>)
+} // namespace NJson2Udf
REGISTER_MODULES(NJson2Udf::TJson2Module)
diff --git a/yql/essentials/udfs/common/json2/parse.h b/yql/essentials/udfs/common/json2/parse.h
index 6df4bce9b0a..72db2106fa5 100644
--- a/yql/essentials/udfs/common/json2/parse.h
+++ b/yql/essentials/udfs/common/json2/parse.h
@@ -9,58 +9,57 @@
#include <library/cpp/json/json_reader.h>
namespace NJson2Udf {
- using namespace NKikimr;
- using namespace NUdf;
- using namespace NYql;
- using namespace NDom;
+using namespace NKikimr;
+using namespace NUdf;
+using namespace NYql;
+using namespace NDom;
- class TParse: public TBoxedValue {
- public:
- TParse(TSourcePosition pos)
- : Pos_(pos)
- {
- }
+class TParse: public TBoxedValue {
+public:
+ TParse(TSourcePosition pos)
+ : Pos_(pos)
+ {
+ }
- static const TStringRef& Name() {
- static auto name = TStringRef::Of("Parse");
- return name;
- }
+ static const TStringRef& Name() {
+ static auto name = TStringRef::Of("Parse");
+ return name;
+ }
- static bool DeclareSignature(
- const TStringRef& name,
- TType* userType,
- IFunctionTypeInfoBuilder& builder,
- bool typesOnly) {
- Y_UNUSED(userType);
- if (name != Name()) {
- return false;
- }
+ static bool DeclareSignature(
+ const TStringRef& name,
+ TType* userType,
+ IFunctionTypeInfoBuilder& builder,
+ bool typesOnly) {
+ Y_UNUSED(userType);
+ if (name != Name()) {
+ return false;
+ }
- builder.Args()
- ->Add<TAutoMap<TJson>>()
- .Done()
- .Returns<TJsonNodeResource>();
+ builder.Args()
+ ->Add<TAutoMap<TJson>>()
+ .Done()
+ .Returns<TJsonNodeResource>();
- if (!typesOnly) {
- builder.Implementation(new TParse(builder.GetSourcePosition()));
- }
- return true;
+ if (!typesOnly) {
+ builder.Implementation(new TParse(builder.GetSourcePosition()));
}
+ return true;
+ }
- private:
- TUnboxedValue Run(
- const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const final {
- Y_UNUSED(valueBuilder);
- try {
- const auto json = args[0].AsStringRef();
- return TryParseJsonDom(json, valueBuilder);
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).c_str());
- }
+private:
+ TUnboxedValue Run(
+ const IValueBuilder* valueBuilder,
+ const TUnboxedValuePod* args) const final {
+ Y_UNUSED(valueBuilder);
+ try {
+ const auto json = args[0].AsStringRef();
+ return TryParseJsonDom(json, valueBuilder);
+ } catch (const std::exception& e) {
+ UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).c_str());
}
+ }
- TSourcePosition Pos_;
- };
-}
-
+ TSourcePosition Pos_;
+};
+} // namespace NJson2Udf
diff --git a/yql/essentials/udfs/common/json2/resource.h b/yql/essentials/udfs/common/json2/resource.h
index aa65b14818d..5d2cc6e7b0b 100644
--- a/yql/essentials/udfs/common/json2/resource.h
+++ b/yql/essentials/udfs/common/json2/resource.h
@@ -4,14 +4,13 @@
#include <yql/essentials/minikql/jsonpath/jsonpath.h>
namespace NJson2Udf {
- using namespace NKikimr;
- using namespace NUdf;
- using namespace NYql;
+using namespace NKikimr;
+using namespace NUdf;
+using namespace NYql;
- extern const char JSONPATH_RESOURCE_NAME[] = "JsonPath";
- using TJsonPathResource = TBoxedResource<NJsonPath::TJsonPathPtr, JSONPATH_RESOURCE_NAME>;
-
- extern const char JSON_NODE_RESOURCE_NAME[] = "JsonNode";
- using TJsonNodeResource = TResource<JSON_NODE_RESOURCE_NAME>;
-}
+extern const char JSONPATH_RESOURCE_NAME[] = "JsonPath";
+using TJsonPathResource = TBoxedResource<NJsonPath::TJsonPathPtr, JSONPATH_RESOURCE_NAME>;
+extern const char JSON_NODE_RESOURCE_NAME[] = "JsonNode";
+using TJsonNodeResource = TResource<JSON_NODE_RESOURCE_NAME>;
+} // namespace NJson2Udf
diff --git a/yql/essentials/udfs/common/json2/serialize.h b/yql/essentials/udfs/common/json2/serialize.h
index cda95e77f5a..2443259fbee 100644
--- a/yql/essentials/udfs/common/json2/serialize.h
+++ b/yql/essentials/udfs/common/json2/serialize.h
@@ -9,81 +9,80 @@
#include <yql/essentials/types/binary_json/write.h>
namespace NJson2Udf {
- using namespace NKikimr;
- using namespace NUdf;
- using namespace NYql;
- using namespace NDom;
- using namespace NBinaryJson;
-
- template <EDataSlot ResultType>
- class TSerialize : public TBoxedValue {
- public:
- TSerialize(TSourcePosition pos)
- : Pos_(pos)
- {
- }
+using namespace NKikimr;
+using namespace NUdf;
+using namespace NYql;
+using namespace NDom;
+using namespace NBinaryJson;
+
+template <EDataSlot ResultType>
+class TSerialize: public TBoxedValue {
+public:
+ TSerialize(TSourcePosition pos)
+ : Pos_(pos)
+ {
+ }
- static const TStringRef& Name();
+ static const TStringRef& Name();
- static bool DeclareSignature(
- const TStringRef& name,
- TType* userType,
- IFunctionTypeInfoBuilder& builder,
- bool typesOnly) {
- Y_UNUSED(userType);
- if (name != Name()) {
- return false;
- }
+ static bool DeclareSignature(
+ const TStringRef& name,
+ TType* userType,
+ IFunctionTypeInfoBuilder& builder,
+ bool typesOnly) {
+ Y_UNUSED(userType);
+ if (name != Name()) {
+ return false;
+ }
- TType* resultType = nullptr;
- if constexpr (ResultType == EDataSlot::Json) {
- resultType = builder.SimpleType<TJson>();
- } else {
- resultType = builder.SimpleType<TJsonDocument>();
- }
+ TType* resultType = nullptr;
+ if constexpr (ResultType == EDataSlot::Json) {
+ resultType = builder.SimpleType<TJson>();
+ } else {
+ resultType = builder.SimpleType<TJsonDocument>();
+ }
- builder.Args()
- ->Add<TAutoMap<TJsonNodeResource>>()
- .Done()
- .Returns(resultType);
+ builder.Args()
+ ->Add<TAutoMap<TJsonNodeResource>>()
+ .Done()
+ .Returns(resultType);
- if (!typesOnly) {
- builder.Implementation(new TSerialize(builder.GetSourcePosition()));
- }
- return true;
+ if (!typesOnly) {
+ builder.Implementation(new TSerialize(builder.GetSourcePosition()));
}
+ return true;
+ }
- private:
- TUnboxedValue Run(
- const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const final {
- try {
- const TUnboxedValue& jsonDom = args[0];
+private:
+ TUnboxedValue Run(
+ const IValueBuilder* valueBuilder,
+ const TUnboxedValuePod* args) const final {
+ try {
+ const TUnboxedValue& jsonDom = args[0];
- if constexpr (ResultType == EDataSlot::Json) {
- return valueBuilder->NewString(SerializeJsonDom(jsonDom));
- } else {
- const auto binaryJson = SerializeToBinaryJson(jsonDom);
- return valueBuilder->NewString(TStringBuf(binaryJson.Data(), binaryJson.Size()));
- }
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).c_str());
+ if constexpr (ResultType == EDataSlot::Json) {
+ return valueBuilder->NewString(SerializeJsonDom(jsonDom));
+ } else {
+ const auto binaryJson = SerializeToBinaryJson(jsonDom);
+ return valueBuilder->NewString(TStringBuf(binaryJson.Data(), binaryJson.Size()));
}
+ } catch (const std::exception& e) {
+ UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).c_str());
}
-
- TSourcePosition Pos_;
- };
-
- template <>
- const TStringRef& TSerialize<EDataSlot::Json>::Name() {
- static auto name = TStringRef::Of("Serialize");
- return name;
}
- template <>
- const TStringRef& TSerialize<EDataSlot::JsonDocument>::Name() {
- static auto name = TStringRef::Of("SerializeToJsonDocument");
- return name;
- }
+ TSourcePosition Pos_;
+};
+
+template <>
+const TStringRef& TSerialize<EDataSlot::Json>::Name() {
+ static auto name = TStringRef::Of("Serialize");
+ return name;
}
+template <>
+const TStringRef& TSerialize<EDataSlot::JsonDocument>::Name() {
+ static auto name = TStringRef::Of("SerializeToJsonDocument");
+ return name;
+}
+} // namespace NJson2Udf
diff --git a/yql/essentials/udfs/common/json2/sql_exists.h b/yql/essentials/udfs/common/json2/sql_exists.h
index cb89f20ec21..955c1b1ce7f 100644
--- a/yql/essentials/udfs/common/json2/sql_exists.h
+++ b/yql/essentials/udfs/common/json2/sql_exists.h
@@ -10,126 +10,125 @@
#include <util/generic/yexception.h>
namespace NJson2Udf {
- using namespace NKikimr;
- using namespace NUdf;
- using namespace NYql;
- using namespace NJsonPath;
-
- template <EDataSlot InputType, bool ThrowException>
- class TSqlExists: public TBoxedValue {
- public:
- explicit TSqlExists(TSourcePosition pos)
- : Pos_(pos)
- {
+using namespace NKikimr;
+using namespace NUdf;
+using namespace NYql;
+using namespace NJsonPath;
+
+template <EDataSlot InputType, bool ThrowException>
+class TSqlExists: public TBoxedValue {
+public:
+ explicit TSqlExists(TSourcePosition pos)
+ : Pos_(pos)
+ {
+ }
+
+ static TStringRef Name();
+
+ static bool DeclareSignature(
+ const TStringRef& name,
+ TType* userType,
+ IFunctionTypeInfoBuilder& builder,
+ bool typesOnly) {
+ Y_UNUSED(userType);
+ if (name != Name()) {
+ return false;
}
- static TStringRef Name();
+ auto jsonType = builder.Resource(JSON_NODE_RESOURCE_NAME);
+ TType* inputType = nullptr;
+ if constexpr (InputType == EDataSlot::JsonDocument) {
+ inputType = builder.SimpleType<TJsonDocument>();
+ } else {
+ inputType = jsonType;
+ }
+ auto inputOptionalType = builder.Optional()->Item(inputType).Build();
+ auto jsonPathType = builder.Resource(JSONPATH_RESOURCE_NAME);
+ auto dictType = builder.Dict()->Key<TUtf8>().Value(jsonType).Build();
+ auto optionalBoolType = builder.Optional()->Item<bool>().Build();
+
+ if constexpr (ThrowException) {
+ builder.Args()
+ ->Add(inputOptionalType)
+ .Add(jsonPathType)
+ .Add(dictType)
+ .Done()
+ .Returns(optionalBoolType);
+ } else {
+ builder.Args()
+ ->Add(inputOptionalType)
+ .Add(jsonPathType)
+ .Add(dictType)
+ .Add(optionalBoolType)
+ .Done()
+ .Returns(optionalBoolType);
+ }
- static bool DeclareSignature(
- const TStringRef& name,
- TType* userType,
- IFunctionTypeInfoBuilder& builder,
- bool typesOnly) {
- Y_UNUSED(userType);
- if (name != Name()) {
- return false;
+ if (!typesOnly) {
+ builder.Implementation(new TSqlExists(builder.GetSourcePosition()));
+ }
+ if constexpr (!ThrowException) {
+ builder.IsStrict();
+ }
+ return true;
+ }
+
+private:
+ TUnboxedValue Run(
+ const IValueBuilder* valueBuilder,
+ const TUnboxedValuePod* args) const final {
+ Y_UNUSED(valueBuilder);
+ try {
+ if (!args[0].HasValue()) {
+ return TUnboxedValuePod();
}
- auto jsonType = builder.Resource(JSON_NODE_RESOURCE_NAME);
- TType* inputType = nullptr;
+ TValue jsonDom;
if constexpr (InputType == EDataSlot::JsonDocument) {
- inputType = builder.SimpleType<TJsonDocument>();
- } else {
- inputType = jsonType;
- }
- auto inputOptionalType = builder.Optional()->Item(inputType).Build();
- auto jsonPathType = builder.Resource(JSONPATH_RESOURCE_NAME);
- auto dictType = builder.Dict()->Key<TUtf8>().Value(jsonType).Build();
- auto optionalBoolType = builder.Optional()->Item<bool>().Build();
-
- if constexpr (ThrowException) {
- builder.Args()
- ->Add(inputOptionalType)
- .Add(jsonPathType)
- .Add(dictType)
- .Done()
- .Returns(optionalBoolType);
+ jsonDom = TValue(NBinaryJson::TBinaryJsonReader::Make(args[0].AsStringRef())->GetRootCursor());
} else {
- builder.Args()
- ->Add(inputOptionalType)
- .Add(jsonPathType)
- .Add(dictType)
- .Add(optionalBoolType)
- .Done()
- .Returns(optionalBoolType);
+ jsonDom = TValue(args[0]);
}
- if (!typesOnly) {
- builder.Implementation(new TSqlExists(builder.GetSourcePosition()));
- }
- if constexpr (!ThrowException) {
- builder.IsStrict();
- }
- return true;
- }
+ auto* jsonPathResource = static_cast<TJsonPathResource*>(args[1].AsBoxed().Get());
+ const auto& jsonPath = *jsonPathResource->Get();
+ const auto variables = DictToVariables(args[2]);
- private:
- TUnboxedValue Run(
- const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const final {
- Y_UNUSED(valueBuilder);
- try {
- if (!args[0].HasValue()) {
- return TUnboxedValuePod();
- }
-
- TValue jsonDom;
- if constexpr (InputType == EDataSlot::JsonDocument) {
- jsonDom = TValue(NBinaryJson::TBinaryJsonReader::Make(args[0].AsStringRef())->GetRootCursor());
+ const auto result = ExecuteJsonPath(jsonPath, jsonDom, variables, valueBuilder);
+ if (result.IsError()) {
+ if constexpr (ThrowException) {
+ ythrow yexception() << "Error executing jsonpath:" << Endl << result.GetError() << Endl;
} else {
- jsonDom = TValue(args[0]);
- }
-
- auto* jsonPathResource = static_cast<TJsonPathResource*>(args[1].AsBoxed().Get());
- const auto& jsonPath = *jsonPathResource->Get();
- const auto variables = DictToVariables(args[2]);
-
- const auto result = ExecuteJsonPath(jsonPath, jsonDom, variables, valueBuilder);
- if (result.IsError()) {
- if constexpr (ThrowException) {
- ythrow yexception() << "Error executing jsonpath:" << Endl << result.GetError() << Endl;
- } else {
- return args[3];
- }
+ return args[3];
}
-
- return TUnboxedValuePod(!result.GetNodes().empty());
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).c_str());
}
- }
-
- TSourcePosition Pos_;
- };
- template <>
- TStringRef TSqlExists<EDataSlot::Json, false>::Name() {
- return "SqlExists";
+ return TUnboxedValuePod(!result.GetNodes().empty());
+ } catch (const std::exception& e) {
+ UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).c_str());
+ }
}
- template <>
- TStringRef TSqlExists<EDataSlot::Json, true>::Name() {
- return "SqlTryExists";
- }
+ TSourcePosition Pos_;
+};
- template <>
- TStringRef TSqlExists<EDataSlot::JsonDocument, false>::Name() {
- return "JsonDocumentSqlExists";
- }
+template <>
+TStringRef TSqlExists<EDataSlot::Json, false>::Name() {
+ return "SqlExists";
+}
- template <>
- TStringRef TSqlExists<EDataSlot::JsonDocument, true>::Name() {
- return "JsonDocumentSqlTryExists";
- }
+template <>
+TStringRef TSqlExists<EDataSlot::Json, true>::Name() {
+ return "SqlTryExists";
}
+template <>
+TStringRef TSqlExists<EDataSlot::JsonDocument, false>::Name() {
+ return "JsonDocumentSqlExists";
+}
+
+template <>
+TStringRef TSqlExists<EDataSlot::JsonDocument, true>::Name() {
+ return "JsonDocumentSqlTryExists";
+}
+} // namespace NJson2Udf
diff --git a/yql/essentials/udfs/common/json2/sql_query.h b/yql/essentials/udfs/common/json2/sql_query.h
index 1c2d610f923..00bf6fb2d74 100644
--- a/yql/essentials/udfs/common/json2/sql_query.h
+++ b/yql/essentials/udfs/common/json2/sql_query.h
@@ -12,173 +12,172 @@
#include <util/generic/yexception.h>
namespace NJson2Udf {
- using namespace NKikimr;
- using namespace NUdf;
- using namespace NYql;
- using namespace NDom;
- using namespace NJsonPath;
-
- template <EDataSlot InputType, EJsonQueryWrap Mode>
- class TSqlQuery: public TBoxedValue {
- public:
- explicit TSqlQuery(TSourcePosition pos)
- : Pos_(pos)
- {
+using namespace NKikimr;
+using namespace NUdf;
+using namespace NYql;
+using namespace NDom;
+using namespace NJsonPath;
+
+template <EDataSlot InputType, EJsonQueryWrap Mode>
+class TSqlQuery: public TBoxedValue {
+public:
+ explicit TSqlQuery(TSourcePosition pos)
+ : Pos_(pos)
+ {
+ }
+
+ static TStringRef Name();
+
+ static bool DeclareSignature(
+ const TStringRef& name,
+ TType* userType,
+ IFunctionTypeInfoBuilder& builder,
+ bool typesOnly) {
+ Y_UNUSED(userType);
+ if (name != Name()) {
+ return false;
}
- static TStringRef Name();
+ auto jsonType = builder.Resource(JSON_NODE_RESOURCE_NAME);
+ auto optionalJsonType = builder.Optional()->Item(jsonType).Build();
+ TType* inputType = nullptr;
+ if constexpr (InputType == EDataSlot::JsonDocument) {
+ inputType = builder.SimpleType<TJsonDocument>();
+ } else {
+ inputType = jsonType;
+ }
+ auto inputOptionalType = builder.Optional()->Item(inputType).Build();
+ auto jsonPathType = builder.Resource(JSONPATH_RESOURCE_NAME);
+ auto dictType = builder.Dict()->Key<TUtf8>().Value(jsonType).Build();
+
+ /*
+ Arguments:
+ 0. Resource<JsonNode>? or JsonDocument?. Input json
+ 1. Resource<JsonPath>. Jsonpath to execute on json
+ 2. Dict<TUtf8, Resource<JsonNode>>. Variables to pass into jsonpath
+ 3. Bool. True - throw on empty result, false otherwise
+ 4. Resource<JsonNode>?. Default value to return on empty result. Ignored if 2d argument is true
+ 5. Bool. True - throw on error, false - otherwise
+ 6. Resource<JsonNode>?. Default value to return on error. Ignored if 4th argument is true
+ */
+ // we can't mark TSqlQuery as strict due to runtime throw policy setting
+ // TODO: optimizer can mark SqlQuery as strict if 3th/5th arguments are literal booleans
+ builder.Args()
+ ->Add(inputOptionalType)
+ .Add(jsonPathType)
+ .Add(dictType)
+ .Add<bool>()
+ .Add(optionalJsonType)
+ .Add<bool>()
+ .Add(optionalJsonType)
+ .Done()
+ .Returns(optionalJsonType);
+
+ if (!typesOnly) {
+ builder.Implementation(new TSqlQuery(builder.GetSourcePosition()));
+ }
+ return true;
+ }
- static bool DeclareSignature(
- const TStringRef& name,
- TType* userType,
- IFunctionTypeInfoBuilder& builder,
- bool typesOnly) {
- Y_UNUSED(userType);
- if (name != Name()) {
- return false;
+private:
+ TUnboxedValue Run(
+ const IValueBuilder* valueBuilder,
+ const TUnboxedValuePod* args) const final {
+ Y_UNUSED(valueBuilder);
+ try {
+ if (!args[0].HasValue()) {
+ return TUnboxedValuePod();
}
- auto jsonType = builder.Resource(JSON_NODE_RESOURCE_NAME);
- auto optionalJsonType = builder.Optional()->Item(jsonType).Build();
- TType* inputType = nullptr;
+ TValue jsonDom;
if constexpr (InputType == EDataSlot::JsonDocument) {
- inputType = builder.SimpleType<TJsonDocument>();
+ jsonDom = TValue(NBinaryJson::TBinaryJsonReader::Make(args[0].AsStringRef())->GetRootCursor());
} else {
- inputType = jsonType;
- }
- auto inputOptionalType = builder.Optional()->Item(inputType).Build();
- auto jsonPathType = builder.Resource(JSONPATH_RESOURCE_NAME);
- auto dictType = builder.Dict()->Key<TUtf8>().Value(jsonType).Build();
-
- /*
- Arguments:
- 0. Resource<JsonNode>? or JsonDocument?. Input json
- 1. Resource<JsonPath>. Jsonpath to execute on json
- 2. Dict<TUtf8, Resource<JsonNode>>. Variables to pass into jsonpath
- 3. Bool. True - throw on empty result, false otherwise
- 4. Resource<JsonNode>?. Default value to return on empty result. Ignored if 2d argument is true
- 5. Bool. True - throw on error, false - otherwise
- 6. Resource<JsonNode>?. Default value to return on error. Ignored if 4th argument is true
- */
- // we can't mark TSqlQuery as strict due to runtime throw policy setting
- // TODO: optimizer can mark SqlQuery as strict if 3th/5th arguments are literal booleans
- builder.Args()
- ->Add(inputOptionalType)
- .Add(jsonPathType)
- .Add(dictType)
- .Add<bool>()
- .Add(optionalJsonType)
- .Add<bool>()
- .Add(optionalJsonType)
- .Done()
- .Returns(optionalJsonType);
-
- if (!typesOnly) {
- builder.Implementation(new TSqlQuery(builder.GetSourcePosition()));
+ jsonDom = TValue(args[0]);
}
- return true;
- }
- private:
- TUnboxedValue Run(
- const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const final {
- Y_UNUSED(valueBuilder);
- try {
- if (!args[0].HasValue()) {
- return TUnboxedValuePod();
- }
+ auto* jsonPathResource = static_cast<TJsonPathResource*>(args[1].AsBoxed().Get());
+ const auto& jsonPath = *jsonPathResource->Get();
- TValue jsonDom;
- if constexpr (InputType == EDataSlot::JsonDocument) {
- jsonDom = TValue(NBinaryJson::TBinaryJsonReader::Make(args[0].AsStringRef())->GetRootCursor());
- } else {
- jsonDom = TValue(args[0]);
- }
-
- auto* jsonPathResource = static_cast<TJsonPathResource*>(args[1].AsBoxed().Get());
- const auto& jsonPath = *jsonPathResource->Get();
-
- const bool throwOnEmpty = args[3].Get<bool>();
- const auto emptyDefault = args[4];
- const bool throwOnError = args[5].Get<bool>();
- const auto errorDefault = args[6];
- const auto variables = DictToVariables(args[2]);
-
- auto result = ExecuteJsonPath(jsonPath, jsonDom, variables, valueBuilder);
+ const bool throwOnEmpty = args[3].Get<bool>();
+ const auto emptyDefault = args[4];
+ const bool throwOnError = args[5].Get<bool>();
+ const auto errorDefault = args[6];
+ const auto variables = DictToVariables(args[2]);
- const auto handleCase = [](TStringBuf message, bool throws, const TUnboxedValuePod& caseDefault) {
- if (throws) {
- ythrow yexception() << message;
- }
- return caseDefault;
- };
+ auto result = ExecuteJsonPath(jsonPath, jsonDom, variables, valueBuilder);
- if (result.IsError()) {
- return handleCase(TStringBuilder() << "Error executing jsonpath:" << Endl << result.GetError() << Endl, throwOnError, errorDefault);
+ const auto handleCase = [](TStringBuf message, bool throws, const TUnboxedValuePod& caseDefault) {
+ if (throws) {
+ ythrow yexception() << message;
}
+ return caseDefault;
+ };
- auto& nodes = result.GetNodes();
- const bool isSingleStruct = nodes.size() == 1 && (nodes[0].Is(EValueType::Array) || nodes[0].Is(EValueType::Object));
- if (Mode == EJsonQueryWrap::Wrap || (Mode == EJsonQueryWrap::ConditionalWrap && !isSingleStruct)) {
- TVector<TUnboxedValue> converted;
- converted.reserve(nodes.size());
- for (auto& node : nodes) {
- converted.push_back(node.ConvertToUnboxedValue(valueBuilder));
- }
- return MakeList(converted.data(), converted.size(), valueBuilder);
- }
-
- if (nodes.empty()) {
- return handleCase("Empty result", throwOnEmpty, emptyDefault);
- }
+ if (result.IsError()) {
+ return handleCase(TStringBuilder() << "Error executing jsonpath:" << Endl << result.GetError() << Endl, throwOnError, errorDefault);
+ }
- // No wrapping is applicable and result is not empty. Result must be a single object or array
- if (nodes.size() > 1) {
- return handleCase("Result consists of multiple items", throwOnError, errorDefault);
+ auto& nodes = result.GetNodes();
+ const bool isSingleStruct = nodes.size() == 1 && (nodes[0].Is(EValueType::Array) || nodes[0].Is(EValueType::Object));
+ if (Mode == EJsonQueryWrap::Wrap || (Mode == EJsonQueryWrap::ConditionalWrap && !isSingleStruct)) {
+ TVector<TUnboxedValue> converted;
+ converted.reserve(nodes.size());
+ for (auto& node : nodes) {
+ converted.push_back(node.ConvertToUnboxedValue(valueBuilder));
}
+ return MakeList(converted.data(), converted.size(), valueBuilder);
+ }
- if (!nodes[0].Is(EValueType::Array) && !nodes[0].Is(EValueType::Object)) {
- return handleCase("Result is neither object nor array", throwOnError, errorDefault);
- }
+ if (nodes.empty()) {
+ return handleCase("Empty result", throwOnEmpty, emptyDefault);
+ }
- return nodes[0].ConvertToUnboxedValue(valueBuilder);
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).c_str());
+ // No wrapping is applicable and result is not empty. Result must be a single object or array
+ if (nodes.size() > 1) {
+ return handleCase("Result consists of multiple items", throwOnError, errorDefault);
}
- }
- TSourcePosition Pos_;
- };
+ if (!nodes[0].Is(EValueType::Array) && !nodes[0].Is(EValueType::Object)) {
+ return handleCase("Result is neither object nor array", throwOnError, errorDefault);
+ }
- template <>
- TStringRef TSqlQuery<EDataSlot::Json, EJsonQueryWrap::NoWrap>::Name() {
- return "SqlQuery";
+ return nodes[0].ConvertToUnboxedValue(valueBuilder);
+ } catch (const std::exception& e) {
+ UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).c_str());
+ }
}
- template <>
- TStringRef TSqlQuery<EDataSlot::Json, EJsonQueryWrap::Wrap>::Name() {
- return "SqlQueryWrap";
- }
+ TSourcePosition Pos_;
+};
- template <>
- TStringRef TSqlQuery<EDataSlot::Json, EJsonQueryWrap::ConditionalWrap>::Name() {
- return "SqlQueryConditionalWrap";
- }
+template <>
+TStringRef TSqlQuery<EDataSlot::Json, EJsonQueryWrap::NoWrap>::Name() {
+ return "SqlQuery";
+}
- template <>
- TStringRef TSqlQuery<EDataSlot::JsonDocument, EJsonQueryWrap::NoWrap>::Name() {
- return "JsonDocumentSqlQuery";
- }
+template <>
+TStringRef TSqlQuery<EDataSlot::Json, EJsonQueryWrap::Wrap>::Name() {
+ return "SqlQueryWrap";
+}
- template <>
- TStringRef TSqlQuery<EDataSlot::JsonDocument, EJsonQueryWrap::Wrap>::Name() {
- return "JsonDocumentSqlQueryWrap";
- }
+template <>
+TStringRef TSqlQuery<EDataSlot::Json, EJsonQueryWrap::ConditionalWrap>::Name() {
+ return "SqlQueryConditionalWrap";
+}
- template <>
- TStringRef TSqlQuery<EDataSlot::JsonDocument, EJsonQueryWrap::ConditionalWrap>::Name() {
- return "JsonDocumentSqlQueryConditionalWrap";
- }
+template <>
+TStringRef TSqlQuery<EDataSlot::JsonDocument, EJsonQueryWrap::NoWrap>::Name() {
+ return "JsonDocumentSqlQuery";
+}
+
+template <>
+TStringRef TSqlQuery<EDataSlot::JsonDocument, EJsonQueryWrap::Wrap>::Name() {
+ return "JsonDocumentSqlQueryWrap";
}
+template <>
+TStringRef TSqlQuery<EDataSlot::JsonDocument, EJsonQueryWrap::ConditionalWrap>::Name() {
+ return "JsonDocumentSqlQueryConditionalWrap";
+}
+} // namespace NJson2Udf
diff --git a/yql/essentials/udfs/common/json2/sql_value.h b/yql/essentials/udfs/common/json2/sql_value.h
index 53b451c6275..525d1296a6b 100644
--- a/yql/essentials/udfs/common/json2/sql_value.h
+++ b/yql/essentials/udfs/common/json2/sql_value.h
@@ -15,282 +15,282 @@
#include <util/string/cast.h>
namespace NJson2Udf {
- using namespace NKikimr;
- using namespace NUdf;
- using namespace NYql;
- using namespace NDom;
- using namespace NJsonPath;
-
- namespace {
- template <class TValueType, bool ForceConvert = false>
- TUnboxedValue TryConvertJson(const IValueBuilder* valueBuilder, const TUnboxedValue& source) {
- Y_UNUSED(valueBuilder);
- Y_UNUSED(source);
- Y_ABORT("Unsupported type");
- }
+using namespace NKikimr;
+using namespace NUdf;
+using namespace NYql;
+using namespace NDom;
+using namespace NJsonPath;
+
+namespace {
+template <class TValueType, bool ForceConvert = false>
+TUnboxedValue TryConvertJson(const IValueBuilder* valueBuilder, const TUnboxedValue& source) {
+ Y_UNUSED(valueBuilder);
+ Y_UNUSED(source);
+ Y_ABORT("Unsupported type");
+}
- template <>
- TUnboxedValue TryConvertJson<TUtf8>(const IValueBuilder* valueBuilder, const TUnboxedValue& source) {
- Y_UNUSED(valueBuilder);
- if (IsNodeType(source, ENodeType::String)) {
- return source;
- }
+template <>
+TUnboxedValue TryConvertJson<TUtf8>(const IValueBuilder* valueBuilder, const TUnboxedValue& source) {
+ Y_UNUSED(valueBuilder);
+ if (IsNodeType(source, ENodeType::String)) {
+ return source;
+ }
+ return {};
+}
+
+template <>
+TUnboxedValue TryConvertJson<TUtf8, true>(const IValueBuilder* valueBuilder, const TUnboxedValue& source) {
+ switch (GetNodeType(source)) {
+ case ENodeType::String:
+ return source;
+ case ENodeType::Uint64:
+ return valueBuilder->NewString(ToString(source.Get<ui64>())).Release();
+ case ENodeType::Int64:
+ return valueBuilder->NewString(ToString(source.Get<i64>())).Release();
+ case ENodeType::Bool:
+ return source.Get<bool>() ? TUnboxedValuePod::Embedded("true") : TUnboxedValuePod::Embedded("false");
+ case ENodeType::Double:
+ return valueBuilder->NewString(ToString(source.Get<double>())).Release();
+ case ENodeType::Entity:
+ return TUnboxedValuePod::Embedded("null");
+ case ENodeType::List:
+ case ENodeType::Dict:
+ case ENodeType::Attr:
return {};
- }
+ }
+}
- template <>
- TUnboxedValue TryConvertJson<TUtf8, true>(const IValueBuilder* valueBuilder, const TUnboxedValue& source) {
- switch (GetNodeType(source)) {
- case ENodeType::String:
- return source;
- case ENodeType::Uint64:
- return valueBuilder->NewString(ToString(source.Get<ui64>())).Release();
- case ENodeType::Int64:
- return valueBuilder->NewString(ToString(source.Get<i64>())).Release();
- case ENodeType::Bool:
- return source.Get<bool>() ? TUnboxedValuePod::Embedded("true") : TUnboxedValuePod::Embedded("false");
- case ENodeType::Double:
- return valueBuilder->NewString(ToString(source.Get<double>())).Release();
- case ENodeType::Entity:
- return TUnboxedValuePod::Embedded("null");
- case ENodeType::List:
- case ENodeType::Dict:
- case ENodeType::Attr:
- return {};
- }
- }
+template <>
+TUnboxedValue TryConvertJson<i64>(const IValueBuilder* valueBuilder, const TUnboxedValue& source) {
+ Y_UNUSED(valueBuilder);
+ if (!source.IsEmbedded()) {
+ return {};
+ }
- template <>
- TUnboxedValue TryConvertJson<i64>(const IValueBuilder* valueBuilder, const TUnboxedValue& source) {
- Y_UNUSED(valueBuilder);
- if (!source.IsEmbedded()) {
- return {};
- }
+ if (IsNodeType(source, ENodeType::Int64)) {
+ return TUnboxedValuePod(source.Get<i64>());
+ } else if (IsNodeType(source, ENodeType::Uint64) && source.Get<ui64>() < Max<i64>()) {
+ return TUnboxedValuePod(static_cast<i64>(source.Get<ui64>()));
+ } else if (IsNodeType(source, ENodeType::Double) && static_cast<i64>(source.Get<double>()) == source.Get<double>()) {
+ return TUnboxedValuePod(static_cast<i64>(source.Get<double>()));
+ }
- if (IsNodeType(source, ENodeType::Int64)) {
- return TUnboxedValuePod(source.Get<i64>());
- } else if (IsNodeType(source, ENodeType::Uint64) && source.Get<ui64>() < Max<i64>()) {
- return TUnboxedValuePod(static_cast<i64>(source.Get<ui64>()));
- } else if (IsNodeType(source, ENodeType::Double) && static_cast<i64>(source.Get<double>()) == source.Get<double>()) {
- return TUnboxedValuePod(static_cast<i64>(source.Get<double>()));
- }
+ return {};
+}
- return {};
- }
+template <>
+TUnboxedValue TryConvertJson<double>(const IValueBuilder* valueBuilder, const TUnboxedValue& source) {
+ Y_UNUSED(valueBuilder);
+ if (!source.IsEmbedded()) {
+ return {};
+ }
- template <>
- TUnboxedValue TryConvertJson<double>(const IValueBuilder* valueBuilder, const TUnboxedValue& source) {
- Y_UNUSED(valueBuilder);
- if (!source.IsEmbedded()) {
- return {};
- }
+ if (IsNodeType(source, ENodeType::Double)) {
+ return TUnboxedValuePod(source.Get<double>());
+ } else if (IsNodeType(source, ENodeType::Int64)) {
+ return TUnboxedValuePod(static_cast<double>(source.Get<i64>()));
+ } else if (IsNodeType(source, ENodeType::Uint64)) {
+ return TUnboxedValuePod(static_cast<double>(source.Get<ui64>()));
+ }
- if (IsNodeType(source, ENodeType::Double)) {
- return TUnboxedValuePod(source.Get<double>());
- } else if (IsNodeType(source, ENodeType::Int64)) {
- return TUnboxedValuePod(static_cast<double>(source.Get<i64>()));
- } else if (IsNodeType(source, ENodeType::Uint64)) {
- return TUnboxedValuePod(static_cast<double>(source.Get<ui64>()));
- }
+ return {};
+}
- return {};
+template <>
+TUnboxedValue TryConvertJson<bool>(const IValueBuilder* valueBuilder, const TUnboxedValue& source) {
+ Y_UNUSED(valueBuilder);
+ if (!source.IsEmbedded() || !IsNodeType(source, ENodeType::Bool)) {
+ return {};
+ }
+ return {TUnboxedValuePod(source.Get<bool>())};
+}
+} // namespace
+
+template <EDataSlot InputType, class TValueType, bool ForceConvert = false>
+class TSqlValue: public TBoxedValue {
+public:
+ enum class TErrorCode: ui8 {
+ Empty = 0,
+ Error = 1
+ };
+
+ TSqlValue(TSourcePosition pos)
+ : Pos_(pos)
+ {
+ }
+
+ static TStringRef Name();
+
+ static bool DeclareSignature(
+ const TStringRef& name,
+ TType* userType,
+ IFunctionTypeInfoBuilder& builder,
+ bool typesOnly) {
+ Y_UNUSED(userType);
+ if (name != Name()) {
+ return false;
}
- template <>
- TUnboxedValue TryConvertJson<bool>(const IValueBuilder* valueBuilder, const TUnboxedValue& source) {
- Y_UNUSED(valueBuilder);
- if (!source.IsEmbedded() || !IsNodeType(source, ENodeType::Bool)) {
- return {};
- }
- return {TUnboxedValuePod(source.Get<bool>())};
+ auto optionalValueType = builder.Optional()->Item<TValueType>().Build();
+ auto errorTupleType = builder.Tuple(2)->Add<ui8>().Add<char*>().Build();
+ auto returnTypeTuple = builder.Tuple(2)
+ ->Add(errorTupleType)
+ .Add(optionalValueType)
+ .Build();
+ auto returnType = builder.Variant()->Over(returnTypeTuple).Build();
+
+ TType* jsonType = nullptr;
+ if constexpr (InputType == EDataSlot::Json) {
+ jsonType = builder.Resource(JSON_NODE_RESOURCE_NAME);
+ } else {
+ jsonType = builder.SimpleType<TJsonDocument>();
}
- }
+ auto optionalJsonType = builder.Optional()->Item(jsonType).Build();
+ auto jsonPathType = builder.Resource(JSONPATH_RESOURCE_NAME);
+ auto dictType = builder.Dict()->Key<TUtf8>().Value(builder.Resource(JSON_NODE_RESOURCE_NAME)).Build();
+
+ builder.Args()
+ ->Add(optionalJsonType)
+ .Add(jsonPathType)
+ .Add(dictType)
+ .Done()
+ .Returns(returnType);
- template <EDataSlot InputType, class TValueType, bool ForceConvert = false>
- class TSqlValue: public TBoxedValue {
- public:
- enum class TErrorCode : ui8 {
- Empty = 0,
- Error = 1
- };
-
- TSqlValue(TSourcePosition pos)
- : Pos_(pos)
- {
+ builder.IsStrict();
+
+ if (!typesOnly) {
+ builder.Implementation(new TSqlValue(builder.GetSourcePosition()));
}
+ return true;
+ }
- static TStringRef Name();
+private:
+ TUnboxedValue BuildErrorResult(const IValueBuilder* valueBuilder, TErrorCode code, const TStringBuf message) const {
+ TUnboxedValue* items = nullptr;
+ auto errorTuple = valueBuilder->NewArray(2, items);
+ items[0] = TUnboxedValuePod(static_cast<ui8>(code));
+ items[1] = valueBuilder->NewString(message);
+ return valueBuilder->NewVariant(0, std::move(errorTuple));
+ }
+
+ TUnboxedValue BuildSuccessfulResult(const IValueBuilder* valueBuilder, TUnboxedValue&& value) const {
+ return valueBuilder->NewVariant(1, std::move(value));
+ }
- static bool DeclareSignature(
- const TStringRef& name,
- TType* userType,
- IFunctionTypeInfoBuilder& builder,
- bool typesOnly) {
- Y_UNUSED(userType);
- if (name != Name()) {
- return false;
+ TUnboxedValue Run(
+ const IValueBuilder* valueBuilder,
+ const TUnboxedValuePod* args) const final {
+ try {
+ if (!args[0].HasValue()) {
+ return BuildSuccessfulResult(valueBuilder, TUnboxedValuePod());
}
- auto optionalValueType = builder.Optional()->Item<TValueType>().Build();
- auto errorTupleType = builder.Tuple(2)->Add<ui8>().Add<char*>().Build();
- auto returnTypeTuple = builder.Tuple(2)
- ->Add(errorTupleType)
- .Add(optionalValueType)
- .Build();
- auto returnType = builder.Variant()->Over(returnTypeTuple).Build();
-
- TType* jsonType = nullptr;
- if constexpr (InputType == EDataSlot::Json) {
- jsonType = builder.Resource(JSON_NODE_RESOURCE_NAME);
+ TValue jsonDom;
+ if constexpr (InputType == EDataSlot::JsonDocument) {
+ jsonDom = TValue(NBinaryJson::TBinaryJsonReader::Make(args[0].AsStringRef())->GetRootCursor());
} else {
- jsonType = builder.SimpleType<TJsonDocument>();
+ jsonDom = TValue(args[0]);
}
- auto optionalJsonType = builder.Optional()->Item(jsonType).Build();
- auto jsonPathType = builder.Resource(JSONPATH_RESOURCE_NAME);
- auto dictType = builder.Dict()->Key<TUtf8>().Value(builder.Resource(JSON_NODE_RESOURCE_NAME)).Build();
- builder.Args()
- ->Add(optionalJsonType)
- .Add(jsonPathType)
- .Add(dictType)
- .Done()
- .Returns(returnType);
+ auto* jsonPathResource = static_cast<TJsonPathResource*>(args[1].AsBoxed().Get());
+ const auto& jsonPath = *jsonPathResource->Get();
+ const auto variables = DictToVariables(args[2]);
- builder.IsStrict();
+ const auto result = ExecuteJsonPath(jsonPath, jsonDom, variables, valueBuilder);
- if (!typesOnly) {
- builder.Implementation(new TSqlValue(builder.GetSourcePosition()));
+ if (result.IsError()) {
+ return BuildErrorResult(valueBuilder, TErrorCode::Error, TStringBuilder() << "Error executing jsonpath:" << Endl << result.GetError() << Endl);
}
- return true;
- }
- private:
- TUnboxedValue BuildErrorResult(const IValueBuilder* valueBuilder, TErrorCode code, const TStringBuf message) const {
- TUnboxedValue* items = nullptr;
- auto errorTuple = valueBuilder->NewArray(2, items);
- items[0] = TUnboxedValuePod(static_cast<ui8>(code));
- items[1] = valueBuilder->NewString(message);
- return valueBuilder->NewVariant(0, std::move(errorTuple));
- }
+ const auto& nodes = result.GetNodes();
+ if (nodes.empty()) {
+ return BuildErrorResult(valueBuilder, TErrorCode::Empty, "Result is empty");
+ }
- TUnboxedValue BuildSuccessfulResult(const IValueBuilder* valueBuilder, TUnboxedValue&& value) const {
- return valueBuilder->NewVariant(1, std::move(value));
- }
+ if (nodes.size() > 1) {
+ return BuildErrorResult(valueBuilder, TErrorCode::Error, "Result consists of multiple items");
+ }
- TUnboxedValue Run(
- const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const final {
- try {
- if (!args[0].HasValue()) {
- return BuildSuccessfulResult(valueBuilder, TUnboxedValuePod());
- }
-
- TValue jsonDom;
- if constexpr (InputType == EDataSlot::JsonDocument) {
- jsonDom = TValue(NBinaryJson::TBinaryJsonReader::Make(args[0].AsStringRef())->GetRootCursor());
- } else {
- jsonDom = TValue(args[0]);
- }
-
- auto* jsonPathResource = static_cast<TJsonPathResource*>(args[1].AsBoxed().Get());
- const auto& jsonPath = *jsonPathResource->Get();
- const auto variables = DictToVariables(args[2]);
-
- const auto result = ExecuteJsonPath(jsonPath, jsonDom, variables, valueBuilder);
-
- if (result.IsError()) {
- return BuildErrorResult(valueBuilder, TErrorCode::Error, TStringBuilder() << "Error executing jsonpath:" << Endl << result.GetError() << Endl);
- }
-
- const auto& nodes = result.GetNodes();
- if (nodes.empty()) {
- return BuildErrorResult(valueBuilder, TErrorCode::Empty, "Result is empty");
- }
-
- if (nodes.size() > 1) {
- return BuildErrorResult(valueBuilder, TErrorCode::Error, "Result consists of multiple items");
- }
-
- const auto& value = nodes[0];
- if (value.Is(EValueType::Array) || value.Is(EValueType::Object)) {
- // SqlValue can return only scalar values
- return BuildErrorResult(valueBuilder, TErrorCode::Error, "Extracted JSON value is either object or array");
- }
-
- if (value.Is(EValueType::Null)) {
- // JSON nulls must be converted to SQL nulls
- return BuildSuccessfulResult(valueBuilder, TUnboxedValuePod());
- }
-
- const auto source = value.ConvertToUnboxedValue(valueBuilder);
- TUnboxedValue convertedValue = TryConvertJson<TValueType, ForceConvert>(valueBuilder, source);
- if (!convertedValue) {
- // error while converting JSON value type to TValueType
- return BuildErrorResult(valueBuilder, TErrorCode::Error, "Cannot convert extracted JSON value to target type");
- }
-
- return BuildSuccessfulResult(valueBuilder, std::move(convertedValue));
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).c_str());
+ const auto& value = nodes[0];
+ if (value.Is(EValueType::Array) || value.Is(EValueType::Object)) {
+ // SqlValue can return only scalar values
+ return BuildErrorResult(valueBuilder, TErrorCode::Error, "Extracted JSON value is either object or array");
}
- }
- TSourcePosition Pos_;
- };
+ if (value.Is(EValueType::Null)) {
+ // JSON nulls must be converted to SQL nulls
+ return BuildSuccessfulResult(valueBuilder, TUnboxedValuePod());
+ }
- template <EDataSlot InputType, class TValueType, bool ForceConvert>
- TStringRef TSqlValue<InputType, TValueType, ForceConvert>::Name() {
- Y_ABORT("Unknown name");
- }
+ const auto source = value.ConvertToUnboxedValue(valueBuilder);
+ TUnboxedValue convertedValue = TryConvertJson<TValueType, ForceConvert>(valueBuilder, source);
+ if (!convertedValue) {
+ // error while converting JSON value type to TValueType
+ return BuildErrorResult(valueBuilder, TErrorCode::Error, "Cannot convert extracted JSON value to target type");
+ }
- template<>
- TStringRef TSqlValue<EDataSlot::Json, TUtf8, true>::Name() {
- return TStringRef::Of("SqlValueConvertToUtf8");
+ return BuildSuccessfulResult(valueBuilder, std::move(convertedValue));
+ } catch (const std::exception& e) {
+ UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).c_str());
+ }
}
- template <>
- TStringRef TSqlValue<EDataSlot::Json, TUtf8>::Name() {
- return TStringRef::Of("SqlValueUtf8");
- }
+ TSourcePosition Pos_;
+};
- template <>
- TStringRef TSqlValue<EDataSlot::Json, i64>::Name() {
- return TStringRef::Of("SqlValueInt64");
- }
+template <EDataSlot InputType, class TValueType, bool ForceConvert>
+TStringRef TSqlValue<InputType, TValueType, ForceConvert>::Name() {
+ Y_ABORT("Unknown name");
+}
- template <>
- TStringRef TSqlValue<EDataSlot::Json, double>::Name() {
- return TStringRef::Of("SqlValueNumber");
- }
+template <>
+TStringRef TSqlValue<EDataSlot::Json, TUtf8, true>::Name() {
+ return TStringRef::Of("SqlValueConvertToUtf8");
+}
- template <>
- TStringRef TSqlValue<EDataSlot::Json, bool>::Name() {
- return TStringRef::Of("SqlValueBool");
- }
+template <>
+TStringRef TSqlValue<EDataSlot::Json, TUtf8>::Name() {
+ return TStringRef::Of("SqlValueUtf8");
+}
- template<>
- TStringRef TSqlValue<EDataSlot::JsonDocument, TUtf8, true>::Name() {
- return TStringRef::Of("JsonDocumentSqlValueConvertToUtf8");
- }
+template <>
+TStringRef TSqlValue<EDataSlot::Json, i64>::Name() {
+ return TStringRef::Of("SqlValueInt64");
+}
- template <>
- TStringRef TSqlValue<EDataSlot::JsonDocument, TUtf8>::Name() {
- return TStringRef::Of("JsonDocumentSqlValueUtf8");
- }
+template <>
+TStringRef TSqlValue<EDataSlot::Json, double>::Name() {
+ return TStringRef::Of("SqlValueNumber");
+}
- template <>
- TStringRef TSqlValue<EDataSlot::JsonDocument, i64>::Name() {
- return TStringRef::Of("JsonDocumentSqlValueInt64");
- }
+template <>
+TStringRef TSqlValue<EDataSlot::Json, bool>::Name() {
+ return TStringRef::Of("SqlValueBool");
+}
- template <>
- TStringRef TSqlValue<EDataSlot::JsonDocument, double>::Name() {
- return TStringRef::Of("JsonDocumentSqlValueNumber");
- }
+template <>
+TStringRef TSqlValue<EDataSlot::JsonDocument, TUtf8, true>::Name() {
+ return TStringRef::Of("JsonDocumentSqlValueConvertToUtf8");
+}
- template <>
- TStringRef TSqlValue<EDataSlot::JsonDocument, bool>::Name() {
- return TStringRef::Of("JsonDocumentSqlValueBool");
- }
+template <>
+TStringRef TSqlValue<EDataSlot::JsonDocument, TUtf8>::Name() {
+ return TStringRef::Of("JsonDocumentSqlValueUtf8");
+}
+template <>
+TStringRef TSqlValue<EDataSlot::JsonDocument, i64>::Name() {
+ return TStringRef::Of("JsonDocumentSqlValueInt64");
}
+
+template <>
+TStringRef TSqlValue<EDataSlot::JsonDocument, double>::Name() {
+ return TStringRef::Of("JsonDocumentSqlValueNumber");
+}
+
+template <>
+TStringRef TSqlValue<EDataSlot::JsonDocument, bool>::Name() {
+ return TStringRef::Of("JsonDocumentSqlValueBool");
+}
+
+} // namespace NJson2Udf
diff --git a/yql/essentials/udfs/common/json2/ya.make b/yql/essentials/udfs/common/json2/ya.make
index 52289125941..fa5e47018ce 100644
--- a/yql/essentials/udfs/common/json2/ya.make
+++ b/yql/essentials/udfs/common/json2/ya.make
@@ -5,6 +5,8 @@ YQL_UDF_CONTRIB(json2_udf)
28
0
)
+
+ ENABLE(YQL_STYLE_CPP)
SRCS(
json2_udf.cpp