yql_skiff_schema.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. #include "yql_skiff_schema.h"
  2. #include <yql/essentials/providers/common/schema/parser/yql_type_parser.h>
  3. #include <yql/essentials/providers/common/codec/yql_codec_type_flags.h>
  4. #include <yql/essentials/public/udf/udf_data_type.h>
  5. #include <library/cpp/yson/node/node_io.h>
  6. #include <util/generic/yexception.h>
  7. namespace NYql {
  8. namespace NCommon {
  9. struct TSkiffTypeLoader {
  10. typedef NYT::TNode TType;
  11. TSkiffTypeLoader(ui64 nativeYTTypesFlags)
  12. : NativeYTTypesFlags(nativeYTTypesFlags)
  13. {
  14. }
  15. TMaybe<TType> LoadVoidType(ui32 /*level*/) {
  16. return NYT::TNode()("wire_type", (NativeYTTypesFlags & NTCF_VOID) ? "nothing" : "yson32");
  17. }
  18. TMaybe<TType> LoadNullType(ui32 /*level*/) {
  19. return NYT::TNode()("wire_type", (NativeYTTypesFlags & NTCF_NULL) ? "nothing" : "yson32");
  20. }
  21. TMaybe<TType> LoadUnitType(ui32 /*level*/) {
  22. ythrow yexception() << "Unsupported type: Unit";
  23. }
  24. TMaybe<TType> LoadGenericType(ui32 /*level*/) {
  25. ythrow yexception() << "Unsupported type: Generic";
  26. }
  27. TMaybe<TType> LoadEmptyListType(ui32 /*level*/) {
  28. return NYT::TNode()("wire_type", (NativeYTTypesFlags & NTCF_COMPLEX) ? "nothing" : "yson32");
  29. }
  30. TMaybe<TType> LoadEmptyDictType(ui32 /*level*/) {
  31. return NYT::TNode()("wire_type", (NativeYTTypesFlags & NTCF_COMPLEX) ? "nothing" : "yson32");
  32. }
  33. TMaybe<TType> LoadDataType(const TString& dataType, ui32 /*level*/) {
  34. const auto slot = NUdf::FindDataSlot(dataType);
  35. if (!slot) {
  36. ythrow yexception() << "Unsupported data type: " << dataType;
  37. }
  38. switch (*slot) {
  39. case NUdf::EDataSlot::Bool:
  40. return NYT::TNode()("wire_type", "boolean");
  41. case NUdf::EDataSlot::Int8:
  42. case NUdf::EDataSlot::Int16:
  43. case NUdf::EDataSlot::Int32:
  44. case NUdf::EDataSlot::Int64:
  45. case NUdf::EDataSlot::Interval:
  46. case NUdf::EDataSlot::Date32:
  47. case NUdf::EDataSlot::Datetime64:
  48. case NUdf::EDataSlot::Timestamp64:
  49. case NUdf::EDataSlot::Interval64:
  50. return NYT::TNode()("wire_type", "int64");
  51. case NUdf::EDataSlot::Uint8:
  52. case NUdf::EDataSlot::Uint16:
  53. case NUdf::EDataSlot::Uint32:
  54. case NUdf::EDataSlot::Uint64:
  55. case NUdf::EDataSlot::Date:
  56. case NUdf::EDataSlot::Datetime:
  57. case NUdf::EDataSlot::Timestamp:
  58. return NYT::TNode()("wire_type", "uint64");
  59. case NUdf::EDataSlot::String:
  60. case NUdf::EDataSlot::Utf8:
  61. case NUdf::EDataSlot::Json:
  62. case NUdf::EDataSlot::Uuid:
  63. case NUdf::EDataSlot::DyNumber:
  64. case NUdf::EDataSlot::JsonDocument:
  65. return NYT::TNode()("wire_type", "string32");
  66. case NUdf::EDataSlot::Yson:
  67. return NYT::TNode()("wire_type", "yson32");
  68. case NUdf::EDataSlot::Float:
  69. case NUdf::EDataSlot::Double:
  70. return NYT::TNode()("wire_type", "double");
  71. case NUdf::EDataSlot::TzDate:
  72. case NUdf::EDataSlot::TzDatetime:
  73. case NUdf::EDataSlot::TzTimestamp:
  74. case NUdf::EDataSlot::TzDate32:
  75. case NUdf::EDataSlot::TzDatetime64:
  76. case NUdf::EDataSlot::TzTimestamp64:
  77. return NYT::TNode()("wire_type", "string32");
  78. case NUdf::EDataSlot::Decimal:
  79. ythrow yexception() << "Decimal type without parameters.";
  80. break;
  81. }
  82. ythrow yexception() << "Unsupported data type" << NUdf::GetDataTypeInfo(*slot).Name;
  83. }
  84. TMaybe<TType> LoadPgType(const TString& pgType, ui32 level) {
  85. if (!(NativeYTTypesFlags & NTCF_COMPLEX) && level > 1) {
  86. return NYT::TNode()("wire_type", "yson32");
  87. }
  88. TType itemType;
  89. if (pgType == "bool") {
  90. itemType = NYT::TNode()("wire_type", "boolean");
  91. } else if (pgType == "int2" || pgType == "int4" || pgType == "int8") {
  92. itemType = NYT::TNode()("wire_type", "int64");
  93. } else if (pgType == "float4" || pgType == "float8") {
  94. itemType = NYT::TNode()("wire_type", "double");
  95. } else {
  96. itemType = NYT::TNode()("wire_type", "string32");
  97. }
  98. return NYT::TNode()
  99. ("wire_type", "variant8")
  100. ("children", NYT::TNode()
  101. .Add(NYT::TNode()("wire_type", "nothing"))
  102. .Add(std::move(itemType))
  103. );
  104. }
  105. TMaybe<TType> LoadDataTypeParams(const TString& dataType, const TString& paramOne, const TString& /*paramTwo*/, ui32 /*level*/) {
  106. const auto slot = NUdf::FindDataSlot(dataType);
  107. if (!slot) {
  108. ythrow yexception() << "Unsupported data type: " << dataType;
  109. }
  110. if (NUdf::EDataSlot::Decimal != slot) {
  111. ythrow yexception() << "Unexpected parameters for type: " << dataType;
  112. }
  113. ui8 precision = 0;
  114. if (!TryFromString(paramOne, precision) || !precision || precision > 35) {
  115. ythrow yexception() << "Invalid decimal precision: " << paramOne;
  116. }
  117. if (NativeYTTypesFlags & NTCF_DECIMAL) {
  118. if (precision < 10) {
  119. return NYT::TNode()("wire_type", "int32");
  120. } else if (precision < 19) {
  121. return NYT::TNode()("wire_type", "int64");
  122. } else {
  123. return NYT::TNode()("wire_type", "int128");
  124. }
  125. }
  126. return NYT::TNode()("wire_type", "string32");
  127. }
  128. TMaybe<TType> LoadResourceType(const TString& /*tag*/, ui32 /*level*/) {
  129. ythrow yexception() << "Unsupported type: Resource";
  130. }
  131. TMaybe<TType> LoadTaggedType(TType baseType, const TString& /*tag*/, ui32 /*level*/) {
  132. return baseType;
  133. }
  134. TMaybe<TType> LoadErrorType(ui32 /*row*/, ui32 /*column*/, const TString& /*file*/, const TString& msg, ui32 /*level*/) {
  135. ythrow yexception() << msg;
  136. }
  137. TMaybe<TType> LoadStructType(const TVector<std::pair<TString, TType>>& members, ui32 level) {
  138. if (!(NativeYTTypesFlags & NTCF_COMPLEX) && level > 0) {
  139. return NYT::TNode()("wire_type", "yson32");
  140. }
  141. auto children = NYT::TNode::CreateList();
  142. for (auto& item: members) {
  143. NYT::TNode innerNode = item.second;
  144. innerNode["name"] = item.first;
  145. children.Add(std::move(innerNode));
  146. }
  147. return NYT::TNode()
  148. ("wire_type", "tuple")
  149. ("children", std::move(children));
  150. }
  151. TMaybe<TType> LoadListType(TType itemType, ui32 /*level*/) {
  152. if (!(NativeYTTypesFlags & NTCF_COMPLEX)) {
  153. return NYT::TNode()("wire_type", "yson32");
  154. }
  155. return NYT::TNode()
  156. ("wire_type", "repeated_variant8")
  157. ("children", NYT::TNode()
  158. .Add(std::move(itemType))
  159. );
  160. }
  161. TMaybe<TType> LoadStreamType(TType /*itemType*/, ui32 /*level*/) {
  162. ythrow yexception() << "Unsupported type: Stream";
  163. }
  164. TMaybe<TType> LoadOptionalType(TType itemType, ui32 level) {
  165. if (!(NativeYTTypesFlags & NTCF_COMPLEX) && level > 1) {
  166. return NYT::TNode()("wire_type", "yson32");
  167. }
  168. return NYT::TNode()
  169. ("wire_type", "variant8")
  170. ("children", NYT::TNode()
  171. .Add(NYT::TNode()("wire_type", "nothing"))
  172. .Add(std::move(itemType))
  173. );
  174. }
  175. TMaybe<TType> LoadTupleType(const TVector<TType>& elements, ui32 /*level*/) {
  176. if (!(NativeYTTypesFlags & NTCF_COMPLEX)) {
  177. return NYT::TNode()("wire_type", "yson32");
  178. }
  179. auto children = NYT::TNode::CreateList();
  180. for (auto& inner: elements) {
  181. children.Add(inner);
  182. }
  183. return NYT::TNode()
  184. ("wire_type", "tuple")
  185. ("children", std::move(children));
  186. }
  187. TMaybe<TType> LoadDictType(TType keyType, TType valType, ui32 /*level*/) {
  188. if (!(NativeYTTypesFlags & NTCF_COMPLEX)) {
  189. return NYT::TNode()("wire_type", "yson32");
  190. }
  191. return NYT::TNode()
  192. ("wire_type", "repeated_variant8")
  193. ("children", NYT::TNode()
  194. .Add(NYT::TNode()
  195. ("wire_type", "tuple")
  196. ("children", NYT::TNode()
  197. .Add(std::move(keyType))
  198. .Add(std::move(valType))
  199. )
  200. )
  201. );
  202. }
  203. TMaybe<TType> LoadCallableType(TType /*returnType*/, const TVector<TType>& /*argTypes*/, const TVector<TString>& /*argNames*/,
  204. const TVector<ui64>& /*argFlags*/, size_t /*optionalCount*/, const TString& /*payload*/, ui32 /*level*/) {
  205. ythrow yexception() << "Unsupported type: Callable";
  206. }
  207. TMaybe<TType> LoadVariantType(TType underlyingType, ui32 /*level*/) {
  208. if (!(NativeYTTypesFlags & NTCF_COMPLEX)) {
  209. return NYT::TNode()("wire_type", "yson32");
  210. }
  211. if (!underlyingType.IsMap() || !underlyingType.HasKey("children") || !underlyingType["children"].IsList()) {
  212. ythrow yexception() << "Bad variant underlying type: " << NYT::NodeToYsonString(underlyingType);
  213. }
  214. auto altCount = underlyingType["children"].AsList().size();
  215. underlyingType["wire_type"] = altCount < 256 ? "variant8" : "variant16";
  216. return underlyingType;
  217. }
  218. void Error(const TString& info) {
  219. ythrow yexception() << info;
  220. }
  221. ui64 NativeYTTypesFlags;
  222. };
  223. NYT::TNode ParseSkiffTypeFromYson(const NYT::TNode& node, ui64 nativeYTTypesFlags) {
  224. TSkiffTypeLoader loader(nativeYTTypesFlags);
  225. return DoLoadTypeFromYson(loader, node, 0).GetOrElse(NYT::TNode());
  226. }
  227. } // namespace NCommon
  228. } // namespace NYql