aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshishmak <shishmak@yandex-team.com>2024-09-19 16:27:03 +0300
committershishmak <shishmak@yandex-team.com>2024-09-19 16:41:50 +0300
commitf4a740ff0d5b53d8a44150c09e019eaa6d331821 (patch)
tree89a423f89845db654d6433580c2b499f206a62cd
parentaa20162565ccc09b8d98b4c8d3fa73766c9cc2e8 (diff)
downloadydb-f4a740ff0d5b53d8a44150c09e019eaa6d331821.tar.gz
YT: Fix fail on WriteSchema for null object of type TYsonStruct
commit_hash:771e910a67daff1e39c97a2518d523db3714002e
-rw-r--r--yt/yt/core/ytree/unittests/yson_schema_ut.cpp38
-rw-r--r--yt/yt/core/ytree/yson_schema-inl.h21
2 files changed, 58 insertions, 1 deletions
diff --git a/yt/yt/core/ytree/unittests/yson_schema_ut.cpp b/yt/yt/core/ytree/unittests/yson_schema_ut.cpp
index 220e38975a..88df8268a2 100644
--- a/yt/yt/core/ytree/unittests/yson_schema_ut.cpp
+++ b/yt/yt/core/ytree/unittests/yson_schema_ut.cpp
@@ -157,6 +157,20 @@ struct TTestStructWithCustomType
}
};
+struct TTestStructWithUndefinedType
+ : public TYsonStruct
+{
+ NYT::NYTree::TYsonStructPtr UndefinedTypeField;
+
+ REGISTER_YSON_STRUCT(TTestStructWithUndefinedType);
+
+ static void Register(TRegistrar registrar)
+ {
+ registrar.Parameter("undefined_type_field", &TThis::UndefinedTypeField)
+ .Optional();
+ }
+};
+
////////////////////////////////////////////////////////////////////////////////
void CheckSchema(const TYsonStructPtr& ysonStruct, TStringBuf expected)
@@ -236,6 +250,30 @@ TEST(TYsonStructSchemaTest, TestYsonStructWithCustomType)
]})");
}
+TEST(TYsonStructSchemaTest, TestYsonStructWithUndefinedType)
+{
+ auto ysonStruct = New<TTestStructWithUndefinedType>();
+ CheckSchema(
+ ysonStruct,
+ R"({type_name="struct";
+ members=[
+ {
+ name="undefined_type_field";
+ type={type_name="optional";item={type_name="struct";members=[];};};
+ };
+ ]})");
+ ysonStruct->UndefinedTypeField = New<TTestSubStruct>();
+ CheckSchema(
+ ysonStruct,
+ R"({type_name="struct";
+ members=[
+ {
+ name="undefined_type_field";
+ type={type_name="optional";item={type_name="struct";members=[{name="my_uint";type="uint32";}]}};
+ };
+ ]})");
+}
+
////////////////////////////////////////////////////////////////////////////////
} // namespace
diff --git a/yt/yt/core/ytree/yson_schema-inl.h b/yt/yt/core/ytree/yson_schema-inl.h
index 821048f19f..2f7b98912a 100644
--- a/yt/yt/core/ytree/yson_schema-inl.h
+++ b/yt/yt/core/ytree/yson_schema-inl.h
@@ -90,13 +90,32 @@ void WriteSchema(const T&, NYson::IYsonConsumer* consumer)
}
template <CYsonStructDerived T>
+void WriteSchemaForNull(NYson::IYsonConsumer* consumer)
+{
+ if constexpr (std::is_same_v<T, TYsonStruct>) {
+ // It is not allowed to instantiate object of type `TYsonStruct`.
+ BuildYsonFluently(consumer)
+ .BeginMap()
+ .Item("type_name").Value("struct")
+ .Item("members").BeginList().EndList()
+ .EndMap();
+ } else {
+ New<T>()->WriteSchema(consumer);
+ }
+}
+
+template <CYsonStructDerived T>
void WriteSchema(const NYT::TIntrusivePtr<T>& value, NYson::IYsonConsumer* consumer)
{
BuildYsonFluently(consumer)
.BeginMap()
.Item("type_name").Value("optional")
.Item("item").Do([&] (auto fluent) {
- (value ? value : New<T>())->WriteSchema(fluent.GetConsumer());
+ if (value) {
+ value->WriteSchema(fluent.GetConsumer());
+ } else {
+ WriteSchemaForNull<T>(fluent.GetConsumer());
+ }
})
.EndMap();
}