yql_constraint.cpp 85 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382
  1. #include "yql_constraint.h"
  2. #include "yql_expr.h"
  3. #include <util/digest/murmur.h>
  4. #include <util/generic/utility.h>
  5. #include <util/generic/algorithm.h>
  6. #include <util/string/join.h>
  7. #include <algorithm>
  8. #include <iterator>
  9. namespace NYql {
  10. TConstraintNode::TConstraintNode(TExprContext& ctx, std::string_view name)
  11. : Hash_(MurmurHash<ui64>(name.data(), name.size()))
  12. , Name_(ctx.AppendString(name))
  13. {
  14. }
  15. TConstraintNode::TConstraintNode(TConstraintNode&& constr)
  16. : Hash_(constr.Hash_)
  17. , Name_(constr.Name_)
  18. {
  19. constr.Hash_ = 0;
  20. constr.Name_ = {};
  21. }
  22. void TConstraintNode::Out(IOutputStream& out) const {
  23. out.Write(Name_);
  24. }
  25. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  26. TPartOfConstraintBase::TPartOfConstraintBase(TExprContext& ctx, std::string_view name)
  27. : TConstraintNode(ctx, name)
  28. {}
  29. TConstraintWithFieldsNode::TConstraintWithFieldsNode(TExprContext& ctx, std::string_view name)
  30. : TPartOfConstraintBase(ctx, name)
  31. {}
  32. const TTypeAnnotationNode* TPartOfConstraintBase::GetSubTypeByPath(const TPathType& path, const TTypeAnnotationNode& type) {
  33. if (path.empty() && ETypeAnnotationKind::Optional != type.GetKind())
  34. return &type;
  35. const auto tail = [](const TPathType& path) {
  36. auto p(path);
  37. p.pop_front();
  38. return p;
  39. };
  40. switch (type.GetKind()) {
  41. case ETypeAnnotationKind::Optional:
  42. return GetSubTypeByPath(path, *type.Cast<TOptionalExprType>()->GetItemType());
  43. case ETypeAnnotationKind::List: // TODO: Remove later: temporary stub for single AsList in FlatMap and same cases.
  44. return GetSubTypeByPath(path, *type.Cast<TListExprType>()->GetItemType());
  45. case ETypeAnnotationKind::Struct:
  46. if (const auto itemType = type.Cast<TStructExprType>()->FindItemType(path.front()))
  47. return GetSubTypeByPath(tail(path), *itemType);
  48. break;
  49. case ETypeAnnotationKind::Tuple:
  50. if (const auto index = TryFromString<ui64>(TStringBuf(path.front())))
  51. if (const auto typleType = type.Cast<TTupleExprType>(); typleType->GetSize() > *index)
  52. return GetSubTypeByPath(tail(path), *typleType->GetItems()[*index]);
  53. break;
  54. case ETypeAnnotationKind::Multi:
  55. if (const auto index = TryFromString<ui64>(TStringBuf(path.front())))
  56. if (const auto multiType = type.Cast<TMultiExprType>(); multiType->GetSize() > *index)
  57. return GetSubTypeByPath(tail(path), *multiType->GetItems()[*index]);
  58. break;
  59. case ETypeAnnotationKind::Variant:
  60. return GetSubTypeByPath(path, *type.Cast<TVariantExprType>()->GetUnderlyingType());
  61. case ETypeAnnotationKind::Dict:
  62. if (const auto index = TryFromString<ui8>(TStringBuf(path.front())))
  63. switch (*index) {
  64. case 0U: return GetSubTypeByPath(tail(path), *type.Cast<TDictExprType>()->GetKeyType());
  65. case 1U: return GetSubTypeByPath(tail(path), *type.Cast<TDictExprType>()->GetPayloadType());
  66. default: break;
  67. }
  68. break;
  69. default:
  70. break;
  71. }
  72. return nullptr;
  73. }
  74. bool TPartOfConstraintBase::HasDuplicates(const TSetOfSetsType& sets) {
  75. for (auto ot = sets.cbegin(); sets.cend() != ot; ++ot) {
  76. for (auto it = sets.cbegin(); sets.cend() != it; ++it) {
  77. if (ot->size() < it->size() && std::all_of(ot->cbegin(), ot->cend(), [it](const TPathType& path) { return it->contains(path); }))
  78. return true;
  79. }
  80. }
  81. return false;
  82. }
  83. NYT::TNode TPartOfConstraintBase::PathToNode(const TPartOfConstraintBase::TPathType& path) {
  84. if (1U == path.size())
  85. return TStringBuf(path.front());
  86. return std::accumulate(path.cbegin(), path.cend(),
  87. NYT::TNode::CreateList(),
  88. [](NYT::TNode node, std::string_view p) -> NYT::TNode { return std::move(node).Add(TStringBuf(p)); }
  89. );
  90. };
  91. NYT::TNode TPartOfConstraintBase::SetToNode(const TPartOfConstraintBase::TSetType& set, bool withShortcut) {
  92. if (withShortcut && 1U == set.size() && 1U == set.front().size())
  93. return TStringBuf(set.front().front());
  94. return std::accumulate(set.cbegin(), set.cend(),
  95. NYT::TNode::CreateList(),
  96. [](NYT::TNode node, const TPathType& path) -> NYT::TNode { return std::move(node).Add(PathToNode(path)); }
  97. );
  98. };
  99. NYT::TNode TPartOfConstraintBase::SetOfSetsToNode(const TPartOfConstraintBase::TSetOfSetsType& sets) {
  100. return std::accumulate(sets.cbegin(), sets.cend(),
  101. NYT::TNode::CreateList(),
  102. [](NYT::TNode node, const TSetType& s) {
  103. return std::move(node).Add(TPartOfConstraintBase::SetToNode(s, true));
  104. });
  105. }
  106. TPartOfConstraintBase::TPathType TPartOfConstraintBase::NodeToPath(TExprContext& ctx, const NYT::TNode& node) {
  107. if (node.IsString())
  108. return TPartOfConstraintBase::TPathType{ctx.AppendString(node.AsString())};
  109. TPartOfConstraintBase::TPathType path;
  110. for (const auto& col : node.AsList()) {
  111. path.emplace_back(ctx.AppendString(col.AsString()));
  112. }
  113. return path;
  114. };
  115. TPartOfConstraintBase::TSetType TPartOfConstraintBase::NodeToSet(TExprContext& ctx, const NYT::TNode& node) {
  116. if (node.IsString())
  117. return TPartOfConstraintBase::TSetType{TPartOfConstraintBase::TPathType(1U, ctx.AppendString(node.AsString()))};
  118. TPartOfConstraintBase::TSetType set;
  119. for (const auto& col : node.AsList()) {
  120. set.insert_unique(NodeToPath(ctx, col));
  121. }
  122. return set;
  123. };
  124. TPartOfConstraintBase::TSetOfSetsType TPartOfConstraintBase::NodeToSetOfSets(TExprContext& ctx, const NYT::TNode& node) {
  125. TSetOfSetsType sets;
  126. for (const auto& s : node.AsList()) {
  127. sets.insert_unique(NodeToSet(ctx, s));
  128. }
  129. return sets;
  130. }
  131. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  132. const TConstraintNode* TConstraintSet::GetConstraint(std::string_view name) const {
  133. const auto it = std::lower_bound(Constraints_.cbegin(), Constraints_.cend(), name, TConstraintNode::TCompare());
  134. if (it != Constraints_.cend() && (*it)->GetName() == name) {
  135. return *it;
  136. }
  137. return nullptr;
  138. }
  139. void TConstraintSet::AddConstraint(const TConstraintNode* node) {
  140. if (!node) {
  141. return;
  142. }
  143. const auto it = std::lower_bound(Constraints_.begin(), Constraints_.end(), node, TConstraintNode::TCompare());
  144. if (it == Constraints_.end() || (*it)->GetName() != node->GetName()) {
  145. Constraints_.insert(it, node);
  146. } else {
  147. Y_ENSURE(node->Equals(**it), "Adding unequal constraint: " << *node << " != " << **it);
  148. }
  149. }
  150. const TConstraintNode* TConstraintSet::RemoveConstraint(std::string_view name) {
  151. const TConstraintNode* res = nullptr;
  152. const auto it = std::lower_bound(Constraints_.begin(), Constraints_.end(), name, TConstraintNode::TCompare());
  153. if (it != Constraints_.end() && (*it)->GetName() == name) {
  154. res = *it;
  155. Constraints_.erase(it);
  156. }
  157. return res;
  158. }
  159. void TConstraintSet::Out(IOutputStream& out) const {
  160. out.Write('{');
  161. bool first = true;
  162. for (const auto& c: Constraints_) {
  163. if (!first)
  164. out.Write(',');
  165. out << *c;
  166. first = false;
  167. }
  168. out.Write('}');
  169. }
  170. void TConstraintSet::ToJson(NJson::TJsonWriter& writer) const {
  171. writer.OpenMap();
  172. for (const auto& node : Constraints_) {
  173. writer.WriteKey(node->GetName());
  174. node->ToJson(writer);
  175. }
  176. writer.CloseMap();
  177. }
  178. NYT::TNode TConstraintSet::ToYson() const {
  179. auto res = NYT::TNode::CreateMap();
  180. for (const auto& node : Constraints_) {
  181. auto serialized = node->ToYson();
  182. YQL_ENSURE(!serialized.IsUndefined(), "Cannot serialize " << node->GetName() << " constraint");
  183. res[node->GetName()] = std::move(serialized);
  184. }
  185. return res;
  186. }
  187. bool TConstraintSet::FilterConstraints(const TPredicate& predicate) {
  188. const auto size = Constraints_.size();
  189. for (auto it = Constraints_.begin(); Constraints_.end() != it;)
  190. if (predicate((*it)->GetName()))
  191. ++it;
  192. else
  193. it = Constraints_.erase(it);
  194. return Constraints_.size() != size;
  195. }
  196. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  197. namespace {
  198. size_t GetElementsCount(const TTypeAnnotationNode* type) {
  199. if (type) {
  200. switch (type->GetKind()) {
  201. case ETypeAnnotationKind::Tuple: return type->Cast<TTupleExprType>()->GetSize();
  202. case ETypeAnnotationKind::Multi: return type->Cast<TMultiExprType>()->GetSize();
  203. case ETypeAnnotationKind::Struct: return type->Cast<TStructExprType>()->GetSize();
  204. default: break;
  205. }
  206. }
  207. return 0U;
  208. }
  209. std::deque<std::string_view> GetAllItemTypeFields(const TTypeAnnotationNode* type, TExprContext& ctx) {
  210. std::deque<std::string_view> fields;
  211. if (type) {
  212. switch (type->GetKind()) {
  213. case ETypeAnnotationKind::Struct:
  214. if (const auto structType = type->Cast<TStructExprType>()) {
  215. fields.resize(structType->GetSize());
  216. std::transform(structType->GetItems().cbegin(), structType->GetItems().cend(), fields.begin(), std::bind(&TItemExprType::GetName, std::placeholders::_1));
  217. }
  218. break;
  219. case ETypeAnnotationKind::Tuple:
  220. if (const auto size = type->Cast<TTupleExprType>()->GetSize()) {
  221. fields.resize(size);
  222. ui32 i = 0U;
  223. std::generate(fields.begin(), fields.end(), [&]() { return ctx.GetIndexAsString(i++); });
  224. }
  225. break;
  226. case ETypeAnnotationKind::Multi:
  227. if (const auto size = type->Cast<TMultiExprType>()->GetSize()) {
  228. fields.resize(size);
  229. ui32 i = 0U;
  230. std::generate(fields.begin(), fields.end(), [&]() { return ctx.GetIndexAsString(i++); });
  231. }
  232. break;
  233. default:
  234. break;
  235. }
  236. }
  237. return fields;
  238. }
  239. TPartOfConstraintBase::TSetOfSetsType MakeFullSet(const TPartOfConstraintBase::TSetType& keys) {
  240. TPartOfConstraintBase::TSetOfSetsType sets;
  241. sets.reserve(sets.size());
  242. for (const auto& key : keys)
  243. sets.insert_unique(TPartOfConstraintBase::TSetType{key});
  244. return sets;
  245. }
  246. }
  247. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  248. TSortedConstraintNode::TSortedConstraintNode(TExprContext& ctx, TContainerType&& content)
  249. : TConstraintWithFieldsT(ctx, Name())
  250. , Content_(std::move(content))
  251. {
  252. YQL_ENSURE(!Content_.empty());
  253. for (const auto& c : Content_) {
  254. YQL_ENSURE(!c.first.empty());
  255. for (const auto& path : c.first)
  256. Hash_ = std::accumulate(path.cbegin(), path.cend(), c.second ? Hash_ : ~Hash_, [](ui64 hash, const std::string_view& field) { return MurmurHash<ui64>(field.data(), field.size(), hash); });
  257. }
  258. }
  259. TSortedConstraintNode::TSortedConstraintNode(TExprContext& ctx, const NYT::TNode& serialized)
  260. : TSortedConstraintNode(ctx, NodeToContainer(ctx, serialized))
  261. {
  262. }
  263. TSortedConstraintNode::TContainerType TSortedConstraintNode::NodeToContainer(TExprContext& ctx, const NYT::TNode& serialized) {
  264. TSortedConstraintNode::TContainerType sorted;
  265. try {
  266. for (const auto& pair : serialized.AsList()) {
  267. TPartOfConstraintBase::TSetType set = TPartOfConstraintBase::NodeToSet(ctx, pair.AsList().front());
  268. sorted.emplace_back(std::move(set), pair.AsList().back().AsBool());
  269. }
  270. } catch (...) {
  271. YQL_ENSURE(false, "Cannot deserialize " << Name() << " constraint: " << CurrentExceptionMessage());
  272. }
  273. return sorted;
  274. }
  275. TSortedConstraintNode::TSortedConstraintNode(TSortedConstraintNode&&) = default;
  276. bool TSortedConstraintNode::Equals(const TConstraintNode& node) const {
  277. if (this == &node) {
  278. return true;
  279. }
  280. if (const auto c = dynamic_cast<const TSortedConstraintNode*>(&node)) {
  281. return GetContent() == c->GetContent();
  282. }
  283. return false;
  284. }
  285. bool TSortedConstraintNode::Includes(const TConstraintNode& node) const {
  286. if (this == &node) {
  287. return true;
  288. }
  289. if (GetName() != node.GetName()) {
  290. return false;
  291. }
  292. const auto& content = static_cast<const TSortedConstraintNode&>(node).GetContent();
  293. if (content.size() > Content_.size())
  294. return false;
  295. for (TContainerType::size_type i = 0U; i < content.size(); ++i) {
  296. if (Content_[i].second != content[i].second ||
  297. !(std::includes(Content_[i].first.cbegin(), Content_[i].first.cend(), content[i].first.cbegin(), content[i].first.cend()) || std::includes(content[i].first.cbegin(), content[i].first.cend(), Content_[i].first.cbegin(), Content_[i].first.cend())))
  298. return false;
  299. }
  300. return true;
  301. }
  302. void TSortedConstraintNode::Out(IOutputStream& out) const {
  303. TConstraintNode::Out(out);
  304. out.Write('(');
  305. bool first = true;
  306. for (const auto& c : Content_) {
  307. if (first)
  308. first = false;
  309. else
  310. out.Write(';');
  311. out.Write(JoinSeq(',', c.first));
  312. out.Write('[');
  313. out.Write(c.second ? "asc" : "desc");
  314. out.Write(']');
  315. }
  316. out.Write(')');
  317. }
  318. void TSortedConstraintNode::ToJson(NJson::TJsonWriter& out) const {
  319. out.OpenArray();
  320. for (const auto& c : Content_) {
  321. out.OpenArray();
  322. out.Write(JoinSeq(';', c.first));
  323. out.Write(c.second);
  324. out.CloseArray();
  325. }
  326. out.CloseArray();
  327. }
  328. NYT::TNode TSortedConstraintNode::ToYson() const {
  329. return std::accumulate(Content_.cbegin(), Content_.cend(),
  330. NYT::TNode::CreateList(),
  331. [](NYT::TNode node, const std::pair<TSetType, bool>& pair) {
  332. return std::move(node).Add(NYT::TNode::CreateList().Add(TPartOfConstraintBase::SetToNode(pair.first, false)).Add(pair.second));
  333. });
  334. }
  335. bool TSortedConstraintNode::IsPrefixOf(const TSortedConstraintNode& node) const {
  336. return node.Includes(*this);
  337. }
  338. bool TSortedConstraintNode::StartsWith(const TSetType& prefix) const {
  339. auto set = prefix;
  340. for (const auto& key : Content_) {
  341. bool found = false;
  342. std::for_each(key.first.cbegin(), key.first.cend(), [&set, &found] (const TPathType& path) {
  343. if (const auto it = set.find(path); set.cend() != it) {
  344. set.erase(it);
  345. found = true;
  346. }
  347. });
  348. if (!found)
  349. break;
  350. }
  351. return set.empty();
  352. }
  353. TPartOfConstraintBase::TSetType TSortedConstraintNode::GetFullSet() const {
  354. TSetType set;
  355. set.reserve(Content_.size());
  356. for (const auto& key : Content_)
  357. set.insert_unique(key.first.cbegin(), key.first.cend());
  358. return set;
  359. }
  360. void TSortedConstraintNode::FilterUncompleteReferences(TSetType& references) const {
  361. TSetType complete;
  362. complete.reserve(references.size());
  363. for (const auto& item : Content_) {
  364. bool found = false;
  365. for (const auto& path : item.first) {
  366. if (references.contains(path)) {
  367. found = true;
  368. complete.insert_unique(path);
  369. }
  370. }
  371. if (!found)
  372. break;
  373. }
  374. references = std::move(complete);
  375. }
  376. const TSortedConstraintNode* TSortedConstraintNode::MakeCommon(const std::vector<const TConstraintSet*>& constraints, TExprContext& ctx) {
  377. if (constraints.empty()) {
  378. return nullptr;
  379. }
  380. if (constraints.size() == 1) {
  381. return constraints.front()->GetConstraint<TSortedConstraintNode>();
  382. }
  383. std::optional<TContainerType> content;
  384. for (size_t i = 0U; i < constraints.size(); ++i) {
  385. if (const auto sort = constraints[i]->GetConstraint<TSortedConstraintNode>()) {
  386. const auto& nextContent = sort->GetContent();
  387. if (content) {
  388. const auto size = std::min(content->size(), nextContent.size());
  389. content->resize(size);
  390. for (auto j = 0U; j < size; ++j) {
  391. auto& one = (*content)[j];
  392. auto& two = nextContent[j];
  393. TSetType common;
  394. common.reserve(std::min(one.first.size(), two.first.size()));
  395. std::set_intersection(one.first.cbegin(), one.first.cend(), two.first.cbegin(), two.first.cend(), std::back_inserter(common));
  396. if (common.empty() || one.second != two.second) {
  397. content->resize(j);
  398. break;
  399. } else
  400. one.first = std::move(common);
  401. }
  402. if (content->empty())
  403. break;
  404. } else {
  405. content = nextContent;
  406. }
  407. } else if (!constraints[i]->GetConstraint<TEmptyConstraintNode>()) {
  408. content.reset();
  409. break;
  410. }
  411. }
  412. return !content || content->empty() ? nullptr : ctx.MakeConstraint<TSortedConstraintNode>(std::move(*content));
  413. }
  414. const TSortedConstraintNode* TSortedConstraintNode::MakeCommon(const TSortedConstraintNode* other, TExprContext& ctx) const {
  415. if (!other) {
  416. return nullptr;
  417. } else if (this == other) {
  418. return this;
  419. }
  420. auto content = other->GetContent();
  421. const auto size = std::min(content.size(), Content_.size());
  422. content.resize(size);
  423. for (auto j = 0U; j < size; ++j) {
  424. auto& one = content[j];
  425. auto& two = Content_[j];
  426. TSetType common;
  427. common.reserve(std::min(one.first.size(), two.first.size()));
  428. std::set_intersection(one.first.cbegin(), one.first.cend(), two.first.cbegin(), two.first.cend(), std::back_inserter(common));
  429. if (common.empty() || one.second != two.second) {
  430. content.resize(j);
  431. break;
  432. } else
  433. one.first = std::move(common);
  434. }
  435. return content.empty() ? nullptr : ctx.MakeConstraint<TSortedConstraintNode>(std::move(content));
  436. }
  437. const TSortedConstraintNode* TSortedConstraintNode::CutPrefix(size_t newPrefixLength, TExprContext& ctx) const {
  438. if (!newPrefixLength)
  439. return nullptr;
  440. if (newPrefixLength >= Content_.size())
  441. return this;
  442. auto content = Content_;
  443. content.resize(newPrefixLength);
  444. return ctx.MakeConstraint<TSortedConstraintNode>(std::move(content));
  445. }
  446. const TConstraintWithFieldsNode* TSortedConstraintNode::DoFilterFields(TExprContext& ctx, const TPathFilter& filter) const {
  447. if (!filter)
  448. return this;
  449. TContainerType sorted;
  450. sorted.reserve(Content_.size());
  451. for (const auto& item : Content_) {
  452. TSetType newSet;
  453. newSet.reserve(item.first.size());
  454. for (const auto& path : item.first) {
  455. if (filter(path))
  456. newSet.insert_unique(path);
  457. }
  458. if (newSet.empty())
  459. break;
  460. else
  461. sorted.emplace_back(std::move(newSet), item.second);
  462. }
  463. return sorted.empty() ? nullptr : ctx.MakeConstraint<TSortedConstraintNode>(std::move(sorted));
  464. }
  465. const TConstraintWithFieldsNode* TSortedConstraintNode::DoRenameFields(TExprContext& ctx, const TPathReduce& reduce) const {
  466. if (!reduce)
  467. return this;
  468. TContainerType sorted;
  469. sorted.reserve(Content_.size());
  470. for (const auto& item : Content_) {
  471. TSetType newSet;
  472. newSet.reserve(item.first.size());
  473. for (const auto& path : item.first) {
  474. if (const auto& newPaths = reduce(path); !newPaths.empty())
  475. newSet.insert_unique(newPaths.cbegin(), newPaths.cend());
  476. }
  477. if (newSet.empty())
  478. break;
  479. else
  480. sorted.emplace_back(std::move(newSet), item.second);
  481. }
  482. return sorted.empty() ? nullptr : ctx.MakeConstraint<TSortedConstraintNode>(std::move(sorted));
  483. }
  484. bool TSortedConstraintNode::IsApplicableToType(const TTypeAnnotationNode& type) const {
  485. const auto& itemType = GetSeqItemType(type);
  486. return std::all_of(Content_.cbegin(), Content_.cend(), [&itemType](const std::pair<TSetType, bool>& pair) {
  487. return std::all_of(pair.first.cbegin(), pair.first.cend(), std::bind(&GetSubTypeByPath, std::placeholders::_1, std::cref(itemType)));
  488. });
  489. }
  490. const TConstraintWithFieldsNode*
  491. TSortedConstraintNode::DoGetComplicatedForType(const TTypeAnnotationNode& type, TExprContext& ctx) const {
  492. const auto& rowType = GetSeqItemType(type);
  493. bool changed = false;
  494. auto content = Content_;
  495. for (auto it = content.begin(); content.end() != it;) {
  496. const auto subType = GetSubTypeByPath(it->first.front(), rowType);
  497. auto fields = GetAllItemTypeFields(subType, ctx);
  498. for (auto j = it->first.cbegin(); it->first.cend() != ++j;) {
  499. if (!IsSameAnnotation(*GetSubTypeByPath(*j, rowType), *subType)) {
  500. fields.clear();
  501. break;
  502. }
  503. }
  504. if (fields.empty() || ETypeAnnotationKind::Struct == subType->GetKind())
  505. ++it;
  506. else {
  507. changed = true;
  508. const bool dir = it->second;
  509. auto set = it->first;
  510. for (auto& path : set)
  511. path.emplace_back();
  512. for (it = content.erase(it); !fields.empty(); fields.pop_front()) {
  513. auto paths = set;
  514. for (auto& path : paths)
  515. path.back() = fields.front();
  516. it = content.emplace(it, std::move(paths), dir);
  517. ++it;
  518. }
  519. }
  520. }
  521. return changed ? ctx.MakeConstraint<TSortedConstraintNode>(std::move(content)) : this;
  522. }
  523. const TConstraintWithFieldsNode*
  524. TSortedConstraintNode::DoGetSimplifiedForType(const TTypeAnnotationNode& type, TExprContext& ctx) const {
  525. if (Content_.size() == 1U && Content_.front().first.size() == 1U && Content_.front().first.front().empty())
  526. return DoGetComplicatedForType(type, ctx);
  527. const auto& rowType = GetSeqItemType(type);
  528. const auto getPrefix = [](TPartOfConstraintBase::TPathType path) {
  529. path.pop_back();
  530. return path;
  531. };
  532. bool changed = false;
  533. auto content = Content_;
  534. for (bool setChanged = true; setChanged;) {
  535. setChanged = false;
  536. for (auto it = content.begin(); content.end() != it;) {
  537. if (it->first.size() > 1U) {
  538. for (const auto& path : it->first) {
  539. if (path.size() > 1U && path.back() == ctx.GetIndexAsString(0U)) {
  540. const auto prefix = getPrefix(path);
  541. if (const auto subType = GetSubTypeByPath(prefix, rowType); ETypeAnnotationKind::Struct != subType->GetKind() && 1 == GetElementsCount(subType)) {
  542. it->first.erase(path);
  543. it->first.insert(prefix);
  544. changed = setChanged = true;
  545. }
  546. }
  547. }
  548. ++it;
  549. } else if (it->first.size() == 1U && it->first.front().size() > 1U) {
  550. const auto prefix = getPrefix(it->first.front());
  551. if (const auto subType = GetSubTypeByPath(prefix, rowType); it->first.front().back() == ctx.GetIndexAsString(0U) && ETypeAnnotationKind::Struct != subType->GetKind()) {
  552. auto from = it++;
  553. for (auto i = 1U; content.cend() != it && it->first.size() == 1U && it->first.front().size() > 1U && ctx.GetIndexAsString(i) == it->first.front().back() && prefix == getPrefix(it->first.front()) && from->second == it->second; ++i)
  554. ++it;
  555. if (ssize_t(GetElementsCount(subType)) == std::distance(from, it)) {
  556. *from = std::make_pair(TPartOfConstraintBase::TSetType{std::move(prefix)}, from->second);
  557. ++from;
  558. it = content.erase(from, it);
  559. changed = setChanged = true;
  560. }
  561. } else
  562. ++it;
  563. } else
  564. ++it;
  565. }
  566. }
  567. return changed ? ctx.MakeConstraint<TSortedConstraintNode>(std::move(content)) : this;
  568. }
  569. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  570. TChoppedConstraintNode::TChoppedConstraintNode(TExprContext& ctx, TSetOfSetsType&& sets)
  571. : TConstraintWithFieldsT(ctx, Name())
  572. , Sets_(std::move(sets))
  573. {
  574. YQL_ENSURE(!Sets_.empty());
  575. YQL_ENSURE(!HasDuplicates(Sets_));
  576. const auto size = Sets_.size();
  577. Hash_ = MurmurHash<ui64>(&size, sizeof(size), Hash_);
  578. for (const auto& set : Sets_) {
  579. YQL_ENSURE(!set.empty());
  580. for (const auto& path : set)
  581. Hash_ = std::accumulate(path.cbegin(), path.cend(), Hash_, [](ui64 hash, const std::string_view& field) { return MurmurHash<ui64>(field.data(), field.size(), hash); });
  582. }
  583. }
  584. TChoppedConstraintNode::TChoppedConstraintNode(TExprContext& ctx, const TSetType& keys)
  585. : TChoppedConstraintNode(ctx, MakeFullSet(keys))
  586. {}
  587. TChoppedConstraintNode::TChoppedConstraintNode(TExprContext& ctx, const NYT::TNode& serialized)
  588. : TChoppedConstraintNode(ctx, NodeToSets(ctx, serialized))
  589. {
  590. }
  591. TChoppedConstraintNode::TSetOfSetsType TChoppedConstraintNode::NodeToSets(TExprContext& ctx, const NYT::TNode& serialized) {
  592. try {
  593. return TPartOfConstraintBase::NodeToSetOfSets(ctx, serialized);
  594. } catch (...) {
  595. YQL_ENSURE(false, "Cannot deserialize " << Name() << " constraint: " << CurrentExceptionMessage());
  596. }
  597. Y_UNREACHABLE();
  598. }
  599. TChoppedConstraintNode::TChoppedConstraintNode(TChoppedConstraintNode&& constr) = default;
  600. TPartOfConstraintBase::TSetType TChoppedConstraintNode::GetFullSet() const {
  601. TSetType set;
  602. set.reserve(Sets_.size());
  603. for (const auto& key : Sets_)
  604. set.insert_unique(key.cbegin(), key.cend());
  605. return set;
  606. }
  607. bool TChoppedConstraintNode::Equals(const TConstraintNode& node) const {
  608. if (this == &node) {
  609. return true;
  610. }
  611. if (GetHash() != node.GetHash()) {
  612. return false;
  613. }
  614. if (const auto c = dynamic_cast<const TChoppedConstraintNode*>(&node)) {
  615. return Sets_ == c->Sets_;
  616. }
  617. return false;
  618. }
  619. bool TChoppedConstraintNode::Includes(const TConstraintNode& node) const {
  620. if (this == &node) {
  621. return true;
  622. }
  623. if (const auto c = dynamic_cast<const TChoppedConstraintNode*>(&node)) {
  624. return std::includes(Sets_.cbegin(), Sets_.cend(), c->Sets_.cbegin(), c->Sets_.cend());
  625. }
  626. return false;
  627. }
  628. void TChoppedConstraintNode::Out(IOutputStream& out) const {
  629. TConstraintNode::Out(out);
  630. out.Write('(');
  631. for (const auto& set : Sets_) {
  632. out.Write('(');
  633. bool first = true;
  634. for (const auto& path : set) {
  635. if (first)
  636. first = false;
  637. else
  638. out.Write(',');
  639. out << path;
  640. }
  641. out.Write(')');
  642. }
  643. out.Write(')');
  644. }
  645. void TChoppedConstraintNode::ToJson(NJson::TJsonWriter& out) const {
  646. out.OpenArray();
  647. for (const auto& set : Sets_) {
  648. out.OpenArray();
  649. for (const auto& path : set) {
  650. out.Write(JoinSeq(';', path));
  651. }
  652. out.CloseArray();
  653. }
  654. out.CloseArray();
  655. }
  656. NYT::TNode TChoppedConstraintNode::ToYson() const {
  657. return TPartOfConstraintBase::SetOfSetsToNode(Sets_);
  658. }
  659. bool TChoppedConstraintNode::Equals(const TSetType& prefix) const {
  660. auto set = prefix;
  661. for (const auto& key : Sets_) {
  662. bool found = false;
  663. std::for_each(key.cbegin(), key.cend(), [&set, &found] (const TPathType& path) {
  664. if (const auto it = set.find(path); set.cend() != it) {
  665. set.erase(it);
  666. found = true;
  667. }
  668. });
  669. if (!found)
  670. return false;
  671. }
  672. return set.empty();
  673. }
  674. void TChoppedConstraintNode::FilterUncompleteReferences(TSetType& references) const {
  675. TSetType complete;
  676. complete.reserve(references.size());
  677. for (const auto& item : Sets_) {
  678. bool found = false;
  679. for (const auto& path : item) {
  680. if (references.contains(path)) {
  681. found = true;
  682. complete.insert_unique(path);
  683. }
  684. }
  685. if (!found)
  686. break;
  687. }
  688. references = std::move(complete);
  689. }
  690. const TChoppedConstraintNode* TChoppedConstraintNode::MakeCommon(const std::vector<const TConstraintSet*>& constraints, TExprContext& ctx) {
  691. if (constraints.empty()) {
  692. return nullptr;
  693. }
  694. if (constraints.size() == 1) {
  695. return constraints.front()->GetConstraint<TChoppedConstraintNode>();
  696. }
  697. TSetOfSetsType sets;
  698. for (auto c: constraints) {
  699. if (const auto uniq = c->GetConstraint<TChoppedConstraintNode>()) {
  700. if (sets.empty())
  701. sets = uniq->GetContent();
  702. else {
  703. TSetOfSetsType both;
  704. both.reserve(std::min(sets.size(), uniq->GetContent().size()));
  705. std::set_intersection(sets.cbegin(), sets.cend(), uniq->GetContent().cbegin(), uniq->GetContent().cend(), std::back_inserter(both));
  706. if (both.empty()) {
  707. if (!c->GetConstraint<TEmptyConstraintNode>())
  708. return nullptr;
  709. } else
  710. sets = std::move(both);
  711. }
  712. } else if (!c->GetConstraint<TEmptyConstraintNode>()) {
  713. return nullptr;
  714. }
  715. }
  716. return sets.empty() ? nullptr : ctx.MakeConstraint<TChoppedConstraintNode>(std::move(sets));
  717. }
  718. const TConstraintWithFieldsNode*
  719. TChoppedConstraintNode::DoFilterFields(TExprContext& ctx, const TPathFilter& predicate) const {
  720. if (!predicate)
  721. return this;
  722. TSetOfSetsType chopped;
  723. chopped.reserve(Sets_.size());
  724. for (const auto& set : Sets_) {
  725. auto newSet = set;
  726. for (auto it = newSet.cbegin(); newSet.cend() != it;) {
  727. if (predicate(*it))
  728. ++it;
  729. else
  730. it = newSet.erase(it);
  731. }
  732. if (newSet.empty())
  733. return nullptr;;
  734. chopped.insert_unique(std::move(newSet));
  735. }
  736. return ctx.MakeConstraint<TChoppedConstraintNode>(std::move(chopped));
  737. }
  738. const TConstraintWithFieldsNode*
  739. TChoppedConstraintNode::DoRenameFields(TExprContext& ctx, const TPathReduce& reduce) const {
  740. if (!reduce)
  741. return this;
  742. TSetOfSetsType chopped;
  743. chopped.reserve(Sets_.size());
  744. for (const auto& set : Sets_) {
  745. TSetType newSet;
  746. newSet.reserve(set.size());
  747. for (const auto& path : set) {
  748. if (const auto& newPaths = reduce(path); !newPaths.empty())
  749. newSet.insert_unique(newPaths.cbegin(), newPaths.cend());
  750. }
  751. if (newSet.empty())
  752. return nullptr;
  753. chopped.insert_unique(std::move(newSet));
  754. }
  755. return ctx.MakeConstraint<TChoppedConstraintNode>(std::move(chopped));
  756. }
  757. const TChoppedConstraintNode*
  758. TChoppedConstraintNode::MakeCommon(const TChoppedConstraintNode* other, TExprContext& ctx) const {
  759. if (!other) {
  760. return nullptr;
  761. }
  762. if (this == other) {
  763. return this;
  764. }
  765. TSetOfSetsType both;
  766. both.reserve(std::min(Sets_.size(), other->Sets_.size()));
  767. std::set_intersection(Sets_.cbegin(), Sets_.cend(), other->Sets_.cbegin(), other->Sets_.cend(), std::back_inserter(both));
  768. return both.empty() ? nullptr : ctx.MakeConstraint<TChoppedConstraintNode>(std::move(both));
  769. }
  770. bool TChoppedConstraintNode::IsApplicableToType(const TTypeAnnotationNode& type) const {
  771. const auto& itemType = GetSeqItemType(type);
  772. return std::all_of(Sets_.cbegin(), Sets_.cend(), [&itemType](const TSetType& set) {
  773. return std::all_of(set.cbegin(), set.cend(), std::bind(&GetSubTypeByPath, std::placeholders::_1, std::cref(itemType)));
  774. });
  775. }
  776. const TConstraintWithFieldsNode*
  777. TChoppedConstraintNode::DoGetComplicatedForType(const TTypeAnnotationNode& type, TExprContext& ctx) const {
  778. const auto& rowType = GetSeqItemType(type);
  779. bool changed = false;
  780. auto sets = Sets_;
  781. for (auto it = sets.begin(); sets.end() != it;) {
  782. auto fields = GetAllItemTypeFields(GetSubTypeByPath(it->front(), rowType), ctx);
  783. for (auto j = it->cbegin(); it->cend() != ++j;) {
  784. if (const auto& copy = GetAllItemTypeFields(GetSubTypeByPath(*j, rowType), ctx); copy != fields) {
  785. fields.clear();
  786. break;
  787. }
  788. }
  789. if (fields.empty())
  790. ++it;
  791. else {
  792. changed = true;
  793. auto set = *it;
  794. for (auto& path : set)
  795. path.emplace_back();
  796. for (it = sets.erase(it); !fields.empty(); fields.pop_front()) {
  797. auto paths = set;
  798. for (auto& path : paths)
  799. path.back() = fields.front();
  800. it = sets.insert_unique(std::move(paths)).first;
  801. }
  802. }
  803. }
  804. return changed ? ctx.MakeConstraint<TChoppedConstraintNode>(std::move(sets)) : this;
  805. }
  806. const TConstraintWithFieldsNode*
  807. TChoppedConstraintNode::DoGetSimplifiedForType(const TTypeAnnotationNode& type, TExprContext& ctx) const {
  808. if (Sets_.size() == 1U && Sets_.front().size() == 1U && Sets_.front().front().empty())
  809. return DoGetComplicatedForType(type, ctx);
  810. const auto& rowType = GetSeqItemType(type);
  811. const auto getPrefix = [](TPartOfConstraintBase::TPathType path) {
  812. path.pop_back();
  813. return path;
  814. };
  815. bool changed = false;
  816. auto sets = Sets_;
  817. for (bool setChanged = true; setChanged;) {
  818. setChanged = false;
  819. for (auto it = sets.begin(); sets.end() != it;) {
  820. if (it->size() != 1U || it->front().size() <= 1U)
  821. ++it;
  822. else {
  823. auto from = it++;
  824. const auto prefix = getPrefix(from->front());
  825. while (sets.cend() != it && it->size() == 1U && it->front().size() > 1U && prefix == getPrefix(it->front()))
  826. ++it;
  827. if (ssize_t(GetElementsCount(GetSubTypeByPath(prefix, rowType))) == std::distance(from, it)) {
  828. *from++ = TPartOfConstraintBase::TSetType{std::move(prefix)};
  829. it = sets.erase(from, it);
  830. changed = setChanged = true;
  831. }
  832. }
  833. }
  834. }
  835. return changed ? ctx.MakeConstraint<TChoppedConstraintNode>(std::move(sets)) : this;
  836. }
  837. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  838. template<bool Distinct>
  839. TConstraintWithFieldsNode::TSetOfSetsType
  840. TUniqueConstraintNodeBase<Distinct>::ColumnsListToSets(const std::vector<std::string_view>& columns) {
  841. YQL_ENSURE(!columns.empty());
  842. TConstraintWithFieldsNode::TSetOfSetsType sets;
  843. sets.reserve(columns.size());
  844. std::for_each(columns.cbegin(), columns.cend(), [&sets](const std::string_view& column) { sets.insert_unique(TConstraintWithFieldsNode::TSetType{column.empty() ? TConstraintWithFieldsNode::TPathType() : TConstraintWithFieldsNode::TPathType(1U, column)}); });
  845. return sets;
  846. }
  847. template<bool Distinct>
  848. typename TUniqueConstraintNodeBase<Distinct>::TContentType
  849. TUniqueConstraintNodeBase<Distinct>::DedupSets(TContentType&& sets) {
  850. for (bool found = true; found && sets.size() > 1U;) {
  851. found = false;
  852. for (auto ot = sets.cbegin(); !found && sets.cend() != ot; ++ot) {
  853. for (auto it = sets.cbegin(); sets.cend() != it;) {
  854. if (ot->size() < it->size() && std::all_of(ot->cbegin(), ot->cend(), [it](const TConstraintWithFieldsNode::TSetType& set) { return it->contains(set); })) {
  855. it = sets.erase(it);
  856. found = true;
  857. } else
  858. ++it;
  859. }
  860. }
  861. }
  862. return std::move(sets);
  863. }
  864. template<bool Distinct>
  865. typename TUniqueConstraintNodeBase<Distinct>::TContentType
  866. TUniqueConstraintNodeBase<Distinct>::MakeCommonContent(const TContentType& one, const TContentType& two) {
  867. TContentType both;
  868. both.reserve(std::min(one.size(), two.size()));
  869. for (const auto& setsOne : one) {
  870. for (const auto& setsTwo : two) {
  871. if (setsOne.size() == setsTwo.size()) {
  872. TConstraintWithFieldsNode::TSetOfSetsType sets;
  873. sets.reserve(setsTwo.size());
  874. for (const auto& setOne : setsOne) {
  875. for (const auto& setTwo : setsTwo) {
  876. TConstraintWithFieldsNode::TSetType set;
  877. set.reserve(std::min(setOne.size(), setTwo.size()));
  878. std::set_intersection(setOne.cbegin(), setOne.cend(), setTwo.cbegin(), setTwo.cend(), std::back_inserter(set));
  879. if (!set.empty())
  880. sets.insert_unique(std::move(set));
  881. }
  882. }
  883. if (sets.size() == setsOne.size())
  884. both.insert_unique(std::move(sets));
  885. }
  886. }
  887. }
  888. return both;
  889. }
  890. template<bool Distinct>
  891. TUniqueConstraintNodeBase<Distinct>::TUniqueConstraintNodeBase(TExprContext& ctx, TContentType&& sets)
  892. : TBase(ctx, Name())
  893. , Content_(DedupSets(std::move(sets)))
  894. {
  895. YQL_ENSURE(!Content_.empty());
  896. const auto size = Content_.size();
  897. TBase::Hash_ = MurmurHash<ui64>(&size, sizeof(size), TBase::Hash_);
  898. for (const auto& sets : Content_) {
  899. YQL_ENSURE(!sets.empty());
  900. YQL_ENSURE(!TConstraintWithFieldsNode::HasDuplicates(sets));
  901. for (const auto& set : sets) {
  902. YQL_ENSURE(!set.empty());
  903. for (const auto& path : set)
  904. TBase::Hash_ = std::accumulate(path.cbegin(), path.cend(), TBase::Hash_, [](ui64 hash, const std::string_view& field) { return MurmurHash<ui64>(field.data(), field.size(), hash); });
  905. }
  906. }
  907. }
  908. template<bool Distinct>
  909. TUniqueConstraintNodeBase<Distinct>::TUniqueConstraintNodeBase(TExprContext& ctx, const std::vector<std::string_view>& columns)
  910. : TUniqueConstraintNodeBase(ctx, TContentType{TPartOfConstraintBase::TSetOfSetsType{ColumnsListToSets(columns)}})
  911. {}
  912. template<bool Distinct>
  913. TUniqueConstraintNodeBase<Distinct>::TUniqueConstraintNodeBase(TExprContext& ctx, const NYT::TNode& serialized)
  914. : TUniqueConstraintNodeBase(ctx, NodeToContent(ctx, serialized))
  915. {
  916. }
  917. template<bool Distinct>
  918. typename TUniqueConstraintNodeBase<Distinct>::TContentType TUniqueConstraintNodeBase<Distinct>::NodeToContent(TExprContext& ctx, const NYT::TNode& serialized) {
  919. TUniqueConstraintNode::TContentType content;
  920. try {
  921. for (const auto& item : serialized.AsList()) {
  922. content.insert_unique(TPartOfConstraintBase::NodeToSetOfSets(ctx, item));
  923. }
  924. } catch (...) {
  925. YQL_ENSURE(false, "Cannot deserialize " << Name() << " constraint: " << CurrentExceptionMessage());
  926. }
  927. return content;
  928. }
  929. template<bool Distinct>
  930. TUniqueConstraintNodeBase<Distinct>::TUniqueConstraintNodeBase(TUniqueConstraintNodeBase&& constr) = default;
  931. template<bool Distinct>
  932. TPartOfConstraintBase::TSetType
  933. TUniqueConstraintNodeBase<Distinct>::GetFullSet() const {
  934. TPartOfConstraintBase::TSetType set;
  935. set.reserve(Content_.size());
  936. for (const auto& sets : Content_)
  937. for (const auto& key : sets)
  938. set.insert_unique(key.cbegin(), key.cend());
  939. return set;
  940. }
  941. template<bool Distinct>
  942. bool TUniqueConstraintNodeBase<Distinct>::Equals(const TConstraintNode& node) const {
  943. if (this == &node) {
  944. return true;
  945. }
  946. if (TBase::GetHash() != node.GetHash()) {
  947. return false;
  948. }
  949. if (const auto c = dynamic_cast<const TUniqueConstraintNodeBase*>(&node)) {
  950. return Content_ == c->Content_;
  951. }
  952. return false;
  953. }
  954. template<bool Distinct>
  955. bool TUniqueConstraintNodeBase<Distinct>::Includes(const TConstraintNode& node) const {
  956. if (this == &node)
  957. return true;
  958. if (const auto c = dynamic_cast<const TUniqueConstraintNodeBase*>(&node)) {
  959. return std::all_of(c->Content_.cbegin(), c->Content_.cend(), [&] (const TConstraintWithFieldsNode::TSetOfSetsType& oldSets) {
  960. return std::any_of(Content_.cbegin(), Content_.cend(), [&] (const TConstraintWithFieldsNode::TSetOfSetsType& newSets) {
  961. return oldSets.size() == newSets.size() && std::all_of(oldSets.cbegin(), oldSets.cend(), [&] (const TConstraintWithFieldsNode::TSetType& oldSet) {
  962. return std::any_of(newSets.cbegin(), newSets.cend(), [&] (const TConstraintWithFieldsNode::TSetType& newSet) {
  963. return std::includes(newSet.cbegin(), newSet.cend(), oldSet.cbegin(), oldSet.cend());
  964. });
  965. });
  966. });
  967. });
  968. }
  969. return false;
  970. }
  971. template<bool Distinct>
  972. void TUniqueConstraintNodeBase<Distinct>::Out(IOutputStream& out) const {
  973. TConstraintNode::Out(out);
  974. out.Write('(');
  975. for (const auto& sets : Content_) {
  976. out.Write('(');
  977. bool first = true;
  978. for (const auto& set : sets) {
  979. if (first)
  980. first = false;
  981. else
  982. out << ',';
  983. if (1U == set.size())
  984. out << set.front();
  985. else
  986. out << set;
  987. }
  988. out.Write(')');
  989. }
  990. out.Write(')');
  991. }
  992. template<bool Distinct>
  993. void TUniqueConstraintNodeBase<Distinct>::ToJson(NJson::TJsonWriter& out) const {
  994. out.OpenArray();
  995. for (const auto& sets : Content_) {
  996. out.OpenArray();
  997. for (const auto& set : sets) {
  998. out.OpenArray();
  999. for (const auto& path : set) {
  1000. out.Write(JoinSeq(';', path));
  1001. }
  1002. out.CloseArray();
  1003. }
  1004. out.CloseArray();
  1005. }
  1006. out.CloseArray();
  1007. }
  1008. template<bool Distinct>
  1009. NYT::TNode TUniqueConstraintNodeBase<Distinct>::ToYson() const {
  1010. return std::accumulate(Content_.cbegin(), Content_.cend(),
  1011. NYT::TNode::CreateList(),
  1012. [](NYT::TNode node, const TConstraintWithFieldsNode::TSetOfSetsType& sets) {
  1013. return std::move(node).Add(TConstraintWithFieldsNode::SetOfSetsToNode(sets));
  1014. });
  1015. }
  1016. template<bool Distinct>
  1017. const TUniqueConstraintNodeBase<Distinct>* TUniqueConstraintNodeBase<Distinct>::MakeCommon(const std::vector<const TConstraintSet*>& constraints, TExprContext& ctx) {
  1018. if (constraints.empty()) {
  1019. return nullptr;
  1020. }
  1021. if (constraints.size() == 1) {
  1022. return constraints.front()->GetConstraint<TUniqueConstraintNodeBase>();
  1023. }
  1024. TContentType content;
  1025. for (auto c: constraints) {
  1026. if (const auto uniq = c->GetConstraint<TUniqueConstraintNodeBase>()) {
  1027. if (content.empty())
  1028. content = uniq->GetContent();
  1029. else {
  1030. if (auto both = MakeCommonContent(content, uniq->Content_); both.empty()) {
  1031. if (!c->GetConstraint<TEmptyConstraintNode>())
  1032. return nullptr;
  1033. } else
  1034. content = std::move(both);
  1035. }
  1036. } else if (!c->GetConstraint<TEmptyConstraintNode>()) {
  1037. return nullptr;
  1038. }
  1039. }
  1040. return content.empty() ? nullptr : ctx.MakeConstraint<TUniqueConstraintNodeBase>(std::move(content));
  1041. }
  1042. template<bool Distinct>
  1043. bool TUniqueConstraintNodeBase<Distinct>::IsOrderBy(const TSortedConstraintNode& sorted) const {
  1044. TConstraintWithFieldsNode::TSetType ordered;
  1045. TConstraintWithFieldsNode::TSetOfSetsType columns;
  1046. for (const auto& key : sorted.GetContent()) {
  1047. ordered.insert_unique(key.first.cbegin(), key.first.cend());
  1048. columns.insert_unique(key.first);
  1049. }
  1050. for (const auto& sets : Content_) {
  1051. if (std::all_of(sets.cbegin(), sets.cend(), [&ordered](const TConstraintWithFieldsNode::TSetType& set) {
  1052. return std::any_of(set.cbegin(), set.cend(), [&ordered](const TConstraintWithFieldsNode::TPathType& path) { return ordered.contains(path); });
  1053. })) {
  1054. std::for_each(sets.cbegin(), sets.cend(), [&columns](const TConstraintWithFieldsNode::TSetType& set) {
  1055. std::for_each(set.cbegin(), set.cend(), [&columns](const TConstraintWithFieldsNode::TPathType& path) {
  1056. if (const auto it = std::find_if(columns.cbegin(), columns.cend(), [&path](const TConstraintWithFieldsNode::TSetType& s) { return s.contains(path); }); columns.cend() != it)
  1057. columns.erase(it);
  1058. });
  1059. });
  1060. if (columns.empty())
  1061. return true;
  1062. }
  1063. }
  1064. return false;
  1065. }
  1066. template<bool Distinct>
  1067. bool TUniqueConstraintNodeBase<Distinct>::ContainsCompleteSet(const std::vector<std::string_view>& columns) const {
  1068. if (columns.empty())
  1069. return false;
  1070. const std::unordered_set<std::string_view> ordered(columns.cbegin(), columns.cend());
  1071. for (const auto& sets : Content_) {
  1072. if (std::all_of(sets.cbegin(), sets.cend(), [&ordered](const TConstraintWithFieldsNode::TSetType& set) {
  1073. return std::any_of(set.cbegin(), set.cend(), [&ordered](const TConstraintWithFieldsNode::TPathType& path) { return !path.empty() && ordered.contains(path.front()); });
  1074. }))
  1075. return true;
  1076. }
  1077. return false;
  1078. }
  1079. template<bool Distinct>
  1080. void TUniqueConstraintNodeBase<Distinct>::FilterUncompleteReferences(TPartOfConstraintBase::TSetType& references) const {
  1081. TPartOfConstraintBase::TSetType input(std::move(references));
  1082. references.clear();
  1083. references.reserve(input.size());
  1084. for (const auto& sets : Content_) {
  1085. if (std::all_of(sets.cbegin(), sets.cend(), [&input] (const TPartOfConstraintBase::TSetType& set) { return std::any_of(set.cbegin(), set.cend(), std::bind(&TPartOfConstraintBase::TSetType::contains<TPartOfConstraintBase::TPathType>, std::cref(input), std::placeholders::_1)); }))
  1086. std::for_each(sets.cbegin(), sets.cend(), [&] (const TPartOfConstraintBase::TSetType& set) { std::for_each(set.cbegin(), set.cend(), [&] (const TPartOfConstraintBase::TPathType& path) {
  1087. if (input.contains(path))
  1088. references.insert_unique(path);
  1089. }); });
  1090. }
  1091. }
  1092. template<bool Distinct>
  1093. const TConstraintWithFieldsNode*
  1094. TUniqueConstraintNodeBase<Distinct>::DoFilterFields(TExprContext& ctx, const TPartOfConstraintBase::TPathFilter& predicate) const {
  1095. if (!predicate)
  1096. return this;
  1097. TContentType content;
  1098. content.reserve(Content_.size());
  1099. for (const auto& sets : Content_) {
  1100. if (std::all_of(sets.cbegin(), sets.cend(), [&predicate](const TPartOfConstraintBase::TSetType& set) { return std::any_of(set.cbegin(), set.cend(), predicate); })) {
  1101. TPartOfConstraintBase::TSetOfSetsType newSets;
  1102. newSets.reserve(sets.size());
  1103. std::for_each(sets.cbegin(), sets.cend(), [&](const TPartOfConstraintBase::TSetType& set) {
  1104. TPartOfConstraintBase::TSetType newSet;
  1105. newSet.reserve(set.size());
  1106. std::copy_if(set.cbegin(), set.cend(), std::back_inserter(newSet), predicate);
  1107. newSets.insert_unique(std::move(newSet));
  1108. });
  1109. content.insert_unique(std::move(newSets));
  1110. }
  1111. }
  1112. return content.empty() ? nullptr : ctx.MakeConstraint<TUniqueConstraintNodeBase>(std::move(content));
  1113. }
  1114. template<bool Distinct>
  1115. const TConstraintWithFieldsNode*
  1116. TUniqueConstraintNodeBase<Distinct>::DoRenameFields(TExprContext& ctx, const TPartOfConstraintBase::TPathReduce& reduce) const {
  1117. if (!reduce)
  1118. return this;
  1119. TContentType content;
  1120. content.reserve(Content_.size());
  1121. for (const auto& sets : Content_) {
  1122. TPartOfConstraintBase::TSetOfSetsType newSets;
  1123. newSets.reserve(sets.size());
  1124. for (const auto& set : sets) {
  1125. TPartOfConstraintBase::TSetType newSet;
  1126. newSet.reserve(set.size());
  1127. for (const auto& path : set) {
  1128. const auto newPaths = reduce(path);
  1129. newSet.insert_unique(newPaths.cbegin(), newPaths.cend());
  1130. }
  1131. if (!newSet.empty())
  1132. newSets.insert_unique(std::move(newSet));
  1133. }
  1134. if (sets.size() == newSets.size())
  1135. content.insert_unique(std::move(newSets));
  1136. }
  1137. return content.empty() ? nullptr : ctx.MakeConstraint<TUniqueConstraintNodeBase>(std::move(content));
  1138. }
  1139. template<bool Distinct>
  1140. const TUniqueConstraintNodeBase<Distinct>*
  1141. TUniqueConstraintNodeBase<Distinct>::MakeCommon(const TUniqueConstraintNodeBase* other, TExprContext& ctx) const {
  1142. if (!other)
  1143. return nullptr;
  1144. if (this == other)
  1145. return this;
  1146. auto both = MakeCommonContent(Content_, other->Content_);
  1147. return both.empty() ? nullptr : ctx.MakeConstraint<TUniqueConstraintNodeBase>(std::move(both));
  1148. }
  1149. template<bool Distinct>
  1150. const TUniqueConstraintNodeBase<Distinct>* TUniqueConstraintNodeBase<Distinct>::Merge(const TUniqueConstraintNodeBase* one, const TUniqueConstraintNodeBase* two, TExprContext& ctx) {
  1151. if (!one)
  1152. return two;
  1153. if (!two)
  1154. return one;
  1155. auto content = one->Content_;
  1156. content.insert_unique(two->Content_.cbegin(), two->Content_.cend());
  1157. return ctx.MakeConstraint<TUniqueConstraintNodeBase<Distinct>>(std::move(content));
  1158. }
  1159. template<bool Distinct>
  1160. const TConstraintWithFieldsNode*
  1161. TUniqueConstraintNodeBase<Distinct>::DoGetComplicatedForType(const TTypeAnnotationNode& type, TExprContext& ctx) const {
  1162. const auto& rowType = GetSeqItemType(type);
  1163. bool changed = false;
  1164. auto content = Content_;
  1165. for (auto& sets : content) {
  1166. for (auto it = sets.begin(); sets.end() != it;) {
  1167. auto fields = GetAllItemTypeFields(TBase::GetSubTypeByPath(it->front(), rowType), ctx);
  1168. for (auto j = it->cbegin(); it->cend() != ++j;) {
  1169. if (const auto& copy = GetAllItemTypeFields(TBase::GetSubTypeByPath(*j, rowType), ctx); copy != fields) {
  1170. fields.clear();
  1171. break;
  1172. }
  1173. }
  1174. if (fields.empty())
  1175. ++it;
  1176. else {
  1177. changed = true;
  1178. auto set = *it;
  1179. for (auto& path : set)
  1180. path.emplace_back();
  1181. for (it = sets.erase(it); !fields.empty(); fields.pop_front()) {
  1182. auto paths = set;
  1183. for (auto& path : paths)
  1184. path.back() = fields.front();
  1185. it = sets.insert_unique(std::move(paths)).first;
  1186. }
  1187. }
  1188. }
  1189. }
  1190. return changed ? ctx.MakeConstraint<TUniqueConstraintNodeBase<Distinct>>(std::move(content)) : this;
  1191. }
  1192. template<bool Distinct>
  1193. const TConstraintWithFieldsNode*
  1194. TUniqueConstraintNodeBase<Distinct>::DoGetSimplifiedForType(const TTypeAnnotationNode& type, TExprContext& ctx) const {
  1195. if (Content_.size() == 1U && Content_.front().size() == 1U && Content_.front().front().size() == 1U && Content_.front().front().front().empty())
  1196. return DoGetComplicatedForType(type, ctx);
  1197. const auto& rowType = GetSeqItemType(type);
  1198. const auto getPrefix = [](TPartOfConstraintBase::TPathType path) {
  1199. path.pop_back();
  1200. return path;
  1201. };
  1202. bool changed = false;
  1203. auto content = Content_;
  1204. for (auto& sets : content) {
  1205. for (bool setChanged = true; setChanged;) {
  1206. setChanged = false;
  1207. for (auto it = sets.begin(); sets.end() != it;) {
  1208. if (!it->empty() && it->front().size() > 1U) {
  1209. TPartOfConstraintBase::TSetType prefixes;
  1210. prefixes.reserve(it->size());
  1211. for (const auto& path : *it) {
  1212. if (path.size() > 1U) {
  1213. prefixes.emplace_back(getPrefix(path));
  1214. }
  1215. }
  1216. auto from = it++;
  1217. if (prefixes.size() < from->size())
  1218. continue;
  1219. while (sets.cend() != it && it->size() == prefixes.size() &&
  1220. std::all_of(it->cbegin(), it->cend(), [&](const TPartOfConstraintBase::TPathType& path) { return path.size() > 1U && prefixes.contains(getPrefix(path)); })) {
  1221. ++it;
  1222. }
  1223. if (std::all_of(prefixes.cbegin(), prefixes.cend(),
  1224. [width = std::distance(from, it), &rowType] (const TPartOfConstraintBase::TPathType& path) { return width == ssize_t(GetElementsCount(TBase::GetSubTypeByPath(path, rowType))); })) {
  1225. *from++ =std::move(prefixes);
  1226. it = sets.erase(from, it);
  1227. changed = setChanged = true;
  1228. }
  1229. } else
  1230. ++it;
  1231. }
  1232. }
  1233. }
  1234. return changed ? ctx.MakeConstraint<TUniqueConstraintNodeBase<Distinct>>(std::move(content)) : this;
  1235. }
  1236. template<bool Distinct>
  1237. bool TUniqueConstraintNodeBase<Distinct>::IsApplicableToType(const TTypeAnnotationNode& type) const {
  1238. if (ETypeAnnotationKind::Dict == type.GetKind())
  1239. return true; // TODO: check for dict.
  1240. const auto& itemType = GetSeqItemType(type);
  1241. return std::all_of(Content_.cbegin(), Content_.cend(), [&itemType](const TConstraintWithFieldsNode::TSetOfSetsType& sets) {
  1242. return std::all_of(sets.cbegin(), sets.cend(), [&itemType](const TConstraintWithFieldsNode::TSetType& set) {
  1243. return std::all_of(set.cbegin(), set.cend(), std::bind(&TConstraintWithFieldsNode::GetSubTypeByPath, std::placeholders::_1, std::cref(itemType)));
  1244. });
  1245. });
  1246. }
  1247. template class TUniqueConstraintNodeBase<false>;
  1248. template class TUniqueConstraintNodeBase<true>;
  1249. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1250. template<class TOriginalConstraintNode>
  1251. TPartOfConstraintNode<TOriginalConstraintNode>::TPartOfConstraintNode(TExprContext& ctx, TMapType&& mapping)
  1252. : TBase(ctx, Name())
  1253. , Mapping_(std::move(mapping))
  1254. {
  1255. YQL_ENSURE(!Mapping_.empty());
  1256. for (const auto& part : Mapping_) {
  1257. YQL_ENSURE(!part.second.empty());
  1258. const auto hash = part.first->GetHash();
  1259. TBase::Hash_ = MurmurHash<ui64>(&hash, sizeof(hash), TBase::Hash_);
  1260. for (const auto& item: part.second) {
  1261. TBase::Hash_ = std::accumulate(item.first.cbegin(), item.first.cend(), TBase::Hash_, [](ui64 hash, const std::string_view& field) { return MurmurHash<ui64>(field.data(), field.size(), hash); });
  1262. TBase::Hash_ = std::accumulate(item.second.cbegin(), item.second.cend(), TBase::Hash_, [](ui64 hash, const std::string_view& field) { return MurmurHash<ui64>(field.data(), field.size(), hash); });
  1263. }
  1264. }
  1265. }
  1266. template<class TOriginalConstraintNode>
  1267. TPartOfConstraintNode<TOriginalConstraintNode>::TPartOfConstraintNode(TExprContext& ctx, const NYT::TNode&)
  1268. : TBase(ctx, Name())
  1269. {
  1270. YQL_ENSURE(false, "TPartOfConstraintNode cannot be deserialized");
  1271. }
  1272. template<class TOriginalConstraintNode>
  1273. TPartOfConstraintNode<TOriginalConstraintNode>::TPartOfConstraintNode(TPartOfConstraintNode&& constr) = default;
  1274. template<class TOriginalConstraintNode>
  1275. bool TPartOfConstraintNode<TOriginalConstraintNode>::Equals(const TConstraintNode& node) const {
  1276. if (this == &node) {
  1277. return true;
  1278. }
  1279. if (TBase::GetHash() != node.GetHash()) {
  1280. return false;
  1281. }
  1282. if (const auto c = dynamic_cast<const TPartOfConstraintNode*>(&node)) {
  1283. return Mapping_ == c->Mapping_;
  1284. }
  1285. return false;
  1286. }
  1287. template<class TOriginalConstraintNode>
  1288. bool TPartOfConstraintNode<TOriginalConstraintNode>::Includes(const TConstraintNode& node) const {
  1289. if (this == &node) {
  1290. return true;
  1291. }
  1292. if (const auto c = dynamic_cast<const TPartOfConstraintNode*>(&node)) {
  1293. for (const auto& part : c->Mapping_) {
  1294. if (const auto it = Mapping_.find(part.first); Mapping_.cend() != it) {
  1295. for (const auto& pair : part.second) {
  1296. if (const auto p = it->second.find(pair.first); it->second.cend() == p || p->second != pair.second) {
  1297. return false;
  1298. }
  1299. }
  1300. } else
  1301. return false;
  1302. }
  1303. return true;
  1304. }
  1305. return false;
  1306. }
  1307. template<class TOriginalConstraintNode>
  1308. void TPartOfConstraintNode<TOriginalConstraintNode>::Out(IOutputStream& out) const {
  1309. TConstraintNode::Out(out);
  1310. out.Write('(');
  1311. bool first = true;
  1312. for (const auto& part : Mapping_) {
  1313. for (const auto& item : part.second) {
  1314. if (first)
  1315. first = false;
  1316. else
  1317. out.Write(',');
  1318. out << item.first;
  1319. out.Write(':');
  1320. out << item.second;
  1321. }
  1322. }
  1323. out.Write(')');
  1324. }
  1325. template<class TOriginalConstraintNode>
  1326. void TPartOfConstraintNode<TOriginalConstraintNode>::ToJson(NJson::TJsonWriter& out) const {
  1327. out.OpenMap();
  1328. for (const auto& part : Mapping_) {
  1329. for (const auto& [resultColumn, originalColumn] : part.second) {
  1330. out.Write(JoinSeq(';', resultColumn), JoinSeq(';', originalColumn));
  1331. }
  1332. }
  1333. out.CloseMap();
  1334. }
  1335. template<class TOriginalConstraintNode>
  1336. NYT::TNode TPartOfConstraintNode<TOriginalConstraintNode>::ToYson() const {
  1337. return {}; // cannot be serialized
  1338. }
  1339. template<class TOriginalConstraintNode>
  1340. const TPartOfConstraintNode<TOriginalConstraintNode>*
  1341. TPartOfConstraintNode<TOriginalConstraintNode>::ExtractField(TExprContext& ctx, const std::string_view& field) const {
  1342. TMapType passtrought;
  1343. for (const auto& part : Mapping_) {
  1344. auto it = part.second.lower_bound(TPartOfConstraintBase::TPathType(1U, field));
  1345. if (part.second.cend() == it || it->first.front() != field)
  1346. continue;
  1347. TPartType mapping;
  1348. mapping.reserve(part.second.size());
  1349. while (it < part.second.cend() && !it->first.empty() && field == it->first.front()) {
  1350. auto item = *it++;
  1351. item.first.pop_front();
  1352. mapping.emplace_back(std::move(item));
  1353. }
  1354. if (!mapping.empty()) {
  1355. passtrought.emplace(part.first, std::move(mapping));
  1356. }
  1357. }
  1358. return passtrought.empty() ? nullptr : ctx.MakeConstraint<TPartOfConstraintNode>(std::move(passtrought));
  1359. }
  1360. template<class TOriginalConstraintNode>
  1361. const TPartOfConstraintBase*
  1362. TPartOfConstraintNode<TOriginalConstraintNode>::DoFilterFields(TExprContext& ctx, const TPartOfConstraintBase::TPathFilter& predicate) const {
  1363. if (!predicate)
  1364. return this;
  1365. auto mapping = Mapping_;
  1366. for (auto part = mapping.begin(); mapping.end() != part;) {
  1367. for (auto it = part->second.cbegin(); part->second.cend() != it;) {
  1368. if (predicate(it->first))
  1369. ++it;
  1370. else
  1371. it = part->second.erase(it);
  1372. }
  1373. if (part->second.empty())
  1374. part = mapping.erase(part);
  1375. else
  1376. ++part;
  1377. }
  1378. return mapping.empty() ? nullptr : ctx.MakeConstraint<TPartOfConstraintNode>(std::move(mapping));
  1379. }
  1380. template<class TOriginalConstraintNode>
  1381. const TPartOfConstraintBase*
  1382. TPartOfConstraintNode<TOriginalConstraintNode>::DoRenameFields(TExprContext& ctx, const TPartOfConstraintBase::TPathReduce& rename) const {
  1383. if (!rename)
  1384. return this;
  1385. TMapType mapping(Mapping_.size());
  1386. for (const auto& part : Mapping_) {
  1387. TPartType map;
  1388. map.reserve(part.second.size());
  1389. for (const auto& item : part.second) {
  1390. for (auto& path : rename(item.first)) {
  1391. map.insert_unique(std::make_pair(std::move(path), item.second));
  1392. }
  1393. }
  1394. if (!map.empty())
  1395. mapping.emplace(part.first, std::move(map));
  1396. }
  1397. return mapping.empty() ? nullptr : ctx.MakeConstraint<TPartOfConstraintNode>(std::move(mapping));
  1398. }
  1399. template<class TOriginalConstraintNode>
  1400. const TPartOfConstraintNode<TOriginalConstraintNode>*
  1401. TPartOfConstraintNode<TOriginalConstraintNode>::CompleteOnly(TExprContext& ctx) const {
  1402. TMapType mapping(Mapping_);
  1403. for (auto it = mapping.begin(); mapping.end() != it;) {
  1404. TPartOfConstraintBase::TSetType set;
  1405. set.reserve(it->second.size());
  1406. std::for_each(it->second.cbegin(), it->second.cend(), [&](const typename TPartType::value_type& pair) { set.insert_unique(pair.second); });
  1407. it->first->FilterUncompleteReferences(set);
  1408. for (auto jt = it->second.cbegin(); it->second.cend() != jt;) {
  1409. if (set.contains(jt->second))
  1410. ++jt;
  1411. else
  1412. jt = it->second.erase(jt);
  1413. }
  1414. if (it->second.empty())
  1415. it = mapping.erase(it);
  1416. else
  1417. ++it;
  1418. }
  1419. return mapping.empty() ? nullptr : ctx.MakeConstraint<TPartOfConstraintNode>(std::move(mapping));
  1420. }
  1421. template<class TOriginalConstraintNode>
  1422. const TPartOfConstraintNode<TOriginalConstraintNode>*
  1423. TPartOfConstraintNode<TOriginalConstraintNode>:: RemoveOriginal(TExprContext& ctx, const TMainConstraint* original) const {
  1424. TMapType mapping(Mapping_);
  1425. mapping.erase(original);
  1426. return mapping.empty() ? nullptr : ctx.MakeConstraint<TPartOfConstraintNode>(std::move(mapping));
  1427. }
  1428. template<class TOriginalConstraintNode>
  1429. typename TPartOfConstraintNode<TOriginalConstraintNode>::TMapType
  1430. TPartOfConstraintNode<TOriginalConstraintNode>::GetColumnMapping(const std::string_view& asField) const {
  1431. auto mapping = Mapping_;
  1432. if (!asField.empty()) {
  1433. for (auto& item : mapping) {
  1434. for (auto& part : item.second) {
  1435. part.first.emplace_front(asField);
  1436. }
  1437. }
  1438. }
  1439. return mapping;
  1440. }
  1441. template<class TOriginalConstraintNode>
  1442. typename TPartOfConstraintNode<TOriginalConstraintNode>::TMapType
  1443. TPartOfConstraintNode<TOriginalConstraintNode>::GetColumnMapping(TExprContext& ctx, const std::string_view& prefix) const {
  1444. auto mapping = Mapping_;
  1445. if (!prefix.empty()) {
  1446. const TString str(prefix);
  1447. for (auto& item : mapping) {
  1448. for (auto& part : item.second) {
  1449. if (part.first.empty())
  1450. part.first.emplace_front(prefix);
  1451. else
  1452. part.first.front() = ctx.AppendString(str + part.first.front());
  1453. }
  1454. }
  1455. }
  1456. return mapping;
  1457. }
  1458. template<class TOriginalConstraintNode>
  1459. const TPartOfConstraintNode<TOriginalConstraintNode>*
  1460. TPartOfConstraintNode<TOriginalConstraintNode>::MakeCommon(const std::vector<const TConstraintSet*>& constraints, TExprContext& ctx) {
  1461. if (constraints.empty()) {
  1462. return nullptr;
  1463. }
  1464. if (constraints.size() == 1) {
  1465. return constraints.front()->GetConstraint<TPartOfConstraintNode>();
  1466. }
  1467. bool first = true;
  1468. TMapType mapping;
  1469. for (size_t i = 0; i < constraints.size(); ++i) {
  1470. const auto part = constraints[i]->GetConstraint<TPartOfConstraintNode>();
  1471. if (!part)
  1472. return nullptr;
  1473. if (first) {
  1474. mapping = part->GetColumnMapping();
  1475. first = false;
  1476. } else {
  1477. for (const auto& nextMapping : part->GetColumnMapping()) {
  1478. if (const auto it = mapping.find(nextMapping.first); mapping.cend() != it) {
  1479. TPartType result;
  1480. std::set_intersection(
  1481. it->second.cbegin(), it->second.cend(),
  1482. nextMapping.second.cbegin(), nextMapping.second.cend(),
  1483. std::back_inserter(result),
  1484. [] (const typename TPartType::value_type& c1, const typename TPartType::value_type& c2) {
  1485. return c1 < c2;
  1486. }
  1487. );
  1488. if (result.empty())
  1489. mapping.erase(it);
  1490. else
  1491. it->second = std::move(result);
  1492. }
  1493. }
  1494. }
  1495. if (mapping.empty()) {
  1496. break;
  1497. }
  1498. }
  1499. return mapping.empty() ? nullptr : ctx.MakeConstraint<TPartOfConstraintNode>(std::move(mapping));
  1500. }
  1501. template<class TOriginalConstraintNode>
  1502. const typename TPartOfConstraintNode<TOriginalConstraintNode>::TMapType&
  1503. TPartOfConstraintNode<TOriginalConstraintNode>::GetColumnMapping() const {
  1504. return Mapping_;
  1505. }
  1506. template<class TOriginalConstraintNode>
  1507. typename TPartOfConstraintNode<TOriginalConstraintNode>::TMapType
  1508. TPartOfConstraintNode<TOriginalConstraintNode>::GetCommonMapping(const TOriginalConstraintNode* complete, const TPartOfConstraintNode* incomplete, const std::string_view& field) {
  1509. TMapType mapping;
  1510. if (incomplete) {
  1511. mapping = incomplete->GetColumnMapping();
  1512. mapping.erase(complete);
  1513. if (!field.empty()) {
  1514. for (auto& part : mapping) {
  1515. std::for_each(part.second.begin(), part.second.end(), [&field](typename TPartType::value_type& map) { map.first.push_front(field); });
  1516. }
  1517. }
  1518. }
  1519. if (complete) {
  1520. auto& part = mapping[complete];
  1521. for (const auto& path : complete->GetFullSet()) {
  1522. auto key = path;
  1523. if (!field.empty())
  1524. key.emplace_front(field);
  1525. part.insert_unique(std::make_pair(key, path));
  1526. }
  1527. }
  1528. return mapping;
  1529. }
  1530. template<class TOriginalConstraintNode>
  1531. void TPartOfConstraintNode<TOriginalConstraintNode>::UniqueMerge(TMapType& output, TMapType&& input) {
  1532. output.merge(input);
  1533. while (!input.empty()) {
  1534. const auto exists = input.extract(input.cbegin());
  1535. auto& target = output[exists.key()];
  1536. target.reserve(target.size() + exists.mapped().size());
  1537. for (auto& item : exists.mapped())
  1538. target.insert_unique(std::move(item));
  1539. }
  1540. }
  1541. template<class TOriginalConstraintNode>
  1542. typename TPartOfConstraintNode<TOriginalConstraintNode>::TMapType
  1543. TPartOfConstraintNode<TOriginalConstraintNode>::ExtractField(const TMapType& mapping, const std::string_view& field) {
  1544. TMapType parts;
  1545. for (const auto& part : mapping) {
  1546. auto it = part.second.lower_bound(TPartOfConstraintBase::TPathType(1U, field));
  1547. if (part.second.cend() == it || it->first.empty() || it->first.front() != field)
  1548. continue;
  1549. TPartType mapping;
  1550. mapping.reserve(part.second.size());
  1551. while (it < part.second.cend() && !it->first.empty() && field == it->first.front()) {
  1552. auto item = *it++;
  1553. item.first.pop_front();
  1554. mapping.emplace_back(std::move(item));
  1555. }
  1556. if (!mapping.empty()) {
  1557. parts.emplace(part.first, std::move(mapping));
  1558. }
  1559. }
  1560. return parts;
  1561. }
  1562. template<class TOriginalConstraintNode>
  1563. const TOriginalConstraintNode*
  1564. TPartOfConstraintNode<TOriginalConstraintNode>::MakeComplete(TExprContext& ctx, const TMapType& mapping, const TOriginalConstraintNode* original, const std::string_view& field) {
  1565. if (const auto it = mapping.find(original); mapping.cend() != it) {
  1566. TReversePartType reverseMap;
  1567. reverseMap.reserve(it->second.size());
  1568. for (const auto& map : it->second)
  1569. reverseMap[map.second].insert_unique(map.first);
  1570. const auto rename = [&](const TPartOfConstraintBase::TPathType& path) {
  1571. const auto& set = reverseMap[path];
  1572. std::vector<TPartOfConstraintBase::TPathType> out(set.cbegin(), set.cend());
  1573. if (!field.empty())
  1574. std::for_each(out.begin(), out.end(), [&field](TPartOfConstraintBase::TPathType& path) { path.emplace_front(field); });
  1575. return out;
  1576. };
  1577. return it->first->RenameFields(ctx, rename);
  1578. }
  1579. return nullptr;
  1580. }
  1581. template<class TOriginalConstraintNode>
  1582. const TOriginalConstraintNode*
  1583. TPartOfConstraintNode<TOriginalConstraintNode>::MakeComplete(TExprContext& ctx, const TPartOfConstraintNode* partial, const TOriginalConstraintNode* original, const std::string_view& field) {
  1584. if (!partial)
  1585. return nullptr;
  1586. return MakeComplete(ctx, partial->GetColumnMapping(), original, field);
  1587. }
  1588. template<class TOriginalConstraintNode>
  1589. bool TPartOfConstraintNode<TOriginalConstraintNode>::IsApplicableToType(const TTypeAnnotationNode& type) const {
  1590. if (ETypeAnnotationKind::Dict == type.GetKind())
  1591. return true; // TODO: check for dict.
  1592. const auto itemType = GetSeqItemType(&type);
  1593. const auto& actualType = itemType ? *itemType : type;
  1594. return std::all_of(Mapping_.cbegin(), Mapping_.cend(), [&actualType](const typename TMapType::value_type& pair) {
  1595. return std::all_of(pair.second.cbegin(), pair.second.cend(), [&actualType](const typename TPartType::value_type& part) { return bool(TPartOfConstraintBase::GetSubTypeByPath(part.first, actualType)); });
  1596. });
  1597. }
  1598. template class TPartOfConstraintNode<TSortedConstraintNode>;
  1599. template class TPartOfConstraintNode<TChoppedConstraintNode>;
  1600. template class TPartOfConstraintNode<TUniqueConstraintNode>;
  1601. template class TPartOfConstraintNode<TDistinctConstraintNode>;
  1602. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1603. TEmptyConstraintNode::TEmptyConstraintNode(TExprContext& ctx)
  1604. : TConstraintNode(ctx, Name())
  1605. {
  1606. }
  1607. TEmptyConstraintNode::TEmptyConstraintNode(TEmptyConstraintNode&& constr)
  1608. : TConstraintNode(std::move(static_cast<TConstraintNode&>(constr)))
  1609. {
  1610. }
  1611. TEmptyConstraintNode::TEmptyConstraintNode(TExprContext& ctx, const NYT::TNode& serialized)
  1612. : TConstraintNode(ctx, Name())
  1613. {
  1614. YQL_ENSURE(serialized.IsEntity(), "Unexpected serialized content of " << Name() << " constraint");
  1615. }
  1616. bool TEmptyConstraintNode::Equals(const TConstraintNode& node) const {
  1617. if (this == &node) {
  1618. return true;
  1619. }
  1620. if (GetHash() != node.GetHash()) {
  1621. return false;
  1622. }
  1623. return GetName() == node.GetName();
  1624. }
  1625. void TEmptyConstraintNode::ToJson(NJson::TJsonWriter& out) const {
  1626. out.Write(true);
  1627. }
  1628. NYT::TNode TEmptyConstraintNode::ToYson() const {
  1629. return NYT::TNode::CreateEntity();
  1630. }
  1631. const TEmptyConstraintNode* TEmptyConstraintNode::MakeCommon(const std::vector<const TConstraintSet*>& constraints, TExprContext& /*ctx*/) {
  1632. if (constraints.empty()) {
  1633. return nullptr;
  1634. }
  1635. auto empty = constraints.front()->GetConstraint<TEmptyConstraintNode>();
  1636. if (AllOf(constraints.cbegin() + 1, constraints.cend(), [empty](const TConstraintSet* c) { return c->GetConstraint<TEmptyConstraintNode>() == empty; })) {
  1637. return empty;
  1638. }
  1639. return nullptr;
  1640. }
  1641. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1642. TVarIndexConstraintNode::TVarIndexConstraintNode(TExprContext& ctx, const TMapType& mapping)
  1643. : TConstraintNode(ctx, Name())
  1644. , Mapping_(mapping)
  1645. {
  1646. Hash_ = MurmurHash<ui64>(Mapping_.data(), Mapping_.size() * sizeof(TMapType::value_type), Hash_);
  1647. YQL_ENSURE(!Mapping_.empty());
  1648. }
  1649. TVarIndexConstraintNode::TVarIndexConstraintNode(TExprContext& ctx, const TVariantExprType& itemType)
  1650. : TVarIndexConstraintNode(ctx, itemType.GetUnderlyingType()->Cast<TTupleExprType>()->GetSize())
  1651. {
  1652. }
  1653. TVarIndexConstraintNode::TVarIndexConstraintNode(TExprContext& ctx, size_t mapItemsCount)
  1654. : TConstraintNode(ctx, Name())
  1655. {
  1656. YQL_ENSURE(mapItemsCount > 0);
  1657. for (size_t i = 0; i < mapItemsCount; ++i) {
  1658. Mapping_.push_back(std::make_pair(i, i));
  1659. }
  1660. Hash_ = MurmurHash<ui64>(Mapping_.data(), Mapping_.size() * sizeof(TMapType::value_type), Hash_);
  1661. YQL_ENSURE(!Mapping_.empty());
  1662. }
  1663. TVarIndexConstraintNode::TVarIndexConstraintNode(TExprContext& ctx, const NYT::TNode& serialized)
  1664. : TVarIndexConstraintNode(ctx, NodeToMapping(serialized))
  1665. {
  1666. }
  1667. TVarIndexConstraintNode::TVarIndexConstraintNode(TVarIndexConstraintNode&& constr)
  1668. : TConstraintNode(std::move(static_cast<TConstraintNode&>(constr)))
  1669. , Mapping_(std::move(constr.Mapping_))
  1670. {
  1671. }
  1672. TVarIndexConstraintNode::TMapType TVarIndexConstraintNode::NodeToMapping(const NYT::TNode& serialized) {
  1673. TMapType mapping;
  1674. try {
  1675. for (const auto& pair: serialized.AsList()) {
  1676. mapping.insert(std::make_pair<ui32, ui32>(pair.AsList().front().AsUint64(), pair.AsList().back().AsUint64()));
  1677. }
  1678. } catch (...) {
  1679. YQL_ENSURE(false, "Cannot deserialize " << Name() << " constraint: " << CurrentExceptionMessage());
  1680. }
  1681. return mapping;
  1682. }
  1683. TVarIndexConstraintNode::TMapType TVarIndexConstraintNode::GetReverseMapping() const {
  1684. TMapType reverseMapping;
  1685. std::transform(Mapping_.cbegin(), Mapping_.cend(),
  1686. std::back_inserter(reverseMapping),
  1687. [] (const std::pair<size_t, size_t>& p) { return std::make_pair(p.second, p.first); }
  1688. );
  1689. ::Sort(reverseMapping);
  1690. return reverseMapping;
  1691. }
  1692. bool TVarIndexConstraintNode::Equals(const TConstraintNode& node) const {
  1693. if (this == &node) {
  1694. return true;
  1695. }
  1696. if (GetHash() != node.GetHash()) {
  1697. return false;
  1698. }
  1699. if (GetName() != node.GetName()) {
  1700. return false;
  1701. }
  1702. if (auto c = dynamic_cast<const TVarIndexConstraintNode*>(&node)) {
  1703. return GetIndexMapping() == c->GetIndexMapping();
  1704. }
  1705. return false;
  1706. }
  1707. bool TVarIndexConstraintNode::Includes(const TConstraintNode& node) const {
  1708. if (this == &node) {
  1709. return true;
  1710. }
  1711. if (GetName() != node.GetName()) {
  1712. return false;
  1713. }
  1714. if (auto c = dynamic_cast<const TVarIndexConstraintNode*>(&node)) {
  1715. for (auto& pair: c->Mapping_) {
  1716. if (auto p = Mapping_.FindPtr(pair.first)) {
  1717. if (*p != pair.second) {
  1718. return false;
  1719. }
  1720. } else {
  1721. return false;
  1722. }
  1723. }
  1724. return true;
  1725. }
  1726. return false;
  1727. }
  1728. void TVarIndexConstraintNode::Out(IOutputStream& out) const {
  1729. TConstraintNode::Out(out);
  1730. out.Write('(');
  1731. bool first = true;
  1732. for (auto& item: Mapping_) {
  1733. if (!first) {
  1734. out.Write(',');
  1735. }
  1736. out << item.first << ':' << item.second;
  1737. first = false;
  1738. }
  1739. out.Write(')');
  1740. }
  1741. void TVarIndexConstraintNode::ToJson(NJson::TJsonWriter& out) const {
  1742. out.OpenArray();
  1743. for (const auto& [resultIndex, originalIndex]: Mapping_) {
  1744. out.OpenArray();
  1745. out.Write(resultIndex);
  1746. out.Write(originalIndex);
  1747. out.CloseArray();
  1748. }
  1749. out.CloseArray();
  1750. }
  1751. NYT::TNode TVarIndexConstraintNode::ToYson() const {
  1752. return std::accumulate(Mapping_.cbegin(), Mapping_.cend(),
  1753. NYT::TNode::CreateList(),
  1754. [](NYT::TNode node, const TMapType::value_type& p) {
  1755. return std::move(node).Add(NYT::TNode::CreateList().Add(p.first).Add(p.second));
  1756. });
  1757. }
  1758. const TVarIndexConstraintNode* TVarIndexConstraintNode::MakeCommon(const std::vector<const TConstraintSet*>& constraints, TExprContext& ctx) {
  1759. if (constraints.empty()) {
  1760. return nullptr;
  1761. }
  1762. if (constraints.size() == 1) {
  1763. return constraints.front()->GetConstraint<TVarIndexConstraintNode>();
  1764. }
  1765. TVarIndexConstraintNode::TMapType mapping;
  1766. for (size_t i = 0; i < constraints.size(); ++i) {
  1767. if (auto varIndex = constraints[i]->GetConstraint<TVarIndexConstraintNode>()) {
  1768. mapping.insert(varIndex->GetIndexMapping().begin(), varIndex->GetIndexMapping().end());
  1769. }
  1770. }
  1771. if (mapping.empty()) {
  1772. return nullptr;
  1773. }
  1774. ::SortUnique(mapping);
  1775. return ctx.MakeConstraint<TVarIndexConstraintNode>(std::move(mapping));
  1776. }
  1777. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1778. TMultiConstraintNode::TMultiConstraintNode(TExprContext& ctx, TMapType&& items)
  1779. : TConstraintNode(ctx, Name())
  1780. , Items_(std::move(items))
  1781. {
  1782. YQL_ENSURE(Items_.size());
  1783. for (auto& item: Items_) {
  1784. Hash_ = MurmurHash<ui64>(&item.first, sizeof(item.first), Hash_);
  1785. for (auto c: item.second.GetAllConstraints()) {
  1786. const auto itemHash = c->GetHash();
  1787. Hash_ = MurmurHash<ui64>(&itemHash, sizeof(itemHash), Hash_);
  1788. }
  1789. }
  1790. }
  1791. TMultiConstraintNode::TMultiConstraintNode(TExprContext& ctx, ui32 index, const TConstraintSet& constraints)
  1792. : TMultiConstraintNode(ctx, TMapType{{index, constraints}})
  1793. {
  1794. }
  1795. TMultiConstraintNode::TMultiConstraintNode(TExprContext& ctx, const NYT::TNode& serialized)
  1796. : TMultiConstraintNode(ctx, NodeToMapping(ctx, serialized))
  1797. {
  1798. }
  1799. TMultiConstraintNode::TMultiConstraintNode(TMultiConstraintNode&& constr)
  1800. : TConstraintNode(std::move(static_cast<TConstraintNode&>(constr)))
  1801. , Items_(std::move(constr.Items_))
  1802. {
  1803. }
  1804. TMultiConstraintNode::TMapType TMultiConstraintNode::NodeToMapping(TExprContext& ctx, const NYT::TNode& serialized) {
  1805. TMapType mapping;
  1806. try {
  1807. for (const auto& pair: serialized.AsList()) {
  1808. mapping.insert(std::make_pair((ui32)pair.AsList().front().AsUint64(), ctx.MakeConstraintSet(pair.AsList().back())));
  1809. }
  1810. } catch (...) {
  1811. YQL_ENSURE(false, "Cannot deserialize " << Name() << " constraint: " << CurrentExceptionMessage());
  1812. }
  1813. return mapping;
  1814. }
  1815. bool TMultiConstraintNode::Equals(const TConstraintNode& node) const {
  1816. if (this == &node) {
  1817. return true;
  1818. }
  1819. if (GetHash() != node.GetHash()) {
  1820. return false;
  1821. }
  1822. if (GetName() != node.GetName()) {
  1823. return false;
  1824. }
  1825. if (auto c = dynamic_cast<const TMultiConstraintNode*>(&node)) {
  1826. return GetItems() == c->GetItems();
  1827. }
  1828. return false;
  1829. }
  1830. bool TMultiConstraintNode::Includes(const TConstraintNode& node) const {
  1831. if (this == &node) {
  1832. return true;
  1833. }
  1834. if (GetName() != node.GetName()) {
  1835. return false;
  1836. }
  1837. if (auto m = dynamic_cast<const TMultiConstraintNode*>(&node)) {
  1838. for (auto& item: Items_) {
  1839. const auto it = m->Items_.find(item.first);
  1840. if (it == m->Items_.end()) {
  1841. if (!item.second.GetConstraint<TEmptyConstraintNode>()) {
  1842. return false;
  1843. }
  1844. continue;
  1845. }
  1846. for (auto c: it->second.GetAllConstraints()) {
  1847. auto cit = item.second.GetConstraint(c->GetName());
  1848. if (!cit) {
  1849. return false;
  1850. }
  1851. if (!cit->Includes(*c)) {
  1852. return false;
  1853. }
  1854. }
  1855. }
  1856. return true;
  1857. }
  1858. return false;
  1859. }
  1860. bool TMultiConstraintNode::FilteredIncludes(const TConstraintNode& node, const THashSet<TString>& blacklist) const {
  1861. if (this == &node) {
  1862. return true;
  1863. }
  1864. if (GetName() != node.GetName()) {
  1865. return false;
  1866. }
  1867. if (auto m = dynamic_cast<const TMultiConstraintNode*>(&node)) {
  1868. for (auto& item: Items_) {
  1869. const auto it = m->Items_.find(item.first);
  1870. if (it == m->Items_.end()) {
  1871. if (!item.second.GetConstraint<TEmptyConstraintNode>()) {
  1872. return false;
  1873. }
  1874. continue;
  1875. }
  1876. for (auto c: it->second.GetAllConstraints()) {
  1877. if (!blacklist.contains(c->GetName())) {
  1878. const auto cit = item.second.GetConstraint(c->GetName());
  1879. if (!cit) {
  1880. return false;
  1881. }
  1882. if (!cit->Includes(*c)) {
  1883. return false;
  1884. }
  1885. }
  1886. }
  1887. }
  1888. return true;
  1889. }
  1890. return false;
  1891. }
  1892. void TMultiConstraintNode::Out(IOutputStream& out) const {
  1893. TConstraintNode::Out(out);
  1894. out.Write('(');
  1895. bool first = true;
  1896. for (auto& item: Items_) {
  1897. if (!first) {
  1898. out.Write(',');
  1899. }
  1900. out << item.first << ':' << '{';
  1901. bool firstConstr = true;
  1902. for (auto c: item.second.GetAllConstraints()) {
  1903. if (!firstConstr) {
  1904. out.Write(',');
  1905. }
  1906. out << *c;
  1907. firstConstr = false;
  1908. }
  1909. out << '}';
  1910. first = false;
  1911. }
  1912. out.Write(')');
  1913. }
  1914. void TMultiConstraintNode::ToJson(NJson::TJsonWriter& out) const {
  1915. out.OpenMap();
  1916. for (const auto& [index, constraintSet] : Items_) {
  1917. out.WriteKey(ToString(index));
  1918. constraintSet.ToJson(out);
  1919. }
  1920. out.CloseMap();
  1921. }
  1922. NYT::TNode TMultiConstraintNode::ToYson() const {
  1923. return std::accumulate(Items_.cbegin(), Items_.cend(),
  1924. NYT::TNode::CreateList(),
  1925. [](NYT::TNode node, const TMapType::value_type& p) {
  1926. return std::move(node).Add(NYT::TNode::CreateList().Add(p.first).Add(p.second.ToYson()));
  1927. });
  1928. }
  1929. const TMultiConstraintNode* TMultiConstraintNode::MakeCommon(const std::vector<const TConstraintSet*>& constraints, TExprContext& ctx) {
  1930. if (constraints.empty()) {
  1931. return nullptr;
  1932. } else if (constraints.size() == 1) {
  1933. return constraints.front()->GetConstraint<TMultiConstraintNode>();
  1934. }
  1935. TMapType multiItems;
  1936. for (auto c: constraints) {
  1937. if (auto m = c->GetConstraint<TMultiConstraintNode>()) {
  1938. multiItems.insert(m->GetItems().begin(), m->GetItems().end());
  1939. } else if (!c->GetConstraint<TEmptyConstraintNode>()) {
  1940. return nullptr;
  1941. }
  1942. }
  1943. if (multiItems.empty()) {
  1944. return nullptr;
  1945. }
  1946. multiItems.sort();
  1947. // Remove duplicates
  1948. // For duplicated items keep only Empty constraint
  1949. auto cur = multiItems.begin();
  1950. while (cur != multiItems.end()) {
  1951. auto start = cur;
  1952. do {
  1953. ++cur;
  1954. } while (cur != multiItems.end() && start->first == cur->first);
  1955. switch (std::distance(start, cur)) {
  1956. case 0:
  1957. break;
  1958. case 1:
  1959. if (start->second.GetConstraint<TEmptyConstraintNode>()) {
  1960. cur = multiItems.erase(start, cur);
  1961. }
  1962. break;
  1963. default:
  1964. {
  1965. std::vector<TMapType::value_type> nonEmpty;
  1966. std::copy_if(start, cur, std::back_inserter(nonEmpty),
  1967. [] (const TMapType::value_type& v) {
  1968. return !v.second.GetConstraint<TEmptyConstraintNode>();
  1969. }
  1970. );
  1971. start->second.Clear();
  1972. if (nonEmpty.empty()) {
  1973. start->second.AddConstraint(ctx.MakeConstraint<TEmptyConstraintNode>());
  1974. } else if (nonEmpty.size() == 1) {
  1975. start->second = nonEmpty.front().second;
  1976. }
  1977. cur = multiItems.erase(start + 1, cur);
  1978. }
  1979. }
  1980. }
  1981. if (!multiItems.empty()) {
  1982. return ctx.MakeConstraint<TMultiConstraintNode>(std::move(multiItems));
  1983. }
  1984. return nullptr;
  1985. }
  1986. const TMultiConstraintNode* TMultiConstraintNode::FilterConstraints(TExprContext& ctx, const TConstraintSet::TPredicate& predicate) const {
  1987. auto items = Items_;
  1988. bool hasContent = false, hasChanges = false;
  1989. for (auto& item : items) {
  1990. hasChanges = hasChanges || item.second.FilterConstraints(predicate);
  1991. hasContent = hasContent || item.second;
  1992. }
  1993. return hasContent ? hasChanges ? ctx.MakeConstraint<TMultiConstraintNode>(std::move(items)) : this : nullptr;
  1994. }
  1995. } // namespace NYql
  1996. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1997. template<>
  1998. void Out<NYql::TPartOfConstraintBase::TPathType>(IOutputStream& out, const NYql::TPartOfConstraintBase::TPathType& path) {
  1999. if (path.empty())
  2000. out.Write('/');
  2001. else {
  2002. bool first = true;
  2003. for (const auto& c : path) {
  2004. if (first)
  2005. first = false;
  2006. else
  2007. out.Write('/');
  2008. out.Write(c);
  2009. }
  2010. }
  2011. }
  2012. template<>
  2013. void Out<NYql::TPartOfConstraintBase::TSetType>(IOutputStream& out, const NYql::TPartOfConstraintBase::TSetType& c) {
  2014. out.Write('{');
  2015. bool first = true;
  2016. for (const auto& path : c) {
  2017. if (first)
  2018. first = false;
  2019. else
  2020. out.Write(',');
  2021. out << path;
  2022. }
  2023. out.Write('}');
  2024. }
  2025. template<>
  2026. void Out<NYql::TPartOfConstraintBase::TSetOfSetsType>(IOutputStream& out, const NYql::TPartOfConstraintBase::TSetOfSetsType& c) {
  2027. out.Write('{');
  2028. bool first = true;
  2029. for (const auto& path : c) {
  2030. if (first)
  2031. first = false;
  2032. else
  2033. out.Write(',');
  2034. out << path;
  2035. }
  2036. out.Write('}');
  2037. }
  2038. template<>
  2039. void Out<NYql::TConstraintNode>(IOutputStream& out, const NYql::TConstraintNode& c) {
  2040. c.Out(out);
  2041. }
  2042. template<>
  2043. void Out<NYql::TConstraintSet>(IOutputStream& out, const NYql::TConstraintSet& s) {
  2044. s.Out(out);
  2045. }
  2046. template<>
  2047. void Out<NYql::TSortedConstraintNode>(IOutputStream& out, const NYql::TSortedConstraintNode& c) {
  2048. c.Out(out);
  2049. }
  2050. template<>
  2051. void Out<NYql::TChoppedConstraintNode>(IOutputStream& out, const NYql::TChoppedConstraintNode& c) {
  2052. c.Out(out);
  2053. }
  2054. template<>
  2055. void Out<NYql::TUniqueConstraintNode>(IOutputStream& out, const NYql::TUniqueConstraintNode& c) {
  2056. c.Out(out);
  2057. }
  2058. template<>
  2059. void Out<NYql::TDistinctConstraintNode>(IOutputStream& out, const NYql::TDistinctConstraintNode& c) {
  2060. c.Out(out);
  2061. }
  2062. template<>
  2063. void Out<NYql::TPartOfSortedConstraintNode>(IOutputStream& out, const NYql::TPartOfSortedConstraintNode& c) {
  2064. c.Out(out);
  2065. }
  2066. template<>
  2067. void Out<NYql::TPartOfChoppedConstraintNode>(IOutputStream& out, const NYql::TPartOfChoppedConstraintNode& c) {
  2068. c.Out(out);
  2069. }
  2070. template<>
  2071. void Out<NYql::TPartOfUniqueConstraintNode>(IOutputStream& out, const NYql::TPartOfUniqueConstraintNode& c) {
  2072. c.Out(out);
  2073. }
  2074. template<>
  2075. void Out<NYql::TPartOfDistinctConstraintNode>(IOutputStream& out, const NYql::TPartOfDistinctConstraintNode& c) {
  2076. c.Out(out);
  2077. }
  2078. template<>
  2079. void Out<NYql::TEmptyConstraintNode>(IOutputStream& out, const NYql::TEmptyConstraintNode& c) {
  2080. c.Out(out);
  2081. }
  2082. template<>
  2083. void Out<NYql::TVarIndexConstraintNode>(IOutputStream& out, const NYql::TVarIndexConstraintNode& c) {
  2084. c.Out(out);
  2085. }
  2086. template<>
  2087. void Out<NYql::TMultiConstraintNode>(IOutputStream& out, const NYql::TMultiConstraintNode& c) {
  2088. c.Out(out);
  2089. }