yql_mkql_schema.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. #include "yql_mkql_schema.h"
  2. #include <yql/essentials/providers/common/schema/parser/yql_type_parser.h>
  3. #include <yql/essentials/providers/common/codec/yql_codec.h>
  4. #include <yql/essentials/minikql/mkql_program_builder.h>
  5. #include <yql/essentials/minikql/mkql_node.h>
  6. #include <yql/essentials/minikql/mkql_node_cast.h>
  7. #include <yql/essentials/minikql/mkql_type_builder.h>
  8. #include <yql/essentials/minikql/mkql_runtime_version.h>
  9. #include <yql/essentials/public/udf/udf_type_inspection.h>
  10. #include <yql/essentials/public/udf/udf_data_type.h>
  11. #include <yql/essentials/utils/yql_panic.h>
  12. #include <yql/essentials/parser/pg_catalog/catalog.h>
  13. #include <library/cpp/yson/node/node_io.h>
  14. #include <library/cpp/yson/node/node_builder.h>
  15. #include <library/cpp/yson/writer.h>
  16. #include <util/stream/str.h>
  17. namespace NYql {
  18. namespace NCommon {
  19. template <template<typename> class TSaver>
  20. class TRuntimeTypeSaver: public TSaver<TRuntimeTypeSaver<TSaver>> {
  21. typedef TSaver<TRuntimeTypeSaver> TBase;
  22. struct TCallableAdaptor {
  23. const NKikimr::NMiniKQL::TCallableType* Type;
  24. NKikimr::NMiniKQL::TTypeInfoHelper TypeHelper;
  25. NKikimr::NUdf::TCallableTypeInspector CallableInspector;
  26. TCallableAdaptor(const NKikimr::NMiniKQL::TCallableType* type)
  27. : Type(type)
  28. , TypeHelper()
  29. , CallableInspector(TypeHelper, Type)
  30. {
  31. }
  32. size_t GetOptionalArgsCount() const {
  33. return CallableInspector.GetOptionalArgsCount();
  34. }
  35. TStringBuf GetPayload() const {
  36. return CallableInspector.GetPayload();
  37. }
  38. NKikimr::NMiniKQL::TType* GetReturnType() const {
  39. return Type->GetReturnType();
  40. }
  41. size_t GetArgumentsCount() const {
  42. return Type->GetArgumentsCount();
  43. }
  44. TStringBuf GetArgumentName(size_t i) const {
  45. return CallableInspector.GetArgumentName(i);
  46. }
  47. ui64 GetArgumentFlags(size_t i) const {
  48. return CallableInspector.GetArgumentFlags(i);
  49. }
  50. NKikimr::NMiniKQL::TType* GetArgumentType(size_t i) const {
  51. return Type->GetArgumentType(i);
  52. }
  53. };
  54. public:
  55. TRuntimeTypeSaver(typename TBase::TConsumer& consumer)
  56. : TBase(consumer, false)
  57. {
  58. }
  59. void Save(const NKikimr::NMiniKQL::TType* type) {
  60. using namespace NKikimr;
  61. using namespace NKikimr::NMiniKQL;
  62. switch (type->GetKind()) {
  63. case TType::EKind::Type:
  64. TBase::SaveType();
  65. break;
  66. case TType::EKind::Void:
  67. TBase::SaveVoidType();
  68. break;
  69. case TType::EKind::Null:
  70. TBase::SaveNullType();
  71. break;
  72. case TType::EKind::EmptyList:
  73. TBase::SaveEmptyListType();
  74. break;
  75. case TType::EKind::EmptyDict:
  76. TBase::SaveEmptyDictType();
  77. break;
  78. case TType::EKind::Data: {
  79. const auto schemeType = static_cast<const TDataType*>(type)->GetSchemeType();
  80. auto slot = NUdf::FindDataSlot(schemeType);
  81. if (!slot) {
  82. ythrow yexception() << "Unsupported data type: " << schemeType;
  83. }
  84. auto dataType = NUdf::GetDataTypeInfo(*slot).Name;
  85. if (NKikimr::NUdf::TDataType<NUdf::TDecimal>::Id == schemeType) {
  86. const auto params = static_cast<const TDataDecimalType*>(type)->GetParams();
  87. TBase::SaveDataTypeParams(dataType, ToString(params.first), ToString(params.second));
  88. } else {
  89. TBase::SaveDataType(dataType);
  90. }
  91. break;
  92. }
  93. case TType::EKind::Pg: {
  94. const auto name = static_cast<const TPgType*>(type)->GetName();
  95. TBase::SavePgType(name);
  96. break;
  97. }
  98. case TType::EKind::Struct:
  99. TBase::SaveStructType(*static_cast<const TStructType*>(type));
  100. break;
  101. case TType::EKind::List:
  102. TBase::SaveListType(*static_cast<const TListType*>(type));
  103. break;
  104. case TType::EKind::Optional:
  105. TBase::SaveOptionalType(*static_cast<const TOptionalType*>(type));
  106. break;
  107. case TType::EKind::Dict:
  108. TBase::SaveDictType(*static_cast<const TDictType*>(type));
  109. break;
  110. case TType::EKind::Callable:
  111. TBase::SaveCallableType(TCallableAdaptor(static_cast<const TCallableType*>(type)));
  112. break;
  113. case TType::EKind::Tuple:
  114. TBase::SaveTupleType(*static_cast<const TTupleType*>(type));
  115. break;
  116. case TType::EKind::Resource:
  117. TBase::SaveResourceType(static_cast<const TResourceType*>(type)->GetTag());
  118. break;
  119. case TType::EKind::Variant:
  120. TBase::SaveVariantType(*static_cast<const TVariantType*>(type));
  121. break;
  122. case TType::EKind::Stream:
  123. TBase::SaveStreamType(*static_cast<const TStreamType*>(type));
  124. break;
  125. case TType::EKind::Tagged:
  126. TBase::SaveTaggedType(*static_cast<const TTaggedType*>(type));
  127. break;
  128. default:
  129. YQL_ENSURE(false, "Unsupported type kind:" << (ui32)type->GetKind());
  130. }
  131. }
  132. };
  133. void WriteTypeToYson(NYson::TYsonConsumerBase& writer, const NKikimr::NMiniKQL::TType* type) {
  134. TRuntimeTypeSaver<TYqlTypeYsonSaverImpl> saver(writer);
  135. saver.Save(type);
  136. }
  137. NYT::TNode TypeToYsonNode(const NKikimr::NMiniKQL::TType* type) {
  138. NYT::TNode res;
  139. NYT::TNodeBuilder builder(&res);
  140. WriteTypeToYson(builder, type);
  141. return res;
  142. }
  143. TString WriteTypeToYson(const NKikimr::NMiniKQL::TType* type, NYson::EYsonFormat format) {
  144. TStringStream stream;
  145. NYson::TYsonWriter writer(&stream, format);
  146. WriteTypeToYson(writer, type);
  147. return stream.Str();
  148. }
  149. struct TRuntimeTypeLoader {
  150. typedef NKikimr::NMiniKQL::TType* TType;
  151. NKikimr::NMiniKQL::TProgramBuilder& Builder;
  152. IOutputStream& Err;
  153. TRuntimeTypeLoader(NKikimr::NMiniKQL::TProgramBuilder& builder, IOutputStream& err)
  154. : Builder(builder)
  155. , Err(err)
  156. {
  157. }
  158. TMaybe<TType> LoadVoidType(ui32 /*level*/) {
  159. return Builder.NewVoid().GetStaticType();
  160. }
  161. TMaybe<TType> LoadNullType(ui32 /*level*/) {
  162. return Builder.NewNull().GetStaticType();
  163. }
  164. TMaybe<TType> LoadUnitType(ui32 /*level*/) {
  165. return Builder.NewVoid().GetStaticType();
  166. }
  167. TMaybe<TType> LoadGenericType(ui32 /*level*/) {
  168. return Builder.GetTypeEnvironment().GetTypeOfTypeLazy();
  169. }
  170. TMaybe<TType> LoadEmptyListType(ui32 /*level*/) {
  171. if (NKikimr::NMiniKQL::RuntimeVersion < 11) {
  172. return Builder.NewListType(Builder.NewVoid().GetStaticType());
  173. }
  174. return Builder.GetTypeEnvironment().GetTypeOfEmptyListLazy();
  175. }
  176. TMaybe<TType> LoadEmptyDictType(ui32 /*level*/) {
  177. if (NKikimr::NMiniKQL::RuntimeVersion < 11) {
  178. return Builder.NewDictType(Builder.NewVoid().GetStaticType(), Builder.NewVoid().GetStaticType(), false);
  179. }
  180. return Builder.GetTypeEnvironment().GetTypeOfEmptyDictLazy();
  181. }
  182. TMaybe<TType> LoadDataType(const TString& dataType, ui32 /*level*/) {
  183. const auto slot = NUdf::FindDataSlot(dataType);
  184. if (!slot) {
  185. Err << "Unsupported data type: " << dataType;
  186. return Nothing();
  187. }
  188. if (NKikimr::NUdf::EDataSlot::Decimal == slot) {
  189. Err << "Decimal type without parameters.";
  190. return Nothing();
  191. }
  192. return Builder.NewDataType(NUdf::GetDataTypeInfo(*slot).TypeId);
  193. }
  194. TMaybe<TType> LoadPgType(const TString& pgType, ui32 /*level*/) {
  195. auto typeId = NYql::NPg::HasType(pgType) ? NYql::NPg::LookupType(pgType).TypeId : Max<ui32>();
  196. return Builder.NewPgType(typeId);
  197. }
  198. TMaybe<TType> LoadDataTypeParams(const TString& dataType, const TString& paramOne, const TString& paramTwo, ui32 /*level*/) {
  199. const auto slot = NUdf::FindDataSlot(dataType);
  200. if (!slot) {
  201. Err << "Unsupported data type: " << dataType;
  202. return Nothing();
  203. }
  204. if (NKikimr::NUdf::EDataSlot::Decimal != slot) {
  205. Err << "Unexpected parameters for type: " << dataType;
  206. return Nothing();
  207. }
  208. return Builder.NewDecimalType(FromString<ui8>(paramOne), FromString<ui8>(paramTwo));
  209. }
  210. TMaybe<TType> LoadResourceType(const TString& tag, ui32 /*level*/) {
  211. return Builder.NewResourceType(tag);
  212. }
  213. TMaybe<TType> LoadTaggedType(TType baseType, const TString& /*tag*/, ui32 /*level*/) {
  214. return baseType;
  215. }
  216. TMaybe<TType> LoadErrorType(ui32 /*row*/, ui32 /*column*/, const TString& /*file*/, const TString& msg, ui32 /*level*/) {
  217. Err << msg;
  218. return Nothing();
  219. }
  220. TMaybe<TType> LoadStructType(const TVector<std::pair<TString, TType>>& members, ui32 /*level*/) {
  221. auto structType = Builder.NewEmptyStructType();
  222. for (auto& member : members) {
  223. structType = Builder.NewStructType(structType, member.first, member.second);
  224. }
  225. return structType;
  226. }
  227. TMaybe<TType> LoadListType(TType itemType, ui32 /*level*/) {
  228. return Builder.NewListType(itemType);
  229. }
  230. TMaybe<TType> LoadStreamType(TType itemType, ui32 /*level*/) {
  231. return Builder.NewStreamType(itemType);
  232. }
  233. TMaybe<TType> LoadOptionalType(TType itemType, ui32 /*level*/) {
  234. return Builder.NewOptionalType(itemType);
  235. }
  236. TMaybe<TType> LoadTupleType(const TVector<TType>& elements, ui32 /*level*/) {
  237. return Builder.NewTupleType(elements);
  238. }
  239. TMaybe<TType> LoadDictType(TType keyType, TType valType, ui32 /*level*/) {
  240. return Builder.NewDictType(keyType, valType, false);
  241. }
  242. TMaybe<TType> LoadCallableType(TType returnType, const TVector<TType>& argTypes, const TVector<TString>& argNames,
  243. const TVector<ui64>& argFlags, size_t optionalCount, const TString& payload, ui32 /*level*/) {
  244. YQL_ENSURE(argTypes.size() == argNames.size() && argTypes.size() == argFlags.size());
  245. NKikimr::NMiniKQL::TCallableTypeBuilder callableTypeBuilder(Builder.GetTypeEnvironment(), "", returnType);
  246. for (size_t i = 0; i < argTypes.size(); ++i) {
  247. callableTypeBuilder.Add(argTypes[i]);
  248. if (!argNames[i].empty()) {
  249. callableTypeBuilder.SetArgumentName(argNames[i]);
  250. }
  251. if (argFlags[i] != 0) {
  252. callableTypeBuilder.SetArgumentFlags(argFlags[i]);
  253. }
  254. }
  255. callableTypeBuilder.SetOptionalArgs(optionalCount);
  256. if (!payload.empty()) {
  257. callableTypeBuilder.SetPayload(payload);
  258. }
  259. return callableTypeBuilder.Build();
  260. }
  261. TMaybe<TType> LoadVariantType(TType underlyingType, ui32 /*level*/) {
  262. return Builder.NewVariantType(underlyingType);
  263. }
  264. void Error(const TString& info) {
  265. Err << info;
  266. }
  267. };
  268. NKikimr::NMiniKQL::TType* ParseTypeFromYson(const TStringBuf yson, NKikimr::NMiniKQL::TProgramBuilder& builder, IOutputStream& err) {
  269. NYT::TNode node;
  270. if (!ParseYson(node, yson, err)) {
  271. return nullptr;
  272. }
  273. TRuntimeTypeLoader loader(builder, err);
  274. return DoLoadTypeFromYson(loader, node, 0).GetOrElse(nullptr);
  275. }
  276. NKikimr::NMiniKQL::TType* ParseTypeFromYson(const NYT::TNode& node, NKikimr::NMiniKQL::TProgramBuilder& builder, IOutputStream& err) {
  277. TRuntimeTypeLoader loader(builder, err);
  278. return DoLoadTypeFromYson(loader, node, 0).GetOrElse(nullptr);
  279. }
  280. struct TOrderAwareRuntimeTypeLoader: public TRuntimeTypeLoader {
  281. typedef NKikimr::NMiniKQL::TType* TType;
  282. NCommon::TCodecContext& Ctx;
  283. TOrderAwareRuntimeTypeLoader(NCommon::TCodecContext& ctx, IOutputStream& err)
  284. : TRuntimeTypeLoader(ctx.Builder, err)
  285. , Ctx(ctx)
  286. {
  287. }
  288. TMaybe<TType> LoadStructType(const TVector<std::pair<TString, TType>>& members, ui32 level) {
  289. auto type = Builder.NewEmptyStructType();
  290. bool sorted = true;
  291. TString prev;
  292. for (auto& member : members) {
  293. if (member.first < prev) {
  294. sorted = false;
  295. }
  296. prev = member.first;
  297. type = Builder.NewStructType(type, member.first, member.second);
  298. }
  299. if (level > 0 && !sorted) {
  300. std::vector<size_t> reorder(members.size(), 0);
  301. using namespace NKikimr::NMiniKQL;
  302. auto structType = AS_TYPE(TStructType, type);
  303. size_t i = 0;
  304. for (auto& member : members) {
  305. reorder[i++] = structType->GetMemberIndex(member.first);
  306. }
  307. Ctx.StructReorders.push_back(std::move(reorder));
  308. type->SetCookie((ui64)&Ctx.StructReorders.back());
  309. }
  310. return type;
  311. }
  312. };
  313. NKikimr::NMiniKQL::TType* ParseOrderAwareTypeFromYson(const NYT::TNode& node, TCodecContext& ctx, IOutputStream& err) {
  314. TOrderAwareRuntimeTypeLoader loader(ctx, err);
  315. return DoLoadTypeFromYson(loader, node, 0).GetOrElse(nullptr);
  316. }
  317. } // namespace NCommon
  318. } // namespace NYql