123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892 |
- #include "node.h"
- #include "context.h"
- #include <yql/essentials/ast/yql_ast_escaping.h>
- #include <yql/essentials/ast/yql_expr.h>
- #include <yql/essentials/minikql/mkql_type_ops.h>
- #include <yql/essentials/utils/yql_panic.h>
- #include <library/cpp/containers/stack_vector/stack_vec.h>
- #include <library/cpp/charset/ci_string.h>
- #include <util/generic/hash_set.h>
- #include <util/stream/str.h>
- #include <util/string/cast.h>
- #include <util/string/subst.h>
- using namespace NYql;
- namespace NSQLTranslationV0 {
- TString ErrorDistinctWithoutCorrelation(const TString& column) {
- return TStringBuilder() << "DISTINCT columns for JOIN in SELECT should have table aliases (correlation name),"
- " add it if necessary to FROM section over 'AS <alias>' keyword and put it like '<alias>." << column << "'";
- }
- TString ErrorDistinctByGroupKey(const TString& column) {
- return TStringBuilder() << "Unable to use DISTINCT by grouping column: " << column << ". You should leave one of them.";
- }
- TTableRef::TTableRef(const TString& refName, const TString& cluster, TNodePtr keys)
- : RefName(refName)
- , Cluster(cluster)
- , Keys(keys)
- {
- }
- TTableRef::TTableRef(const TTableRef& tr)
- : RefName(tr.RefName)
- , Cluster(tr.Cluster)
- , Keys(tr.Keys)
- , Options(tr.Options)
- {
- }
- TString TTableRef::ShortName() const {
- Y_DEBUG_ABORT_UNLESS(Keys);
- if (Keys->GetTableKeys()->GetTableName()) {
- return *Keys->GetTableKeys()->GetTableName();
- }
- return TString();
- }
- TString TTableRef::ServiceName(const TContext& ctx) const {
- auto service = ctx.GetClusterProvider(Cluster);
- YQL_ENSURE(service);
- return *service;
- }
- bool TTableRef::Check(TContext& ctx) const {
- if (Cluster.empty()) {
- ctx.Error() << "No cluster name given and no default cluster is selected";
- return false;
- }
- auto service = ctx.GetClusterProvider(Cluster);
- if (!service) {
- ctx.Error() << "Unknown cluster name: " << Cluster;
- return false;
- }
- if (!Keys) {
- ctx.Error() << "No table name given";
- return false;
- }
- return true;
- }
- TColumnSchema::TColumnSchema(TPosition pos, const TString& name, const TString& type, bool nullable, bool isTypeString)
- : Pos(pos)
- , Name(name)
- , Type(type)
- , Nullable(nullable)
- , IsTypeString(isTypeString)
- {
- }
- INode::INode(TPosition pos)
- : Pos(pos)
- {
- }
- INode::~INode()
- {
- }
- TPosition INode::GetPos() const {
- return Pos;
- }
- const TString& INode::GetLabel() const {
- return Label;
- }
- void INode::SetLabel(const TString& label) {
- Label = label;
- }
- void INode::SetCountHint(bool isCount) {
- State.Set(ENodeState::CountHint, isCount);
- }
- bool INode::GetCountHint() const {
- return State.Test(ENodeState::CountHint);
- }
- bool INode::IsConstant() const {
- return HasState(ENodeState::Const);
- }
- bool INode::IsAggregated() const {
- return HasState(ENodeState::Aggregated);
- }
- bool INode::IsAggregationKey() const {
- return HasState(ENodeState::AggregationKey);
- }
- bool INode::IsOverWindow() const {
- return HasState(ENodeState::OverWindow);
- }
- bool INode::IsNull() const {
- return false;
- }
- bool INode::IsIntegerLiteral() const {
- return false;
- }
- bool INode::IsAsterisk() const {
- return false;
- }
- const TString* INode::SubqueryAlias() const {
- return nullptr;
- }
- TString INode::GetOpName() const {
- return TString();
- }
- const TString* INode::GetLiteral(const TString& type) const {
- Y_UNUSED(type);
- return nullptr;
- }
- const TString* INode::GetColumnName() const {
- return nullptr;
- }
- void INode::AssumeColumn() {
- }
- const TString* INode::GetSourceName() const {
- return nullptr;
- }
- const TString* INode::GetAtomContent() const {
- return nullptr;
- }
- size_t INode::GetTupleSize() const {
- return 0;
- }
- INode::TPtr INode::GetTupleElement(size_t index) const {
- Y_UNUSED(index);
- return nullptr;
- }
- ITableKeys* INode::GetTableKeys() {
- return nullptr;
- }
- ISource* INode::GetSource() {
- return nullptr;
- }
- TVector<TNodePtr>* INode::ContentListPtr() {
- return nullptr;
- }
- bool INode::Init(TContext& ctx, ISource* src) {
- if (State.Test(ENodeState::Failed)) {
- return false;
- }
- if (!State.Test(ENodeState::Initialized)) {
- if (!DoInit(ctx, src)) {
- State.Set(ENodeState::Failed);
- return false;
- }
- State.Set(ENodeState::Initialized);
- }
- return true;
- }
- bool INode::DoInit(TContext& ctx, ISource* src) {
- Y_UNUSED(ctx);
- Y_UNUSED(src);
- return true;
- }
- TNodePtr INode::AstNode() const {
- return new TAstListNodeImpl(Pos);
- }
- TNodePtr INode::AstNode(TNodePtr node) const {
- return node;
- }
- TNodePtr INode::AstNode(const TString& str) const {
- return new TAstAtomNodeImpl(Pos, str, TNodeFlags::Default);
- }
- TNodePtr INode::AstNode(TAstNode* node) const {
- return new TAstDirectNode(node);
- }
- TNodePtr INode::Clone() const {
- TNodePtr clone = DoClone();
- if (!clone) {
- clone = const_cast<INode*>(this);
- } else {
- YQL_ENSURE(!State.Test(ENodeState::Initialized), "Clone shold be for uninitialized or persistent node");
- clone->SetLabel(Label);
- }
- return clone;
- }
- TAggregationPtr INode::GetAggregation() const {
- return {};
- }
- INode::TPtr INode::WindowSpecFunc(const TPtr& type) const {
- Y_UNUSED(type);
- return {};
- }
- void INode::UseAsInner() {
- AsInner = true;
- }
- bool INode::UsedSubquery() const {
- return false;
- }
- bool INode::IsSelect() const {
- return false;
- }
- TNodePtr INode::ShallowCopy() const {
- Y_DEBUG_ABORT_UNLESS(false, "Node is not copyable");
- return nullptr;
- }
- void INode::DoUpdateState() const {
- }
- void INode::PrecacheState() const {
- if (State.Test(ENodeState::Failed)) {
- return;
- }
- /// Not work right now! It's better use Init at first, because some kind of update depend on it
- /// \todo turn on and remove all issues
- //Y_DEBUG_ABORT_UNLESS(State.Test(ENodeState::Initialized));
- if (State.Test(ENodeState::Precached)) {
- return;
- }
- DoUpdateState();
- State.Set(ENodeState::Precached);
- }
- void INode::DoAdd(TNodePtr node) {
- Y_UNUSED(node);
- Y_DEBUG_ABORT_UNLESS(false, "Node is not expandable");
- }
- TAstAtomNode::TAstAtomNode(TPosition pos, const TString& content, ui32 flags)
- : INode(pos)
- , Content(content)
- , Flags(flags)
- {
- }
- TAstAtomNode::~TAstAtomNode()
- {
- }
- void TAstAtomNode::DoUpdateState() const {
- State.Set(ENodeState::Const);
- }
- TAstNode* TAstAtomNode::Translate(TContext& ctx) const {
- return TAstNode::NewAtom(Pos, Content, *ctx.Pool, Flags);
- }
- const TString* TAstAtomNode::GetAtomContent() const {
- return &Content;
- }
- TAstDirectNode::TAstDirectNode(TAstNode* node)
- : INode(node->GetPosition())
- , Node(node)
- {
- }
- TAstNode* TAstDirectNode::Translate(TContext& ctx) const {
- Y_UNUSED(ctx);
- return Node;
- }
- TNodePtr BuildAtom(TPosition pos, const TString& content, ui32 flags) {
- return new TAstAtomNodeImpl(pos, content, flags);
- }
- TAstListNode::TAstListNode(TPosition pos)
- : INode(pos)
- {
- }
- TAstListNode::~TAstListNode()
- {
- }
- bool TAstListNode::DoInit(TContext& ctx, ISource* src) {
- for (auto& node: Nodes) {
- if (!node->Init(ctx, src)) {
- return false;
- }
- }
- return true;
- }
- TAstNode* TAstListNode::Translate(TContext& ctx) const {
- TSmallVec<TAstNode*> children;
- children.reserve(Nodes.size());
- auto listPos = Pos;
- for (auto& node: Nodes) {
- if (node) {
- auto astNode = node->Translate(ctx);
- if (!astNode) {
- return nullptr;
- }
- children.push_back(astNode);
- } else {
- ctx.Error(Pos) << "Translation error: encountered empty TNodePtr";
- return nullptr;
- }
- }
- return TAstNode::NewList(listPos, children.data(), children.size(), *ctx.Pool);
- }
- void TAstListNode::UpdateStateByListNodes(const TVector<TNodePtr>& nodes) const {
- bool isConst = true;
- struct TAttributesFlags {
- bool has = false;
- bool all = true;
- };
- std::array<ENodeState, 3> checkStates = {{ENodeState::Aggregated, ENodeState::AggregationKey, ENodeState::OverWindow}};
- std::map<ENodeState, TAttributesFlags> flags;
- for (auto& node: nodes) {
- const bool isNodeConst = node->IsConstant();
- for (auto state: checkStates) {
- if (node->HasState(state)) {
- flags[state].has = true;
- } else if (!isNodeConst) {
- isConst = false;
- flags[state].all = false;
- }
- }
- }
- State.Set(ENodeState::Const, isConst);
- for (auto& flag: flags) {
- State.Set(flag.first, flag.second.has && flag.second.all);
- }
- }
- void TAstListNode::DoUpdateState() const {
- UpdateStateByListNodes(Nodes);
- }
- TAstListNode::TAstListNode(const TAstListNode& node)
- : INode(node.Pos)
- , Nodes(node.Nodes)
- {
- Label = node.Label;
- State = node.State;
- }
- TAstListNode::TAstListNode(TPosition pos, TVector<TNodePtr>&& nodes)
- : INode(pos)
- , Nodes(std::move(nodes))
- {
- }
- TNodePtr TAstListNode::ShallowCopy() const {
- return new TAstListNodeImpl(Pos, Nodes);
- }
- void TAstListNode::DoAdd(TNodePtr node) {
- Y_DEBUG_ABORT_UNLESS(node);
- Y_DEBUG_ABORT_UNLESS(node.Get() != this);
- Nodes.push_back(node);
- }
- TAstListNodeImpl::TAstListNodeImpl(TPosition pos)
- : TAstListNode(pos)
- {}
- TAstListNodeImpl::TAstListNodeImpl(TPosition pos, TVector<TNodePtr> nodes)
- : TAstListNode(pos)
- {
- Nodes.swap(nodes);
- }
- TNodePtr TAstListNodeImpl::DoClone() const {
- return new TAstListNodeImpl(Pos, CloneContainer(Nodes));
- }
- bool ValidateAllNodesForAggregation(TContext& ctx, const TVector<TNodePtr>& nodes) {
- for (auto& node: nodes) {
- if (node->IsConstant()) {
- continue;
- }
- if (!node->IsAggregated() && !node->IsOverWindow()) {
- ctx.Error(node->GetPos()) << "Expression has to be an aggregation function or key column, because aggregation is used elsewhere in this subquery";
- return false;
- }
- }
- return true;
- }
- TCallNode::TCallNode(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args)
- : TAstListNode(pos)
- , OpName(opName)
- , MinArgs(minArgs)
- , MaxArgs(maxArgs)
- , Args(args)
- {
- }
- TString TCallNode::GetOpName() const {
- return OpName;
- }
- const TString* TCallNode::GetSourceName() const {
- const TString* name = nullptr;
- for (auto& arg: Args) {
- auto n = arg->GetSourceName();
- if (!n) {
- continue;
- }
- if (name && *n != *name) {
- return nullptr;
- }
- name = n;
- }
- return name;
- }
- const TVector<TNodePtr>& TCallNode::GetArgs() const {
- return Args;
- }
- void TCallNode::DoUpdateState() const {
- UpdateStateByListNodes(Args);
- }
- TString TCallNode::GetCallExplain() const {
- auto derivedName = GetOpName();
- TStringBuilder sb;
- sb << derivedName << "()";
- if (derivedName != OpName) {
- sb << ", converted to " << OpName << "()";
- }
- return std::move(sb);
- }
- bool TCallNode::ValidateArguments(TContext& ctx) const {
- const auto argsCount = static_cast<i32>(Args.size());
- if (MinArgs >= 0 && MaxArgs == MinArgs && argsCount != MinArgs) {
- ctx.Error(Pos) << GetCallExplain() << " requires exactly " << MinArgs << " arguments, given: " << Args.size();
- return false;
- }
- if (MinArgs >= 0 && argsCount < MinArgs) {
- ctx.Error(Pos) << GetCallExplain() << " requires at least " << MinArgs << " arguments, given: " << Args.size();
- return false;
- }
- if (MaxArgs >= 0 && argsCount > MaxArgs) {
- ctx.Error(Pos) << GetCallExplain() << " requires at most " << MaxArgs << " arguments, given: " << Args.size();
- return false;
- }
- return true;
- }
- bool TCallNode::DoInit(TContext& ctx, ISource* src) {
- if (!ValidateArguments(ctx)) {
- return false;
- }
- bool hasError = false;
- for (auto& arg: Args) {
- if (!arg->Init(ctx, src)) {
- hasError = true;
- continue;
- }
- }
- if (hasError) {
- return false;
- }
- Nodes.push_back(BuildAtom(Pos, OpName));
- Nodes.insert(Nodes.end(), Args.begin(), Args.end());
- return true;
- }
- TCallNodeImpl::TCallNodeImpl(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args)
- : TCallNode(pos, opName, minArgs, maxArgs, args)
- {}
- TCallNodeImpl::TCallNodeImpl(TPosition pos, const TString& opName, const TVector<TNodePtr>& args)
- : TCallNode(pos, opName, args.size(), args.size(), args)
- {}
- TCallNode::TPtr TCallNodeImpl::DoClone() const {
- return new TCallNodeImpl(GetPos(), OpName, MinArgs, MaxArgs, CloneContainer(Args));
- }
- TCallNodeDepArgs::TCallNodeDepArgs(ui32 reqArgsCount, TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args)
- : TCallNode(pos, opName, minArgs, maxArgs, args)
- , ReqArgsCount(reqArgsCount)
- {}
- TCallNodeDepArgs::TCallNodeDepArgs(ui32 reqArgsCount, TPosition pos, const TString& opName, const TVector<TNodePtr>& args)
- : TCallNode(pos, opName, args.size(), args.size(), args)
- , ReqArgsCount(reqArgsCount)
- {}
- TCallNode::TPtr TCallNodeDepArgs::DoClone() const {
- return new TCallNodeDepArgs(ReqArgsCount, GetPos(), OpName, MinArgs, MaxArgs, CloneContainer(Args));
- }
- bool TCallNodeDepArgs::DoInit(TContext& ctx, ISource* src) {
- if (!TCallNode::DoInit(ctx, src)) {
- return false;
- }
- for (ui32 i = 1 + ReqArgsCount; i < Nodes.size(); ++i) {
- Nodes[i] = Y("DependsOn", Nodes[i]);
- }
- return true;
- }
- TCallDirectRow::TPtr TCallDirectRow::DoClone() const {
- return new TCallDirectRow(Pos, OpName, CloneContainer(Args));
- }
- TCallDirectRow::TCallDirectRow(TPosition pos, const TString& opName, const TVector<TNodePtr>& args)
- : TCallNode(pos, opName, 0, 0, args)
- {}
- bool TCallDirectRow::DoInit(TContext& ctx, ISource* src) {
- if (!src) {
- ctx.Error(Pos) << "Unable to use function: " << OpName << " without source";
- return false;
- }
- if (src->IsCompositeSource() || src->GetJoin() || src->HasAggregations() || src->IsFlattenByColumns() || src->IsOverWindowSource()) {
- ctx.Error(Pos) << "Failed to use function: " << OpName << " with aggregation, join, flatten by or window functions";
- return false;
- }
- if (!TCallNode::DoInit(ctx, src)) {
- return false;
- }
- Nodes.push_back(Y("DependsOn", "row"));
- return true;
- }
- void TCallDirectRow::DoUpdateState() const {
- State.Set(ENodeState::Const, false);
- }
- void TWinAggrEmulation::DoUpdateState() const {
- State.Set(ENodeState::OverWindow, true);
- }
- bool TWinAggrEmulation::DoInit(TContext& ctx, ISource* src) {
- if (!src) {
- ctx.Error(Pos) << "Unable to use window function: " << OpName << " without source";
- return false;
- }
- if (!src->IsOverWindowSource()) {
- ctx.Error(Pos) << "Failed to use window function: " << OpName << " without window specification";
- return false;
- }
- if (!src->AddFuncOverWindow(ctx, this)) {
- ctx.Error(Pos) << "Failed to use window function: " << OpName << " without specification or in wrong place";
- return false;
- }
- FuncAlias = "_yql_" + src->MakeLocalName(OpName);
- src->AddTmpWindowColumn(FuncAlias);
- ctx.PushBlockShortcuts();
- if (!TCallNode::DoInit(ctx, src)) {
- return false;
- }
- WinAggrGround = ctx.GroundBlockShortcuts(Pos);
- Nodes.clear();
- Add("Member", "row", Q(FuncAlias));
- return true;
- }
- INode::TPtr TWinAggrEmulation::WindowSpecFunc(const TPtr& type) const {
- auto result = Y(OpName, type);
- for (const auto& arg: Args) {
- result = L(result, arg);
- }
- return Q(Y(Q(FuncAlias), result));
- }
- TWinAggrEmulation::TWinAggrEmulation(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args)
- : TCallNode(pos, opName, minArgs, maxArgs, args)
- , FuncAlias(opName)
- {}
- TWinRowNumber::TWinRowNumber(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args)
- : TWinAggrEmulation(pos, opName, minArgs, maxArgs, args)
- {}
- TWinLeadLag::TWinLeadLag(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args)
- : TWinAggrEmulation(pos, opName, minArgs, maxArgs, args)
- {}
- bool TWinLeadLag::DoInit(TContext& ctx, ISource* src) {
- if (Args.size() >= 2) {
- if (!Args[1]->IsIntegerLiteral()) {
- ctx.Error(Args[1]->GetPos()) << "Expected integer literal as second parameter of " << OpName << "( ) function";
- return false;
- }
- }
- if (!TWinAggrEmulation::DoInit(ctx, src)) {
- return false;
- }
- if (Args.size() >= 1) {
- Args[0] = BuildLambda(Pos, Y("row"), GroundWithExpr(WinAggrGround, Args[0]));
- }
- return true;
- }
- class TQuotedAtomNode: public TAstListNode {
- public:
- TQuotedAtomNode(TPosition pos, const TString& content, ui32 flags)
- : TAstListNode(pos)
- {
- Add("quote", BuildAtom(pos, content, flags));
- }
- protected:
- TQuotedAtomNode(const TQuotedAtomNode& other)
- : TAstListNode(other.Pos)
- {
- Nodes = CloneContainer(other.Nodes);
- }
- TPtr DoClone() const final {
- return new TQuotedAtomNode(*this);
- }
- };
- TNodePtr BuildQuotedAtom(TPosition pos, const TString& content, ui32 flags) {
- return new TQuotedAtomNode(pos, content, flags);
- }
- bool TColumns::Add(const TString* column, bool countHint, bool isArtificial, bool isReliable, bool hasName) {
- if (!column || *column == "*") {
- if (!countHint) {
- SetAll();
- }
- } else if (!All) {
- if (column->EndsWith('*')) {
- QualifiedAll = true;
- }
- bool inserted = false;
- if (isArtificial) {
- inserted = Artificial.insert(*column).second;
- } else {
- inserted = Real.insert(*column).second;
- }
- if (!isReliable) {
- HasUnreliable = true;
- }
- if (std::find(List.begin(), List.end(), *column) == List.end()) {
- List.push_back(*column);
- NamedColumns.push_back(hasName);
- }
- return inserted;
- }
- return All;
- }
- void TColumns::Merge(const TColumns& columns) {
- if (columns.All) {
- SetAll();
- } else {
- for (auto& c: columns.List) {
- if (columns.Real.contains(c)) {
- Add(&c, false, false);
- }
- if (columns.Artificial.contains(c)) {
- Add(&c, false, true);
- }
- }
- HasUnreliable |= columns.HasUnreliable;
- }
- }
- void TColumns::SetPrefix(const TString& prefix) {
- Y_DEBUG_ABORT_UNLESS(!prefix.empty());
- auto addPrefixFunc = [&prefix](const TString& str) {
- return prefix + "." + str;
- };
- TSet<TString> newReal;
- TSet<TString> newArtificial;
- TVector<TString> newList;
- std::transform(Real.begin(), Real.end(), std::inserter(newReal, newReal.begin()), addPrefixFunc);
- std::transform(Artificial.begin(), Artificial.end(), std::inserter(newArtificial, newArtificial.begin()), addPrefixFunc);
- std::transform(List.begin(), List.end(), std::back_inserter(newList), addPrefixFunc);
- newReal.swap(Real);
- newArtificial.swap(Artificial);
- newList.swap(List);
- }
- void TColumns::SetAll() {
- All = true;
- Real.clear();
- List.clear();
- Artificial.clear();
- }
- bool TColumns::IsColumnPossible(TContext& ctx, const TString& name) {
- if (All || Real.contains(name) || Artificial.contains(name)) {
- return true;
- }
- if (QualifiedAll) {
- if (ctx.SimpleColumns) {
- return true;
- }
- for (const auto& real: Real) {
- const auto pos = real.find_first_of("*");
- if (pos == TString::npos) {
- continue;
- }
- if (name.StartsWith(real.substr(0, pos))) {
- return true;
- }
- }
- }
- return false;
- }
- TSortSpecificationPtr TSortSpecification::Clone() const {
- auto res = MakeIntrusive<TSortSpecification>();
- res->OrderExpr = OrderExpr->Clone();
- res->Ascending = Ascending;
- return res;
- }
- TWindowSpecificationPtr TWindowSpecification::Clone() const {
- auto res = MakeIntrusive<TWindowSpecification>();
- res->ExistingWindowName = ExistingWindowName;
- res->Partitions = CloneContainer(Partitions);
- res->OrderBy = CloneContainer(OrderBy);
- res->Frame = Frame;
- return res;
- }
- THoppingWindowSpecPtr THoppingWindowSpec::Clone() const {
- auto res = MakeIntrusive<THoppingWindowSpec>();
- res->TimeExtractor = TimeExtractor->Clone();
- res->Hop = Hop->Clone();
- res->Interval = Interval->Clone();
- res->Delay = Delay->Clone();
- return res;
- }
- TColumnNode::TColumnNode(TPosition pos, const TString& column, const TString& source)
- : INode(pos)
- , ColumnName(column)
- , Source(source)
- {
- }
- TColumnNode::TColumnNode(TPosition pos, const TNodePtr& column, const TString& source)
- : INode(pos)
- , ColumnExpr(column)
- , Source(source)
- {
- }
- TColumnNode::~TColumnNode()
- {
- }
- bool TColumnNode::IsAsterisk() const {
- return ColumnName == "*";
- }
- bool TColumnNode::IsArtificial() const {
- return Artificial;
- }
- const TString* TColumnNode::GetColumnName() const {
- return UseSourceAsColumn ? &Source : (ColumnExpr ? nullptr : &ColumnName);
- }
- const TString* TColumnNode::GetSourceName() const {
- return UseSourceAsColumn ? &Empty : &Source;
- }
- bool TColumnNode::DoInit(TContext& ctx, ISource* src) {
- if (src) {
- YQL_ENSURE(!State.Test(ENodeState::Initialized)); /// should be not initialized or Aggregated already invalid
- if (src->ShouldUseSourceAsColumn(*GetSourceName())) {
- if (!IsAsterisk() && IsReliable()) {
- SetUseSourceAsColumn();
- }
- }
- if (GetColumnName()) {
- auto fullName = Source ? DotJoin(Source, *GetColumnName()) : *GetColumnName();
- auto alias = src->GetGroupByColumnAlias(fullName);
- if (alias) {
- ResetColumn(alias, {});
- }
- Artificial = !Source && src->IsExprAlias(*GetColumnName());
- }
- if (!src->AddColumn(ctx, *this)) {
- return false;
- }
- if (GetColumnName()) {
- if (src->GetJoin() && Source) {
- GroupKey = src->IsGroupByColumn(DotJoin(Source, *GetColumnName()));
- } else {
- GroupKey = src->IsGroupByColumn(*GetColumnName()) || src->IsAlias(EExprSeat::GroupBy, *GetColumnName());
- }
- }
- }
- if (IsAsterisk()) {
- Node = AstNode("row");
- } else {
- Node = Y(Reliable && !UseSource ? "Member" : "SqlColumn", "row", ColumnExpr ?
- Y("EvaluateAtom", ColumnExpr) : BuildQuotedAtom(Pos, *GetColumnName()));
- if (UseSource) {
- YQL_ENSURE(Source);
- Node = L(Node, BuildQuotedAtom(Pos, Source));
- }
- }
- return Node->Init(ctx, src);
- }
- void TColumnNode::SetUseSourceAsColumn() {
- YQL_ENSURE(!State.Test(ENodeState::Initialized)); /// should be not initialized or Aggregated already invalid
- YQL_ENSURE(!IsAsterisk());
- UseSourceAsColumn = true;
- }
- void TColumnNode::ResetAsReliable() {
- Reliable = true;
- }
- void TColumnNode::SetAsNotReliable() {
- Reliable = false;
- }
- void TColumnNode::SetUseSource() {
- UseSource = true;
- }
- bool TColumnNode::IsUseSourceAsColumn() const {
- return UseSourceAsColumn;
- }
- bool TColumnNode::IsReliable() const {
- return Reliable;
- }
- TNodePtr TColumnNode::DoClone() const {
- YQL_ENSURE(!Node, "TColumnNode::Clone: Node should not be initialized");
- auto copy = ColumnExpr ? new TColumnNode(Pos, ColumnExpr, Source) : new TColumnNode(Pos, ColumnName, Source);
- copy->GroupKey = GroupKey;
- copy->Artificial = Artificial;
- copy->Reliable = Reliable;
- copy->UseSource = UseSource;
- copy->UseSourceAsColumn = UseSourceAsColumn;
- return copy;
- }
- void TColumnNode::DoUpdateState() const {
- State.Set(ENodeState::Const, false);
- State.Set(ENodeState::Aggregated, GroupKey);
- State.Set(ENodeState::AggregationKey, GroupKey);
- }
- TAstNode* TColumnNode::Translate(TContext& ctx) const {
- return Node->Translate(ctx);
- }
- void TColumnNode::ResetColumn(const TString& column, const TString& source) {
- YQL_ENSURE(!State.Test(ENodeState::Initialized)); /// should be not initialized
- Reliable = true;
- UseSource = false;
- UseSourceAsColumn = false;
- ColumnName = column;
- ColumnExpr = nullptr;
- Source = source;
- }
- void TColumnNode::ResetColumn(const TNodePtr& column, const TString& source) {
- YQL_ENSURE(!State.Test(ENodeState::Initialized)); /// should be not initialized
- Reliable = true;
- UseSource = false;
- UseSourceAsColumn = false;
- ColumnName = "";
- ColumnExpr = column;
- Source = source;
- }
- const TString TColumnNode::Empty;
- TNodePtr BuildColumn(TPosition pos, const TString& column, const TString& source) {
- return new TColumnNode(pos, column, source);
- }
- TNodePtr BuildColumn(TPosition pos, const TNodePtr& column, const TString& source) {
- return new TColumnNode(pos, column, source);
- }
- TNodePtr BuildColumn(TPosition pos, const TDeferredAtom& column, const TString& source) {
- return column.GetLiteral() ? BuildColumn(pos, *column.GetLiteral(), source) : BuildColumn(pos, column.Build(), source);
- }
- ITableKeys::ITableKeys(TPosition pos)
- : INode(pos)
- {
- }
- const TString* ITableKeys::GetTableName() const {
- return nullptr;
- }
- ITableKeys* ITableKeys::GetTableKeys() {
- return this;
- }
- TAstNode* ITableKeys::Translate(TContext& ctx) const {
- Y_DEBUG_ABORT_UNLESS(false);
- Y_UNUSED(ctx);
- return nullptr;
- }
- bool IAggregation::IsDistinct() const {
- return !DistinctKey.empty();
- }
- void IAggregation::DoUpdateState() const {
- State.Set(ENodeState::Aggregated, AggMode == EAggregateMode::Normal);
- State.Set(ENodeState::OverWindow, AggMode == EAggregateMode::OverWindow);
- }
- const TString* IAggregation::GetGenericKey() const {
- return nullptr;
- }
- void IAggregation::Join(IAggregation*) {
- Y_ABORT_UNLESS(false);
- }
- const TString& IAggregation::GetName() const {
- return Name;
- }
- IAggregation::IAggregation(TPosition pos, const TString& name, const TString& func, EAggregateMode aggMode)
- : INode(pos), Name(name), Func(func), AggMode(aggMode)
- {}
- TAstNode* IAggregation::Translate(TContext& ctx) const {
- Y_DEBUG_ABORT_UNLESS(false);
- Y_UNUSED(ctx);
- return nullptr;
- }
- TNodePtr IAggregation::AggregationTraits(const TNodePtr& type) const {
- const bool distinct = AggMode == EAggregateMode::Distinct;
- const auto listType = distinct ? Y("ListType", Y("StructMemberType", Y("ListItemType", type), BuildQuotedAtom(Pos, DistinctKey))) : type;
- return distinct ? Q(Y(Q(Name), GetApply(listType), BuildQuotedAtom(Pos, DistinctKey))): Q(Y(Q(Name), GetApply(listType)));
- }
- void IAggregation::AddFactoryArguments(TNodePtr& apply) const {
- Y_UNUSED(apply);
- }
- std::vector<ui32> IAggregation::GetFactoryColumnIndices() const {
- return {0u};
- }
- TNodePtr IAggregation::WindowTraits(const TNodePtr& type) const {
- YQL_ENSURE(AggMode == EAggregateMode::OverWindow, "Windows traits is unavailable");
- return Q(Y(Q(Name), GetApply(type)));
- }
- ISource::ISource(TPosition pos)
- : INode(pos)
- {
- }
- ISource::~ISource()
- {
- }
- TSourcePtr ISource::CloneSource() const {
- Y_DEBUG_ABORT_UNLESS(dynamic_cast<ISource*>(Clone().Get()), "Cloned node is no source");
- TSourcePtr result = static_cast<ISource*>(Clone().Get());
- for (auto curFilter: Filters) {
- result->Filters.emplace_back(curFilter->Clone());
- }
- for (int i = 0; i < static_cast<int>(EExprSeat::Max); ++i) {
- result->NamedExprs[i] = CloneContainer(NamedExprs[i]);
- }
- result->FlattenColumns = FlattenColumns;
- return result;
- }
- bool ISource::IsFake() const {
- return false;
- }
- void ISource::AllColumns() {
- return;
- }
- const TColumns* ISource::GetColumns() const {
- return nullptr;
- }
- void ISource::GetInputTables(TTableList& tableList) const {
- for (auto srcPtr: UsedSources) {
- srcPtr->GetInputTables(tableList);
- }
- return;
- }
- TMaybe<bool> ISource::AddColumn(TContext& ctx, TColumnNode& column) {
- if (column.IsReliable()) {
- ctx.Error(Pos) << "Source does not allow column references";
- }
- return {};
- }
- void ISource::FinishColumns() {
- }
- bool ISource::AddFilter(TContext& ctx, TNodePtr filter) {
- Y_UNUSED(ctx);
- Filters.push_back(filter);
- return true;
- }
- bool ISource::AddGroupKey(TContext& ctx, const TString& column) {
- if (!GroupKeys.insert(column).second) {
- ctx.Error() << "Duplicate grouping column: " << column;
- return false;
- }
- OrderedGroupKeys.push_back(column);
- return true;
- }
- bool ISource::AddExpressions(TContext& ctx, const TVector<TNodePtr>& expressions, EExprSeat exprSeat) {
- YQL_ENSURE(exprSeat < EExprSeat::Max);
- TSet<TString> names;
- for (const auto& expr: expressions) {
- const auto& alias = expr->GetLabel();
- const auto& columnNamePtr = expr->GetColumnName();
- if (alias) {
- if (!ExprAliases.emplace(alias).second) {
- ctx.Error(expr->GetPos()) << "Duplicate alias found: " << alias << " in " << exprSeat << " section";
- return false;
- }
- if (names.contains(alias)) {
- ctx.Error(expr->GetPos()) << "Collision between alias and column name: " << alias << " in " << exprSeat << " section";
- return false;
- }
- }
- if (columnNamePtr) {
- const auto& sourceName = *expr->GetSourceName();
- auto columnName = *columnNamePtr;
- if (sourceName) {
- columnName = DotJoin(sourceName, columnName);
- }
- if (!names.emplace(columnName).second) {
- ctx.Error(expr->GetPos()) << "Duplicate column name found: " << columnName << " in " << exprSeat << " section";
- return false;
- }
- if (!alias && ExprAliases.contains(columnName)) {
- ctx.Error(expr->GetPos()) << "Collision between alias and column name: " << columnName << " in " << exprSeat << " section";
- return false;
- }
- if (alias && exprSeat == EExprSeat::GroupBy) {
- auto columnAlias = GroupByColumnAliases.emplace(columnName, alias);
- auto oldAlias = columnAlias.first->second;
- if (columnAlias.second && oldAlias != alias) {
- ctx.Error(expr->GetPos()) << "Alias for column not same, column: " << columnName <<
- ", exist alias: " << oldAlias << ", another alias: " << alias;
- return false;
- }
- }
- }
- Expressions(exprSeat).emplace_back(expr);
- }
- return true;
- }
- void ISource::SetFlattenByMode(const TString& mode) {
- FlattenMode = mode;
- }
- void ISource::MarkFlattenColumns() {
- FlattenColumns = true;
- }
- bool ISource::IsFlattenColumns() const {
- return FlattenColumns;
- }
- TString ISource::MakeLocalName(const TString& name) {
- auto iter = GenIndexes.find(name);
- if (iter == GenIndexes.end()) {
- iter = GenIndexes.emplace(name, 0).first;
- }
- TStringBuilder str;
- str << name << iter->second;
- ++iter->second;
- return std::move(str);
- }
- bool ISource::AddAggregation(TContext& ctx, TAggregationPtr aggr) {
- Y_UNUSED(ctx);
- Aggregations.push_back(aggr);
- return true;
- }
- bool ISource::HasAggregations() const {
- return !Aggregations.empty() || !GroupKeys.empty();
- }
- void ISource::AddWindowSpecs(TWinSpecs winSpecs) {
- WinSpecs = winSpecs;
- }
- bool ISource::AddFuncOverWindow(TContext& ctx, TNodePtr expr) {
- Y_UNUSED(ctx);
- Y_UNUSED(expr);
- return false;
- }
- void ISource::AddTmpWindowColumn(const TString& column) {
- TmpWindowColumns.push_back(column);
- }
- const TVector<TString>& ISource::GetTmpWindowColumns() const {
- return TmpWindowColumns;
- }
- void ISource::SetHoppingWindowSpec(THoppingWindowSpecPtr spec) {
- HoppingWindowSpec = spec;
- }
- THoppingWindowSpecPtr ISource::GetHoppingWindowSpec() const {
- return HoppingWindowSpec;
- }
- TWindowSpecificationPtr ISource::FindWindowSpecification(TContext& ctx, const TString& windowName) const {
- auto winIter = WinSpecs.find(windowName);
- if (winIter == WinSpecs.end()) {
- ctx.Error(Pos) << "Can't refer to the window specification with name: " << windowName;
- return {};
- }
- auto winSpec = winIter->second;
- if (winSpec->Frame) {
- ctx.Error(Pos) << "Frame that not default is not supported yet for window: " << windowName;
- return {};
- }
- return winSpec;
- }
- inline TVector<TNodePtr>& ISource::Expressions(EExprSeat exprSeat) {
- return NamedExprs[static_cast<size_t>(exprSeat)];
- }
- inline const TVector<TNodePtr>& ISource::Expressions(EExprSeat exprSeat) const {
- return NamedExprs[static_cast<size_t>(exprSeat)];
- }
- inline TNodePtr ISource::AliasOrColumn(const TNodePtr& node, bool withSource) {
- auto result = node->GetLabel();
- if (!result) {
- const auto columnNamePtr = node->GetColumnName();
- YQL_ENSURE(columnNamePtr);
- result = *columnNamePtr;
- if (withSource) {
- const auto sourceNamePtr = node->GetSourceName();
- if (sourceNamePtr) {
- result = DotJoin(*sourceNamePtr, result);
- }
- }
- }
- return node->Q(result);
- }
- bool ISource::AddAggregationOverWindow(TContext& ctx, const TString& windowName, TAggregationPtr func) {
- if (func->IsDistinct()) {
- ctx.Error(func->GetPos()) << "Aggregation with distinct is not allowed over window: " << windowName;
- return false;
- }
- if (!FindWindowSpecification(ctx, windowName)) {
- return false;
- }
- AggregationOverWindow.emplace(windowName, func);
- return true;
- }
- bool ISource::AddFuncOverWindow(TContext& ctx, const TString& windowName, TNodePtr func) {
- if (!FindWindowSpecification(ctx, windowName)) {
- return false;
- }
- FuncOverWindow.emplace(windowName, func);
- return true;
- }
- bool ISource::IsCompositeSource() const {
- return false;
- }
- bool ISource::IsGroupByColumn(const TString& column) const {
- return GroupKeys.contains(column);
- }
- bool ISource::IsFlattenByColumns() const {
- return !Expressions(EExprSeat::FlattenBy).empty();
- }
- bool ISource::IsAlias(EExprSeat exprSeat, const TString& column) const {
- for (const auto& exprNode: Expressions(exprSeat)) {
- const auto& labelName = exprNode->GetLabel();
- if (labelName && labelName == column) {
- return true;
- }
- }
- return false;
- }
- bool ISource::IsExprAlias(const TString& column) const {
- std::array<EExprSeat, 3> exprSeats = {{EExprSeat::FlattenBy, EExprSeat::GroupBy, EExprSeat::WindowPartitionBy}};
- for (auto seat: exprSeats) {
- if (IsAlias(seat, column)) {
- return true;
- }
- }
- return false;
- }
- bool ISource::IsExprSeat(EExprSeat exprSeat, EExprType type) const {
- auto expressions = Expressions(exprSeat);
- if (!expressions) {
- return false;
- }
- for (const auto& exprNode: expressions) {
- if (exprNode->GetLabel()) {
- return type == EExprType::WithExpression;
- }
- }
- return type == EExprType::ColumnOnly;
- }
- TString ISource::GetGroupByColumnAlias(const TString& column) const {
- auto iter = GroupByColumnAliases.find(column);
- if (iter == GroupByColumnAliases.end()) {
- return {};
- }
- return iter->second;
- }
- const TString* ISource::GetWindowName() const {
- return {};
- }
- bool ISource::IsCalcOverWindow() const {
- return !AggregationOverWindow.empty() || !FuncOverWindow.empty();
- }
- bool ISource::IsOverWindowSource() const {
- return !WinSpecs.empty();
- }
- bool ISource::IsStream() const {
- return false;
- }
- bool ISource::IsOrdered() const {
- return false;
- }
- TWriteSettings ISource::GetWriteSettings() const {
- return {};
- }
- bool ISource::SetSamplingOptions(TContext& ctx,
- TPosition pos,
- ESampleMode mode,
- TNodePtr samplingRate,
- TNodePtr samplingSeed) {
- Y_UNUSED(pos);
- Y_UNUSED(mode);
- Y_UNUSED(samplingRate);
- Y_UNUSED(samplingSeed);
- ctx.Error() << "Sampling is only supported for table sources";
- return false;
- }
- bool ISource::CalculateGroupingHint(TContext& ctx, const TVector<TString>& columns, ui64& hint) const {
- Y_UNUSED(columns);
- Y_UNUSED(hint);
- ctx.Error() << "Source not support grouping hint";
- return false;
- }
- TNodePtr ISource::BuildFilter(TContext& ctx, const TString& label, const TNodePtr& groundNode) {
- return Filters.empty() ? nullptr : Y(ctx.UseUnordered(*this) ? "OrderedFilter" : "Filter", label, BuildFilterLambda(groundNode));
- }
- TNodePtr ISource::BuildFilterLambda(const TNodePtr& groundNode) {
- if (Filters.empty()) {
- return BuildLambda(Pos, Y("row"), Y("Bool", Q("true")));
- }
- YQL_ENSURE(Filters[0]->HasState(ENodeState::Initialized));
- TNodePtr filter(Filters[0]);
- for (ui32 i = 1; i < Filters.size(); ++i) {
- YQL_ENSURE(Filters[i]->HasState(ENodeState::Initialized));
- filter = Y("And", filter, Filters[i]);
- }
- filter = Y("Coalesce", filter, Y("Bool", Q("false")));
- if (groundNode) {
- filter = Y("block", Q(L(groundNode, Y("return", filter))));
- }
- return BuildLambda(Pos, Y("row"), filter);
- }
- TNodePtr ISource::BuildFlattenByColumns(const TString& label) {
- auto columnsList = Y("FlattenByColumns", Q(FlattenMode), label);
- for (const auto& column: Expressions(EExprSeat::FlattenBy)) {
- const auto columnNamePtr = column->GetColumnName();
- YQL_ENSURE(columnNamePtr);
- if (column->GetLabel().empty()) {
- columnsList = L(columnsList, Q(*columnNamePtr));
- } else {
- columnsList = L(columnsList, Q(Y(Q(*columnNamePtr), Q(column->GetLabel()))));
- }
- }
- return Y(Y("let", "res", columnsList));
- }
- TNodePtr ISource::BuildFlattenColumns(const TString& label) {
- return Y(Y("let", "res", Y("Just", Y("FlattenStructs", label))));
- }
- TNodePtr ISource::BuildPreaggregatedMap(TContext& ctx) {
- const TColumns* columnsPtr = GetColumns();
- if (!columnsPtr) {
- ctx.Error(GetPos()) << "Missed columns for preaggregated map";
- return nullptr;
- }
- auto structObj = BuildAtom(Pos, "row", TNodeFlags::Default);
- for (const auto& exprNode: Expressions(EExprSeat::GroupBy)) {
- const auto name = exprNode->GetLabel();
- if (name) {
- structObj = Y("ForceRemoveMember", structObj, Q(name));
- structObj = Y("AddMember", structObj, Q(name), exprNode);
- }
- }
- auto block = Y("AsList", structObj);
- return block;
- }
- TNodePtr ISource::BuildPrewindowMap(TContext& ctx, const TNodePtr& groundNode) {
- Y_UNUSED(ctx);
- auto feed = BuildAtom(Pos, "row", TNodeFlags::Default);
- for (const auto& exprNode: Expressions(EExprSeat::WindowPartitionBy)) {
- const auto name = exprNode->GetLabel();
- if (name) {
- feed = Y("AddMember", feed, Q(name), GroundWithExpr(groundNode, exprNode));
- }
- }
- return Y(ctx.UseUnordered(*this) ? "OrderedFlatMap" : "FlatMap", "core", BuildLambda(Pos, Y("row"), Y("AsList", feed)));
- }
- TNodePtr ISource::BuildAggregation(const TString& label) {
- if (GroupKeys.empty() && Aggregations.empty() && !IsCompositeSource()) {
- return nullptr;
- }
- auto keysTuple = Y();
- for (const auto& key: GroupKeys) {
- keysTuple = L(keysTuple, BuildQuotedAtom(Pos, key));
- }
- std::map<std::pair<bool, TString>, std::vector<IAggregation*>> genericAggrs;
- for (const auto& aggr: Aggregations) {
- if (const auto key = aggr->GetGenericKey()) {
- genericAggrs[{aggr->IsDistinct(), *key}].emplace_back(aggr.Get());
- }
- }
- for (const auto& aggr : genericAggrs) {
- for (size_t i = 1U; i < aggr.second.size(); ++i) {
- aggr.second.front()->Join(aggr.second[i]);
- }
- }
- const auto listType = Y("TypeOf", label);
- auto aggrArgs = Y();
- for (const auto& aggr: Aggregations) {
- if (const auto traits = aggr->AggregationTraits(listType))
- aggrArgs = L(aggrArgs, traits);
- }
- if (HoppingWindowSpec) {
- auto hoppingTraits = Y(
- "HoppingTraits",
- Y("ListItemType", listType),
- BuildLambda(Pos, Y("row"), HoppingWindowSpec->TimeExtractor),
- HoppingWindowSpec->Hop,
- HoppingWindowSpec->Interval,
- HoppingWindowSpec->Delay,
- Q("False"),
- Q("v1"));
- return Y("Aggregate", label, Q(keysTuple), Q(aggrArgs),
- Q(Y(Q(Y(BuildQuotedAtom(Pos, "hopping"), hoppingTraits)))));
- }
- return Y("Aggregate", label, Q(keysTuple), Q(aggrArgs));
- }
- TMaybe<TString> ISource::FindColumnMistype(const TString& name) const {
- auto result = FindMistypeIn(GroupKeys, name);
- return result ? result : FindMistypeIn(ExprAliases, name);
- }
- void ISource::AddDependentSource(ISource* usedSource) {
- UsedSources.push_back(usedSource);
- }
- /// \todo fill it
- struct TWinFrame {
- };
- struct TWinPartition {
- TString ParentLabel;
- size_t Id = 0;
- TVector<size_t> FrameIds;
- TVector<TSortSpecificationPtr> OrderBy;
- TVector<TNodePtr> Partitions;
- };
- /// \todo use few levels of grouping (got from group by cube, etc)
- class WindowFuncSupp {
- public:
- struct EvalOverWindow {
- TVector<TAggregationPtr> Aggregations;
- TVector<TNodePtr> Functions;
- };
- size_t GetWindowByName(const TString& windowName) {
- auto iter = WindowMap.find(windowName);
- return iter != WindowMap.end() ? iter->second : 0;
- }
- size_t CreateWindowBySpec(const TString& windowName, const TWindowSpecificationPtr& winSpec) {
- Y_UNUSED(windowName);
- auto curPartitions = winSpec->Partitions;
- auto curOrderBy = winSpec->OrderBy;
- auto partition = std::find_if(Partitions.begin(), Partitions.end(), [&curPartitions, &curOrderBy](const TWinPartition& other) {
- /// \todo this compare is too strong;
- if (curPartitions != other.Partitions) {
- return false;
- }
- if (curOrderBy.size() != other.OrderBy.size()) {
- return false;
- }
- for (unsigned i = 0; i < curOrderBy.size(); ++i) {
- // failed in common case
- if (curOrderBy[i]->OrderExpr != other.OrderBy[i]->OrderExpr) {
- return false;
- }
- if (curOrderBy[i]->Ascending != other.OrderBy[i]->Ascending) {
- return false;
- }
- }
- return true;
- });
- if (partition == Partitions.end()) {
- TWinPartition newPartition;
- newPartition.Partitions = curPartitions;
- newPartition.OrderBy = curOrderBy;
- Partitions.emplace_back(newPartition);
- partition = Partitions.end() - 1;
- }
- /// \todo add smart frame search and creation
- auto frame = partition->FrameIds.begin();
- if (frame == partition->FrameIds.end()) {
- YQL_ENSURE(!winSpec->Frame, "Supported only default frame yet!");
- Evals.push_back({});
- const size_t curEval = Evals.size();
- partition->FrameIds.push_back(curEval);
- frame = partition->FrameIds.end() - 1;
- }
- return *frame;
- }
- void AddAggregationFunc(size_t windowId, TAggregationPtr func) {
- Evals[windowId-1].Aggregations.push_back(func);
- }
- void AddSimpleFunc(size_t windowId, TNodePtr func) {
- Evals[windowId-1].Functions.push_back(func);
- }
- const TVector<TWinPartition>& GetPartitions() {
- return Partitions;
- }
- const EvalOverWindow& GetEvals(size_t frameId) {
- YQL_ENSURE(frameId && frameId <= Evals.size());
- return Evals[frameId-1];
- }
- TNodePtr BuildFrame(TPosition pos, size_t frameId) {
- Y_UNUSED(frameId);
- /// \todo support not default frame
- return BuildLiteralVoid(pos);
- }
- private:
- TVector<TWinPartition> Partitions;
- TMap<TString, size_t> WindowMap;
- TVector<EvalOverWindow> Evals;
- };
- TNodePtr ISource::BuildCalcOverWindow(TContext& ctx, const TString& label, const TNodePtr& ground) {
- if (AggregationOverWindow.empty() && FuncOverWindow.empty()) {
- return {};
- }
- WindowFuncSupp winSupp;
- for (auto iter: AggregationOverWindow) {
- auto windowId = winSupp.GetWindowByName(iter.first);
- if (!windowId) {
- windowId = winSupp.CreateWindowBySpec(iter.first, WinSpecs.at(iter.first));
- }
- winSupp.AddAggregationFunc(windowId, iter.second);
- }
- for (auto iter: FuncOverWindow) {
- auto windowId = winSupp.GetWindowByName(iter.first);
- if (!windowId) {
- windowId = winSupp.CreateWindowBySpec(iter.first, WinSpecs.at(iter.first));
- }
- winSupp.AddSimpleFunc(windowId, iter.second);
- }
- auto partitions = winSupp.GetPartitions();
- const bool onePartition = partitions.size() == 1;
- const auto useLabel = onePartition ? label : "partitioning";
- const auto listType = Y("TypeOf", useLabel);
- auto framesProcess = Y();
- auto resultNode = onePartition ? Y() : Y(Y("let", "partitioning", label));
- for (auto partition: partitions) {
- if (!partition.ParentLabel.empty()) {
- ctx.Error(GetPos()) << "Dependent partition for Window function unsupported yet!";
- return nullptr;
- }
- auto keysTuple = Y();
- for (const auto& key: partition.Partitions) {
- keysTuple = L(keysTuple, AliasOrColumn(key, GetJoin()));
- }
- auto frames = Y();
- for (auto frameId: partition.FrameIds) {
- auto callOnFrame = Y("WinOnRows", winSupp.BuildFrame(ctx.Pos(), frameId));
- const auto& evals = winSupp.GetEvals(frameId);
- for (auto eval: evals.Aggregations) {
- if (!eval->IsOverWindow()) {
- ctx.Error(eval->GetPos()) << "Aggregation over window is not supported for function: " << eval->GetName();
- return nullptr;
- }
- auto winTraits = eval->WindowTraits(listType);
- callOnFrame = L(callOnFrame, winTraits);
- }
- for (auto eval: evals.Functions) {
- auto winSpec = eval->WindowSpecFunc(listType);
- callOnFrame = L(callOnFrame, winSpec);
- }
- /// \todo some smart frame building not "WinOnRows" hardcode
- frames = L(frames, callOnFrame);
- }
- auto sortSpec = partition.OrderBy.empty() ? BuildLiteralVoid(ctx.Pos()) : BuildSortSpec(partition.OrderBy, useLabel, ground, true);
- framesProcess = Y("CalcOverWindow", useLabel, Q(keysTuple), sortSpec, Q(frames));
- if (!onePartition) {
- resultNode = L(resultNode, Y("let", "partitioning", framesProcess));
- }
- }
- if (onePartition) {
- return framesProcess;
- } else {
- return Y("block", Q(L(resultNode, Y("return", "partitioning"))));
- }
- }
- TNodePtr ISource::BuildSort(TContext& ctx, const TString& label) {
- Y_UNUSED(ctx);
- Y_UNUSED(label);
- return nullptr;
- }
- IJoin* ISource::GetJoin() {
- return nullptr;
- }
- ISource* ISource::GetCompositeSource() {
- return nullptr;
- }
- bool ISource::IsSelect() const {
- return true;
- }
- bool ISource::IsTableSource() const {
- return false;
- }
- bool ISource::ShouldUseSourceAsColumn(const TString& source) {
- Y_UNUSED(source);
- return false;
- }
- bool ISource::IsJoinKeysInitializing() const {
- return false;
- }
- bool ISource::DoInit(TContext& ctx, ISource* src) {
- for (auto& column: Expressions(EExprSeat::FlattenBy)) {
- if (!column->Init(ctx, this)) {
- return false;
- }
- }
- if (IsFlattenColumns() && src) {
- src->AllColumns();
- }
- return true;
- }
- bool ISource::InitFilters(TContext& ctx) {
- for (auto& filter: Filters) {
- if (!filter->Init(ctx, this)) {
- return false;
- }
- if (filter->IsAggregated() && !filter->IsConstant() && !filter->HasState(ENodeState::AggregationKey)) {
- ctx.Error(filter->GetPos()) << "Can not use aggregated values in filtering";
- return false;
- }
- }
- return true;
- }
- TAstNode* ISource::Translate(TContext& ctx) const {
- Y_DEBUG_ABORT_UNLESS(false);
- Y_UNUSED(ctx);
- return nullptr;
- }
- void ISource::FillSortParts(const TVector<TSortSpecificationPtr>& orderBy, TNodePtr& sortDirection, TNodePtr& sortKeySelector) {
- TNodePtr expr;
- if (orderBy.empty()) {
- YQL_ENSURE(!sortKeySelector);
- sortDirection = sortKeySelector = Y("Void");
- return;
- } else if (orderBy.size() == 1) {
- auto& sortSpec = orderBy.front();
- expr = Y("EnsurePersistable", sortSpec->OrderExpr);
- sortDirection = Y("Bool", Q(sortSpec->Ascending ? "true" : "false"));
- } else {
- auto exprList = Y();
- sortDirection = Y();
- for (const auto& sortSpec: orderBy) {
- const auto asc = sortSpec->Ascending;
- sortDirection = L(sortDirection, Y("Bool", Q(asc ? "true" : "false")));
- exprList = L(exprList, Y("EnsurePersistable", sortSpec->OrderExpr));
- }
- sortDirection = Q(sortDirection);
- expr = Q(exprList);
- }
- expr = sortKeySelector ? expr->Y("block", expr->Q(expr->L(sortKeySelector, expr->Y("return", expr)))) : expr;
- sortKeySelector = BuildLambda(Pos, Y("row"), expr);
- }
- TNodePtr ISource::BuildSortSpec(const TVector<TSortSpecificationPtr>& orderBy, const TString& label, const TNodePtr& ground, bool traits) {
- YQL_ENSURE(!orderBy.empty());
- TNodePtr dirsNode;
- auto keySelectorNode = ground;
- FillSortParts(orderBy, dirsNode, keySelectorNode);
- if (traits) {
- return Y("SortTraits", Y("TypeOf", label), dirsNode, keySelectorNode);
- } else {
- return Y("Sort", label, dirsNode, keySelectorNode);
- }
- }
- IJoin::IJoin(TPosition pos)
- : ISource(pos)
- {
- }
- IJoin::~IJoin()
- {
- }
- IJoin* IJoin::GetJoin() {
- return this;
- }
- bool TryStringContent(const TString& str, TString& result, ui32& flags, TString& error, TPosition& pos) {
- error.clear();
- result.clear();
- bool doubleQuoted = (str.StartsWith('"') && str.EndsWith('"'));
- bool singleQuoted = !doubleQuoted && (str.StartsWith('\'') && str.EndsWith('\''));
- if (str.size() >= 2 && (doubleQuoted || singleQuoted)) {
- flags = TNodeFlags::ArbitraryContent;
- char quoteChar = doubleQuoted ? '"' : '\'';
- size_t readBytes = 0;
- TStringBuf atom(str);
- TStringOutput sout(result);
- atom.Skip(1);
- result.reserve(str.size());
- auto unescapeResult = UnescapeArbitraryAtom(atom, quoteChar, &sout, &readBytes);
- if (unescapeResult != EUnescapeResult::OK) {
- TTextWalker walker(pos, false);
- walker.Advance(atom.Trunc(readBytes));
- error = UnescapeResultToString(unescapeResult);
- return false;
- }
- } else if (str.size() >= 4 && str.StartsWith("@@") && str.EndsWith("@@")) {
- flags = TNodeFlags::MultilineContent;
- TString s = str.substr(2, str.length() - 4);
- SubstGlobal(s, "@@@@", "@@");
- result.swap(s);
- } else {
- flags = TNodeFlags::Default;
- result = str;
- }
- return true;
- }
- TString StringContent(TContext& ctx, const TString& str) {
- ui32 flags = 0;
- TString result;
- TString error;
- TPosition pos;
- if (!TryStringContent(str, result, flags, error, pos)) {
- ctx.Error(pos) << "Failed to parse string literal: " << error;
- return {};
- }
- return result;
- }
- TString IdContent(TContext& ctx, const TString& s) {
- YQL_ENSURE(!s.empty(), "Empty identifier not expected");
- if (!s.StartsWith('[') && !s.StartsWith('`')) {
- return s;
- }
- auto endSym = s.StartsWith('[') ? ']' : '`';
- if (s.size() < 2 || !s.EndsWith(endSym)) {
- ctx.Error() << "The identifier that starts with: '" << s[0] << "' should ends with: '" << endSym << "'";
- return {};
- }
- size_t skipSymbols = 1;
- /// @TODO: temporary back compatibility case
- if (s.StartsWith('[') && s[1] == '"') {
- ctx.Warning(ctx.Pos(), TIssuesIds::YQL_DEPRECATED_DOUBLE_QUOTE_IN_BRACKETS) <<
- "The use of double quotes in the identifier in square brackets is deprecated."
- " Either simply remove the double quotes or use backticks."
- " If you need quotes they can be escaped by '\\'.";
- if (s.size() < 4 || s[s.size() - 2] != '"') {
- ctx.Error() << "Missed closed quote for identifier, either remove double quote after '[', "
- " or put double quote before ']'";
- return {};
- }
- endSym = '"';
- skipSymbols += 1;
- }
- TStringBuf atom(s.data() + skipSymbols, s.size() - 2 * skipSymbols + 1);
- TString unescapedStr;
- TStringOutput sout(unescapedStr);
- unescapedStr.reserve(s.size());
- size_t readBytes = 0;
- TPosition pos = ctx.Pos();
- pos.Column += skipSymbols - 1;
- auto unescapeResult = UnescapeArbitraryAtom(atom, endSym, &sout, &readBytes);
- if (unescapeResult != EUnescapeResult::OK) {
- TTextWalker walker(pos, false);
- walker.Advance(atom.Trunc(readBytes));
- ctx.Error(pos) << "Cannot parse broken identifier: " << UnescapeResultToString(unescapeResult);
- return {};
- }
- if (readBytes != atom.size()) {
- ctx.Error() << "The identifier not parsed completely";
- return {};
- }
- return unescapedStr;
- }
- namespace {
- class TInvalidLiteralNode final: public INode {
- public:
- TInvalidLiteralNode(TPosition pos)
- : INode(pos)
- {
- }
- bool DoInit(TContext& ctx, ISource* source) override {
- Y_UNUSED(ctx);
- Y_UNUSED(source);
- return false;
- }
- TAstNode* Translate(TContext& ctx) const override {
- Y_UNUSED(ctx);
- return nullptr;
- }
- TPtr DoClone() const override {
- return {};
- }
- };
- }
- TLiteralNode::TLiteralNode(TPosition pos, bool isNull)
- : TAstListNode(pos)
- , Null(isNull)
- , Void(!isNull)
- {
- Add(isNull ? "Null" : "Void");
- }
- TLiteralNode::TLiteralNode(TPosition pos, const TString& type, const TString& value)
- : TAstListNode(pos)
- , Null(false)
- , Void(false)
- , Type(type)
- , Value(value)
- {
- Add(Type, BuildQuotedAtom(Pos, Value));
- }
- TLiteralNode::TLiteralNode(TPosition pos, const TString& value, ui32 nodeFlags)
- : TAstListNode(pos)
- , Null(false)
- , Void(false)
- , Type("String")
- , Value(value)
- {
- Add(Type, BuildQuotedAtom(pos, Value, nodeFlags));
- }
- bool TLiteralNode::IsNull() const {
- return Null;
- }
- const TString* TLiteralNode::GetLiteral(const TString& type) const {
- return type == Type ? &Value : nullptr;
- }
- void TLiteralNode::DoUpdateState() const {
- State.Set(ENodeState::Const);
- }
- TNodePtr TLiteralNode::DoClone() const {
- auto res = (Null || Void) ? MakeIntrusive<TLiteralNode>(Pos, Null) : MakeIntrusive<TLiteralNode>(Pos, Type, Value);
- res->Nodes = Nodes;
- return res;
- }
- template<typename T>
- TLiteralNumberNode<T>::TLiteralNumberNode(TPosition pos, const TString& type, const TString& value)
- : TLiteralNode(pos, type, value)
- {}
- template<typename T>
- TNodePtr TLiteralNumberNode<T>::DoClone() const {
- return new TLiteralNumberNode<T>(Pos, Type, Value);
- }
- template<typename T>
- bool TLiteralNumberNode<T>::DoInit(TContext& ctx, ISource* src) {
- Y_UNUSED(src);
- T val;
- if (!TryFromString(Value, val)) {
- ctx.Error(Pos) << "Failed to convert string: " << Value << " to " << Type << " value";
- return false;
- }
- return true;
- }
- template<typename T>
- bool TLiteralNumberNode<T>::IsIntegerLiteral() const {
- return std::numeric_limits<T>::is_integer;
- }
- template class TLiteralNumberNode<i32>;
- template class TLiteralNumberNode<i64>;
- template class TLiteralNumberNode<ui32>;
- template class TLiteralNumberNode<ui64>;
- template class TLiteralNumberNode<float>;
- template class TLiteralNumberNode<double>;
- template class TLiteralNumberNode<ui8>;
- template class TLiteralNumberNode<i8>;
- template class TLiteralNumberNode<ui16>;
- template class TLiteralNumberNode<i16>;
- TNodePtr BuildLiteralNull(TPosition pos) {
- return new TLiteralNode(pos, true);
- }
- TNodePtr BuildLiteralVoid(TPosition pos) {
- return new TLiteralNode(pos, false);
- }
- TNodePtr BuildLiteralSmartString(TContext& ctx, const TString& value) {
- TString unescaped;
- TString error;
- TPosition pos = ctx.Pos();
- ui32 flags = 0;
- if (TryStringContent(value, unescaped, flags, error, pos)) {
- return new TLiteralNode(ctx.Pos(), unescaped, flags);
- } else {
- ctx.Error(pos) << "Failed to parse string literal: " << error;
- return new TInvalidLiteralNode(ctx.Pos());
- }
- }
- TNodePtr BuildLiteralRawString(TPosition pos, const TString& value) {
- return new TLiteralNode(pos, "String", value);
- }
- TNodePtr BuildLiteralBool(TPosition pos, const TString& value) {
- return new TLiteralNode(pos, "Bool", value);
- }
- TNodePtr BuildEmptyAction(TPosition pos) {
- TNodePtr params = new TAstListNodeImpl(pos);
- TNodePtr arg = new TAstAtomNodeImpl(pos, "x", TNodeFlags::Default);
- params->Add(arg);
- return BuildLambda(pos, params, arg);
- }
- TDeferredAtom::TDeferredAtom()
- {}
- TDeferredAtom::TDeferredAtom(TPosition pos, const TString& str)
- {
- Node = BuildQuotedAtom(pos, str);
- Explicit = str;
- Repr = str;
- }
- TDeferredAtom::TDeferredAtom(TNodePtr node, TContext& ctx)
- {
- Node = node;
- Repr = ctx.MakeName("DeferredAtom");
- }
- const TString* TDeferredAtom::GetLiteral() const {
- return Explicit.Get();
- }
- TNodePtr TDeferredAtom::Build() const {
- return Node;
- }
- TString TDeferredAtom::GetRepr() const {
- return Repr;
- }
- bool TDeferredAtom::Empty() const {
- return !Node || Repr.empty();
- }
- TTupleNode::TTupleNode(TPosition pos, const TVector<TNodePtr>& exprs)
- : TAstListNode(pos)
- , Exprs(exprs)
- {}
- bool TTupleNode::IsEmpty() const {
- return Exprs.empty();
- }
- const TVector<TNodePtr>& TTupleNode::Elements() const {
- return Exprs;
- }
- bool TTupleNode::DoInit(TContext& ctx, ISource* src) {
- auto node(Y());
- for (auto& expr: Exprs) {
- if (expr->GetLabel()) {
- ctx.Error(expr->GetPos()) << "Tuple does not allow named members";
- return false;
- }
- node = L(node, expr);
- }
- Add("quote", node);
- return TAstListNode::DoInit(ctx, src);
- }
- size_t TTupleNode::GetTupleSize() const {
- return Exprs.size();
- }
- TNodePtr TTupleNode::GetTupleElement(size_t index) const {
- return Exprs[index];
- }
- TNodePtr TTupleNode::DoClone() const {
- return new TTupleNode(Pos, CloneContainer(Exprs));
- }
- TNodePtr BuildTuple(TPosition pos, const TVector<TNodePtr>& exprs) {
- return new TTupleNode(pos, exprs);
- }
- TStructNode::TStructNode(TPosition pos, const TVector<TNodePtr>& exprs)
- : TAstListNode(pos)
- , Exprs(exprs)
- {}
- bool TStructNode::DoInit(TContext& ctx, ISource* src) {
- Nodes.push_back(BuildAtom(Pos, "AsStruct", TNodeFlags::Default));
- for (const auto& expr : Exprs) {
- const auto& label = expr->GetLabel();
- if (!label) {
- ctx.Error(expr->GetPos()) << "Structure does not allow anonymous members";
- return false;
- }
- Nodes.push_back(Q(Y(BuildQuotedAtom(expr->GetPos(), label), expr)));
- }
- return TAstListNode::DoInit(ctx, src);
- }
- TNodePtr TStructNode::DoClone() const {
- return new TStructNode(Pos, CloneContainer(Exprs));
- }
- TNodePtr BuildStructure(TPosition pos, const TVector<TNodePtr>& exprs) {
- return new TStructNode(pos, exprs);
- }
- TListOfNamedNodes::TListOfNamedNodes(TPosition pos, TVector<TNodePtr>&& exprs)
- : INode(pos)
- , Exprs(std::move(exprs))
- {}
- TVector<TNodePtr>* TListOfNamedNodes::ContentListPtr() {
- return &Exprs;
- }
- TAstNode* TListOfNamedNodes::Translate(TContext& ctx) const {
- YQL_ENSURE(!"Unexpected usage");
- Y_UNUSED(ctx);
- return nullptr;
- }
- TNodePtr TListOfNamedNodes::DoClone() const {
- return {};
- }
- TNodePtr BuildListOfNamedNodes(TPosition pos, TVector<TNodePtr>&& exprs) {
- return new TListOfNamedNodes(pos, std::move(exprs));
- }
- const char* const TArgPlaceholderNode::ProcessRows = "$ROWS";
- const char* const TArgPlaceholderNode::ProcessRow = "$ROW";
- TArgPlaceholderNode::TArgPlaceholderNode(TPosition pos, const TString &name) :
- INode(pos),
- Name(name)
- {
- }
- bool TArgPlaceholderNode::DoInit(TContext& ctx, ISource* src) {
- Y_UNUSED(src);
- ctx.Error(Pos) << Name << " can't be used as a part of expression.";
- return false;
- }
- TAstNode* TArgPlaceholderNode::Translate(TContext& ctx) const {
- Y_UNUSED(ctx);
- return nullptr;
- }
- TString TArgPlaceholderNode::GetName() const {
- return Name;
- }
- TNodePtr TArgPlaceholderNode::DoClone() const {
- return {};
- }
- TNodePtr BuildArgPlaceholder(TPosition pos, const TString& name) {
- return new TArgPlaceholderNode(pos, name);
- }
- class TAccessNode: public INode {
- public:
- TAccessNode(TPosition pos, const TVector<TIdPart>& ids, bool isLookup)
- : INode(pos)
- , Ids(ids)
- , IsLookup(isLookup)
- , ColumnOnly(false)
- , IsColumnRequired(false)
- {
- Y_DEBUG_ABORT_UNLESS(Ids.size() > 1);
- Y_DEBUG_ABORT_UNLESS(Ids[0].Expr);
- auto column = dynamic_cast<TColumnNode*>(Ids[0].Expr.Get());
- if (column) {
- ui32 idx = 1;
- TString source;
- if (Ids.size() > 2) {
- source = Ids[idx].Name;
- ++idx;
- }
- ColumnOnly = !IsLookup && Ids.size() < 4;
- if (ColumnOnly && Ids[idx].Expr) {
- column->ResetColumn(Ids[idx].Expr, source);
- } else {
- column->ResetColumn(Ids[idx].Name, source);
- }
- }
- }
- void AssumeColumn() override {
- IsColumnRequired = true;
- }
- TMaybe<std::pair<TString, TString>> TryMakeClusterAndTable(TContext& ctx, bool& hasErrors) {
- hasErrors = false;
- if (!ColumnOnly) {
- return Nothing();
- }
- ui32 idx = 1;
- TString cluster;
- if (Ids.size() > 2) {
- cluster = Ids[idx].Name;
- ++idx;
- }
- if (cluster.StartsWith('$')) {
- return Nothing();
- }
- TString normalizedClusterName;
- if (!cluster.empty() && !ctx.GetClusterProvider(cluster, normalizedClusterName)) {
- hasErrors = true;
- ctx.Error() << "Unknown cluster: " << cluster;
- return Nothing();
- }
- auto tableName = Ids[idx].Name;
- if (tableName.empty()) {
- return Nothing();
- }
- return std::make_pair(normalizedClusterName, tableName);
- }
- TSourcePtr TryMakeSource(TContext& ctx, const TString& view, bool& hasErrors) {
- auto clusterAndTable = TryMakeClusterAndTable(ctx, hasErrors);
- if (!clusterAndTable) {
- return nullptr;
- }
- auto cluster = clusterAndTable->first.empty() ? ctx.CurrCluster : clusterAndTable->first;
- TNodePtr tableKey = BuildTableKey(GetPos(), cluster, TDeferredAtom(GetPos(), clusterAndTable->second), view);
- TTableRef table(ctx.MakeName("table"), cluster, tableKey);
- table.Options = BuildInputOptions(GetPos(), GetContextHints(ctx));
- return BuildTableSource(GetPos(), table, false);
- }
- TMaybe<TString> TryMakeTable() {
- if (!ColumnOnly) {
- return Nothing();
- }
- ui32 idx = 1;
- if (Ids.size() > 2) {
- return Nothing();
- }
- return Ids[idx].Name;
- }
- const TString* GetColumnName() const override {
- return ColumnOnly ? Ids[0].Expr->GetColumnName() : nullptr;
- }
- const TString* GetSourceName() const override {
- return Ids[0].Expr->GetSourceName();
- }
- bool DoInit(TContext& ctx, ISource* src) override {
- auto expr = Ids[0].Expr;
- const TPosition pos(expr->GetPos());
- if (expr->IsAsterisk()) {
- ctx.Error(pos) << "Asterisk column does not allow any access";
- return false;
- }
- if (!expr->Init(ctx, src)) {
- return false;
- }
- for (auto& id: Ids) {
- if (id.Expr && !id.Expr->Init(ctx, src)) {
- return false;
- }
- }
- ui32 idx = 1;
- auto column = dynamic_cast<TColumnNode*>(expr.Get());
- if (column) {
- const bool useSourceAsColumn = column->IsUseSourceAsColumn();
- ColumnOnly &= !useSourceAsColumn;
- if (IsColumnRequired && !ColumnOnly) {
- ctx.Error(pos) << "Please use a full form (corellation.struct.field) or an alias (struct.field as alias) to access struct's field in the GROUP BY";
- return false;
- }
- if (Ids.size() > 2) {
- if (!CheckColumnId(pos, ctx, Ids[idx], ColumnOnly ? "Correlation" : "Column", true)) {
- return false;
- }
- ++idx;
- }
- if (!useSourceAsColumn) {
- if (!IsLookup && !CheckColumnId(pos, ctx, Ids[idx], ColumnOnly ? "Column" : "Member", false)) {
- return false;
- }
- ++idx;
- }
- }
- for (; idx < Ids.size(); ++idx) {
- const auto& id = Ids[idx];
- if (!id.Name.empty()) {
- expr = Y("SqlAccess", Q("struct"), expr, id.Expr ? Y("EvaluateAtom", id.Expr) : BuildQuotedAtom(Pos, id.Name));
- AccessOpName = "AccessStructMember";
- } else if (id.Expr) {
- expr = Y("SqlAccess", Q("dict"), expr, id.Expr);
- AccessOpName = "AccessDictMember";
- } else if (id.Pos >= 0) {
- expr = Y("SqlAccess", Q("tuple"), expr, Q(ToString(id.Pos)));
- AccessOpName = "AccessTupleElement";
- } else {
- continue;
- }
- if (ctx.PragmaYsonAutoConvert || ctx.PragmaYsonStrict) {
- auto ysonOptions = Y();
- if (ctx.PragmaYsonAutoConvert) {
- ysonOptions->Add(BuildQuotedAtom(Pos, "yson_auto_convert"));
- }
- if (ctx.PragmaYsonStrict) {
- ysonOptions->Add(BuildQuotedAtom(Pos, "yson_strict"));
- }
- expr->Add(Q(ysonOptions));
- }
- }
- Node = expr;
- return true;
- }
- TAstNode* Translate(TContext& ctx) const override {
- Y_DEBUG_ABORT_UNLESS(Node);
- return Node->Translate(ctx);
- }
- TPtr DoClone() const override {
- YQL_ENSURE(!Node, "TAccessNode::Clone: Node should not be initialized");
- TVector<TIdPart> cloneIds;
- cloneIds.reserve(Ids.size());
- for (const auto& id: Ids) {
- cloneIds.emplace_back(id.Clone());
- }
- auto copy = new TAccessNode(Pos, cloneIds, IsLookup);
- copy->ColumnOnly = ColumnOnly;
- return copy;
- }
- protected:
- void DoUpdateState() const override {
- State.Set(ENodeState::Const, Ids[0].Expr->IsConstant());
- State.Set(ENodeState::Aggregated, Ids[0].Expr->IsAggregated());
- State.Set(ENodeState::AggregationKey, Ids[0].Expr->HasState(ENodeState::AggregationKey));
- State.Set(ENodeState::OverWindow, Ids[0].Expr->IsOverWindow());
- }
- bool CheckColumnId(TPosition pos, TContext& ctx, const TIdPart& id, const TString& where, bool checkLookup) {
- if (id.Name.empty()) {
- ctx.Error(pos) << where << " name can not be empty";
- return false;
- }
- if (id.Pos >= 0) {
- ctx.Error(pos) << where << " name does not allow element selection";
- return false;
- }
- if (checkLookup && id.Expr) {
- ctx.Error(pos) << where << " name does not allow dict lookup";
- return false;
- }
- return true;
- }
- TString GetOpName() const override {
- return AccessOpName;
- }
- private:
- TNodePtr Node;
- TVector<TIdPart> Ids;
- bool IsLookup;
- bool ColumnOnly;
- bool IsColumnRequired;
- TString AccessOpName;
- };
- TNodePtr BuildAccess(TPosition pos, const TVector<INode::TIdPart>& ids, bool isLookup) {
- return new TAccessNode(pos, ids, isLookup);
- }
- class TBindNode: public TAstListNode {
- public:
- TBindNode(TPosition pos, const TString& module, const TString& alias)
- : TAstListNode(pos)
- {
- Add("bind", AstNode(module), BuildQuotedAtom(pos, alias));
- }
- TPtr DoClone() const final {
- return {};
- }
- };
- TNodePtr BuildBind(TPosition pos, const TString& module, const TString& alias) {
- return new TBindNode(pos, module, alias);
- }
- class TLambdaNode: public TAstListNode {
- public:
- TLambdaNode(TPosition pos, TNodePtr params, TNodePtr body, const TString& resName)
- : TAstListNode(pos)
- {
- if (!resName.empty()) {
- body = Y("block", Q(L(body, Y("return", resName))));
- }
- Add("lambda", Q(params), body);
- }
- TPtr DoClone() const final {
- return {};
- }
- };
- TNodePtr BuildLambda(TPosition pos, TNodePtr params, TNodePtr body, const TString& resName) {
- return new TLambdaNode(pos, params, body, resName);
- }
- template <bool Bit>
- class TCastNode: public TAstListNode {
- public:
- TCastNode(TPosition pos, TNodePtr expr, const TString& typeName, const TString& paramOne, const TString& paramTwo)
- : TAstListNode(pos)
- , Expr(expr)
- , NormalizedTypeName(TypeByAlias(typeName))
- , ParamOne(paramOne)
- , ParamTwo(paramTwo)
- {}
- const TString* GetSourceName() const override {
- return Expr->GetSourceName();
- }
- TString GetOpName() const override {
- return Bit ? "BitCast" : "Cast";
- }
- void DoUpdateState() const override {
- State.Set(ENodeState::Const, Expr->IsConstant());
- State.Set(ENodeState::Aggregated, Expr->IsAggregated());
- State.Set(ENodeState::OverWindow, Expr->IsOverWindow());
- }
- TPtr DoClone() const final {
- return new TCastNode(Pos, Expr->Clone(), NormalizedTypeName, ParamOne, ParamTwo);
- }
- bool DoInit(TContext& ctx, ISource* src) override;
- private:
- TNodePtr Expr;
- const TString NormalizedTypeName;
- const TString ParamOne, ParamTwo;
- };
- template <>
- bool TCastNode<false>::DoInit(TContext& ctx, ISource* src) {
- if (Expr->IsNull()) {
- if (ParamOne.empty() && ParamTwo.empty()) {
- Add("Nothing", Y("OptionalType", Y("DataType", Q(NormalizedTypeName))));
- } else if (ParamTwo.empty()) {
- Add("Nothing", Y("OptionalType", Y("DataType", Q(NormalizedTypeName), Q(ParamOne))));
- } else {
- Add("Nothing", Y("OptionalType", Y("DataType", Q(NormalizedTypeName), Q(ParamOne), Q(ParamTwo))));
- }
- } else {
- if (ParamOne.empty() && ParamTwo.empty()) {
- Add("Cast", Expr, Q(NormalizedTypeName));
- } else if (ParamTwo.empty()) {
- Add("Cast", Expr, Q(NormalizedTypeName), Q(ParamOne));
- } else {
- Add("Cast", Expr, Q(NormalizedTypeName), Q(ParamOne), Q(ParamTwo));
- }
- }
- return TAstListNode::DoInit(ctx, src);
- }
- template <>
- bool TCastNode<true>::DoInit(TContext& ctx, ISource* src) {
- if (Expr->IsNull()) {
- if (ParamOne.empty() && ParamTwo.empty()) {
- Add("Nothing", Y("OptionalType", Y("DataType", Q(NormalizedTypeName))));
- } else if (ParamTwo.empty()) {
- Add("Nothing", Y("OptionalType", Y("DataType", Q(NormalizedTypeName), Q(ParamOne))));
- } else {
- Add("Nothing", Y("OptionalType", Y("DataType", Q(NormalizedTypeName), Q(ParamOne), Q(ParamTwo))));
- }
- } else {
- if (ParamOne.empty() && ParamTwo.empty()) {
- Add("BitCast", Expr, Q(NormalizedTypeName));
- } else if (ParamTwo.empty()) {
- Add("BitCast", Expr, Q(NormalizedTypeName), Q(ParamOne));
- } else {
- Add("BitCast", Expr, Q(NormalizedTypeName), Q(ParamOne), Q(ParamTwo));
- }
- }
- return TAstListNode::DoInit(ctx, src);
- }
- TNodePtr BuildCast(TContext& ctx, TPosition pos, TNodePtr expr, const TString& typeName, const TString& paramOne, const TString& paramTwo) {
- Y_UNUSED(ctx);
- if (!expr) {
- return nullptr;
- }
- return new TCastNode<false>(pos, expr, typeName, paramOne, paramTwo);
- }
- TNodePtr BuildBitCast(TContext& ctx, TPosition pos, TNodePtr expr, const TString& typeName, const TString& paramOne, const TString& paramTwo) {
- Y_UNUSED(ctx);
- if (!expr) {
- return nullptr;
- }
- return new TCastNode<true>(pos, expr, typeName, paramOne, paramTwo);
- }
- TString TypeByAlias(const TString& alias, bool normalize) {
- TString type(alias);
- TCiString typeAlias(alias);
- if (typeAlias.StartsWith("varchar")) {
- type = "String";
- } else if (typeAlias == "tinyint") {
- type = "Int8";
- } else if (typeAlias == "byte") {
- type = "Uint8";
- } else if (typeAlias == "smallint") {
- type = "Int16";
- } else if (typeAlias == "int" || typeAlias == "integer") {
- type = "Int32";
- } else if (typeAlias == "bigint") {
- type = "Int64";
- }
- return normalize ? NormalizeTypeString(type) : type;
- }
- TNodePtr BuildIsNullOp(TPosition pos, TNodePtr a) {
- if (!a) {
- return nullptr;
- }
- if (a->IsNull()) {
- return BuildLiteralBool(pos, "true");
- }
- return new TCallNodeImpl(pos, "Not", {new TCallNodeImpl(pos, "Exists", {a})});
- }
- TNodePtr BuildUnaryOp(TPosition pos, const TString& opName, TNodePtr a) {
- if (!a) {
- return nullptr;
- }
- if (a->IsNull()) {
- return BuildLiteralNull(pos);
- }
- return new TCallNodeImpl(pos, opName, {a});
- }
- class TBinaryOpNode final: public TCallNode {
- public:
- TBinaryOpNode(TPosition pos, const TString& opName, TNodePtr a, TNodePtr b);
- TNodePtr DoClone() const final {
- YQL_ENSURE(Args.size() == 2);
- return new TBinaryOpNode(Pos, OpName, Args[0]->Clone(), Args[1]->Clone());
- }
- };
- TBinaryOpNode::TBinaryOpNode(TPosition pos, const TString& opName, TNodePtr a, TNodePtr b)
- : TCallNode(pos, opName, 2, 2, { a, b })
- {
- }
- TNodePtr BuildBinaryOp(TPosition pos, const TString& opName, TNodePtr a, TNodePtr b) {
- if (!a || !b) {
- return nullptr;
- }
- if (a->IsNull() && b->IsNull()) {
- return BuildLiteralNull(pos);
- }
- return new TBinaryOpNode(pos, opName, a, b);
- }
- class TCalcOverWindow final: public INode {
- public:
- TCalcOverWindow(TPosition pos, const TString& windowName, TNodePtr node)
- : INode(pos)
- , WindowName(windowName)
- , FuncNode(node)
- {}
- TAstNode* Translate(TContext& ctx) const override {
- return FuncNode->Translate(ctx);
- }
- bool DoInit(TContext& ctx, ISource* src) override {
- YQL_ENSURE(src);
- TSourcePtr overWindowSource = BuildOverWindowSource(ctx.Pos(), WindowName, src);
- if (!FuncNode->Init(ctx, overWindowSource.Get())) {
- return false;
- }
- return true;
- }
- TPtr DoClone() const final {
- return new TCalcOverWindow(Pos, WindowName, SafeClone(FuncNode));
- }
- void DoUpdateState() const override {
- State.Set(ENodeState::Const, FuncNode->IsConstant());
- State.Set(ENodeState::Aggregated, FuncNode->IsAggregated());
- State.Set(ENodeState::OverWindow, true);
- }
- protected:
- const TString WindowName;
- TNodePtr FuncNode;
- };
- TNodePtr BuildCalcOverWindow(TPosition pos, const TString& windowName, TNodePtr call) {
- return new TCalcOverWindow(pos, windowName, call);
- }
- class TYsonOptionsNode final: public INode {
- public:
- TYsonOptionsNode(TPosition pos, bool autoConvert, bool strict)
- : INode(pos)
- , AutoConvert(autoConvert)
- , Strict(strict)
- {
- auto udf = Y("Udf", Q("Yson.Options"));
- auto autoConvertNode = BuildLiteralBool(pos, autoConvert ? "true" : "false");
- autoConvertNode->SetLabel("AutoConvert");
- auto strictNode = BuildLiteralBool(pos, strict ? "true" : "false");
- strictNode->SetLabel("Strict");
- Node = Y("NamedApply", udf, Q(Y()), BuildStructure(pos, { autoConvertNode, strictNode }));
- }
- TAstNode* Translate(TContext& ctx) const override {
- return Node->Translate(ctx);
- }
- bool DoInit(TContext& ctx, ISource* src) override {
- YQL_ENSURE(src);
- if (!Node->Init(ctx, src)) {
- return false;
- }
- return true;
- }
- TPtr DoClone() const final {
- return new TYsonOptionsNode(Pos, AutoConvert, Strict);
- }
- protected:
- TNodePtr Node;
- const bool AutoConvert;
- const bool Strict;
- };
- TNodePtr BuildYsonOptionsNode(TPosition pos, bool autoConvert, bool strict) {
- return new TYsonOptionsNode(pos, autoConvert, strict);
- }
- class TShortcutNode: public TAstAtomNode {
- TNodePtr ShortcutNode;
- TNodePtr SameNode;
- const TString BaseName;
- public:
- TShortcutNode(const TNodePtr& node, const TString& baseName)
- : TAstAtomNode(node->GetPos(), TStringBuilder() << "Shortcut" << baseName, TNodeFlags::Default)
- , ShortcutNode(node)
- , BaseName(baseName)
- {}
- bool DoInit(TContext& ctx, ISource* src) override {
- auto shortcut = ctx.HasBlockShortcut(ShortcutNode);
- if (!shortcut) {
- SameNode = ShortcutNode->Clone();
- if (!SameNode->Init(ctx, src)) {
- return false;
- }
- shortcut = ctx.RegisterBlockShortcut(ShortcutNode, SameNode, BaseName);
- YQL_ENSURE(shortcut);
- } else {
- SameNode = ctx.GetBlockShortcut(shortcut);
- }
- Content = shortcut;
- return true;
- }
- const TString* GetSourceName() const override {
- return ShortcutNode->GetSourceName();
- }
- void DoUpdateState() const override {
- auto& workedNode = SameNode ? SameNode : ShortcutNode;
- State.Set(ENodeState::Const, workedNode->IsConstant());
- State.Set(ENodeState::Aggregated, workedNode->IsAggregated());
- State.Set(ENodeState::OverWindow, workedNode->IsOverWindow());
- }
- TNodePtr DoClone() const final {
- return new TShortcutNode(ShortcutNode, BaseName);
- }
- };
- TNodePtr BuildShortcutNode(const TNodePtr& node, const TString& baseName) {
- return new TShortcutNode(node, baseName);
- }
- class TDoCall final : public INode {
- public:
- TDoCall(TPosition pos, const TNodePtr& node)
- : INode(pos)
- , Node(node)
- {
- FakeSource = BuildFakeSource(pos);
- }
- ISource* GetSource() final {
- return FakeSource.Get();
- }
- bool DoInit(TContext& ctx, ISource* src) final {
- Y_UNUSED(src);
- ctx.PushBlockShortcuts();
- if (!Node->Init(ctx, FakeSource.Get())) {
- return false;
- }
- Node = ctx.GroundBlockShortcutsForExpr(Node);
- return true;
- }
- TAstNode* Translate(TContext& ctx) const final {
- return Node->Translate(ctx);
- }
- TPtr DoClone() const final {
- return new TDoCall(Pos, Node->Clone());
- }
- private:
- TNodePtr Node;
- TSourcePtr FakeSource;
- };
- TNodePtr BuildDoCall(TPosition pos, const TNodePtr& node) {
- return new TDoCall(pos, node);
- }
- bool Parseui32(TNodePtr from, ui32& to) {
- const TString* val;
- if (!(val = from->GetLiteral("Int32"))) {
- if (!(val = from->GetLiteral("Uint32"))) {
- return false;
- }
- }
- return TryFromString(*val, to);
- }
- TNodePtr GroundWithExpr(const TNodePtr& ground, const TNodePtr& expr) {
- return ground ? expr->Y("block", expr->Q(expr->L(ground, expr->Y("return", expr)))) : expr;
- }
- TSourcePtr TryMakeSourceFromExpression(TContext& ctx, TNodePtr node, const TString& view) {
- if (auto literal = node->GetLiteral("String")) {
- if (ctx.CurrCluster.empty()) {
- return nullptr;
- }
- TNodePtr tableKey = BuildTableKey(node->GetPos(), ctx.CurrCluster, TDeferredAtom(node->GetPos(), *literal), view);
- TTableRef table(ctx.MakeName("table"), ctx.CurrCluster, tableKey);
- table.Options = BuildInputOptions(node->GetPos(), GetContextHints(ctx));
- return BuildTableSource(node->GetPos(), table, false);
- }
- if (auto access = dynamic_cast<TAccessNode*>(node.Get())) {
- bool hasErrors;
- auto src = access->TryMakeSource(ctx, view, hasErrors);
- if (src || hasErrors) {
- return src;
- }
- }
- if (dynamic_cast<TLambdaNode*>(node.Get())) {
- ctx.Error() << "Lambda is not allowed to be used as source. Did you forget to call a subquery template?";
- return nullptr;
- }
- if (ctx.CurrCluster.empty()) {
- return nullptr;
- }
- auto wrappedNode = node->Y("EvaluateAtom", node);
- TNodePtr tableKey = BuildTableKey(node->GetPos(), ctx.CurrCluster, TDeferredAtom(wrappedNode, ctx), view);
- TTableRef table(ctx.MakeName("table"), ctx.CurrCluster, tableKey);
- table.Options = BuildInputOptions(node->GetPos(), GetContextHints(ctx));
- return BuildTableSource(node->GetPos(), table, false);
- }
- void MakeTableFromExpression(TContext& ctx, TNodePtr node, TDeferredAtom& table) {
- if (auto literal = node->GetLiteral("String")) {
- table = TDeferredAtom(node->GetPos(), *literal);
- return;
- }
- if (auto access = dynamic_cast<TAccessNode*>(node.Get())) {
- auto ret = access->TryMakeTable();
- if (ret) {
- table = TDeferredAtom(node->GetPos(), *ret);
- return;
- }
- }
- auto wrappedNode = node->Y("EvaluateAtom", node);
- table = TDeferredAtom(wrappedNode, ctx);
- }
- TDeferredAtom MakeAtomFromExpression(TContext& ctx, TNodePtr node) {
- if (auto literal = node->GetLiteral("String")) {
- return TDeferredAtom(node->GetPos(), *literal);
- }
- auto wrappedNode = node->Y("EvaluateAtom", node);
- return TDeferredAtom(wrappedNode, ctx);
- }
- bool TryMakeClusterAndTableFromExpression(TNodePtr node, TString& cluster, TDeferredAtom& table, TContext& ctx) {
- if (auto literal = node->GetLiteral("String")) {
- cluster.clear();
- table = TDeferredAtom(node->GetPos(), *literal);
- return true;
- }
- if (auto access = dynamic_cast<TAccessNode*>(node.Get())) {
- bool hasErrors;
- auto ret = access->TryMakeClusterAndTable(ctx, hasErrors);
- if (ret) {
- cluster = ret->first;
- table = TDeferredAtom(node->GetPos(), ret->second);
- return true;
- }
- if (hasErrors) {
- return false;
- }
- }
- auto wrappedNode = node->Y("EvaluateAtom", node);
- table = TDeferredAtom(wrappedNode, ctx);
- return true;
- }
- class TTupleResultNode: public INode {
- public:
- TTupleResultNode(TNodePtr&& tuple, int ensureTupleSize)
- : INode(tuple->GetPos())
- , Node(std::move(tuple))
- , EnsureTupleSize(ensureTupleSize)
- {
- }
- bool DoInit(TContext& ctx, ISource* src) override {
- ctx.PushBlockShortcuts();
- if (!Node->Init(ctx, src)) {
- return false;
- }
- Node = ctx.GroundBlockShortcutsForExpr(Node);
- Node = Y("EnsureTupleSize", Node, Q(ToString(EnsureTupleSize)));
- return true;
- }
- TAstNode* Translate(TContext& ctx) const override {
- return Node->Translate(ctx);
- }
- TPtr DoClone() const final {
- return {};
- }
- protected:
- TNodePtr Node;
- const int EnsureTupleSize;
- };
- TNodePtr BuildTupleResult(TNodePtr tuple, int ensureTupleSize) {
- return new TTupleResultNode(std::move(tuple), ensureTupleSize);
- }
- } // namespace NSQLTranslationV0
|