1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469 |
- #include "../../parser/pg_wrapper/pg_compat.h"
- #ifdef _WIN32
- #define __restrict
- #endif
- #define TypeName PG_TypeName
- #define SortBy PG_SortBy
- #undef SIZEOF_SIZE_T
- extern "C" {
- #include "postgres.h"
- #include "nodes/pg_list.h"
- #include "nodes/parsenodes.h"
- #include "nodes/value.h"
- #undef Min
- #undef Max
- #undef TypeName
- #undef SortBy
- #undef TRACE
- #undef INFO
- #undef WARNING
- #undef ERROR
- #undef FATAL
- #undef NOTICE
- }
- #include "util/charset/utf8.h"
- #include "utils.h"
- #include <yql/essentials/ast/yql_expr.h>
- #include <yql/essentials/sql/settings/partitioning.h>
- #include <yql/essentials/sql/settings/translator.h>
- #include <yql/essentials/parser/pg_wrapper/interface/config.h>
- #include <yql/essentials/parser/pg_wrapper/interface/parser.h>
- #include <yql/essentials/parser/pg_wrapper/interface/utils.h>
- #include <yql/essentials/parser/pg_wrapper/interface/raw_parser.h>
- #include <yql/essentials/parser/pg_wrapper/postgresql/src/backend/catalog/pg_type_d.h>
- #include <yql/essentials/parser/pg_catalog/catalog.h>
- #include <yql/essentials/providers/common/provider/yql_provider_names.h>
- #include <yql/essentials/minikql/mkql_type_builder.h>
- #include <yql/essentials/core/issue/yql_issue.h>
- #include <yql/essentials/core/sql_types/yql_callable_names.h>
- #include <yql/essentials/parser/pg_catalog/catalog.h>
- #include <yql/essentials/utils/log/log_level.h>
- #include <yql/essentials/utils/log/log.h>
- #include <util/string/builder.h>
- #include <util/string/cast.h>
- #include <util/string/join.h>
- #include <util/string/split.h>
- #include <util/generic/scope.h>
- #include <util/generic/stack.h>
- #include <util/generic/hash_set.h>
- constexpr auto PREPARED_PARAM_PREFIX = "$p";
- constexpr auto AUTO_PARAM_PREFIX = "a";
- constexpr auto DEFAULT_PARAM_TYPE = "unknown";
- namespace NSQLTranslationPG {
- using namespace NYql;
- static const THashSet<TString> SystemColumns = { "tableoid", "xmin", "cmin", "xmax", "cmax", "ctid" };
- template <typename T>
- const T* CastNode(const void* nodeptr, int tag) {
- Y_ENSURE(nodeTag(nodeptr) == tag);
- return static_cast<const T*>(nodeptr);
- }
- const Node* Expr2Node(const Expr* e) {
- return reinterpret_cast<const Node*>(e);
- }
- int NodeTag(const Node* node) {
- return nodeTag(node);
- }
- int NodeTag(const ValUnion& val) {
- return NodeTag(&val.node);
- }
- int IntVal(const ValUnion& val) {
- Y_ENSURE(val.node.type == T_Integer);
- return intVal(&val.node);
- }
- bool BoolVal(const ValUnion& val) {
- Y_ENSURE(val.node.type == T_Boolean);
- return boolVal(&val.node);
- }
- const char* StrFloatVal(const ValUnion& val) {
- Y_ENSURE(val.node.type == T_Float);
- return strVal(&val.node);
- }
- const char* StrVal(const ValUnion& val) {
- Y_ENSURE(val.node.type == T_String || val.node.type == T_BitString);
- return strVal(&val.node);
- }
- int BoolVal(const Node* node) {
- Y_ENSURE(node->type == T_Boolean);
- return boolVal(node);
- }
- int IntVal(const Node* node) {
- Y_ENSURE(node->type == T_Integer);
- return intVal(node);
- }
- double FloatVal(const Node* node) {
- Y_ENSURE(node->type == T_Float);
- return floatVal(node);
- }
- const char* StrFloatVal(const Node* node) {
- Y_ENSURE(node->type == T_Float);
- return strVal(node);
- }
- const char* StrVal(const Node* node) {
- Y_ENSURE(node->type == T_String || node->type == T_BitString);
- return strVal(node);
- }
- bool ValueAsString(const ValUnion& val, bool isNull, TString& ret) {
- if (isNull) {
- ret = "NULL";
- return true;
- }
- switch (NodeTag(val)) {
- case T_Boolean: {
- ret = BoolVal(val) ? "t" : "f";
- return true;
- }
- case T_Integer: {
- ret = ToString(IntVal(val));
- return true;
- }
- case T_Float: {
- ret = StrFloatVal(val);
- return true;
- }
- case T_String:
- case T_BitString: {
- ret = StrVal(val);
- return true;
- }
- default:
- return false;
- }
- }
- int ListLength(const List* list) {
- return list_length(list);
- }
- int StrLength(const char* s) {
- return s ? strlen(s) : 0;
- }
- int StrCompare(const char* s1, const char* s2) {
- return strcmp(s1 ? s1 : "", s2 ? s2 : "");
- }
- int StrICompare(const char* s1, const char* s2) {
- return stricmp(s1 ? s1 : "", s2 ? s2 : "");
- }
- std::shared_ptr<List> ListMake1(void* cell) {
- return std::shared_ptr<List>(list_make1(cell), list_free);
- }
- #define CAST_NODE(nodeType, nodeptr) CastNode<nodeType>(nodeptr, T_##nodeType)
- #define CAST_NODE_EXT(nodeType, tag, nodeptr) CastNode<nodeType>(nodeptr, tag)
- #define LIST_CAST_NTH(nodeType, list, index) CAST_NODE(nodeType, list_nth(list, index))
- #define LIST_CAST_EXT_NTH(nodeType, tag, list, index) CAST_NODE_EXT(nodeType, tag, list_nth(list, i))
- const Node* ListNodeNth(const List* list, int index) {
- return static_cast<const Node*>(list_nth(list, index));
- }
- const IndexElem* IndexElement(const Node* node) {
- Y_ENSURE(node->type == T_IndexElem);
- return ((const IndexElem*)node);
- }
- #define AT_LOCATION(node) \
- TLocationGuard guard(this, node->location);
- #define AT_LOCATION_EX(node, field) \
- TLocationGuard guard(this, node->field);
- std::tuple<TStringBuf, TStringBuf> getSchemaAndObjectName(const List* nameList) {
- switch (ListLength(nameList)) {
- case 2: {
- const auto clusterName = StrVal(ListNodeNth(nameList, 0));
- const auto tableName = StrVal(ListNodeNth(nameList, 1));
- return {clusterName, tableName};
- }
- case 1: {
- const auto tableName = StrVal(ListNodeNth(nameList, 0));
- return {"", tableName};
- }
- default: {
- return {"", ""};
- }
- }
- }
- struct TPgConst {
- TMaybe<TString> value;
- enum class Type {
- boolean,
- int4,
- int8,
- numeric,
- text,
- unknown,
- bit,
- nil,
- };
- static TString ToString(const TPgConst::Type& type) {
- switch (type) {
- case TPgConst::Type::boolean:
- return "bool";
- case TPgConst::Type::int4:
- return "int4";
- case TPgConst::Type::int8:
- return "int8";
- case TPgConst::Type::numeric:
- return "numeric";
- case TPgConst::Type::text:
- return "text";
- case TPgConst::Type::unknown:
- return "unknown";
- case TPgConst::Type::bit:
- return "bit";
- case TPgConst::Type::nil:
- return "unknown";
- }
- }
- Type type;
- };
- TMaybe<TPgConst> GetValueNType(const A_Const* value) {
- TPgConst pgConst;
- if (value->isnull) {
- pgConst.type = TPgConst::Type::nil;
- return pgConst;
- }
- const auto& val = value->val;
- switch (NodeTag(val)) {
- case T_Boolean: {
- pgConst.value = BoolVal(val) ? "t" : "f";
- pgConst.type = TPgConst::Type::boolean;
- return pgConst;
- }
- case T_Integer: {
- pgConst.value = ToString(IntVal(val));
- pgConst.type = TPgConst::Type::int4;
- return pgConst;
- }
- case T_Float: {
- auto s = StrFloatVal(val);
- i64 v;
- const bool isInt8 = TryFromString<i64>(s, v);
- pgConst.value = ToString(s);
- pgConst.type = isInt8 ? TPgConst::Type::int8 : TPgConst::Type::numeric;
- return pgConst;
- }
- case T_String: {
- pgConst.value = ToString(StrVal(val));
- pgConst.type = TPgConst::Type::unknown; // to support implicit casts
- return pgConst;
- }
- case T_BitString: {
- pgConst.value = ToString(StrVal(val));
- pgConst.type = TPgConst::Type::bit;
- return pgConst;
- }
- default: {
- return {};
- }
- }
- }
- class TConverter : public IPGParseEvents {
- friend class TLocationGuard;
- private:
- class TLocationGuard {
- private:
- TConverter* Owner;
- public:
- TLocationGuard(TConverter* owner, int location)
- : Owner(owner)
- {
- Owner->PushPosition(location);
- }
- ~TLocationGuard() {
- Owner->PopPosition();
- }
- };
- public:
- struct TFromDesc {
- TAstNode* Source = nullptr;
- TString Alias;
- TVector<TString> ColNames;
- bool InjectRead = false;
- };
- struct TReadWriteKeyExprs {
- TAstNode* SinkOrSource = nullptr;
- TAstNode* Key = nullptr;
- };
- struct TExprSettings {
- bool AllowColumns = false;
- bool AllowAggregates = false;
- bool AllowOver = false;
- bool AllowReturnSet = false;
- bool AllowSubLinks = false;
- bool AutoParametrizeEnabled = true;
- TVector<TAstNode*>* WindowItems = nullptr;
- TString Scope;
- };
- struct TView {
- TString Name;
- TVector<TString> ColNames;
- TAstNode* Source = nullptr;
- };
- using TViews = THashMap<TString, TView>;
- struct TState {
- TMaybe<TString> ApplicationName;
- TString CostBasedOptimizer;
- TVector<TAstNode*> Statements;
- ui32 ReadIndex = 0;
- TViews Views;
- TVector<TViews> CTE;
- const TView* CurrentRecursiveView = nullptr;
- TVector<NYql::TPosition> Positions = {NYql::TPosition()};
- THashMap<TString, TString> ParamNameToPgTypeName;
- NYql::IAutoParamBuilderPtr AutoParamValues;
- };
- TConverter(TVector<TAstParseResult>& astParseResults, const NSQLTranslation::TTranslationSettings& settings,
- const TString& query, TVector<TStmtParseInfo>* stmtParseInfo, bool perStatementResult,
- TMaybe<ui32> sqlProcArgsCount)
- : AstParseResults(astParseResults)
- , Settings(settings)
- , DqEngineEnabled(Settings.DqDefaultAuto->Allow())
- , BlockEngineEnabled(Settings.BlockDefaultAuto->Allow())
- , StmtParseInfo(stmtParseInfo)
- , PerStatementResult(perStatementResult)
- , SqlProcArgsCount(sqlProcArgsCount)
- {
- Y_ENSURE(settings.Mode == NSQLTranslation::ESqlMode::QUERY || settings.Mode == NSQLTranslation::ESqlMode::LIMITED_VIEW);
- Y_ENSURE(settings.Mode != NSQLTranslation::ESqlMode::LIMITED_VIEW || !perStatementResult);
- State.ApplicationName = Settings.ApplicationName;
- AstParseResults.push_back({});
- if (StmtParseInfo) {
- StmtParseInfo->push_back({});
- }
- ScanRows(query);
- for (auto& flag : Settings.Flags) {
- if (flag == "DqEngineEnable") {
- DqEngineEnabled = true;
- } else if (flag == "DqEngineForce") {
- DqEngineForce = true;
- } else if (flag == "BlockEngineEnable") {
- BlockEngineEnabled = true;
- } else if (flag == "BlockEngineForce") {
- BlockEngineForce = true;
- } if (flag == "UnorderedResult") {
- UnorderedResult = true;
- }
- }
- if (Settings.PathPrefix) {
- TablePathPrefix = Settings.PathPrefix + "/";
- }
- for (const auto& [cluster, provider] : Settings.ClusterMapping) {
- if (provider != PgProviderName) {
- Provider = provider;
- break;
- }
- }
- if (!Provider) {
- Provider = PgProviderName;
- }
- Y_ENSURE(!Provider.empty());
- for (size_t i = 0; i < Settings.PgParameterTypeOids.size(); ++i) {
- const auto paramName = PREPARED_PARAM_PREFIX + ToString(i + 1);
- const auto typeOid = Settings.PgParameterTypeOids[i];
- const auto& typeName =
- typeOid != UNKNOWNOID ? NPg::LookupType(typeOid).Name : DEFAULT_PARAM_TYPE;
- State.ParamNameToPgTypeName[paramName] = typeName;
- }
- }
- void OnResult(const List* raw) {
- if (!PerStatementResult) {
- AstParseResults[StatementId].Pool = std::make_unique<TMemoryPool>(4096);
- AstParseResults[StatementId].Root = ParseResult(raw);
- AstParseResults[StatementId].PgAutoParamValues = State.AutoParamValues;
- return;
- }
- AstParseResults.resize(ListLength(raw));
- if (StmtParseInfo) {
- StmtParseInfo->resize(AstParseResults.size());
- }
- for (; StatementId < AstParseResults.size(); ++StatementId) {
- AstParseResults[StatementId].Pool = std::make_unique<TMemoryPool>(4096);
- AstParseResults[StatementId].Root = ParseResult(raw, StatementId);
- AstParseResults[StatementId].PgAutoParamValues = State.AutoParamValues;
- State = {};
- }
- }
- void OnError(const TIssue& issue) {
- AstParseResults[StatementId].Issues.AddIssue(issue);
- }
- void PrepareStatements() {
- auto configSource = L(A("DataSource"), QA(TString(NYql::ConfigProviderName)));
- State.Statements.push_back(L(A("let"), A("world"), L(A(TString(NYql::ConfigureName)), A("world"), configSource,
- QA("OrderedColumns"))));
- }
- TAstNode* ParseResult(const List* raw, const TMaybe<ui32> statementId = Nothing()) {
- PrepareStatements();
- auto configSource = L(A("DataSource"), QA(TString(NYql::ConfigProviderName)));
- ui32 blockEnginePgmPos = State.Statements.size();
- State.Statements.push_back(configSource);
- ui32 costBasedOptimizerPos = State.Statements.size();
- State.Statements.push_back(configSource);
- ui32 dqEnginePgmPos = State.Statements.size();
- State.Statements.push_back(configSource);
- if (statementId) {
- if (!ParseRawStmt(LIST_CAST_NTH(RawStmt, raw, *statementId))) {
- return nullptr;
- }
- } else {
- for (int i = 0; i < ListLength(raw); ++i) {
- if (!ParseRawStmt(LIST_CAST_NTH(RawStmt, raw, i))) {
- return nullptr;
- }
- }
- }
- if (!State.Views.empty()) {
- AddError("Not all views have been dropped");
- return nullptr;
- }
- if (Settings.EndOfQueryCommit && Settings.Mode != NSQLTranslation::ESqlMode::LIMITED_VIEW) {
- State.Statements.push_back(L(A("let"), A("world"), L(A("CommitAll!"),
- A("world"))));
- }
- AddVariableDeclarations();
- if (Settings.Mode != NSQLTranslation::ESqlMode::LIMITED_VIEW) {
- State.Statements.push_back(L(A("return"), A("world")));
- }
- if (DqEngineEnabled) {
- State.Statements[dqEnginePgmPos] = L(A("let"), A("world"), L(A(TString(NYql::ConfigureName)), A("world"), configSource,
- QA("DqEngine"), QA(DqEngineForce ? "force" : "auto")));
- } else {
- State.Statements.erase(State.Statements.begin() + dqEnginePgmPos);
- }
- if (State.CostBasedOptimizer) {
- State.Statements[costBasedOptimizerPos] = L(A("let"), A("world"), L(A(TString(NYql::ConfigureName)), A("world"), configSource,
- QA("CostBasedOptimizer"), QA(State.CostBasedOptimizer)));
- } else {
- State.Statements.erase(State.Statements.begin() + costBasedOptimizerPos);
- }
- if (BlockEngineEnabled) {
- State.Statements[blockEnginePgmPos] = L(A("let"), A("world"), L(A(TString(NYql::ConfigureName)), A("world"), configSource,
- QA("BlockEngine"), QA(BlockEngineForce ? "force" : "auto")));
- } else {
- State.Statements.erase(State.Statements.begin() + blockEnginePgmPos);
- }
- return FinishStatements();
- }
- TAstNode* FinishStatements() {
- return VL(State.Statements.data(), State.Statements.size());
- }
- [[nodiscard]]
- bool ParseRawStmt(const RawStmt* value) {
- AT_LOCATION_EX(value, stmt_location);
- auto node = value->stmt;
- if (Settings.Mode == NSQLTranslation::ESqlMode::LIMITED_VIEW) {
- if (NodeTag(node) != T_SelectStmt && NodeTag(node) != T_VariableSetStmt) {
- AddError("Unsupported statement in LIMITED_VIEW mode");
- return false;
- }
- }
- if (StmtParseInfo) {
- (*StmtParseInfo)[StatementId].CommandTagName = GetCommandName(node);
- }
- switch (NodeTag(node)) {
- case T_SelectStmt:
- return ParseSelectStmt(CAST_NODE(SelectStmt, node), {.Inner = false}) != nullptr;
- case T_InsertStmt:
- return ParseInsertStmt(CAST_NODE(InsertStmt, node)) != nullptr;
- case T_UpdateStmt:
- return ParseUpdateStmt(CAST_NODE(UpdateStmt, node)) != nullptr;
- case T_ViewStmt:
- return ParseViewStmt(CAST_NODE(ViewStmt, node)) != nullptr;
- case T_CreateStmt:
- return ParseCreateStmt(CAST_NODE(CreateStmt, node)) != nullptr;
- case T_DropStmt:
- return ParseDropStmt(CAST_NODE(DropStmt, node)) != nullptr;
- case T_VariableSetStmt:
- {
- // YQL-16284
- const char* node_name = CAST_NODE(VariableSetStmt, node)->name;
- const char* skip_statements[] = {
- "extra_float_digits", // jdbc
- "application_name", // jdbc
- "statement_timeout", // pg_dump
- "lock_timeout", // pg_dump
- "idle_in_transaction_session_timeout", // pg_dump
- "client_encoding", // pg_dump
- "standard_conforming_strings", // pg_dump
- "check_function_bodies", // pg_dump
- "xmloption", // pg_dump
- "client_min_messages", // pg_dump
- "row_security", // pg_dump
- "escape_string_warning", // zabbix
- "bytea_output", // zabbix
- "datestyle", // pgadmin 4
- "timezone", // mediawiki
- NULL,
- };
- for (int i = 0; skip_statements[i] != NULL; i++){
- const char *skip_name = skip_statements[i];
- if (stricmp(node_name, skip_name) == 0){
- return true;
- }
- };
- };
- return ParseVariableSetStmt(CAST_NODE(VariableSetStmt, node)) != nullptr;
- case T_DeleteStmt:
- return ParseDeleteStmt(CAST_NODE(DeleteStmt, node)) != nullptr;
- case T_VariableShowStmt:
- return ParseVariableShowStmt(CAST_NODE(VariableShowStmt, node)) != nullptr;
- case T_TransactionStmt:
- return ParseTransactionStmt(CAST_NODE(TransactionStmt, node));
- case T_IndexStmt:
- return ParseIndexStmt(CAST_NODE(IndexStmt, node)) != nullptr;
- case T_CreateSeqStmt:
- return ParseCreateSeqStmt(CAST_NODE(CreateSeqStmt, node)) != nullptr;
- case T_AlterSeqStmt:
- return ParseAlterSeqStmt(CAST_NODE(AlterSeqStmt, node)) != nullptr;
- case T_AlterTableStmt:
- return ParseAlterTableStmt(CAST_NODE(AlterTableStmt, node)) != nullptr;
- default:
- NodeNotImplemented(value, node);
- return false;
- }
- }
- [[nodiscard]]
- bool ExtractPgConstsForAutoParam(List* rawValuesLists, TVector<TPgConst>& pgConsts) {
- YQL_LOG_CTX_SCOPE(TStringBuf("PgSql Autoparametrize"), __FUNCTION__);
- Y_ABORT_UNLESS(rawValuesLists);
- size_t rows = ListLength(rawValuesLists);
- if (rows == 0 || !Settings.AutoParametrizeEnabled || !Settings.AutoParametrizeValuesStmt) {
- return false;
- }
- size_t cols = ListLength(CAST_NODE(List, ListNodeNth(rawValuesLists, 0)));
- pgConsts.reserve(rows * cols);
- for (int rowIdx = 0; rowIdx < ListLength(rawValuesLists); ++rowIdx) {
- const auto rawRow = CAST_NODE(List, ListNodeNth(rawValuesLists, rowIdx));
- for (int colIdx = 0; colIdx < ListLength(rawRow); ++colIdx) {
- const auto rawCell = ListNodeNth(rawRow, colIdx);
- if (NodeTag(rawCell) != T_A_Const) {
- YQL_CLOG(INFO, Default) << "Auto parametrization of " << NodeTag(rawCell) << " is not supported";
- return false;
- }
- auto pgConst = GetValueNType(CAST_NODE(A_Const, rawCell));
- if (!pgConst) {
- return false;
- }
- pgConsts.push_back(std::move(pgConst.GetRef()));
- }
- }
- return true;
- }
- TMaybe<TVector<TPgConst::Type>> InferColumnTypesForValuesStmt(const TVector<TPgConst>& values, size_t cols) {
- Y_ABORT_UNLESS((values.size() % cols == 0), "wrong amount of columns for auto param values vector");
- TVector<TMaybe<TPgConst::Type>> maybeColumnTypes(cols);
- for (size_t i = 0; i < values.size(); ++i) {
- const auto& value = values[i];
- size_t col = i % cols;
- auto& columnType = maybeColumnTypes[col];
- if (!columnType || columnType.GetRef() == TPgConst::Type::unknown || columnType.GetRef() == TPgConst::Type::nil) {
- columnType = value.type;
- continue;
- }
- // should we allow compatible types here?
- if (columnType.GetRef() != value.type && columnType.GetRef() != TPgConst::Type::unknown && columnType.GetRef() != TPgConst::Type::nil) {
- YQL_CLOG(INFO, Default)
- << "Failed to auto parametrize: different types: "
- << TPgConst::ToString(columnType.GetRef()) << " and " << TPgConst::ToString(value.type)
- << " in col " << col;
- return {};
- }
- }
- TVector<TPgConst::Type> columnTypes;
- for (auto& maybeColumnType: maybeColumnTypes) {
- if (maybeColumnType.Empty()) {
- YQL_CLOG(INFO, Default) << "Failed to auto parametrize: can't infer PgType for column";
- return {};
- }
- columnTypes.emplace_back(maybeColumnType.GetRef());
- }
- return columnTypes;
- }
- TString AddSimpleAutoParam(TPgConst&& valueNType) {
- if (!State.AutoParamValues) {
- Y_ENSURE(Settings.AutoParamBuilderFactory);
- State.AutoParamValues = Settings.AutoParamBuilderFactory->MakeBuilder();
- }
- auto nextName = TString(AUTO_PARAM_PREFIX) + ToString(State.AutoParamValues->Size());
- auto& type = State.AutoParamValues->Add(nextName);
- type.Pg(TPgConst::ToString(valueNType.type));
- auto& data = type.FinishType();
- data.Pg(valueNType.value);
- data.FinishData();
- return nextName;
- }
- TString AddValuesAutoParam(TVector<TPgConst>&& values, TVector<TPgConst::Type>&& columnTypes) {
- if (!State.AutoParamValues) {
- Y_ENSURE(Settings.AutoParamBuilderFactory);
- State.AutoParamValues = Settings.AutoParamBuilderFactory->MakeBuilder();
- }
- auto nextName = TString(AUTO_PARAM_PREFIX) + ToString(State.AutoParamValues->Size());
- auto& type = State.AutoParamValues->Add(nextName);
- type.BeginList();
- type.BeginTuple();
- for (const auto& t : columnTypes) {
- type.BeforeItem();
- type.Pg(TPgConst::ToString(t));
- type.AfterItem();
- }
- type.EndTuple();
- type.EndList();
- auto& data = type.FinishType();
- data.BeginList();
- size_t cols = columnTypes.size();
- for (size_t idx = 0; idx < values.size(); idx += cols){
- data.BeforeItem();
- data.BeginTuple();
- for (size_t delta = 0; delta < cols; ++delta) {
- data.BeforeItem();
- data.Pg(values[idx + delta].value);
- data.AfterItem();
- }
- data.EndTuple();
- data.AfterItem();
- }
- data.EndList();
- data.FinishData();
- return nextName;
- }
- TAstNode* MakeValuesStmtAutoParam(TVector<TPgConst>&& values, TVector<TPgConst::Type>&& columnTypes) {
- TVector<TAstNode*> autoParamTupleType;
- autoParamTupleType.reserve(columnTypes.size());
- autoParamTupleType.push_back(A("TupleType"));
- for (const auto& type : columnTypes) {
- auto pgType = L(A("PgType"), QA(TPgConst::ToString(type)));
- autoParamTupleType.push_back(pgType);
- }
- const auto paramType = L(A("ListType"), VL(autoParamTupleType));
- const auto paramName = AddValuesAutoParam(std::move(values), std::move(columnTypes));
- State.Statements.push_back(L(A("declare"), A(paramName), paramType));
- YQL_CLOG(INFO, Default) << "Successfully autoparametrized VALUES at" << State.Positions.back();
- return A(paramName);
- }
- [[nodiscard]]
- TAstNode* ParseValuesList(List* valuesLists, bool buildCommonType) {
- TVector<TAstNode*> valNames;
- uint64 colIdx = 0;
- TExprSettings settings;
- settings.AllowColumns = false;
- settings.Scope = "VALUES";
- for (int valueIndex = 0; valueIndex < ListLength(valuesLists); ++valueIndex) {
- auto node = ListNodeNth(valuesLists, valueIndex);
- if (NodeTag(node) != T_List) {
- NodeNotImplemented(node);
- return nullptr;
- }
- auto lst = CAST_NODE(List, node);
- if (valueIndex == 0) {
- for (int item = 0; item < ListLength(lst); ++item) {
- valNames.push_back(QA("column" + ToString(colIdx++)));
- }
- } else {
- if (ListLength(lst) != (int)valNames.size()) {
- AddError("VALUES lists must all be the same length");
- return nullptr;
- }
- }
- }
- TVector<TPgConst> pgConsts;
- bool canAutoparametrize = ExtractPgConstsForAutoParam(valuesLists, pgConsts);
- if (canAutoparametrize) {
- auto maybeColumnTypes = InferColumnTypesForValuesStmt(pgConsts, valNames.size());
- if (maybeColumnTypes) {
- auto valuesNode = MakeValuesStmtAutoParam(std::move(pgConsts), std::move(maybeColumnTypes.GetRef()));
- return QL(QA("values"), QVL(valNames.data(), valNames.size()), valuesNode);
- }
- }
- TVector<TAstNode*> valueRows;
- valueRows.reserve(ListLength(valuesLists));
- valueRows.push_back(A(buildCommonType ? "PgValuesList" : "AsList"));
- for (int valueIndex = 0; valueIndex < ListLength(valuesLists); ++valueIndex) {
- auto node = ListNodeNth(valuesLists, valueIndex);
- if (NodeTag(node) != T_List) {
- NodeNotImplemented(node);
- return nullptr;
- }
- auto lst = CAST_NODE(List, node);
- TVector<TAstNode*> row;
- for (int item = 0; item < ListLength(lst); ++item) {
- auto cell = ParseExpr(ListNodeNth(lst, item), settings);
- if (!cell) {
- return nullptr;
- }
- row.push_back(cell);
- }
- valueRows.push_back(QVL(row.data(), row.size()));
- }
- return QL(QA("values"), QVL(valNames.data(), valNames.size()), VL(valueRows));
- }
- TAstNode* ParseSetConfig(const FuncCall* value) {
- auto length = ListLength(value->args);
- if (length != 3) {
- AddError(TStringBuilder() << "Expected 3 arguments, but got: " << length);
- return nullptr;
- }
- VariableSetStmt config;
- config.kind = VAR_SET_VALUE;
- auto arg0 = ListNodeNth(value->args, 0);
- auto arg1 = ListNodeNth(value->args, 1);
- auto arg2 = ListNodeNth(value->args, 2);
- if (NodeTag(arg2) != T_A_Const) {
- AddError(TStringBuilder() << "Expected AConst node as is_local arg, but got node with tag: " << NodeTag(arg2));
- return nullptr;
- }
- auto isLocalConst = CAST_NODE(A_Const, arg2);
- if (isLocalConst->isnull) {
- AddError(TStringBuilder() << "Expected t/f, but got null");
- return nullptr;
- }
- if (NodeTag(isLocalConst->val) != T_Boolean) {
- AddError(TStringBuilder() << "Expected bool in const, but got something wrong: " << NodeTag(isLocalConst->val));
- return nullptr;
- }
- config.is_local = BoolVal(isLocalConst->val);
- if (NodeTag(arg0) != T_A_Const || NodeTag(arg1) != T_A_Const) {
- AddError(TStringBuilder() << "Expected const with string, but got something else: " << NodeTag(arg0));
- return nullptr;
- }
- if (CAST_NODE(A_Const, arg0)->isnull || CAST_NODE(A_Const, arg1)->isnull) {
- AddError(TStringBuilder() << "Expected string const as name arg, but got null");
- return nullptr;
- }
- auto name = CAST_NODE(A_Const, arg0)->val;
- auto val = CAST_NODE(A_Const, arg1)->val;
- if (NodeTag(name) != T_String || NodeTag(val) != T_String) {
- AddError(TStringBuilder() << "Expected string const as name arg, but got something else: " << NodeTag(name));
- return nullptr;
- }
- config.name = (char*)StrVal(name);
- config.args = list_make1((void*)arg1);
- return ParseVariableSetStmt(&config, true);
- }
- using TTraverseSelectStack = TStack<std::pair<const SelectStmt*, bool>>;
- using TTraverseNodeStack = TStack<std::pair<const Node*, bool>>;
- struct TSelectStmtSettings {
- bool Inner = true;
- mutable TVector<TAstNode*> TargetColumns;
- bool AllowEmptyResSet = false;
- bool EmitPgStar = false;
- bool FillTargetColumns = false;
- bool UnknownsAllowed = false;
- const TView* Recursive = nullptr;
- };
- [[nodiscard]]
- TAstNode* ParseSelectStmt(
- const SelectStmt* value,
- const TSelectStmtSettings& selectSettings
- ) {
- if (Settings.Mode == NSQLTranslation::ESqlMode::LIMITED_VIEW) {
- if (HasSelectInLimitedView) {
- AddError("Expected exactly one SELECT in LIMITED_VIEW mode");
- return nullptr;
- }
- HasSelectInLimitedView = true;
- }
- bool isValuesClauseOfInsertStmt = selectSettings.FillTargetColumns;
- State.CTE.emplace_back();
- auto prevRecursiveView = State.CurrentRecursiveView;
- State.CurrentRecursiveView = selectSettings.Recursive;
- Y_DEFER {
- State.CTE.pop_back();
- State.CurrentRecursiveView = prevRecursiveView;
- };
- if (value->withClause) {
- if (!ParseWithClause(CAST_NODE(WithClause, value->withClause))) {
- return nullptr;
- }
- }
- TTraverseSelectStack traverseSelectStack;
- traverseSelectStack.push({ value, false });
- TVector<const SelectStmt*> setItems;
- TVector<TAstNode*> setOpsNodes;
- while (!traverseSelectStack.empty()) {
- auto& top = traverseSelectStack.top();
- if (top.first->op == SETOP_NONE) {
- // leaf
- setItems.push_back(top.first);
- setOpsNodes.push_back(QA("push"));
- traverseSelectStack.pop();
- } else {
- if (!top.first->larg || !top.first->rarg) {
- AddError("SelectStmt: expected larg and rarg");
- return nullptr;
- }
- if (!top.second) {
- traverseSelectStack.push({ top.first->rarg, false });
- traverseSelectStack.push({ top.first->larg, false });
- top.second = true;
- } else {
- TString op;
- switch (top.first->op) {
- case SETOP_UNION:
- op = "union"; break;
- case SETOP_INTERSECT:
- op = "intersect"; break;
- case SETOP_EXCEPT:
- op = "except"; break;
- default:
- AddError(TStringBuilder() << "SetOperation unsupported value: " << (int)top.first->op);
- return nullptr;
- }
- if (top.first->all) {
- op += "_all";
- }
- setOpsNodes.push_back(QA(op));
- traverseSelectStack.pop();
- }
- }
- }
- bool hasCombiningQueries = (1 < setItems.size());
- TAstNode* sort = nullptr;
- if (ListLength(value->sortClause) > 0) {
- TVector<TAstNode*> sortItems;
- for (int i = 0; i < ListLength(value->sortClause); ++i) {
- auto node = ListNodeNth(value->sortClause, i);
- if (NodeTag(node) != T_SortBy) {
- NodeNotImplemented(value, node);
- return nullptr;
- }
- auto sort = ParseSortBy(CAST_NODE_EXT(PG_SortBy, T_SortBy, node), !hasCombiningQueries, true);
- if (!sort) {
- return nullptr;
- }
- sortItems.push_back(sort);
- }
- sort = QVL(sortItems.data(), sortItems.size());
- }
- TVector<TAstNode*> setItemNodes;
- for (size_t id = 0; id < setItems.size(); ++id) {
- const auto& x = setItems[id];
- bool hasDistinctAll = false;
- TVector<TAstNode*> distinctOnItems;
- if (x->distinctClause) {
- if (linitial(x->distinctClause) == NULL) {
- hasDistinctAll = true;
- } else {
- for (int i = 0; i < ListLength(x->distinctClause); ++i) {
- auto node = ListNodeNth(x->distinctClause, i);
- TAstNode* expr;
- if (NodeTag(node) == T_A_Const && (NodeTag(CAST_NODE(A_Const, node)->val) == T_Integer)) {
- expr = MakeProjectionRef("DISTINCT ON", CAST_NODE(A_Const, node));
- } else {
- TExprSettings settings;
- settings.AllowColumns = true;
- settings.Scope = "DISTINCT ON";
- expr = ParseExpr(node, settings);
- }
- if (!expr) {
- return nullptr;
- }
- auto lambda = L(A("lambda"), QL(), expr);
- distinctOnItems.push_back(L(A("PgGroup"), L(A("Void")), lambda));
- }
- }
- }
- if (x->intoClause) {
- AddError("SelectStmt: not supported intoClause");
- return nullptr;
- }
- TVector<TAstNode*> fromList;
- TVector<TAstNode*> joinOps;
- for (int i = 0; i < ListLength(x->fromClause); ++i) {
- auto node = ListNodeNth(x->fromClause, i);
- if (NodeTag(node) != T_JoinExpr) {
- auto p = ParseFromClause(node);
- if (!p) {
- return nullptr;
- }
- AddFrom(*p, fromList);
- joinOps.push_back(QL(QL(QA("push"))));
- } else {
- TTraverseNodeStack traverseNodeStack;
- traverseNodeStack.push({ node, false });
- TVector<TAstNode*> oneJoinGroup;
- while (!traverseNodeStack.empty()) {
- auto& top = traverseNodeStack.top();
- if (NodeTag(top.first) != T_JoinExpr) {
- // leaf
- auto p = ParseFromClause(top.first);
- if (!p) {
- return nullptr;
- }
- AddFrom(*p, fromList);
- traverseNodeStack.pop();
- oneJoinGroup.push_back(QL(QA("push")));
- } else {
- auto join = CAST_NODE(JoinExpr, top.first);
- if (!join->larg || !join->rarg) {
- AddError("JoinExpr: expected larg and rarg");
- return nullptr;
- }
- if (join->alias) {
- AddError("JoinExpr: unsupported alias");
- return nullptr;
- }
- if (join->isNatural) {
- AddError("JoinExpr: unsupported isNatural");
- return nullptr;
- }
- if (!top.second) {
- traverseNodeStack.push({ join->rarg, false });
- traverseNodeStack.push({ join->larg, false });
- top.second = true;
- } else {
- TString op;
- switch (join->jointype) {
- case JOIN_INNER:
- op = join->quals ? "inner" : "cross"; break;
- case JOIN_LEFT:
- op = "left"; break;
- case JOIN_FULL:
- op = "full"; break;
- case JOIN_RIGHT:
- op = "right"; break;
- default:
- AddError(TStringBuilder() << "jointype unsupported value: " << (int)join->jointype);
- return nullptr;
- }
- if (ListLength(join->usingClause) > 0) {
- if (join->join_using_alias) {
- AddError(TStringBuilder() << "join USING: unsupported AS");
- return nullptr;
- }
- if (op == "cross") {
- op = "inner";
- }
- auto len = ListLength(join->usingClause);
- TVector<TAstNode*> fields(len);
- THashSet<TString> present;
- for (decltype(len) i = 0; i < len; ++i) {
- auto node = ListNodeNth(join->usingClause, i);
- if (NodeTag(node) != T_String) {
- AddError("JoinExpr: unexpected non-string constant");
- return nullptr;
- }
- if (present.contains(StrVal(node))) {
- AddError(TStringBuilder() << "USING clause: duplicated column " << StrVal(node));
- return nullptr;
- }
- fields[i] = QAX(StrVal(node));
- }
- oneJoinGroup.push_back(QL(QA(op), QA("using"), QVL(fields)));
- } else {
- if (op != "cross" && !join->quals) {
- AddError("join_expr: expected quals for non-cross join");
- return nullptr;
- }
- if (op == "cross") {
- oneJoinGroup.push_back(QL(QA(op)));
- } else {
- TExprSettings settings;
- settings.AllowColumns = true;
- settings.Scope = "JOIN ON";
- auto quals = ParseExpr(join->quals, settings);
- if (!quals) {
- return nullptr;
- }
- auto lambda = L(A("lambda"), QL(), quals);
- oneJoinGroup.push_back(QL(QA(op), L(A("PgWhere"), L(A("Void")), lambda)));
- }
- }
- traverseNodeStack.pop();
- }
- }
- }
- joinOps.push_back(QVL(oneJoinGroup.data(), oneJoinGroup.size()));
- }
- }
- TAstNode* whereFilter = nullptr;
- if (x->whereClause) {
- TExprSettings settings;
- settings.AllowColumns = true;
- settings.AllowSubLinks = true;
- settings.Scope = "WHERE";
- whereFilter = ParseExpr(x->whereClause, settings);
- if (!whereFilter) {
- return nullptr;
- }
- }
- TAstNode* groupBy = nullptr;
- if (ListLength(x->groupClause) > 0) {
- TVector<TAstNode*> groupByItems;
- for (int i = 0; i < ListLength(x->groupClause); ++i) {
- auto node = ListNodeNth(x->groupClause, i);
- TAstNode* expr;
- if (NodeTag(node) == T_A_Const && (NodeTag(CAST_NODE(A_Const, node)->val) == T_Integer)) {
- expr = MakeProjectionRef("GROUP BY", CAST_NODE(A_Const, node));
- } else {
- TExprSettings settings;
- settings.AllowColumns = true;
- settings.Scope = "GROUP BY";
- if (NodeTag(node) == T_GroupingSet) {
- expr = ParseGroupingSet(CAST_NODE(GroupingSet, node), settings);
- } else {
- expr = ParseExpr(node, settings);
- }
- }
- if (!expr) {
- return nullptr;
- }
- auto lambda = L(A("lambda"), QL(), expr);
- groupByItems.push_back(L(A("PgGroup"), L(A("Void")), lambda));
- }
- groupBy = QVL(groupByItems.data(), groupByItems.size());
- }
- TAstNode* having = nullptr;
- if (x->havingClause) {
- TExprSettings settings;
- settings.AllowColumns = true;
- settings.Scope = "HAVING";
- settings.AllowAggregates = true;
- settings.AllowSubLinks = true;
- having = ParseExpr(x->havingClause, settings);
- if (!having) {
- return nullptr;
- }
- }
- TVector<TAstNode*> windowItems;
- if (ListLength(x->windowClause) > 0) {
- for (int i = 0; i < ListLength(x->windowClause); ++i) {
- auto node = ListNodeNth(x->windowClause, i);
- if (NodeTag(node) != T_WindowDef) {
- NodeNotImplemented(x, node);
- return nullptr;
- }
- auto win = ParseWindowDef(CAST_NODE(WindowDef, node));
- if (!win) {
- return nullptr;
- }
- windowItems.push_back(win);
- }
- }
- if (ListLength(x->valuesLists) && ListLength(x->fromClause)) {
- AddError("SelectStmt: values_lists isn't compatible to from_clause");
- return nullptr;
- }
- if (!selectSettings.AllowEmptyResSet && (ListLength(x->valuesLists) == 0) && (ListLength(x->targetList) == 0)) {
- AddError("SelectStmt: both values_list and target_list are not allowed to be empty");
- return nullptr;
- }
- if (x != value && ListLength(x->sortClause) > 0) {
- AddError("SelectStmt: sortClause should be used only on top");
- return nullptr;
- }
- if (x != value) {
- if (x->limitOption == LIMIT_OPTION_COUNT || x->limitOption == LIMIT_OPTION_DEFAULT) {
- if (x->limitCount || x->limitOffset) {
- AddError("SelectStmt: limit should be used only on top");
- return nullptr;
- }
- } else {
- AddError(TStringBuilder() << "LimitOption unsupported value: " << (int)x->limitOption);
- return nullptr;
- }
- if (ListLength(x->lockingClause) > 0) {
- AddWarning(TIssuesIds::PG_NO_LOCKING_SUPPORT, "SelectStmt: lockingClause is ignored");
- }
- }
- TVector<TAstNode*> res;
- ui32 i = 0;
- if (selectSettings.EmitPgStar && id + 1 == setItems.size()) {
- res.emplace_back(CreatePgStarResultItem());
- i++;
- }
- bool maybeSelectWithJustSetConfig = !selectSettings.Inner && !sort && windowItems.empty() && !having && !groupBy && !whereFilter && !x->distinctClause && ListLength(x->targetList) == 1;
- if (maybeSelectWithJustSetConfig) {
- auto node = ListNodeNth(x->targetList, 0);
- if (NodeTag(node) != T_ResTarget) {
- NodeNotImplemented(x, node);
- return nullptr;
- }
- auto r = CAST_NODE(ResTarget, node);
- if (!r->val) {
- AddError("SelectStmt: expected val");
- return nullptr;
- }
- auto call = r->val;
- if (NodeTag(call) == T_FuncCall) {
- auto fn = CAST_NODE(FuncCall, call);
- if (ListLength(fn->funcname) == 1) {
- auto nameNode = ListNodeNth(fn->funcname, 0);
- if (NodeTag(nameNode) != T_String) {
- AddError("Function name must be string");
- return nullptr;
- }
- auto name = to_lower(TString(StrVal(ListNodeNth(fn->funcname, 0))));
- if (name == "set_config") {
- return ParseSetConfig(fn);
- }
- }
- }
- }
- for (int targetIndex = 0; targetIndex < ListLength(x->targetList); ++targetIndex) {
- auto node = ListNodeNth(x->targetList, targetIndex);
- if (NodeTag(node) != T_ResTarget) {
- NodeNotImplemented(x, node);
- return nullptr;
- }
- auto r = CAST_NODE(ResTarget, node);
- if (!r->val) {
- AddError("SelectStmt: expected val");
- return nullptr;
- }
- TExprSettings settings;
- settings.AllowColumns = true;
- settings.AllowAggregates = true;
- settings.AllowOver = true;
- settings.AllowSubLinks = true;
- settings.WindowItems = &windowItems;
- settings.Scope = "SELECT";
- auto x = ParseExpr(r->val, settings);
- if (!x) {
- return nullptr;
- }
- res.push_back(CreatePgResultItem(r, x, i));
- }
- TVector<TAstNode*> setItemOptions;
- if (selectSettings.EmitPgStar) {
- setItemOptions.push_back(QL(QA("emit_pg_star")));
- }
- if (!selectSettings.TargetColumns.empty()) {
- setItemOptions.push_back(QL(QA("target_columns"), QVL(selectSettings.TargetColumns.data(), selectSettings.TargetColumns.size())));
- }
- if (selectSettings.FillTargetColumns) {
- setItemOptions.push_back(QL(QA("fill_target_columns")));
- }
- if (ListLength(x->targetList) > 0) {
- setItemOptions.push_back(QL(QA("result"), QVL(res.data(), res.size())));
- } else {
- auto valuesList = ParseValuesList(x->valuesLists, /*buildCommonType=*/!isValuesClauseOfInsertStmt);
- if (!valuesList) {
- return nullptr;
- }
- setItemOptions.push_back(valuesList);
- }
- if (!fromList.empty()) {
- setItemOptions.push_back(QL(QA("from"), QVL(fromList.data(), fromList.size())));
- setItemOptions.push_back(QL(QA("join_ops"), QVL(joinOps.data(), joinOps.size())));
- }
- if (whereFilter) {
- auto lambda = L(A("lambda"), QL(), whereFilter);
- setItemOptions.push_back(QL(QA("where"), L(A("PgWhere"), L(A("Void")), lambda)));
- }
- if (groupBy) {
- setItemOptions.push_back(QL(QA("group_by"), groupBy));
- }
- if (windowItems.size()) {
- auto window = QVL(windowItems.data(), windowItems.size());
- setItemOptions.push_back(QL(QA("window"), window));
- }
- if (having) {
- auto lambda = L(A("lambda"), QL(), having);
- setItemOptions.push_back(QL(QA("having"), L(A("PgWhere"), L(A("Void")), lambda)));
- }
- if (hasDistinctAll) {
- setItemOptions.push_back(QL(QA("distinct_all")));
- } else if (!distinctOnItems.empty()) {
- auto distinctOn = QVL(distinctOnItems.data(), distinctOnItems.size());
- setItemOptions.push_back(QL(QA("distinct_on"), distinctOn));
- }
- if (!hasCombiningQueries && sort) {
- setItemOptions.push_back(QL(QA("sort"), sort));
- }
- if (selectSettings.UnknownsAllowed || hasCombiningQueries) {
- setItemOptions.push_back(QL(QA("unknowns_allowed")));
- }
- auto setItem = L(A("PgSetItem"), QVL(setItemOptions.data(), setItemOptions.size()));
- setItemNodes.push_back(setItem);
- }
- if (value->intoClause) {
- AddError("SelectStmt: not supported intoClause");
- return nullptr;
- }
- if (ListLength(value->lockingClause) > 0) {
- AddWarning(TIssuesIds::PG_NO_LOCKING_SUPPORT, "SelectStmt: lockingClause is ignored");
- }
- TAstNode* limit = nullptr;
- TAstNode* offset = nullptr;
- if (value->limitOption == LIMIT_OPTION_COUNT || value->limitOption == LIMIT_OPTION_DEFAULT) {
- if (value->limitCount) {
- TExprSettings settings;
- settings.AllowColumns = false;
- settings.AllowSubLinks = true;
- settings.Scope = "LIMIT";
- limit = ParseExpr(value->limitCount, settings);
- if (!limit) {
- return nullptr;
- }
- }
- if (value->limitOffset) {
- TExprSettings settings;
- settings.AllowColumns = false;
- settings.AllowSubLinks = true;
- settings.Scope = "OFFSET";
- offset = ParseExpr(value->limitOffset, settings);
- if (!offset) {
- return nullptr;
- }
- }
- } else {
- AddError(TStringBuilder() << "LimitOption unsupported value: " << (int)value->limitOption);
- return nullptr;
- }
- TVector<TAstNode*> selectOptions;
- selectOptions.push_back(QL(QA("set_items"), QVL(setItemNodes.data(), setItemNodes.size())));
- selectOptions.push_back(QL(QA("set_ops"), QVL(setOpsNodes.data(), setOpsNodes.size())));
- if (hasCombiningQueries && sort) {
- selectOptions.push_back(QL(QA("sort"), sort));
- }
- if (limit) {
- selectOptions.push_back(QL(QA("limit"), limit));
- }
- if (offset) {
- selectOptions.push_back(QL(QA("offset"), offset));
- }
- auto output = L(A("PgSelect"), QVL(selectOptions.data(), selectOptions.size()));
- if (selectSettings.Inner) {
- return output;
- }
- if (Settings.Mode == NSQLTranslation::ESqlMode::LIMITED_VIEW) {
- State.Statements.push_back(L(A("return"), L(A("Right!"), L(A("Cons!"), A("world"), output))));
- return State.Statements.back();
- }
- auto resOptions = BuildResultOptions(!sort);
- State.Statements.push_back(L(A("let"), A("output"), output));
- State.Statements.push_back(L(A("let"), A("result_sink"), L(A("DataSink"), QA(TString(NYql::ResultProviderName)))));
- State.Statements.push_back(L(A("let"), A("world"), L(A("Write!"),
- A("world"), A("result_sink"), L(A("Key")), A("output"), resOptions)));
- State.Statements.push_back(L(A("let"), A("world"), L(A("Commit!"),
- A("world"), A("result_sink"))));
- return State.Statements.back();
- }
- TAstNode* BuildResultOptions(bool unordered) {
- TVector<TAstNode*> options;
- options.push_back(QL(QA("type")));
- options.push_back(QL(QA("autoref")));
- if (unordered && UnorderedResult) {
- options.push_back(QL(QA("unordered")));
- }
- return QVL(options.data(), options.size());
- }
- [[nodiscard]]
- bool ParseWithClause(const WithClause* value) {
- AT_LOCATION(value);
- for (int i = 0; i < ListLength(value->ctes); ++i) {
- auto object = ListNodeNth(value->ctes, i);
- if (NodeTag(object) != T_CommonTableExpr) {
- NodeNotImplemented(value, object);
- return false;
- }
- if (!ParseCTE(CAST_NODE(CommonTableExpr, object), value->recursive)) {
- return false;
- }
- }
- return true;
- }
- [[nodiscard]]
- bool ParseCTE(const CommonTableExpr* value, bool recursive) {
- AT_LOCATION(value);
- TView view;
- view.Name = value->ctename;
- for (int i = 0; i < ListLength(value->aliascolnames); ++i) {
- auto node = ListNodeNth(value->aliascolnames, i);
- if (NodeTag(node) != T_String) {
- NodeNotImplemented(value, node);
- return false;
- }
- view.ColNames.push_back(StrVal(node));
- }
- if (NodeTag(value->ctequery) != T_SelectStmt) {
- AddError("Expected Select statement as CTE query");
- return false;
- }
- view.Source = ParseSelectStmt(CAST_NODE(SelectStmt, value->ctequery), {
- .Inner = true,
- .Recursive = recursive ? &view : nullptr
- });
- if (!view.Source) {
- return false;
- }
- auto& currentCTEs = State.CTE.back();
- if (currentCTEs.find(view.Name) != currentCTEs.end()) {
- AddError(TStringBuilder() << "CTE already exists: '" << view.Name << "'");
- return false;
- }
- currentCTEs[view.Name] = view;
- return true;
- }
- [[nodiscard]]
- TAstNode* AsScalarContext(TAstNode* subquery) {
- return L(A("SingleMember"), L(A("Head"), L(A("Take"), subquery, L(A("Uint64"), QA("1")))));
- }
- [[nodiscard]]
- TAstNode* MakeLambda(TVector<TAstNode*> args, TAstNode* body) {
- return L(A("lambda"), QVL(args), body);
- }
- [[nodiscard]]
- TAstNode* CreatePgStarResultItem() {
- TAstNode* starLambda = L(A("lambda"), QL(), L(A("PgStar")));
- return L(A("PgResultItem"), QAX(""), L(A("Void")), starLambda);
- }
- [[nodiscard]]
- TAstNode* CreatePgResultItem(const ResTarget* r, TAstNode* x, ui32& columnIndex) {
- bool isStar = false;
- if (NodeTag(r->val) == T_ColumnRef) {
- auto ref = CAST_NODE(ColumnRef, r->val);
- for (int fieldNo = 0; fieldNo < ListLength(ref->fields); ++fieldNo) {
- if (NodeTag(ListNodeNth(ref->fields, fieldNo)) == T_A_Star) {
- isStar = true;
- break;
- }
- }
- }
- TString name;
- if (!isStar) {
- name = r->name;
- if (name.empty()) {
- if (NodeTag(r->val) == T_ColumnRef) {
- auto ref = CAST_NODE(ColumnRef, r->val);
- auto field = ListNodeNth(ref->fields, ListLength(ref->fields) - 1);
- if (NodeTag(field) == T_String) {
- name = StrVal(field);
- }
- } else if (NodeTag(r->val) == T_FuncCall) {
- auto func = CAST_NODE(FuncCall, r->val);
- if (!ExtractFuncName(func, name, nullptr)) {
- return nullptr;
- }
- }
- }
- if (name.empty()) {
- name = "column" + ToString(columnIndex++);
- }
- }
- const auto lambda = L(A("lambda"), QL(), x);
- const auto columnName = QAX(name);
- return L(A("PgResultItem"), columnName, L(A("Void")), lambda);
- }
- [[nodiscard]]
- std::optional<TVector<TAstNode*>> ParseReturningList(const List* returningList) {
- TVector <TAstNode*> list;
- if (ListLength(returningList) == 0) {
- return {};
- }
- ui32 index = 0;
- for (int i = 0; i < ListLength(returningList); i++) {
- auto node = ListNodeNth(returningList, i);
- if (NodeTag(node) != T_ResTarget) {
- NodeNotImplemented(returningList, node);
- return std::nullopt;
- }
- auto r = CAST_NODE(ResTarget, node);
- if (!r->val) {
- AddError("SelectStmt: expected value");
- return std::nullopt;
- }
- if (NodeTag(r->val) != T_ColumnRef) {
- NodeNotImplemented(r, r->val);
- return std::nullopt;
- }
- TExprSettings settings;
- settings.AllowColumns = true;
- auto columnRef = ParseColumnRef(CAST_NODE(ColumnRef, r->val), settings);
- if (!columnRef) {
- return std::nullopt;
- }
- list.emplace_back(CreatePgResultItem(r, columnRef, index));
- }
- return list;
- }
- [[nodiscard]]
- TAstNode* ParseInsertStmt(const InsertStmt* value) {
- if (value->onConflictClause) {
- AddError("InsertStmt: not supported onConflictClause");
- return nullptr;
- }
- TVector <TAstNode*> returningList;
- if (value->returningList) {
- auto list = ParseReturningList(value->returningList);
- if (list.has_value()) {
- returningList = list.value();
- } else {
- return nullptr;
- }
- }
- if (value->withClause) {
- AddError("InsertStmt: not supported withClause");
- return nullptr;
- }
- const auto [sink, key] = ParseWriteRangeVar(value->relation);
- if (!sink || !key) {
- return nullptr;
- }
- TVector <TAstNode*> targetColumns;
- if (value->cols) {
- for (int i = 0; i < ListLength(value->cols); i++) {
- auto node = ListNodeNth(value->cols, i);
- if (NodeTag(node) != T_ResTarget) {
- NodeNotImplemented(value, node);
- return nullptr;
- }
- auto r = CAST_NODE(ResTarget, node);
- if (!r->name) {
- AddError("SelectStmt: expected name");
- return nullptr;
- }
- targetColumns.push_back(QA(r->name));
- }
- }
- const auto select = (value->selectStmt)
- ? ParseSelectStmt(
- CAST_NODE(SelectStmt, value->selectStmt),
- {
- .Inner = true,
- .TargetColumns = targetColumns,
- .AllowEmptyResSet = false,
- .EmitPgStar = false,
- .FillTargetColumns = true,
- .UnknownsAllowed = true
- })
- : L(A("Void"));
- if (!select) {
- return nullptr;
- }
- const auto writeOptions = BuildWriteOptions(value, std::move(returningList));
- State.Statements.push_back(L(
- A("let"),
- A("world"),
- L(
- A("Write!"),
- A("world"),
- sink,
- key,
- select,
- writeOptions
- )
- ));
- return State.Statements.back();
- }
- [[nodiscard]]
- TAstNode* ParseUpdateStmt(const UpdateStmt* value) {
- const auto fromClause = value->fromClause ? value->fromClause : ListMake1(value->relation).get();
- SelectStmt selectStmt {
- .type = T_SelectStmt,
- .targetList = value->targetList,
- .fromClause = fromClause,
- .whereClause = value->whereClause,
- .withClause = value->withClause,
- };
- const auto select = ParseSelectStmt(
- &selectStmt,
- {
- .Inner = true,
- .AllowEmptyResSet = true,
- .EmitPgStar = true,
- .FillTargetColumns = false,
- .UnknownsAllowed = true
- }
- );
- if (!select) {
- return nullptr;
- }
- const auto [sink, key] = ParseWriteRangeVar(value->relation);
- if (!sink || !key) {
- return nullptr;
- }
- TVector<TAstNode*> returningList;
- if (value->returningList) {
- auto list = ParseReturningList(value->returningList);
- if (list.has_value()) {
- returningList = list.value();
- } else {
- return nullptr;
- }
- }
- TVector<TAstNode*> options;
- options.push_back(QL(QA("pg_update"), A("update_select")));
- options.push_back(QL(QA("mode"), QA("update")));
- if (!returningList.empty()) {
- options.push_back(QL(QA("returning"), QVL(returningList.data(), returningList.size())));
- }
- const auto writeUpdate = L(A("block"), QL(
- L(A("let"), A("update_select"), select),
- L(A("let"), A("sink"), sink),
- L(A("let"), A("key"), key),
- L(A("return"), L(
- A("Write!"),
- A("world"),
- A("sink"),
- A("key"),
- L(A("Void")),
- QVL(options.data(), options.size())))
- ));
- State.Statements.push_back(L(
- A("let"),
- A("world"),
- writeUpdate
- ));
- return State.Statements.back();
- }
- [[nodiscard]]
- TAstNode* ParseViewStmt(const ViewStmt* value) {
- if (ListLength(value->options) > 0) {
- AddError("Create view: not supported options");
- return nullptr;
- }
- TView view;
- if (StrLength(value->view->catalogname) > 0) {
- AddError("catalogname is not supported");
- return nullptr;
- }
- if (StrLength(value->view->schemaname) > 0) {
- AddError("schemaname is not supported");
- return nullptr;
- }
- if (StrLength(value->view->relname) == 0) {
- AddError("relname should be specified");
- return nullptr;
- }
- view.Name = value->view->relname;
- if (value->view->alias) {
- AddError("alias is not supported");
- return nullptr;
- }
- if (ListLength(value->aliases) == 0) {
- AddError("expected at least one target column");
- return nullptr;
- }
- for (int i = 0; i < ListLength(value->aliases); ++i) {
- auto node = ListNodeNth(value->aliases, i);
- if (NodeTag(node) != T_String) {
- NodeNotImplemented(value, node);
- return nullptr;
- }
- view.ColNames.push_back(StrVal(node));
- }
- if (value->withCheckOption != NO_CHECK_OPTION) {
- AddError("Create view: not supported options");
- return nullptr;
- }
- view.Source = ParseSelectStmt(CAST_NODE(SelectStmt, value->query), { .Inner = true });
- if (!view.Source) {
- return nullptr;
- }
- auto it = State.Views.find(view.Name);
- if (it != State.Views.end() && !value->replace) {
- AddError(TStringBuilder() << "View already exists: '" << view.Name << "'");
- return nullptr;
- }
- State.Views[view.Name] = view;
- return State.Statements.back();
- }
- #pragma region CreateTable
- private:
- struct TColumnInfo {
- TString Name;
- TString Type;
- bool Serial = false;
- bool NotNull = false;
- TAstNode* Default = nullptr;
- };
- struct TCreateTableCtx {
- std::unordered_map<TString, TColumnInfo> ColumnsSet;
- std::vector<TString> ColumnOrder;
- std::vector<TAstNode*> PrimaryKey;
- std::vector<std::vector<TAstNode*>> UniqConstr;
- bool isTemporary;
- bool ifNotExists;
- };
- bool CheckConstraintSupported(const Constraint* pk) {
- bool isSupported = true;
- if (pk->deferrable) {
- AddError("DEFERRABLE constraints not supported");
- isSupported = false;
- }
- if (pk->initdeferred) {
- AddError("INITIALLY DEFERRED constraints not supported");
- isSupported = false;
- }
- if (0 < ListLength(pk->including)) {
- AddError("INCLUDING columns not supported");
- isSupported = false;
- }
- if (0 < ListLength(pk->options)) {
- AddError("WITH options not supported");
- isSupported = false;
- }
- if (pk->indexname) {
- AddError("INDEX name not supported");
- isSupported = false;
- }
- if (pk->indexspace) {
- AddError("USING INDEX TABLESPACE not supported");
- isSupported = false;
- }
- return isSupported;
- }
- bool FillPrimaryKeyColumns(TCreateTableCtx& ctx, const Constraint* pk) {
- if (!CheckConstraintSupported(pk))
- return false;
- for (int i = 0; i < ListLength(pk->keys); ++i) {
- auto node = ListNodeNth(pk->keys, i);
- auto nodeName = StrVal(node);
- auto it = ctx.ColumnsSet.find(nodeName);
- if (it == ctx.ColumnsSet.end()) {
- AddError("PK column does not belong to table");
- return false;
- }
- it->second.NotNull = true;
- ctx.PrimaryKey.push_back(QA(StrVal(node)));
- }
- Y_ENSURE(0 < ctx.PrimaryKey.size());
- return true;
- }
- bool FillUniqueConstraint(TCreateTableCtx& ctx, const Constraint* constr) {
- if (!CheckConstraintSupported(constr))
- return false;
- const auto length = ListLength(constr->keys);
- std::vector<TAstNode*> uniq;
- uniq.reserve(length);
- for (auto i = 0; i < length; ++i) {
- auto node = ListNodeNth(constr->keys, i);
- auto nodeName = StrVal(node);
- if (!ctx.ColumnsSet.contains(nodeName)) {
- AddError("UNIQUE column does not belong to table");
- return false;
- }
- uniq.push_back(QA(nodeName));
- }
- Y_ENSURE(0 < uniq.size());
- ctx.UniqConstr.emplace_back(std::move(uniq));
- return true;
- }
- const TString& FindColumnTypeAlias(const TString& colType, bool& isTypeSerial) {
- const static std::unordered_map<TString, TString> aliasMap {
- {"smallserial", "int2"},
- {"serial2", "int2"},
- {"serial", "int4"},
- {"serial4", "int4"},
- {"bigserial", "int8"},
- {"serial8", "int8"},
- };
- const auto aliasIt = aliasMap.find(to_lower(colType));
- if (aliasIt == aliasMap.end()) {
- isTypeSerial = false;
- return colType;
- }
- isTypeSerial = true;
- return aliasIt->second;
- }
- bool AddColumn(TCreateTableCtx& ctx, const ColumnDef* node) {
- TColumnInfo cinfo{.Name = node->colname};
- if (SystemColumns.contains(to_lower(cinfo.Name))) {
- AddError(TStringBuilder() << "system column can't be used: " << node->colname);
- return false;
- }
- if (node->constraints) {
- for (int i = 0; i < ListLength(node->constraints); ++i) {
- auto constraintNode =
- CAST_NODE(Constraint, ListNodeNth(node->constraints, i));
- switch (constraintNode->contype) {
- case CONSTR_NOTNULL:
- cinfo.NotNull = true;
- break;
- case CONSTR_PRIMARY: {
- if (!ctx.PrimaryKey.empty()) {
- AddError("Only a single PK is allowed per table");
- return false;
- }
- cinfo.NotNull = true;
- ctx.PrimaryKey.push_back(QA(node->colname));
- } break;
- case CONSTR_UNIQUE: {
- ctx.UniqConstr.push_back({QA(node->colname)});
- } break;
- case CONSTR_DEFAULT: {
- TExprSettings settings;
- settings.AllowColumns = false;
- settings.Scope = "DEFAULT";
- settings.AutoParametrizeEnabled = false;
- cinfo.Default = ParseExpr(constraintNode->raw_expr, settings);
- if (!cinfo.Default) {
- return false;
- }
- } break;
- default:
- AddError("column constraint not supported");
- return false;
- }
- }
- }
- // for now we pass just the last part of the type name
- auto colTypeVal = StrVal( ListNodeNth(node->typeName->names,
- ListLength(node->typeName->names) - 1));
- cinfo.Type = FindColumnTypeAlias(colTypeVal, cinfo.Serial);
- auto [it, inserted] = ctx.ColumnsSet.emplace(node->colname, cinfo);
- if (!inserted) {
- AddError("duplicated column names found");
- return false;
- }
- ctx.ColumnOrder.push_back(node->colname);
- return true;
- }
- bool AddConstraint(TCreateTableCtx& ctx, const Constraint* node) {
- switch (node->contype) {
- case CONSTR_PRIMARY: {
- if (!ctx.PrimaryKey.empty()) {
- AddError("Only a single PK is allowed per table");
- return false;
- }
- if (!FillPrimaryKeyColumns(ctx, node)) {
- return false;
- }
- } break;
- case CONSTR_UNIQUE: {
- if (!FillUniqueConstraint(ctx, node)) {
- return false;
- }
- } break;
- // TODO: support table-level not null constraints like:
- // CHECK (col1 is not null [OR col2 is not null])
- default:
- AddError("table constraint not supported");
- return false;
- }
- return true;
- }
- TAstNode* BuildColumnsOptions(TCreateTableCtx& ctx) {
- std::vector<TAstNode*> columns;
- for(const auto& name: ctx.ColumnOrder) {
- auto it = ctx.ColumnsSet.find(name);
- Y_ENSURE(it != ctx.ColumnsSet.end());
- const auto& cinfo = it->second;
- std::vector<TAstNode*> constraints;
- if (cinfo.Serial) {
- constraints.push_back(QL(QA("serial")));
- }
- if (cinfo.NotNull) {
- constraints.push_back(QL(QA("not_null")));
- }
- if (cinfo.Default) {
- constraints.push_back(QL(QA("default"), cinfo.Default));
- }
- columns.push_back(QL(QA(cinfo.Name), L(A("PgType"), QA(cinfo.Type)), QL(QA("columnConstraints"), QVL(constraints.data(), constraints.size()))));
- }
- return QVL(columns.data(), columns.size());
- }
- TAstNode* BuildCreateTableOptions(TCreateTableCtx& ctx) {
- std::vector<TAstNode*> options;
- TString mode = (ctx.ifNotExists) ? "create_if_not_exists" : "create";
- options.push_back(QL(QA("mode"), QA(mode)));
- options.push_back(QL(QA("columns"), BuildColumnsOptions(ctx)));
- if (!ctx.PrimaryKey.empty()) {
- options.push_back(QL(QA("primarykey"), QVL(ctx.PrimaryKey.data(), ctx.PrimaryKey.size())));
- }
- for (auto& uniq : ctx.UniqConstr) {
- auto columns = QVL(uniq.data(), uniq.size());
- options.push_back(QL(QA("index"), QL(
- QL(QA("indexName")),
- QL(QA("indexType"), QA("syncGlobalUnique")),
- QL(QA("dataColumns"), QL()),
- QL(QA("indexColumns"), columns))));
- }
- if (ctx.isTemporary) {
- options.push_back(QL(QA("temporary")));
- }
- return QVL(options.data(), options.size());
- }
- TAstNode* BuildWriteOptions(const InsertStmt* value, TVector<TAstNode*> returningList = {}) {
- std::vector<TAstNode*> options;
- const auto insertMode = (ProviderToInsertModeMap.contains(Provider))
- ? ProviderToInsertModeMap.at(Provider)
- : "append";
- options.push_back(QL(QA("mode"), QA(insertMode)));
- if (!returningList.empty()) {
- options.push_back(QL(QA("returning"), QVL(returningList.data(), returningList.size())));
- }
- if (!value->selectStmt) {
- options.push_back(QL(QA("default_values")));
- }
- return QVL(options.data(), options.size());
- }
- public:
- [[nodiscard]]
- TAstNode* ParseCreateStmt(const CreateStmt* value) {
- // See also transformCreateStmt() in parse_utilcmd.c
- if (0 < ListLength(value->inhRelations)) {
- AddError("table inheritance not supported");
- return nullptr;
- }
- if (value->partspec) {
- AddError("PARTITION BY clause not supported");
- return nullptr;
- }
- if (value->partbound) {
- AddError("FOR VALUES clause not supported");
- return nullptr;
- }
- // if we ever support typed tables, check transformOfType() in parse_utilcmd.c
- if (value->ofTypename) {
- AddError("typed tables not supported");
- return nullptr;
- }
- if (0 < ListLength(value->options)) {
- AddError("table options not supported");
- return nullptr;
- }
- if (value->oncommit != ONCOMMIT_NOOP && value->oncommit != ONCOMMIT_PRESERVE_ROWS) {
- AddError("ON COMMIT actions not supported");
- return nullptr;
- }
- if (value->tablespacename) {
- AddError("TABLESPACE not supported");
- return nullptr;
- }
- if (value->accessMethod) {
- AddError("USING not supported");
- return nullptr;
- }
- TCreateTableCtx ctx {};
- if (value->if_not_exists) {
- ctx.ifNotExists = true;
- }
- const auto relPersistence = static_cast<NPg::ERelPersistence>(value->relation->relpersistence);
- switch (relPersistence) {
- case NPg::ERelPersistence::Temp:
- ctx.isTemporary = true;
- break;
- case NPg::ERelPersistence::Unlogged:
- AddError("UNLOGGED tables not supported");
- return nullptr;
- break;
- case NPg::ERelPersistence::Permanent:
- break;
- }
- auto [sink, key] = ParseWriteRangeVar(value->relation, true);
- if (!sink || !key) {
- return nullptr;
- }
- for (int i = 0; i < ListLength(value->tableElts); ++i) {
- auto rawNode = ListNodeNth(value->tableElts, i);
- switch (NodeTag(rawNode)) {
- case T_ColumnDef:
- if (!AddColumn(ctx, CAST_NODE(ColumnDef, rawNode))) {
- return nullptr;
- }
- break;
- case T_Constraint:
- if (!AddConstraint(ctx, CAST_NODE(Constraint, rawNode))) {
- return nullptr;
- }
- break;
- default:
- NodeNotImplemented(value, rawNode);
- return nullptr;
- }
- }
- State.Statements.push_back(
- L(A("let"), A("world"),
- L(A("Write!"), A("world"), sink, key, L(A("Void")),
- BuildCreateTableOptions(ctx))));
- return State.Statements.back();
- }
- #pragma endregion CreateTable
- [[nodiscard]]
- TAstNode* ParseDropStmt(const DropStmt* value) {
- TVector<const List*> nameListNodes;
- for (int i = 0; i < ListLength(value->objects); ++i) {
- auto object = ListNodeNth(value->objects, i);
- if (NodeTag(object) != T_List) {
- NodeNotImplemented(value, object);
- return nullptr;
- }
- auto nameListNode = CAST_NODE(List, object);
- nameListNodes.push_back(nameListNode);
- }
- switch (value->removeType) {
- case OBJECT_VIEW: {
- return ParseDropViewStmt(value, nameListNodes);
- }
- case OBJECT_TABLE: {
- return ParseDropTableStmt(value, nameListNodes);
- }
- case OBJECT_INDEX: {
- return ParseDropIndexStmt(value, nameListNodes);
- }
- case OBJECT_SEQUENCE: {
- return ParseDropSequenceStmt(value, nameListNodes);
- }
- default: {
- AddError("Not supported object type for DROP");
- return nullptr;
- }
- }
- }
- TAstNode* ParseDropViewStmt(const DropStmt* value, const TVector<const List*>& names) {
- // behavior and concurrent don't matter here
- for (const auto& nameList : names) {
- if (ListLength(nameList) != 1) {
- AddError("Expected view name");
- }
- const auto nameNode = ListNodeNth(nameList, 0);
- if (NodeTag(nameNode) != T_String) {
- NodeNotImplemented(value, nameNode);
- return nullptr;
- }
- const auto name = StrVal(nameNode);
- auto it = State.Views.find(name);
- if (!value->missing_ok && it == State.Views.end()) {
- AddError(TStringBuilder() << "View not found: '" << name << "'");
- return nullptr;
- }
- if (it != State.Views.end()) {
- State.Views.erase(it);
- }
- }
- return State.Statements.back();
- }
- TAstNode* ParseDropTableStmt(const DropStmt* value, const TVector<const List*>& names) {
- if (value->behavior == DROP_CASCADE) {
- AddError("CASCADE is not implemented");
- return nullptr;
- }
- for (const auto& nameList : names) {
- const auto [clusterName, tableName] = getSchemaAndObjectName(nameList);
- const auto [sink, key] = ParseQualifiedRelationName(
- /* catalogName */ "",
- clusterName,
- tableName,
- /* isSink */ true,
- /* isScheme */ true
- );
- if (sink == nullptr) {
- return nullptr;
- }
- TString mode = (value->missing_ok) ? "drop_if_exists" : "drop";
- State.Statements.push_back(L(
- A("let"),
- A("world"),
- L(
- A("Write!"),
- A("world"),
- sink,
- key,
- L(A("Void")),
- QL(
- QL(QA("mode"), QA(mode))
- )
- )
- ));
- }
- return State.Statements.back();
- }
- TAstNode* ParseDropIndexStmt(const DropStmt* value, const TVector<const List*>& names) {
- if (value->behavior == DROP_CASCADE) {
- AddError("CASCADE is not implemented");
- return nullptr;
- }
- if (names.size() != 1) {
- AddError("DROP INDEX requires exactly one index");
- return nullptr;
- }
- for (const auto& nameList : names) {
- const auto [clusterName, indexName] = getSchemaAndObjectName(nameList);
- const auto [sink, key] = ParseQualifiedPgObjectName(
- /* catalogName */ "",
- clusterName,
- indexName,
- "pgIndex"
- );
- TString missingOk = (value->missing_ok) ? "true" : "false";
- State.Statements.push_back(L(
- A("let"),
- A("world"),
- L(
- A("Write!"),
- A("world"),
- sink,
- key,
- L(A("Void")),
- QL(
- QL(QA("mode"), QA("dropIndex")),
- QL(QA("ifExists"), QA(missingOk))
- )
- )
- ));
- }
- return State.Statements.back();
- }
- TAstNode* ParseDropSequenceStmt(const DropStmt* value, const TVector<const List*>& names) {
- if (value->behavior == DROP_CASCADE) {
- AddError("CASCADE is not implemented");
- return nullptr;
- }
- if (names.size() != 1) {
- AddError("DROP SEQUENCE requires exactly one sequence");
- return nullptr;
- }
- for (const auto& nameList : names) {
- const auto [clusterName, indexName] = getSchemaAndObjectName(nameList);
- const auto [sink, key] = ParseQualifiedPgObjectName(
- /* catalogName */ "",
- clusterName,
- indexName,
- "pgSequence"
- );
- TString mode = (value->missing_ok) ? "drop_if_exists" : "drop";
- State.Statements.push_back(L(
- A("let"),
- A("world"),
- L(
- A("Write!"),
- A("world"),
- sink,
- key,
- L(A("Void")),
- QL(
- QL(QA("mode"), QA(mode))
- )
- )
- ));
- }
- return State.Statements.back();
- }
- [[nodiscard]]
- TAstNode* ParseVariableSetStmt(const VariableSetStmt* value, bool isSetConfig = false) {
- if (value->kind != VAR_SET_VALUE) {
- AddError(TStringBuilder() << "VariableSetStmt, not supported kind: " << (int)value->kind);
- return nullptr;
- }
- auto name = to_lower(TString(value->name));
- if (name == "search_path") {
- THashSet<TString> visitedValues;
- TVector<TString> values;
- for (int i = 0; i < ListLength(value->args); ++i) {
- auto val = ListNodeNth(value->args, i);
- if (NodeTag(val) != T_A_Const || CAST_NODE(A_Const, val)->isnull || NodeTag(CAST_NODE(A_Const, val)->val) != T_String) {
- AddError(TStringBuilder() << "VariableSetStmt, expected string literal for " << value->name << " option");
- return nullptr;
- }
- TString rawStr = to_lower(TString(StrVal(CAST_NODE(A_Const, val)->val)));
- if (visitedValues.emplace(rawStr).second) {
- values.emplace_back(rawStr);
- }
- }
- if (values.size() != 1) {
- AddError(TStringBuilder() << "VariableSetStmt, expected 1 unique scheme, but got: " << values.size());
- return nullptr;
- }
- auto rawStr = values[0];
- if (rawStr != "pg_catalog" && rawStr != "public" && rawStr != "" && rawStr != "information_schema") {
- AddError(TStringBuilder() << "VariableSetStmt, search path supports only 'information_schema', 'public', 'pg_catalog', '' but got: '" << rawStr << "'");
- return nullptr;
- }
- if (Settings.GUCSettings) {
- Settings.GUCSettings->Set(name, rawStr, value->is_local);
- if (StmtParseInfo) {
- (*StmtParseInfo)[StatementId].KeepInCache = false;
- }
- }
- return State.Statements.back();
- }
- if (isSetConfig) {
- if (name != "search_path") {
- AddError(TStringBuilder() << "VariableSetStmt, set_config doesn't support that option:" << name);
- return nullptr;
- }
- }
- if (name == "useblocks" || name == "emitaggapply" || name == "unorderedresult") {
- if (ListLength(value->args) != 1) {
- AddError(TStringBuilder() << "VariableSetStmt, expected 1 arg, but got: " << ListLength(value->args));
- return nullptr;
- }
- auto arg = ListNodeNth(value->args, 0);
- if (NodeTag(arg) == T_A_Const && (NodeTag(CAST_NODE(A_Const, arg)->val) == T_String)) {
- TString rawStr = StrVal(CAST_NODE(A_Const, arg)->val);
- if (name == "unorderedresult") {
- UnorderedResult = (rawStr == "true");
- } else {
- auto configSource = L(A("DataSource"), QA(TString(NYql::ConfigProviderName)));
- State.Statements.push_back(L(A("let"), A("world"), L(A(TString(NYql::ConfigureName)), A("world"), configSource,
- QA(TString(rawStr == "true" ? "" : "Disable") + TString((name == "useblocks") ? "UseBlocks" : "PgEmitAggApply")))));
- }
- } else {
- AddError(TStringBuilder() << "VariableSetStmt, expected string literal for " << value->name << " option");
- return nullptr;
- }
- } else if (name == "dqengine" || name == "blockengine") {
- if (ListLength(value->args) != 1) {
- AddError(TStringBuilder() << "VariableSetStmt, expected 1 arg, but got: " << ListLength(value->args));
- return nullptr;
- }
- auto arg = ListNodeNth(value->args, 0);
- if (NodeTag(arg) == T_A_Const && (NodeTag(CAST_NODE(A_Const, arg)->val) == T_String)) {
- auto rawStr = StrVal(CAST_NODE(A_Const, arg)->val);
- auto str = to_lower(TString(rawStr));
- const bool isDqEngine = name == "dqengine";
- auto& enable = isDqEngine ? DqEngineEnabled : BlockEngineEnabled;
- auto& force = isDqEngine ? DqEngineForce : BlockEngineForce;
- if (str == "auto") {
- enable = true;
- force = false;
- } else if (str == "force") {
- enable = true;
- force = true;
- } else if (str == "disable") {
- enable = false;
- force = false;
- } else {
- AddError(TStringBuilder() << "VariableSetStmt, not supported " << value->name << " option value: " << rawStr);
- return nullptr;
- }
- } else {
- AddError(TStringBuilder() << "VariableSetStmt, expected string literal for " << value->name << " option");
- return nullptr;
- }
- } else if (name.StartsWith("dq.") || name.StartsWith("yt.") || name.StartsWith("s3.") || name.StartsWith("ydb.")) {
- if (ListLength(value->args) != 1) {
- AddError(TStringBuilder() << "VariableSetStmt, expected 1 arg, but got: " << ListLength(value->args));
- return nullptr;
- }
- auto arg = ListNodeNth(value->args, 0);
- if (NodeTag(arg) == T_A_Const && (NodeTag(CAST_NODE(A_Const, arg)->val) == T_String)) {
- auto dotPos = name.find('.');
- auto provider = name.substr(0, dotPos);
- TString providerName;
- if (name.StartsWith("dq.")) {
- providerName = NYql::DqProviderName;
- } else if (name.StartsWith("yt.")) {
- providerName = NYql::YtProviderName;
- } else if (name.StartsWith("s3.")) {
- providerName = NYql::S3ProviderName;
- } else if (name.StartsWith("ydb.")) {
- providerName = NYql::YdbProviderName;
- } else {
- Y_ASSERT(0);
- }
- auto providerSource = L(A("DataSource"), QA(providerName), QA("$all"));
- auto rawStr = StrVal(CAST_NODE(A_Const, arg)->val);
- State.Statements.push_back(L(A("let"), A("world"), L(A(TString(NYql::ConfigureName)), A("world"), providerSource,
- QA("Attr"), QAX(name.substr(dotPos + 1)), QAX(rawStr))));
- } else {
- AddError(TStringBuilder() << "VariableSetStmt, expected string literal for " << value->name << " option");
- return nullptr;
- }
- } else if (name == "tablepathprefix") {
- if (ListLength(value->args) != 1) {
- AddError(TStringBuilder() << "VariableSetStmt, expected 1 arg, but got: " << ListLength(value->args));
- return nullptr;
- }
- auto arg = ListNodeNth(value->args, 0);
- if (NodeTag(arg) == T_A_Const && (NodeTag(CAST_NODE(A_Const, arg)->val) == T_String)) {
- auto rawStr = StrVal(CAST_NODE(A_Const, arg)->val);
- TablePathPrefix = rawStr;
- } else {
- AddError(TStringBuilder() << "VariableSetStmt, expected string literal for " << value->name << " option");
- return nullptr;
- }
- } else if (name == "costbasedoptimizer") {
- if (ListLength(value->args) != 1) {
- AddError(TStringBuilder() << "VariableSetStmt, expected 1 arg, but got: " << ListLength(value->args));
- return nullptr;
- }
- auto arg = ListNodeNth(value->args, 0);
- if (NodeTag(arg) == T_A_Const && (NodeTag(CAST_NODE(A_Const, arg)->val) == T_String)) {
- auto rawStr = StrVal(CAST_NODE(A_Const, arg)->val);
- auto str = to_lower(TString(rawStr));
- if (!(str == "disable" || str == "pg" || str == "native")) {
- AddError(TStringBuilder() << "VariableSetStmt, not supported CostBasedOptimizer option value: " << rawStr);
- return nullptr;
- }
- State.CostBasedOptimizer = str;
- } else {
- AddError(TStringBuilder() << "VariableSetStmt, expected string literal for " << value->name << " option");
- return nullptr;
- }
- } else if (name == "applicationname") {
- if (ListLength(value->args) != 1) {
- AddError(TStringBuilder() << "VariableSetStmt, expected 1 arg, but got: " << ListLength(value->args));
- return nullptr;
- }
- auto arg = ListNodeNth(value->args, 0);
- if (NodeTag(arg) == T_A_Const && (NodeTag(CAST_NODE(A_Const, arg)->val) == T_String)) {
- auto rawStr = StrVal(CAST_NODE(A_Const, arg)->val);
- State.ApplicationName = rawStr;
- } else {
- AddError(TStringBuilder() << "VariableSetStmt, expected string literal for " << value->name << " option");
- return nullptr;
- }
- } else {
- AddError(TStringBuilder() << "VariableSetStmt, not supported name: " << value->name);
- return nullptr;
- }
- return State.Statements.back();
- }
- [[nodiscard]]
- TAstNode* ParseDeleteStmt(const DeleteStmt* value) {
- if (value->usingClause) {
- AddError("using is not supported");
- return nullptr;
- }
- TVector <TAstNode*> returningList;
- if (value->returningList) {
- auto list = ParseReturningList(value->returningList);
- if (list.has_value()) {
- returningList = list.value();
- } else {
- return nullptr;
- }
- }
- if (value->withClause) {
- AddError("with is not supported");
- return nullptr;
- }
- if (!value->relation) {
- AddError("DeleteStmt: expected relation");
- return nullptr;
- }
- TVector<TAstNode*> fromList;
- auto p = ParseRangeVar(value->relation);
- if (!p) {
- return nullptr;
- }
- AddFrom(*p, fromList);
- TAstNode* whereFilter = nullptr;
- if (value->whereClause) {
- TExprSettings settings;
- settings.AllowColumns = true;
- settings.AllowSubLinks = true;
- settings.Scope = "WHERE";
- whereFilter = ParseExpr(value->whereClause, settings);
- if (!whereFilter) {
- return nullptr;
- }
- }
- TVector<TAstNode*> setItemOptions;
- setItemOptions.push_back(QL(QA("result"), QVL(CreatePgStarResultItem())));
- setItemOptions.push_back(QL(QA("from"), QVL(fromList.data(), fromList.size())));
- setItemOptions.push_back(QL(QA("join_ops"), QVL(QL(QL(QA("push"))))));
- NYql::TAstNode* lambda = nullptr;
- if (whereFilter) {
- lambda = L(A("lambda"), QL(), whereFilter);
- setItemOptions.push_back(QL(QA("where"), L(A("PgWhere"), L(A("Void")), lambda)));
- }
- auto setItemNode = L(A("PgSetItem"), QVL(setItemOptions.data(), setItemOptions.size()));
- TVector<TAstNode*> selectOptions;
- selectOptions.push_back(QL(QA("set_items"), QVL(setItemNode)));
- selectOptions.push_back(QL(QA("set_ops"), QVL(QA("push"))));
- auto select = L(A("PgSelect"), QVL(selectOptions.data(), selectOptions.size()));
- auto [sink, key] = ParseWriteRangeVar(value->relation);
- if (!sink || !key) {
- return nullptr;
- }
- std::vector<TAstNode*> options;
- options.push_back(QL(QA("pg_delete"), select));
- options.push_back(QL(QA("mode"), QA("delete")));
- if (!returningList.empty()) {
- options.push_back(QL(QA("returning"), QVL(returningList.data(), returningList.size())));
- }
- State.Statements.push_back(L(
- A("let"),
- A("world"),
- L(
- A("Write!"),
- A("world"),
- sink,
- key,
- L(A("Void")),
- QVL(options.data(), options.size())
- )
- ));
- return State.Statements.back();
- }
- TMaybe<TString> GetConfigVariable(const TString& varName) {
- if (varName == "server_version") {
- return GetPostgresServerVersionStr();
- }
- if (varName == "server_version_num") {
- return GetPostgresServerVersionNum();
- }
- if (varName == "standard_conforming_strings"){
- return "on";
- }
- if (varName == "search_path"){
- auto searchPath = Settings.GUCSettings->Get("search_path");
- return searchPath ? *searchPath : "public";
- }
- if (varName == "default_transaction_read_only"){
- return "off"; // mediawiki
- }
- if (varName == "transaction_isolation"){
- return "serializable";
- }
- return {};
- }
- TMaybe<std::vector<TAstNode*>> ParseIndexElements(List* list) {
- const auto length = ListLength(list);
- std::vector<TAstNode*> columns;
- columns.reserve(length);
- for (auto i = 0; i < length; ++i) {
- auto node = ListNodeNth(list, i);
- auto indexElem = IndexElement(node);
- if (indexElem->expr || indexElem->indexcolname) {
- AddError("index expression is not supported yet");
- return {};
- }
- columns.push_back(QA(indexElem->name));
- }
- return columns;
- }
- [[nodiscard]]
- TAstNode* ParseVariableShowStmt(const VariableShowStmt* value) {
- const auto varName = to_lower(TString(value->name));
- const auto varValue = GetConfigVariable(varName);
- if (!varValue) {
- AddError("unrecognized configuration parameter \"" + varName + "\"");
- return nullptr;
- }
- const auto columnName = QAX(varName);
- const auto varValueNode =
- L(A("PgConst"), QAX(*varValue), L(A("PgType"), QA("text")));
- const auto lambda = L(A("lambda"), QL(), varValueNode);
- const auto res = QL(L(A("PgResultItem"), columnName, L(A("Void")), lambda));
- const auto setItem = L(A("PgSetItem"), QL(QL(QA("result"), res)));
- const auto setItems = QL(QA("set_items"), QL(setItem));
- const auto setOps = QL(QA("set_ops"), QVL(QA("push")));
- const auto selectOptions = QL(setItems, setOps);
- const auto output = L(A("PgSelect"), selectOptions);
- State.Statements.push_back(L(A("let"), A("output"), output));
- State.Statements.push_back(L(A("let"), A("result_sink"), L(A("DataSink"), QA(TString(NYql::ResultProviderName)))));
- const auto resOptions = BuildResultOptions(true);
- State.Statements.push_back(L(A("let"), A("world"), L(A("Write!"),
- A("world"), A("result_sink"), L(A("Key")), A("output"), resOptions)));
- State.Statements.push_back(L(A("let"), A("world"), L(A("Commit!"),
- A("world"), A("result_sink"))));
- return State.Statements.back();
- }
- [[nodiscard]]
- bool ParseTransactionStmt(const TransactionStmt* value) {
- switch (value->kind) {
- case TRANS_STMT_BEGIN:
- case TRANS_STMT_START:
- case TRANS_STMT_SAVEPOINT:
- case TRANS_STMT_RELEASE:
- case TRANS_STMT_ROLLBACK_TO:
- return true;
- case TRANS_STMT_COMMIT:
- State.Statements.push_back(L(A("let"), A("world"), L(A("CommitAll!"),
- A("world"))));
- if (Settings.GUCSettings) {
- Settings.GUCSettings->Commit();
- }
- return true;
- case TRANS_STMT_ROLLBACK:
- State.Statements.push_back(L(A("let"), A("world"), L(A("CommitAll!"),
- A("world"), QL(QL(QA("mode"), QA("rollback"))))));
- if (Settings.GUCSettings) {
- Settings.GUCSettings->RollBack();
- }
- return true;
- default:
- AddError(TStringBuilder() << "TransactionStmt: kind is not supported: " << (int)value->kind);
- return false;
- }
- }
- [[nodiscard]]
- TAstNode* ParseIndexStmt(const IndexStmt* value) {
- if (value->unique) {
- AddError("unique index creation is not supported yet");
- return nullptr;
- }
- if (value->primary) {
- AddError("primary key creation is not supported yet");
- return nullptr;
- }
- if (value->isconstraint || value->deferrable || value->initdeferred) {
- AddError("constraint modification is not supported yet");
- return nullptr;
- }
- if (value->whereClause) {
- AddError("partial index is not supported yet");
- return nullptr;
- }
- if (value->options) {
- AddError("storage parameters for index is not supported yet");
- return nullptr;
- }
- auto columns = ParseIndexElements(value->indexParams);
- if (!columns)
- return nullptr;
- auto coverColumns = ParseIndexElements(value->indexIncludingParams);
- if (!coverColumns)
- return nullptr;
- const auto [sink, key] = ParseWriteRangeVar(value->relation, true);
- if (!sink || !key) {
- return nullptr;
- }
- std::vector<TAstNode*> flags;
- flags.emplace_back(QA("pg"));
- if (value->if_not_exists) {
- flags.emplace_back(QA("ifNotExists"));
- }
- std::vector<TAstNode*> desc;
- auto indexNameAtom = QA("indexName");
- if (value->idxname) {
- desc.emplace_back(QL(indexNameAtom, QA(value->idxname)));
- } else {
- desc.emplace_back(QL(indexNameAtom));
- }
- desc.emplace_back(QL(QA("indexType"), QA(value->unique ? "syncGlobalUnique" : "syncGlobal")));
- desc.emplace_back(QL(QA("indexColumns"), QVL(columns->data(), columns->size())));
- desc.emplace_back(QL(QA("dataColumns"), QVL(coverColumns->data(), coverColumns->size())));
- desc.emplace_back(QL(QA("flags"), QVL(flags.data(), flags.size())));
- State.Statements.push_back(L(
- A("let"),
- A("world"),
- L(
- A("Write!"),
- A("world"),
- sink,
- key,
- L(A("Void")),
- QL(
- QL(QA("mode"), QA("alter")),
- QL(QA("actions"), QL(QL(QA("addIndex"), QVL(desc.data(), desc.size()))))
- )
- )
- ));
- return State.Statements.back();
- }
- [[nodiscard]]
- TAstNode* ParseCreateSeqStmt(const CreateSeqStmt* value) {
- std::vector<TAstNode*> options;
- TString mode = (value->if_not_exists) ? "create_if_not_exists" : "create";
- options.push_back(QL(QA("mode"), QA(mode)));
- auto [sink, key] = ParseQualifiedPgObjectName(
- value->sequence->catalogname,
- value->sequence->schemaname,
- value->sequence->relname,
- "pgSequence"
- );
- if (!sink || !key) {
- return nullptr;
- }
- const auto relPersistence = static_cast<NPg::ERelPersistence>(value->sequence->relpersistence);
- switch (relPersistence) {
- case NPg::ERelPersistence::Temp:
- options.push_back(QL(QA("temporary")));
- break;
- case NPg::ERelPersistence::Unlogged:
- AddError("UNLOGGED sequence not supported");
- return nullptr;
- break;
- case NPg::ERelPersistence::Permanent:
- break;
- }
- for (int i = 0; i < ListLength(value->options); ++i) {
- auto rawNode = ListNodeNth(value->options, i);
- switch (NodeTag(rawNode)) {
- case T_DefElem: {
- const auto* defElem = CAST_NODE(DefElem, rawNode);
- TString nameElem = defElem->defname;
- if (defElem->arg) {
- switch (NodeTag(defElem->arg))
- {
- case T_Boolean:
- options.emplace_back(QL(QAX(nameElem), QA(ToString(boolVal(defElem->arg)))));
- break;
- case T_Integer:
- options.emplace_back(QL(QAX(nameElem), QA(ToString(intVal(defElem->arg)))));
- break;
- case T_Float:
- options.emplace_back(QL(QAX(nameElem), QA(strVal(defElem->arg))));
- break;
- case T_TypeName: {
- const auto* typeName = CAST_NODE_EXT(PG_TypeName, T_TypeName, defElem->arg);
- if (ListLength(typeName->names) > 0) {
- options.emplace_back(QL(QAX(nameElem),
- QAX(StrVal(ListNodeNth(typeName->names, ListLength(typeName->names) - 1)))));
- }
- break;
- }
- default:
- NodeNotImplemented(defElem->arg);
- return nullptr;
- }
- }
- break;
- }
- default:
- NodeNotImplemented(rawNode);
- return nullptr;
- }
- }
- if (value->for_identity) {
- options.push_back(QL(QA("for_identity")));
- }
- if (value->ownerId != InvalidOid) {
- options.push_back(QL(QA("owner_id"), QA(ToString(value->ownerId))));
- }
- State.Statements.push_back(
- L(A("let"), A("world"),
- L(A("Write!"), A("world"), sink, key, L(A("Void")),
- QVL(options.data(), options.size()))));
- return State.Statements.back();
- }
- [[nodiscard]]
- TAstNode* ParseAlterSeqStmt(const AlterSeqStmt* value) {
- std::vector<TAstNode*> options;
- TString mode = (value->missing_ok) ? "alter_if_exists" : "alter";
- options.push_back(QL(QA("mode"), QA(mode)));
- auto [sink, key] = ParseQualifiedPgObjectName(
- value->sequence->catalogname,
- value->sequence->schemaname,
- value->sequence->relname,
- "pgSequence"
- );
- if (!sink || !key) {
- return nullptr;
- }
- for (int i = 0; i < ListLength(value->options); ++i) {
- auto rawNode = ListNodeNth(value->options, i);
- switch (NodeTag(rawNode)) {
- case T_DefElem: {
- const auto* defElem = CAST_NODE(DefElem, rawNode);
- TString nameElem = defElem->defname;
- if (defElem->arg) {
- switch (NodeTag(defElem->arg))
- {
- case T_Boolean:
- options.emplace_back(QL(QAX(nameElem), QA(ToString(boolVal(defElem->arg)))));
- break;
- case T_Integer:
- options.emplace_back(QL(QAX(nameElem), QA(ToString(intVal(defElem->arg)))));
- break;
- case T_Float:
- options.emplace_back(QL(QAX(nameElem), QA(strVal(defElem->arg))));
- break;
- case T_TypeName: {
- const auto* typeName = CAST_NODE_EXT(PG_TypeName, T_TypeName, defElem->arg);
- if (ListLength(typeName->names) > 0) {
- options.emplace_back(QL(QAX(nameElem),
- QAX(StrVal(ListNodeNth(typeName->names, ListLength(typeName->names) - 1)))));
- }
- break;
- }
- default:
- NodeNotImplemented(defElem->arg);
- return nullptr;
- }
- } else {
- if (nameElem == "restart") {
- options.emplace_back(QL(QAX(nameElem), QA(TString())));
- }
- }
- break;
- }
- default:
- NodeNotImplemented(rawNode);
- return nullptr;
- }
- }
- if (value->for_identity) {
- options.push_back(QL(QA("for_identity")));
- }
- State.Statements.push_back(
- L(A("let"), A("world"),
- L(A("Write!"), A("world"), sink, key, L(A("Void")),
- QVL(options.data(), options.size()))));
- return State.Statements.back();
- }
- [[nodiscard]]
- TAstNode* ParseAlterTableStmt(const AlterTableStmt* value) {
- std::vector<TAstNode*> options;
- TString mode = (value->missing_ok) ? "alter_if_exists" : "alter";
- options.push_back(QL(QA("mode"), QA(mode)));
- const auto [sink, key] = ParseWriteRangeVar(value->relation, true);
- if (!sink || !key) {
- return nullptr;
- }
- std::vector<TAstNode*> alterColumns;
- for (int i = 0; i < ListLength(value->cmds); ++i) {
- auto rawNode = ListNodeNth(value->cmds, i);
- const auto* cmd = CAST_NODE(AlterTableCmd, rawNode);
- switch (cmd->subtype) {
- case AT_ColumnDefault: { /* ALTER COLUMN DEFAULT */
- const auto* def = cmd->def;
- const auto* colName = cmd->name;
- if (def == nullptr) {
- alterColumns.push_back(QL(QAX(colName), QL(QA("setDefault"), QL(QA("Null")))));
- break;
- }
- switch (NodeTag(def)) {
- case T_FuncCall: {
- const auto* newDefault = CAST_NODE(FuncCall, def);
- const auto* funcName = ListNodeNth(newDefault->funcname, 0);
- if (NodeTag(funcName) != T_String) {
- NodeNotImplemented(newDefault, funcName);
- return nullptr;
- }
- auto strFuncName = StrVal(funcName);
- if (strcmp(strFuncName, "nextval") != 0) {
- NodeNotImplemented(newDefault, funcName);
- return nullptr;
- }
- const auto* rawArg = ListNodeNth(newDefault->args, 0);
- if (NodeTag(rawArg) != T_TypeCast && NodeTag(rawArg) != T_A_Const) {
- AddError(TStringBuilder() << "Expected type cast node or a_const, but got something wrong: " << NodeTag(rawArg));
- return nullptr;
- }
- const A_Const* localConst = nullptr;
- if (NodeTag(rawArg) == T_TypeCast) {
- auto localCast = CAST_NODE(TypeCast, rawArg)->arg;
- if (NodeTag(localCast) != T_A_Const) {
- AddError(TStringBuilder() << "Expected a_const in cast, but got something wrong: " << NodeTag(localCast));
- return nullptr;
- }
- localConst = CAST_NODE(A_Const, localCast);
- } else {
- localConst = CAST_NODE(A_Const, rawArg);
- }
- if (NodeTag(localConst->val) != T_String) {
- AddError(TStringBuilder() << "Expected string in const, but got something wrong: " << NodeTag(localConst->val));
- return nullptr;
- }
- auto seqName = StrVal(localConst->val);
- TVector<TString> seqNameList;
- Split(seqName, ".", seqNameList);
- if (seqNameList.size() != 2 && seqNameList.size() != 1) {
- AddError(TStringBuilder() << "Expected list size is 1 or 2, but there are " << seqNameList.size());
- return nullptr;
- }
- alterColumns.push_back(QL(QAX(colName), QL(QA("setDefault"), QL(QA("nextval"), QA(seqNameList.back())))));
- break;
- }
- default:
- NodeNotImplemented(def);
- return nullptr;
- }
- break;
- }
- default:
- NodeNotImplemented(rawNode);
- return nullptr;
- }
- }
- std::vector<TAstNode*> actions { QL(QA("alterColumns"), QVL(alterColumns.data(), alterColumns.size())) };
- options.push_back(
- QL(QA("actions"),
- QVL(actions.data(), actions.size())
- )
- );
- State.Statements.push_back(
- L(A("let"), A("world"),
- L(A("Write!"), A("world"), sink, key, L(A("Void")),
- QVL(options.data(), options.size()))));
- return State.Statements.back();
- }
- TMaybe<TFromDesc> ParseFromClause(const Node* node) {
- switch (NodeTag(node)) {
- case T_RangeVar:
- return ParseRangeVar(CAST_NODE(RangeVar, node));
- case T_RangeSubselect:
- return ParseRangeSubselect(CAST_NODE(RangeSubselect, node));
- case T_RangeFunction:
- return ParseRangeFunction(CAST_NODE(RangeFunction, node));
- default:
- NodeNotImplementedImpl<SelectStmt>(node);
- return {};
- }
- }
- void AddFrom(const TFromDesc& p, TVector<TAstNode*>& fromList) {
- auto aliasNode = QAX(p.Alias);
- TVector<TAstNode*> colNamesNodes;
- for (const auto& c : p.ColNames) {
- colNamesNodes.push_back(QAX(c));
- }
- auto colNamesTuple = QVL(colNamesNodes.data(), colNamesNodes.size());
- if (p.InjectRead) {
- auto label = "read" + ToString(State.ReadIndex);
- State.Statements.push_back(L(A("let"), A(label), p.Source));
- State.Statements.push_back(L(A("let"), A("world"), L(A("Left!"), A(label))));
- fromList.push_back(QL(L(A("Right!"), A(label)), aliasNode, colNamesTuple));
- ++State.ReadIndex;
- } else {
- auto source = p.Source;
- if (!source) {
- source = L(A("PgSelf"));
- }
- fromList.push_back(QL(source, aliasNode, colNamesTuple));
- }
- }
- bool ParseAlias(const Alias* alias, TString& res, TVector<TString>& colnames) {
- for (int i = 0; i < ListLength(alias->colnames); ++i) {
- auto node = ListNodeNth(alias->colnames, i);
- if (NodeTag(node) != T_String) {
- NodeNotImplemented(alias, node);
- return false;
- }
- colnames.push_back(StrVal(node));
- }
- res = alias->aliasname;
- return true;
- }
- TString ResolveCluster(const TStringBuf schemaname, TString name) {
- if (NYql::NPg::GetStaticColumns().contains(NPg::TTableInfoKey{"pg_catalog", name})) {
- return "pg_catalog";
- }
- if (schemaname == "public") {
- return Settings.DefaultCluster;;
- }
- if (schemaname == "" && Settings.GUCSettings) {
- auto search_path = Settings.GUCSettings->Get("search_path");
- if (!search_path || *search_path == "public" || search_path->empty()) {
- return Settings.DefaultCluster;
- }
- return TString(*search_path);
- }
- return TString(schemaname);
- }
- TAstNode* BuildClusterSinkOrSourceExpression(
- bool isSink, const TStringBuf schemaname) {
- TString usedCluster(schemaname);
- auto p = Settings.ClusterMapping.FindPtr(usedCluster);
- if (!p) {
- usedCluster = to_lower(usedCluster);
- p = Settings.ClusterMapping.FindPtr(usedCluster);
- }
- if (!p) {
- AddError(TStringBuilder() << "Unknown cluster: " << schemaname);
- return nullptr;
- }
- return L(isSink ? A("DataSink") : A("DataSource"), QAX(*p), QAX(usedCluster));
- }
- TAstNode* BuildTableKeyExpression(const TStringBuf relname,
- const TStringBuf cluster, bool isScheme = false
- ) {
- auto lowerCluster = to_lower(TString(cluster));
- bool noPrefix = (lowerCluster == "pg_catalog" || lowerCluster == "information_schema");
- TString tableName = noPrefix ? to_lower(TString(relname)) : TablePathPrefix + relname;
- return L(A("Key"), QL(QA(isScheme ? "tablescheme" : "table"),
- L(A("String"), QAX(std::move(tableName)))));
- }
- TReadWriteKeyExprs ParseQualifiedRelationName(const TStringBuf catalogname,
- const TStringBuf schemaname,
- const TStringBuf relname,
- bool isSink, bool isScheme) {
- if (!catalogname.empty()) {
- AddError("catalogname is not supported");
- return {};
- }
- if (relname.empty()) {
- AddError("relname should be specified");
- return {};
- }
- const auto cluster = ResolveCluster(schemaname, TString(relname));
- const auto sinkOrSource = BuildClusterSinkOrSourceExpression(isSink, cluster);
- const auto key = BuildTableKeyExpression(relname, cluster, isScheme);
- return {sinkOrSource, key};
- }
- TAstNode* BuildPgObjectExpression(const TStringBuf objectName, const TStringBuf objectType) {
- bool noPrefix = (objectType == "pgIndex");
- TString name = noPrefix ? TString(objectName) : TablePathPrefix + TString(objectName);
- return L(A("Key"), QL(QA("pgObject"),
- L(A("String"), QAX(std::move(name))),
- L(A("String"), QA(objectType))
- ));
- }
- TReadWriteKeyExprs ParseQualifiedPgObjectName(const TStringBuf catalogname,
- const TStringBuf schemaname,
- const TStringBuf objectName,
- const TStringBuf pgObjectType) {
- if (!catalogname.empty()) {
- AddError("catalogname is not supported");
- return {};
- }
- if (objectName.empty()) {
- AddError("objectName should be specified");
- return {};
- }
- const auto cluster = ResolveCluster(schemaname, TString(objectName));
- const auto sinkOrSource = BuildClusterSinkOrSourceExpression(true, cluster);
- const auto key = BuildPgObjectExpression(objectName, pgObjectType);
- return {sinkOrSource, key};
- }
- TReadWriteKeyExprs ParseWriteRangeVar(const RangeVar *value,
- bool isScheme = false) {
- if (value->alias) {
- AddError("alias is not supported");
- return {};
- }
- return ParseQualifiedRelationName(value->catalogname, value->schemaname,
- value->relname,
- /* isSink */ true, isScheme);
- }
- TMaybe<TFromDesc> ParseRangeVar(const RangeVar* value) {
- AT_LOCATION(value);
- const TView* view = nullptr;
- if (StrLength(value->schemaname) == 0) {
- for (auto rit = State.CTE.rbegin(); rit != State.CTE.rend(); ++rit) {
- auto cteIt = rit->find(value->relname);
- if (cteIt != rit->end()) {
- view = &cteIt->second;
- break;
- }
- }
- if (!view && State.CurrentRecursiveView && State.CurrentRecursiveView->Name == value->relname) {
- view = State.CurrentRecursiveView;
- }
- if (!view) {
- auto viewIt = State.Views.find(value->relname);
- if (viewIt != State.Views.end()) {
- view = &viewIt->second;
- }
- }
- }
- TString alias;
- TVector<TString> colnames;
- if (value->alias) {
- if (!ParseAlias(value->alias, alias, colnames)) {
- return {};
- }
- } else {
- alias = value->relname;
- }
- if (view) {
- return TFromDesc{view->Source, alias, colnames.empty() ? view->ColNames : colnames, false };
- }
- TString schemaname = value->schemaname;
- if (!StrCompare(value->schemaname, "bindings")) {
- bool isBinding = false;
- switch (Settings.BindingsMode) {
- case NSQLTranslation::EBindingsMode::DISABLED:
- AddError("Please remove 'bindings.' from your query, the support for this syntax has ended");
- return {};
- case NSQLTranslation::EBindingsMode::ENABLED:
- isBinding = true;
- break;
- case NSQLTranslation::EBindingsMode::DROP_WITH_WARNING:
- AddWarning(TIssuesIds::YQL_DEPRECATED_BINDINGS, "Please remove 'bindings.' from your query, the support for this syntax will be dropped soon");
- [[fallthrough]];
- case NSQLTranslation::EBindingsMode::DROP:
- schemaname = Settings.DefaultCluster;
- break;
- }
- if (isBinding) {
- auto s = BuildBindingSource(value);
- if (!s) {
- return {};
- }
- return TFromDesc{ s, alias, colnames, true };
- }
- }
- const auto [source, key] = ParseQualifiedRelationName(
- value->catalogname, schemaname, value->relname,
- /* isSink */ false,
- /* isScheme */ false);
- if (source == nullptr || key == nullptr) {
- return {};
- }
- const auto readExpr = this->SqlProcArgsCount ?
- L(A("Cons!"),
- A("world"),
- L(
- A("PgTableContent"),
- QA("pg_catalog"),
- QAX(value->relname),
- L(A("Void")),
- QL()
- )
- ) :
- L(
- A("Read!"),
- A("world"),
- source,
- key,
- L(A("Void")),
- QL()
- );
- return TFromDesc {
- readExpr,
- alias,
- colnames,
- /* injectRead */ true,
- };
- }
- TAstNode* BuildBindingSource(const RangeVar* value) {
- if (StrLength(value->relname) == 0) {
- AddError("relname should be specified");
- }
- const TString binding = value->relname;
- NSQLTranslation::TBindingInfo bindingInfo;
- if (const auto& error = ExtractBindingInfo(Settings, binding, bindingInfo)) {
- AddError(error);
- return nullptr;
- }
- TVector<TAstNode*> hints;
- if (bindingInfo.Schema) {
- auto schema = QA(bindingInfo.Schema);
- auto type = L(A("SqlTypeFromYson"), schema);
- auto columns = L(A("SqlColumnOrderFromYson"), schema);
- hints.emplace_back(QL(QA("userschema"), type, columns));
- }
- for (auto& [key, value] : bindingInfo.Attributes) {
- TVector<TAstNode*> hintValues;
- hintValues.push_back(QA(NormalizeName(key)));
- for (auto& v : value) {
- hintValues.push_back(QA(v));
- }
- hints.emplace_back(QVL(hintValues.data(), hintValues.size()));
- }
- auto source = L(A("DataSource"), QAX(bindingInfo.ClusterType), QAX(bindingInfo.Cluster));
- return L(
- A("Read!"),
- A("world"),
- source,
- L(
- A("MrTableConcat"),
- L(
- A("Key"),
- QL(
- QA("table"),
- L(
- A("String"),
- QAX(bindingInfo.Path)
- )
- )
- )
- ),
- L(A("Void")),
- QVL(hints.data(), hints.size())
- );
- }
- TMaybe<TFromDesc> ParseRangeFunction(const RangeFunction* value) {
- if (value->lateral) {
- AddError("RangeFunction: unsupported lateral");
- return {};
- }
- if (value->ordinality) {
- AddError("RangeFunction: unsupported ordinality");
- return {};
- }
- if (value->is_rowsfrom) {
- AddError("RangeFunction: unsupported is_rowsfrom");
- return {};
- }
- if (ListLength(value->coldeflist) > 0) {
- AddError("RangeFunction: unsupported coldeflist");
- return {};
- }
- if (ListLength(value->functions) != 1) {
- AddError("RangeFunction: only one function is supported");
- return {};
- }
- TString alias;
- TVector<TString> colnames;
- if (value->alias) {
- if (!ParseAlias(value->alias, alias, colnames)) {
- return {};
- }
- }
- auto funcNode = ListNodeNth(value->functions, 0);
- if (NodeTag(funcNode) != T_List) {
- AddError("RangeFunction: expected pair");
- return {};
- }
- auto lst = CAST_NODE(List, funcNode);
- if (ListLength(lst) != 2) {
- AddError("RangeFunction: expected pair");
- return {};
- }
- TExprSettings settings;
- settings.AllowColumns = false;
- settings.AllowReturnSet = true;
- settings.Scope = "RANGE FUNCTION";
- auto node = ListNodeNth(lst, 0);
- if (NodeTag(node) != T_FuncCall) {
- AddError("RangeFunction: extected FuncCall");
- return {};
- }
- bool injectRead = false;
- auto func = ParseFuncCall(CAST_NODE(FuncCall, node), settings, true, injectRead);
- if (!func) {
- return {};
- }
- return TFromDesc{ func, alias, colnames, injectRead };
- }
- TMaybe<TFromDesc> ParseRangeSubselect(const RangeSubselect* value) {
- if (value->lateral) {
- AddError("RangeSubselect: unsupported lateral");
- return {};
- }
- if (!value->alias) {
- AddError("RangeSubselect: expected alias");
- return {};
- }
- TString alias;
- TVector<TString> colnames;
- if (!ParseAlias(value->alias, alias, colnames)) {
- return {};
- }
- if (!value->subquery) {
- AddError("RangeSubselect: expected subquery");
- return {};
- }
- if (NodeTag(value->subquery) != T_SelectStmt) {
- NodeNotImplemented(value, value->subquery);
- return {};
- }
- return TFromDesc{ ParseSelectStmt(CAST_NODE(SelectStmt, value->subquery), { .Inner = true }), alias, colnames, false };
- }
- TAstNode* ParseNullTestExpr(const NullTest* value, const TExprSettings& settings) {
- AT_LOCATION(value);
- if (value->argisrow) {
- AddError("NullTest: unsupported argisrow");
- return nullptr;
- }
- auto arg = ParseExpr(Expr2Node(value->arg), settings);
- if (!arg) {
- return nullptr;
- }
- auto result = L(A("Exists"), arg);
- if (value->nulltesttype == IS_NULL) {
- result = L(A("Not"), result);
- }
- return L(A("ToPg"), result);
- }
- struct TCaseBranch {
- TAstNode* Pred;
- TAstNode* Value;
- };
- TCaseBranch ReduceCaseBranches(std::vector<TCaseBranch>::const_iterator begin, std::vector<TCaseBranch>::const_iterator end) {
- Y_ENSURE(begin < end);
- const size_t branchCount = end - begin;
- if (branchCount == 1) {
- return *begin;
- }
- auto mid = begin + branchCount / 2;
- auto left = ReduceCaseBranches(begin, mid);
- auto right = ReduceCaseBranches(mid, end);
- TVector<TAstNode*> preds;
- preds.reserve(branchCount + 1);
- preds.push_back(A("Or"));
- for (auto it = begin; it != end; ++it) {
- preds.push_back(it->Pred);
- }
- TCaseBranch result;
- result.Pred = VL(&preds[0], preds.size());
- result.Value = L(A("If"), left.Pred, left.Value, right.Value);
- return result;
- }
- TAstNode* ParseCaseExpr(const CaseExpr* value, const TExprSettings& settings) {
- AT_LOCATION(value);
- TAstNode* testExpr = nullptr;
- if (value->arg) {
- testExpr = ParseExpr(Expr2Node(value->arg), settings);
- if (!testExpr) {
- return nullptr;
- }
- }
- std::vector<TCaseBranch> branches;
- for (int i = 0; i < ListLength(value->args); ++i) {
- auto node = ListNodeNth(value->args, i);
- auto whenNode = CAST_NODE(CaseWhen, node);
- auto whenExpr = ParseExpr(Expr2Node(whenNode->expr), settings);
- if (!whenExpr) {
- return nullptr;
- }
- if (testExpr) {
- whenExpr = L(A("PgOp"), QA("="), testExpr, whenExpr);
- }
- whenExpr = L(A("Coalesce"),
- L(A("FromPg"), whenExpr),
- L(A("Bool"), QA("false"))
- );
- auto whenResult = ParseExpr(Expr2Node(whenNode->result), settings);
- if (!whenResult) {
- return nullptr;
- }
- branches.emplace_back(TCaseBranch{ .Pred = whenExpr,.Value = whenResult });
- }
- TAstNode* defaultResult = nullptr;
- if (value->defresult) {
- defaultResult = ParseExpr(Expr2Node(value->defresult), settings);
- if (!defaultResult) {
- return nullptr;
- }
- } else {
- defaultResult = L(A("Null"));
- }
- auto final = ReduceCaseBranches(branches.begin(), branches.end());
- return L(A("If"), final.Pred, final.Value, defaultResult);
- }
- TAstNode* ParseParamRefExpr(const ParamRef* value) {
- if (SqlProcArgsCount && (value->number < 1 || (ui32)value->number > *SqlProcArgsCount)) {
- AddError(TStringBuilder() << "Unexpected parameter number: " << value->number);
- return nullptr;
- }
- const auto varName = PREPARED_PARAM_PREFIX + ToString(value->number);
- if (!State.ParamNameToPgTypeName.contains(varName)) {
- State.ParamNameToPgTypeName[varName] = DEFAULT_PARAM_TYPE;
- }
- return A(varName);
- }
- TAstNode* ParseReturnStmt(const ReturnStmt* value) {
- TExprSettings settings;
- settings.AllowColumns = false;
- settings.Scope = "RETURN";
- auto expr = ParseExpr(value->returnval, settings);
- if (!expr) {
- return nullptr;
- }
- State.Statements.push_back(L(A("return"), expr));
- return State.Statements.back();
- }
- TAstNode* ParseSQLValueFunction(const SQLValueFunction* value) {
- AT_LOCATION(value);
- switch (value->op) {
- case SVFOP_CURRENT_DATE:
- return L(A("PgCast"),
- L(A("PgCall"), QA("now"), QL()),
- L(A("PgType"), QA("date"))
- );
- case SVFOP_CURRENT_TIME:
- return L(A("PgCast"),
- L(A("PgCall"), QA("now"), QL()),
- L(A("PgType"), QA("timetz"))
- );
- case SVFOP_CURRENT_TIME_N:
- return L(A("PgCast"),
- L(A("PgCall"), QA("now"), QL()),
- L(A("PgType"), QA("timetz")),
- L(A("PgConst"), QA(ToString(value->typmod)), L(A("PgType"), QA("int4")))
- );
- case SVFOP_CURRENT_TIMESTAMP:
- return L(A("PgCall"), QA("now"), QL());
- case SVFOP_CURRENT_TIMESTAMP_N:
- return L(A("PgCast"),
- L(A("PgCall"), QA("now"), QL()),
- L(A("PgType"), QA("timestamptz")),
- L(A("PgConst"), QA(ToString(value->typmod)), L(A("PgType"), QA("int4")))
- );
- case SVFOP_CURRENT_USER:
- case SVFOP_CURRENT_ROLE:
- case SVFOP_USER: {
- auto user = Settings.GUCSettings->Get("ydb_user");
- return L(A("PgConst"), user ? QAX(TString(*user)) : QA("postgres"), L(A("PgType"), QA("name")));
- }
- case SVFOP_CURRENT_CATALOG: {
- std::optional<TString> database;
- if (Settings.GUCSettings) {
- database = Settings.GUCSettings->Get("ydb_database");
- }
- return L(A("PgConst"), QA(database ? *database : "postgres"), L(A("PgType"), QA("name")));
- }
- case SVFOP_CURRENT_SCHEMA:
- return GetCurrentSchema();
- default:
- AddError(TStringBuilder() << "Usupported SQLValueFunction: " << (int)value->op);
- return nullptr;
- }
- }
- TAstNode* GetCurrentSchema() {
- std::optional<TString> searchPath;
- if (Settings.GUCSettings) {
- searchPath = Settings.GUCSettings->Get("search_path");
- }
- return L(A("PgConst"), QA(searchPath ? *searchPath : "public"), L(A("PgType"), QA("name")));
- }
- TAstNode* ParseBooleanTest(const BooleanTest* value, const TExprSettings& settings) {
- AT_LOCATION(value);
- auto arg = ParseExpr(Expr2Node(value->arg), settings);
- if (!arg) {
- return nullptr;
- }
- TString op;
- bool isNot = false;
- switch (value->booltesttype) {
- case IS_TRUE: {
- op = "PgIsTrue";
- break;
- }
- case IS_NOT_TRUE: {
- op = "PgIsTrue";
- isNot = true;
- break;
- }
- case IS_FALSE: {
- op = "PgIsFalse";
- break;
- }
- case IS_NOT_FALSE: {
- op = "PgIsFalse";
- isNot = true;
- break;
- }
- case IS_UNKNOWN: {
- op = "PgIsUnknown";
- break;
- }
- case IS_NOT_UNKNOWN: {
- op = "PgIsUnknown";
- isNot = true;
- break;
- }
- default: {
- TStringBuilder b;
- b << "Unsupported booltesttype " << static_cast<int>(value->booltesttype);
- AddError(b);
- return nullptr;
- }
- }
- auto result = L(A(op), arg);
- if (isNot) {
- result = L(A("PgNot"), result);
- }
- return result;
- }
- TAstNode* ParseExpr(const Node* node, const TExprSettings& settings) {
- switch (NodeTag(node)) {
- case T_A_Const: {
- return ParseAConst(CAST_NODE(A_Const, node), settings);
- }
- case T_A_Expr: {
- return ParseAExpr(CAST_NODE(A_Expr, node), settings);
- }
- case T_CaseExpr: {
- return ParseCaseExpr(CAST_NODE(CaseExpr, node), settings);
- }
- case T_ColumnRef: {
- return ParseColumnRef(CAST_NODE(ColumnRef, node), settings);
- }
- case T_TypeCast: {
- return ParseTypeCast(CAST_NODE(TypeCast, node), settings);
- }
- case T_BoolExpr: {
- return ParseBoolExpr(CAST_NODE(BoolExpr, node), settings);
- }
- case T_NullTest: {
- return ParseNullTestExpr(CAST_NODE(NullTest, node), settings);
- }
- case T_FuncCall: {
- bool injectRead;
- return ParseFuncCall(CAST_NODE(FuncCall, node), settings, false, injectRead);
- }
- case T_A_ArrayExpr: {
- return ParseAArrayExpr(CAST_NODE(A_ArrayExpr, node), settings);
- }
- case T_SubLink: {
- return ParseSubLinkExpr(CAST_NODE(SubLink, node), settings);
- }
- case T_CoalesceExpr: {
- return ParseCoalesceExpr(CAST_NODE(CoalesceExpr, node), settings);
- }
- case T_GroupingFunc: {
- return ParseGroupingFunc(CAST_NODE(GroupingFunc, node));
- }
- case T_ParamRef: {
- return ParseParamRefExpr(CAST_NODE(ParamRef, node));
- }
- case T_SQLValueFunction: {
- return ParseSQLValueFunction(CAST_NODE(SQLValueFunction, node));
- }
- case T_BooleanTest: {
- return ParseBooleanTest(CAST_NODE(BooleanTest, node), settings);
- }
- default:
- NodeNotImplemented(node);
- return nullptr;
- }
- }
- TAstNode* AutoParametrizeConst(TPgConst&& valueNType, TAstNode* pgType) {
- const auto& paramName = AddSimpleAutoParam(std::move(valueNType));
- State.Statements.push_back(L(A("declare"), A(paramName), pgType));
- YQL_CLOG(INFO, Default) << "Autoparametrized " << paramName << " at " << State.Positions.back();
- return A(paramName);
- }
- TAstNode* ParseAConst(const A_Const* value, const TExprSettings& settings) {
- AT_LOCATION(value);
- const auto& val = value->val;
- auto valueNType = GetValueNType(value);
- if (!valueNType) {
- return nullptr;
- }
- TAstNode* pgTypeNode = !value->isnull
- ? L(A("PgType"), QA(TPgConst::ToString(valueNType->type)))
- : L(A("PgType"), QA("unknown"));
- if (Settings.AutoParametrizeEnabled && settings.AutoParametrizeEnabled) {
- return AutoParametrizeConst(std::move(valueNType.GetRef()), pgTypeNode);
- }
- if (value->isnull) {
- return L(A("PgCast"), L(A("Null")), pgTypeNode);
- }
- switch (NodeTag(val)) {
- case T_Integer:
- case T_Float: {
- return L(A("PgConst"), QA(valueNType->value.GetRef()), pgTypeNode);
- }
- case T_Boolean:
- case T_String:
- case T_BitString: {
- return L(A("PgConst"), QAX(valueNType->value.GetRef()), pgTypeNode);
- }
- default: {
- NodeNotImplemented((const Node*)value);
- return nullptr;
- }
- }
- }
- TAstNode* ParseAArrayExpr(const A_ArrayExpr* value, const TExprSettings& settings) {
- AT_LOCATION(value);
- TVector<TAstNode*> args;
- args.push_back(A("PgArray"));
- for (int i = 0; i < ListLength(value->elements); ++i) {
- auto elem = ParseExpr(ListNodeNth(value->elements, i), settings);
- if (!elem) {
- return nullptr;
- }
- args.push_back(elem);
- }
- return VL(args.data(), args.size());
- }
- TAstNode* ParseCoalesceExpr(const CoalesceExpr* value, const TExprSettings& settings) {
- AT_LOCATION(value);
- TVector<TAstNode*> args;
- args.push_back(A("Coalesce"));
- for (int i = 0; i < ListLength(value->args); ++i) {
- auto elem = ParseExpr(ListNodeNth(value->args, i), settings);
- if (!elem) {
- return nullptr;
- }
- args.push_back(elem);
- }
- return VL(args.data(), args.size());
- }
- TAstNode* ParseGroupingFunc(const GroupingFunc* value) {
- AT_LOCATION(value);
- TVector<TAstNode*> args;
- args.push_back(A("PgGrouping"));
- TExprSettings settings;
- settings.Scope = "GROUPING";
- settings.AllowColumns = true;
- for (int i = 0; i < ListLength(value->args); ++i) {
- auto elem = ParseExpr(ListNodeNth(value->args, i), settings);
- if (!elem) {
- return nullptr;
- }
- args.push_back(elem);
- }
- return VL(args.data(), args.size());
- }
- TAstNode* ParseGroupingSet(const GroupingSet* value, const TExprSettings& settings) {
- AT_LOCATION(value);
- TString mode;
- switch (value->kind) {
- case GROUPING_SET_ROLLUP:
- mode = "rollup";
- break;
- case GROUPING_SET_CUBE:
- mode = "cube";
- break;
- case GROUPING_SET_SETS:
- mode = "sets";
- break;
- default:
- AddError(TStringBuilder() << "Unexpected grouping set kind: " << (int)value->kind);
- return nullptr;
- }
- auto innerSettings = settings;
- innerSettings.Scope = to_title(mode);
- TVector<TAstNode*> args;
- args.push_back(A("PgGroupingSet"));
- args.push_back(QA(mode));
- if (value->kind == GROUPING_SET_SETS) {
- // tuple for each set
- for (int i = 0; i < ListLength(value->content); ++i) {
- auto child = ListNodeNth(value->content, i);
- if (NodeTag(child) == T_GroupingSet) {
- auto kind = CAST_NODE(GroupingSet, child)->kind;
- if (kind != GROUPING_SET_EMPTY) {
- AddError(TStringBuilder() << "Unexpected inner grouping set kind: " << (int)kind);
- return nullptr;
- }
- args.push_back(QL());
- continue;
- }
- if (NodeTag(child) == T_RowExpr) {
- auto row = CAST_NODE(RowExpr, child);
- TVector<TAstNode*> tupleItems;
- for (int j = 0; j < ListLength(row->args); ++j) {
- auto elem = ParseExpr(ListNodeNth(row->args, j), innerSettings);
- if (!elem) {
- return nullptr;
- }
- tupleItems.push_back(elem);
- }
- args.push_back(QVL(tupleItems.data(), tupleItems.size()));
- continue;
- }
- auto elem = ParseExpr(ListNodeNth(value->content, i), innerSettings);
- if (!elem) {
- return nullptr;
- }
- args.push_back(QL(elem));
- }
- } else {
- // one tuple
- TVector<TAstNode*> tupleItems;
- for (int i = 0; i < ListLength(value->content); ++i) {
- auto elem = ParseExpr(ListNodeNth(value->content, i), innerSettings);
- if (!elem) {
- return nullptr;
- }
- tupleItems.push_back(elem);
- }
- args.push_back(QVL(tupleItems.data(), tupleItems.size()));
- }
- return VL(args.data(), args.size());
- }
- TAstNode* ParseSubLinkExpr(const SubLink* value, const TExprSettings& settings) {
- AT_LOCATION(value);
- if (!settings.AllowSubLinks) {
- AddError(TStringBuilder() << "SubLinks are not allowed in: " << settings.Scope);
- return nullptr;
- }
- TString linkType;
- TString operName;
- switch (value->subLinkType) {
- case EXISTS_SUBLINK:
- linkType = "exists";
- break;
- case ALL_SUBLINK:
- linkType = "all";
- operName = "=";
- break;
- case ANY_SUBLINK:
- linkType = "any";
- operName = "=";
- break;
- case EXPR_SUBLINK:
- linkType = "expr";
- break;
- case ARRAY_SUBLINK:
- linkType = "array";
- break;
- default:
- AddError(TStringBuilder() << "SublinkExpr: unsupported link type: " << (int)value->subLinkType);
- return nullptr;
- }
- if (ListLength(value->operName) > 1) {
- AddError("SubLink: unsuppoted opername");
- return nullptr;
- } else if (ListLength(value->operName) == 1) {
- auto nameNode = ListNodeNth(value->operName, 0);
- if (NodeTag(nameNode) != T_String) {
- NodeNotImplemented(value, nameNode);
- return nullptr;
- }
- operName = StrVal(nameNode);
- }
- TAstNode* rowTest;
- if (value->testexpr) {
- TExprSettings localSettings = settings;
- localSettings.Scope = "SUBLINK TEST";
- auto test = ParseExpr(value->testexpr, localSettings);
- if (!test) {
- return nullptr;
- }
- rowTest = L(A("lambda"), QL(A("value")), L(A("PgOp"), QAX(operName), test, A("value")));
- } else {
- rowTest = L(A("Void"));
- }
- auto select = ParseSelectStmt(CAST_NODE(SelectStmt, value->subselect), {.Inner = true});
- if (!select) {
- return nullptr;
- }
- return L(A("PgSubLink"), QA(linkType), L(A("Void")), L(A("Void")), rowTest, L(A("lambda"), QL(), select));
- }
- TAstNode* ParseTableRangeFunction(const TString& name, const TString& schema, List* args) {
- auto source = BuildClusterSinkOrSourceExpression(false, schema);
- if (!source) {
- return nullptr;
- }
- TVector<TString> argStrs;
- for (int i = 0; i < ListLength(args); ++i) {
- auto arg = ListNodeNth(args, i);
- if (NodeTag(arg) == T_A_Const && (NodeTag(CAST_NODE(A_Const, arg)->val) == T_String)) {
- TString rawStr = StrVal(CAST_NODE(A_Const, arg)->val);
- argStrs.push_back(rawStr);
- } else {
- AddError("Expected String argument for table function");
- return nullptr;
- }
- }
- if (argStrs.empty()) {
- AddError("Expected at least one argument for table function");
- return nullptr;
- }
- TAstNode* key;
- auto lowerName = to_lower(name);
- auto options = QL();
- if (lowerName == "concat") {
- TVector<TAstNode*> concatArgs;
- concatArgs.push_back(A("MrTableConcat"));
- for (const auto& s : argStrs) {
- concatArgs.push_back(L(A("Key"), QL(QA("table"),L(A("String"), QAX(s)))));
- }
- key = VL(concatArgs);
- } else if (lowerName == "concat_view") {
- if (argStrs.size() % 2 != 0) {
- AddError("Expected sequence of pairs of table and view for concat_view");
- return nullptr;
- }
- TVector<TAstNode*> concatArgs;
- concatArgs.push_back(A("MrTableConcat"));
- for (ui32 i = 0; i < argStrs.size(); i += 2) {
- concatArgs.push_back(L(A("Key"),
- QL(QA("table"),L(A("String"), QAX(argStrs[i]))),
- QL(QA("view"),L(A("String"), QAX(argStrs[i + 1])))));
- }
- key = VL(concatArgs);
- } else if (lowerName == "range") {
- if (argStrs.size() > 5) {
- AddError("Too many arguments");
- return nullptr;
- }
- options = QL(QL(QA("ignorenonexisting")));
- TAstNode* expr;
- if (argStrs.size() == 1) {
- expr = L(A("Bool"),QA("true"));
- } else if (argStrs.size() == 2) {
- expr = L(A(">="),A("item"),L(A("String"),QAX(argStrs[1])));
- } else {
- expr = L(A("And"),
- L(A(">="),A("item"),L(A("String"),QAX(argStrs[1]))),
- L(A("<="),A("item"),L(A("String"),QAX(argStrs[2])))
- );
- }
- auto lambda = L(A("lambda"), QL(A("item")), expr);
- auto range = L(A("MrTableRange"), QAX(argStrs[0]), lambda, QAX(argStrs.size() < 4 ? "" : argStrs[3]));
- if (argStrs.size() < 5) {
- key = L(A("Key"), QL(QA("table"),range));
- } else {
- key = L(A("Key"), QL(QA("table"),range), QL(QA("view"),L(A("String"), QAX(argStrs[4]))));
- }
- } else if (lowerName == "regexp" || lowerName == "like") {
- if (argStrs.size() < 2 || argStrs.size() > 4) {
- AddError("Expected from 2 to 4 arguments");
- return nullptr;
- }
- options = QL(QL(QA("ignorenonexisting")));
- TAstNode* expr;
- if (lowerName == "regexp") {
- expr = L(A("Apply"),L(A("Udf"),QA("Re2.Grep"),
- QL(L(A("String"),QAX(argStrs[1])),L(A("Null")))),
- A("item"));
- } else {
- expr = L(A("Apply"),L(A("Udf"),QA("Re2.Match"),
- QL(L(A("Apply"),
- L(A("Udf"), QA("Re2.PatternFromLike")),
- L(A("String"),QAX(argStrs[1]))),L(A("Null")))),
- A("item"));
- }
- auto lambda = L(A("lambda"), QL(A("item")), expr);
- auto range = L(A("MrTableRange"), QAX(argStrs[0]), lambda, QAX(argStrs.size() < 3 ? "" : argStrs[2]));
- if (argStrs.size() < 4) {
- key = L(A("Key"), QL(QA("table"),range));
- } else {
- key = L(A("Key"), QL(QA("table"),range), QL(QA("view"),L(A("String"), QAX(argStrs[3]))));
- }
- } else {
- AddError(TStringBuilder() << "Unknown table function: " << name);
- return nullptr;
- }
- return L(
- A("Read!"),
- A("world"),
- source,
- key,
- L(A("Void")),
- options
- );
- }
- TAstNode* ParseFuncCall(const FuncCall* value, const TExprSettings& settings, bool rangeFunction, bool& injectRead) {
- AT_LOCATION(value);
- if (ListLength(value->agg_order) > 0) {
- AddError("FuncCall: unsupported agg_order");
- return nullptr;
- }
- if (value->agg_filter) {
- AddError("FuncCall: unsupported agg_filter");
- return nullptr;
- }
- if (value->agg_within_group) {
- AddError("FuncCall: unsupported agg_within_group");
- return nullptr;
- }
- if (value->func_variadic) {
- AddError("FuncCall: unsupported func_variadic");
- return nullptr;
- }
- TAstNode* window = nullptr;
- if (value->over) {
- if (!settings.AllowOver) {
- AddError(TStringBuilder() << "Over is not allowed in: " << settings.Scope);
- return nullptr;
- }
- if (StrLength(value->over->name)) {
- window = QAX(value->over->name);
- } else {
- auto index = settings.WindowItems->size();
- auto def = ParseWindowDef(value->over);
- if (!def) {
- return nullptr;
- }
- window = L(A("PgAnonWindow"), QA(ToString(index)));
- settings.WindowItems->push_back(def);
- }
- }
- TString name;
- TString schema;
- if (!ExtractFuncName(value, name, rangeFunction ? &schema : nullptr)) {
- return nullptr;
- }
- if (rangeFunction && !schema.empty() && schema != "pg_catalog") {
- injectRead = true;
- return ParseTableRangeFunction(name, schema, value->args);
- }
- if (name == "shobj_description" || name == "obj_description") {
- AddWarning(TIssuesIds::PG_COMPAT, name + " function forced to NULL");
- return L(A("Null"));
- }
- if (name == "current_schema") {
- return GetCurrentSchema();
- }
- // for zabbix https://github.com/ydb-platform/ydb/issues/2904
- if (name == "pg_try_advisory_lock" || name == "pg_try_advisory_lock_shared" || name == "pg_advisory_unlock" || name == "pg_try_advisory_xact_lock" || name == "pg_try_advisory_xact_lock_shared"){
- AddWarning(TIssuesIds::PG_COMPAT, name + " function forced to return OK without waiting and without really lock/unlock");
- return L(A("PgConst"), QA("true"), L(A("PgType"), QA("bool")));
- }
- if (name == "pg_advisory_lock" || name == "pg_advisory_lock_shared" || name == "pg_advisory_unlock_all" || name == "pg_advisory_xact_lock" || name == "pg_advisory_xact_lock_shared"){
- AddWarning(TIssuesIds::PG_COMPAT, name + " function forced to return OK without waiting and without really lock/unlock");
- return L(A("Null"));
- }
- const bool isAggregateFunc = NYql::NPg::HasAggregation(name, NYql::NPg::EAggKind::Normal);
- const bool hasReturnSet = NYql::NPg::HasReturnSetProc(name);
- if (isAggregateFunc && !settings.AllowAggregates) {
- AddError(TStringBuilder() << "Aggregate functions are not allowed in: " << settings.Scope);
- return nullptr;
- }
- if (hasReturnSet && !settings.AllowReturnSet) {
- AddError(TStringBuilder() << "Generator functions are not allowed in: " << settings.Scope);
- return nullptr;
- }
- TVector<TAstNode*> args;
- TString callable;
- if (window) {
- if (isAggregateFunc) {
- callable = "PgAggWindowCall";
- } else {
- callable = "PgWindowCall";
- }
- } else {
- if (isAggregateFunc) {
- callable = "PgAgg";
- } else {
- callable = "PgCall";
- }
- }
- args.push_back(A(callable));
- args.push_back(QAX(name));
- if (window) {
- args.push_back(window);
- }
- TVector<TAstNode*> callSettings;
- if (value->agg_distinct) {
- if (!isAggregateFunc) {
- AddError("FuncCall: agg_distinct must be set only for aggregate functions");
- return nullptr;
- }
- callSettings.push_back(QL(QA("distinct")));
- }
- if (rangeFunction) {
- callSettings.push_back(QL(QA("range")));
- }
- args.push_back(QVL(callSettings.data(), callSettings.size()));
- if (value->agg_star) {
- if (name != "count") {
- AddError("FuncCall: * is expected only in count function");
- return nullptr;
- }
- } else {
- if (name == "count" && ListLength(value->args) == 0) {
- AddError("FuncCall: count(*) must be used to call a parameterless aggregate function");
- return nullptr;
- }
- bool hasError = false;
- for (int i = 0; i < ListLength(value->args); ++i) {
- auto x = ListNodeNth(value->args, i);
- auto arg = ParseExpr(x, settings);
- if (!arg) {
- hasError = true;
- continue;
- }
- args.push_back(arg);
- }
- if (hasError) {
- return nullptr;
- }
- }
- return VL(args.data(), args.size());
- }
- bool ExtractFuncName(const FuncCall* value, TString& name, TString* schemaName) {
- TVector<TString> names;
- for (int i = 0; i < ListLength(value->funcname); ++i) {
- auto x = ListNodeNth(value->funcname, i);
- if (NodeTag(x) != T_String) {
- NodeNotImplemented(value, x);
- return false;
- }
- names.push_back(to_lower(TString(StrVal(x))));
- }
- if (names.empty()) {
- AddError("FuncCall: missing function name");
- return false;
- }
- if (names.size() > 2) {
- AddError(TStringBuilder() << "FuncCall: too many name components:: " << names.size());
- return false;
- }
- if (names.size() == 2) {
- if (!schemaName && names[0] != "pg_catalog") {
- AddError(TStringBuilder() << "FuncCall: expected pg_catalog, but got: " << names[0]);
- return false;
- }
- if (schemaName) {
- *schemaName = names[0];
- }
- }
- name = names.back();
- return true;
- }
- TAstNode* ParseTypeCast(const TypeCast* value, const TExprSettings& settings) {
- AT_LOCATION(value);
- if (!value->arg) {
- AddError("Expected arg");
- return nullptr;
- }
- if (!value->typeName) {
- AddError("Expected type_name");
- return nullptr;
- }
- auto arg = value->arg;
- auto typeName = value->typeName;
- auto supportedTypeName = typeName->typeOid == 0 &&
- !typeName->setof &&
- !typeName->pct_type &&
- (ListLength(typeName->names) == 2 &&
- NodeTag(ListNodeNth(typeName->names, 0)) == T_String &&
- !StrICompare(StrVal(ListNodeNth(typeName->names, 0)), "pg_catalog") || ListLength(typeName->names) == 1) &&
- NodeTag(ListNodeNth(typeName->names, ListLength(typeName->names) - 1)) == T_String;
- if (NodeTag(arg) == T_A_Const &&
- (NodeTag(CAST_NODE(A_Const, arg)->val) == T_String ||
- CAST_NODE(A_Const, arg)->isnull) &&
- supportedTypeName &&
- typeName->typemod == -1 &&
- ListLength(typeName->typmods) == 0 &&
- ListLength(typeName->arrayBounds) == 0) {
- TStringBuf targetType = StrVal(ListNodeNth(typeName->names, ListLength(typeName->names) - 1));
- if (NodeTag(CAST_NODE(A_Const, arg)->val) == T_String && targetType == "bool") {
- auto str = StrVal(CAST_NODE(A_Const, arg)->val);
- return L(A("PgConst"), QAX(str), L(A("PgType"), QA("bool")));
- }
- }
- if (supportedTypeName) {
- AT_LOCATION(typeName);
- TStringBuf targetType = StrVal(ListNodeNth(typeName->names, ListLength(typeName->names) - 1));
- auto input = ParseExpr(arg, settings);
- if (!input) {
- return nullptr;
- }
- auto finalType = TString(targetType);
- if (ListLength(typeName->arrayBounds) && !finalType.StartsWith('_')) {
- finalType = "_" + finalType;
- }
- if (!NPg::HasType(finalType)) {
- AddError(TStringBuilder() << "Unknown type: " << finalType);
- return nullptr;
- }
- if (ListLength(typeName->typmods) == 0 && typeName->typemod == -1) {
- return L(A("PgCast"), input, L(A("PgType"), QAX(finalType)));
- } else {
- const auto& typeDesc = NPg::LookupType(finalType);
- ui32 typeModInFuncId;
- if (typeDesc.ArrayTypeId == typeDesc.TypeId) {
- const auto& typeDescElem = NPg::LookupType(typeDesc.ElementTypeId);
- typeModInFuncId = typeDescElem.TypeModInFuncId;
- } else {
- typeModInFuncId = typeDesc.TypeModInFuncId;
- }
- if (!typeModInFuncId) {
- AddError(TStringBuilder() << "Type " << finalType << " doesn't support modifiers");
- return nullptr;
- }
- const auto& procDesc = NPg::LookupProc(typeModInFuncId);
- TAstNode* typeMod;
- if (typeName->typemod != -1) {
- typeMod = L(A("PgConst"), QA(ToString(typeName->typemod)), L(A("PgType"), QA("int4")));
- } else {
- TVector<TAstNode*> args;
- args.push_back(A("PgArray"));
- for (int i = 0; i < ListLength(typeName->typmods); ++i) {
- auto typeMod = ListNodeNth(typeName->typmods, i);
- if (NodeTag(typeMod) != T_A_Const) {
- AddError("Expected T_A_Const as typmod");
- return nullptr;
- }
- auto aConst = CAST_NODE(A_Const, typeMod);
- TString s;
- if (!ValueAsString(aConst->val, aConst->isnull, s)) {
- AddError("Unsupported format of typmod");
- return nullptr;
- }
- args.push_back(L(A("PgConst"), QAX(s), L(A("PgType"), QA("cstring"))));
- }
- typeMod = L(A("PgCall"), QA(procDesc.Name), QL(), VL(args.data(), args.size()));
- }
- return L(A("PgCast"), input, L(A("PgType"), QAX(finalType)), typeMod);
- }
- }
- AddError("Unsupported form of type cast");
- return nullptr;
- }
- TAstNode* ParseAndOrExpr(const BoolExpr* value, const TExprSettings& settings, const TString& pgOpName) {
- auto length = ListLength(value->args);
- if (length < 2) {
- AddError(TStringBuilder() << "Expected >1 args for " << pgOpName << " but have " << length << " args");
- return nullptr;
- }
- auto lhs = ParseExpr(ListNodeNth(value->args, 0), settings);
- if (!lhs) {
- return nullptr;
- }
- for (auto i = 1; i < length; ++i) {
- auto rhs = ParseExpr(ListNodeNth(value->args, i), settings);
- if (!rhs) {
- return nullptr;
- }
- lhs = L(A(pgOpName), lhs, rhs);
- }
- return lhs;
- }
- TAstNode* ParseBoolExpr(const BoolExpr* value, const TExprSettings& settings) {
- AT_LOCATION(value);
- switch (value->boolop) {
- case AND_EXPR: {
- return ParseAndOrExpr(value, settings, "PgAnd");
- }
- case OR_EXPR: {
- return ParseAndOrExpr(value, settings, "PgOr");
- }
- case NOT_EXPR: {
- if (ListLength(value->args) != 1) {
- AddError("Expected 1 arg for NOT");
- return nullptr;
- }
- auto arg = ParseExpr(ListNodeNth(value->args, 0), settings);
- if (!arg) {
- return nullptr;
- }
- return L(A("PgNot"), arg);
- }
- default:
- AddError(TStringBuilder() << "BoolExprType unsupported value: " << (int)value->boolop);
- return nullptr;
- }
- }
- TAstNode* ParseWindowDef(const WindowDef* value) {
- AT_LOCATION(value);
- auto name = QAX(value->name);
- auto refName = QAX(value->refname);
- TVector<TAstNode*> sortItems;
- for (int i = 0; i < ListLength(value->orderClause); ++i) {
- auto node = ListNodeNth(value->orderClause, i);
- if (NodeTag(node) != T_SortBy) {
- NodeNotImplemented(value, node);
- return nullptr;
- }
- auto sort = ParseSortBy(CAST_NODE_EXT(PG_SortBy, T_SortBy, node), true, false);
- if (!sort) {
- return nullptr;
- }
- sortItems.push_back(sort);
- }
- auto sort = QVL(sortItems.data(), sortItems.size());
- TVector<TAstNode*> groupByItems;
- for (int i = 0; i < ListLength(value->partitionClause); ++i) {
- auto node = ListNodeNth(value->partitionClause, i);
- TExprSettings settings;
- settings.AllowColumns = true;
- settings.AllowAggregates = true;
- settings.Scope = "PARTITITON BY";
- auto expr = ParseExpr(node, settings);
- if (!expr) {
- return nullptr;
- }
- auto lambda = L(A("lambda"), QL(), expr);
- groupByItems.push_back(L(A("PgGroup"), L(A("Void")), lambda));
- }
- auto group = QVL(groupByItems.data(), groupByItems.size());
- TVector<TAstNode*> optionItems;
- if (value->frameOptions & FRAMEOPTION_NONDEFAULT) {
- TString exclude;
- if (value->frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW) {
- if (exclude) {
- AddError("Wrong frame options");
- return nullptr;
- }
- exclude = "c";
- }
- if (value->frameOptions & FRAMEOPTION_EXCLUDE_GROUP) {
- if (exclude) {
- AddError("Wrong frame options");
- return nullptr;
- }
- exclude = "cp";
- }
- if (value->frameOptions & FRAMEOPTION_EXCLUDE_TIES) {
- if (exclude) {
- AddError("Wrong frame options");
- return nullptr;
- }
- exclude = "p";
- }
- if (exclude) {
- optionItems.push_back(QL(QA("exclude"), QA(exclude)));
- }
- TString type;
- if (value->frameOptions & FRAMEOPTION_RANGE) {
- if (type) {
- AddError("Wrong frame options");
- return nullptr;
- }
- type = "range";
- }
- if (value->frameOptions & FRAMEOPTION_ROWS) {
- if (type) {
- AddError("Wrong frame options");
- return nullptr;
- }
- type = "rows";
- }
- if (value->frameOptions & FRAMEOPTION_GROUPS) {
- if (type) {
- AddError("Wrong frame options");
- return nullptr;
- }
- type = "groups";
- }
- if (!type) {
- AddError("Wrong frame options");
- return nullptr;
- }
- TString from;
- if (value->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING) {
- if (from) {
- AddError("Wrong frame options");
- return nullptr;
- }
- from = "up";
- }
- if (value->frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING) {
- if (from) {
- AddError("Wrong frame options");
- return nullptr;
- }
- from = "p";
- auto offset = ConvertFrameOffset(value->startOffset);
- if (!offset) {
- return nullptr;
- }
- optionItems.push_back(QL(QA("from_value"), offset));
- }
- if (value->frameOptions & FRAMEOPTION_START_CURRENT_ROW) {
- if (from) {
- AddError("Wrong frame options");
- return nullptr;
- }
- from = "c";
- }
- if (value->frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING) {
- if (from) {
- AddError("Wrong frame options");
- return nullptr;
- }
- from = "f";
- auto offset = ConvertFrameOffset(value->startOffset);
- if (!offset) {
- return nullptr;
- }
- optionItems.push_back(QL(QA("from_value"), offset));
- }
- if (value->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING) {
- AddError("Wrong frame options");
- return nullptr;
- }
- if (!from) {
- AddError("Wrong frame options");
- return nullptr;
- }
- TString to;
- if (value->frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING) {
- AddError("Wrong frame options");
- return nullptr;
- }
- if (value->frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING) {
- if (to) {
- AddError("Wrong frame options");
- return nullptr;
- }
- to = "p";
- auto offset = ConvertFrameOffset(value->endOffset);
- if (!offset) {
- return nullptr;
- }
- optionItems.push_back(QL(QA("to_value"), offset));
- }
- if (value->frameOptions & FRAMEOPTION_END_CURRENT_ROW) {
- if (to) {
- AddError("Wrong frame options");
- return nullptr;
- }
- to = "c";
- }
- if (value->frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING) {
- if (to) {
- AddError("Wrong frame options");
- return nullptr;
- }
- to = "f";
- auto offset = ConvertFrameOffset(value->endOffset);
- if (!offset) {
- return nullptr;
- }
- optionItems.push_back(QL(QA("to_value"), offset));
- }
- if (value->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING) {
- if (to) {
- AddError("Wrong frame options");
- return nullptr;
- }
- to = "uf";
- }
- if (!to) {
- AddError("Wrong frame options");
- return nullptr;
- }
- optionItems.push_back(QL(QA("type"), QAX(type)));
- optionItems.push_back(QL(QA("from"), QAX(from)));
- optionItems.push_back(QL(QA("to"), QAX(to)));
- }
- auto options = QVL(optionItems.data(), optionItems.size());
- return L(A("PgWindow"), name, refName, group, sort, options);
- }
- TAstNode* ConvertFrameOffset(const Node* off) {
- if (NodeTag(off) == T_A_Const
- && NodeTag(CAST_NODE(A_Const, off)->val) == T_Integer) {
- return L(A("Int32"), QA(ToString(IntVal(CAST_NODE(A_Const, off)->val))));
- } else {
- TExprSettings settings;
- settings.AllowColumns = false;
- settings.Scope = "FRAME";
- auto offset = ParseExpr(off, settings);
- if (!offset) {
- return nullptr;
- }
- return L(A("EvaluateExpr"), L(A("Unwrap"), offset, L(A("String"), QA("Frame offset must be non-null"))));
- }
- }
- TAstNode* ParseSortBy(const PG_SortBy* value, bool allowAggregates, bool useProjectionRefs) {
- AT_LOCATION(value);
- bool asc = true;
- bool nullsFirst = true;
- switch (value->sortby_dir) {
- case SORTBY_DEFAULT:
- case SORTBY_ASC:
- if (Settings.PgSortNulls) {
- nullsFirst = false;
- }
- break;
- case SORTBY_DESC:
- asc = false;
- break;
- default:
- AddError(TStringBuilder() << "sortby_dir unsupported value: " << (int)value->sortby_dir);
- return nullptr;
- }
- switch (value->sortby_nulls) {
- case SORTBY_NULLS_DEFAULT:
- break;
- case SORTBY_NULLS_FIRST:
- nullsFirst = true;
- break;
- case SORTBY_NULLS_LAST:
- nullsFirst = false;
- break;
- default:
- AddError(TStringBuilder() << "sortby_dir unsupported value: " << (int)value->sortby_dir);
- return nullptr;
- }
- if (ListLength(value->useOp) > 0) {
- AddError("Unsupported operators in sort_by");
- return nullptr;
- }
- TAstNode* expr;
- if (useProjectionRefs && NodeTag(value->node) == T_A_Const && (NodeTag(CAST_NODE(A_Const, value->node)->val) == T_Integer)) {
- expr = MakeProjectionRef("ORDER BY", CAST_NODE(A_Const, value->node));
- } else {
- TExprSettings settings;
- settings.AllowColumns = true;
- settings.AllowSubLinks = true;
- settings.Scope = "ORDER BY";
- settings.AllowAggregates = allowAggregates;
- expr = ParseExpr(value->node, settings);
- }
- if (!expr) {
- return nullptr;
- }
- auto lambda = L(A("lambda"), QL(), expr);
- return L(A("PgSort"), L(A("Void")), lambda, QA(asc ? "asc" : "desc"), QA(nullsFirst ? "first" : "last"));
- }
- TAstNode* ParseColumnRef(const ColumnRef* value, const TExprSettings& settings) {
- AT_LOCATION(value);
- if (!settings.AllowColumns) {
- AddError(TStringBuilder() << "Columns are not allowed in: " << settings.Scope);
- return nullptr;
- }
- if (ListLength(value->fields) == 0) {
- AddError("No fields");
- return nullptr;
- }
- if (ListLength(value->fields) > 2) {
- AddError("Too many fields");
- return nullptr;
- }
- bool isStar = false;
- TVector<TString> fields;
- for (int i = 0; i < ListLength(value->fields); ++i) {
- auto x = ListNodeNth(value->fields, i);
- if (isStar) {
- AddError("Star is already defined");
- return nullptr;
- }
- if (NodeTag(x) == T_String) {
- fields.push_back(StrVal(x));
- } else if (NodeTag(x) == T_A_Star) {
- isStar = true;
- } else {
- NodeNotImplemented(value, x);
- return nullptr;
- }
- }
- if (isStar) {
- if (fields.size() == 0) {
- return L(A("PgStar"));
- } else {
- return L(A("PgQualifiedStar"), QAX(fields[0]));
- }
- } else if (fields.size() == 1) {
- return L(A("PgColumnRef"), QAX(fields[0]));
- } else {
- return L(A("PgColumnRef"), QAX(fields[0]), QAX(fields[1]));
- }
- }
- TAstNode* ParseAExprOp(const A_Expr* value, const TExprSettings& settings) {
- AT_LOCATION(value);
- if (ListLength(value->name) != 1) {
- AddError(TStringBuilder() << "Unsupported count of names: " << ListLength(value->name));
- return nullptr;
- }
- auto nameNode = ListNodeNth(value->name, 0);
- if (NodeTag(nameNode) != T_String) {
- NodeNotImplemented(value, nameNode);
- return nullptr;
- }
- auto op = StrVal(nameNode);
- if (!value->rexpr) {
- AddError("Missing operands");
- return nullptr;
- }
- if (!value->lexpr) {
- auto rhs = ParseExpr(value->rexpr, settings);
- if (!rhs) {
- return nullptr;
- }
- return L(A("PgOp"), QAX(op), rhs);
- }
- auto lhs = ParseExpr(value->lexpr, settings);
- auto rhs = ParseExpr(value->rexpr, settings);
- if (!lhs || !rhs) {
- return nullptr;
- }
- return L(A("PgOp"), QAX(op), lhs, rhs);
- }
- TAstNode* ParseAExprOpAnyAll(const A_Expr* value, const TExprSettings& settings, bool all) {
- if (ListLength(value->name) != 1) {
- AddError(TStringBuilder() << "Unsupported count of names: " << ListLength(value->name));
- return nullptr;
- }
- auto nameNode = ListNodeNth(value->name, 0);
- if (NodeTag(nameNode) != T_String) {
- NodeNotImplemented(value, nameNode);
- return nullptr;
- }
- auto op = StrVal(nameNode);
- if (!value->lexpr || !value->rexpr) {
- AddError("Missing operands");
- return nullptr;
- }
- auto lhs = ParseExpr(value->lexpr, settings);
- if (NodeTag(value->rexpr) == T_SubLink) {
- auto sublink = CAST_NODE(SubLink, value->rexpr);
- auto subselect = CAST_NODE(SelectStmt, sublink->subselect);
- if (subselect->withClause && subselect->withClause->recursive) {
- if (State.ApplicationName && State.ApplicationName->StartsWith("pgAdmin")) {
- AddWarning(TIssuesIds::PG_COMPAT, "AEXPR_OP_ANY forced to false");
- return L(A("PgConst"), QA("false"), L(A("PgType"), QA("bool")));
- }
- }
- }
- auto rhs = ParseExpr(value->rexpr, settings);
- if (!lhs || !rhs) {
- return nullptr;
- }
- return L(A(all ? "PgAllOp" : "PgAnyOp"), QAX(op), lhs, rhs);
- }
- TAstNode* ParseAExprLike(const A_Expr* value, const TExprSettings& settings, bool insensitive) {
- if (ListLength(value->name) != 1) {
- AddError(TStringBuilder() << "Unsupported count of names: " << ListLength(value->name));
- return nullptr;
- }
- auto nameNode = ListNodeNth(value->name, 0);
- if (NodeTag(nameNode) != T_String) {
- NodeNotImplemented(value, nameNode);
- return nullptr;
- }
- auto op = TString(StrVal(nameNode));
- if (insensitive) {
- if (op != "~~*" && op != "!~~*") {
- AddError(TStringBuilder() << "Unsupported operation: " << op);
- return nullptr;
- }
- } else {
- if (op != "~~" && op != "!~~") {
- AddError(TStringBuilder() << "Unsupported operation: " << op);
- return nullptr;
- }
- }
- if (!value->lexpr || !value->rexpr) {
- AddError("Missing operands");
- return nullptr;
- }
- auto lhs = ParseExpr(value->lexpr, settings);
- auto rhs = ParseExpr(value->rexpr, settings);
- if (!lhs || !rhs) {
- return nullptr;
- }
- auto ret = L(A(insensitive ? "PgILike" : "PgLike"), lhs, rhs);
- if (op[0] == '!') {
- ret = L(A("PgNot"), ret);
- }
- return ret;
- }
- TAstNode* ParseAExprNullIf(const A_Expr* value, const TExprSettings& settings) {
- if (ListLength(value->name) != 1) {
- AddError(TStringBuilder() << "Unsupported count of names: " << ListLength(value->name));
- return nullptr;
- }
- if (!value->lexpr || !value->rexpr) {
- AddError("Missing operands");
- return nullptr;
- }
- auto lhs = ParseExpr(value->lexpr, settings);
- auto rhs = ParseExpr(value->rexpr, settings);
- if (!lhs || !rhs) {
- return nullptr;
- }
- return L(A("PgNullIf"), lhs, rhs);
- }
- TAstNode* ParseAExprIn(const A_Expr* value, const TExprSettings& settings) {
- if (ListLength(value->name) != 1) {
- AddError(TStringBuilder() << "Unsupported count of names: " << ListLength(value->name));
- return nullptr;
- }
- auto nameNode = ListNodeNth(value->name, 0);
- if (NodeTag(nameNode) != T_String) {
- NodeNotImplemented(value, nameNode);
- return nullptr;
- }
- auto op = TString(StrVal(nameNode));
- if (op != "=" && op != "<>") {
- AddError(TStringBuilder() << "Unsupported operation: " << op);
- return nullptr;
- }
- if (!value->lexpr || !value->rexpr) {
- AddError("Missing operands");
- return nullptr;
- }
- auto lhs = ParseExpr(value->lexpr, settings);
- if (!lhs) {
- return nullptr;
- }
- if (NodeTag(value->rexpr) != T_List) {
- NodeNotImplemented(value, value->rexpr);
- return nullptr;
- }
- auto lst = CAST_NODE(List, value->rexpr);
- TVector<TAstNode*> children;
- children.reserve(2 + ListLength(lst));
- children.push_back(A("PgIn"));
- children.push_back(lhs);
- for (int item = 0; item < ListLength(lst); ++item) {
- auto cell = ParseExpr(ListNodeNth(lst, item), settings);
- if (!cell) {
- return nullptr;
- }
- children.push_back(cell);
- }
- auto ret = VL(children.data(), children.size());
- if (op[0] == '<') {
- ret = L(A("PgNot"), ret);
- }
- return ret;
- }
- TAstNode* ParseAExprBetween(const A_Expr* value, const TExprSettings& settings) {
- if (!value->lexpr || !value->rexpr) {
- AddError("Missing operands");
- return nullptr;
- }
- if (NodeTag(value->rexpr) != T_List) {
- AddError(TStringBuilder() << "Expected T_List tag, but have " << NodeTag(value->rexpr));
- return nullptr;
- }
- const List* rexprList = CAST_NODE(List, value->rexpr);
- if (ListLength(rexprList) != 2) {
- AddError(TStringBuilder() << "Expected 2 args in BETWEEN range, but have " << ListLength(rexprList));
- return nullptr;
- }
- auto b = ListNodeNth(rexprList, 0);
- auto e = ListNodeNth(rexprList, 1);
- auto lhs = ParseExpr(value->lexpr, settings);
- auto rbhs = ParseExpr(b, settings);
- auto rehs = ParseExpr(e, settings);
- if (!lhs || !rbhs || !rehs) {
- return nullptr;
- }
- A_Expr_Kind kind = value->kind;
- bool inverse = false;
- if (kind == AEXPR_NOT_BETWEEN) {
- inverse = true;
- kind = AEXPR_BETWEEN;
- } else if (kind == AEXPR_NOT_BETWEEN_SYM) {
- inverse = true;
- kind = AEXPR_BETWEEN_SYM;
- }
- TAstNode* ret;
- switch (kind) {
- case AEXPR_BETWEEN:
- case AEXPR_BETWEEN_SYM:
- ret = L(A(kind == AEXPR_BETWEEN ? "PgBetween" : "PgBetweenSym"), lhs, rbhs, rehs);
- break;
- default:
- AddError(TStringBuilder() << "BETWEEN kind unsupported value: " << (int)value->kind);
- return nullptr;
- }
- if (inverse) {
- ret = L(A("PgNot"), ret);
- }
- return ret;
- }
- TAstNode* ParseAExpr(const A_Expr* value, const TExprSettings& settings) {
- AT_LOCATION(value);
- switch (value->kind) {
- case AEXPR_OP:
- return ParseAExprOp(value, settings);
- case AEXPR_LIKE:
- case AEXPR_ILIKE:
- return ParseAExprLike(value, settings, value->kind == AEXPR_ILIKE);
- case AEXPR_IN:
- return ParseAExprIn(value, settings);
- case AEXPR_BETWEEN:
- case AEXPR_NOT_BETWEEN:
- case AEXPR_BETWEEN_SYM:
- case AEXPR_NOT_BETWEEN_SYM:
- return ParseAExprBetween(value, settings);
- case AEXPR_OP_ANY:
- case AEXPR_OP_ALL:
- return ParseAExprOpAnyAll(value, settings, value->kind == AEXPR_OP_ALL);
- case AEXPR_NULLIF:
- return ParseAExprNullIf(value, settings);
- default:
- AddError(TStringBuilder() << "A_Expr_Kind unsupported value: " << (int)value->kind);
- return nullptr;
- }
- }
- void AddVariableDeclarations() {
- for (const auto& [varName, typeName] : State.ParamNameToPgTypeName) {
- const auto pgType = L(A("PgType"), QA(typeName));
- State.Statements.push_back(L(A("declare"), A(varName), pgType));
- }
- }
- template <typename T>
- void NodeNotImplementedImpl(const Node* nodeptr) {
- TStringBuilder b;
- b << TypeName<T>() << ": ";
- b << "alternative is not implemented yet : " << NodeTag(nodeptr);
- AddError(b);
- }
- template <typename T>
- void NodeNotImplemented(const T* outer, const Node* nodeptr) {
- Y_UNUSED(outer);
- NodeNotImplementedImpl<T>(nodeptr);
- }
- void NodeNotImplemented(const Node* nodeptr) {
- TStringBuilder b;
- b << "alternative is not implemented yet : " << NodeTag(nodeptr);
- AddError(b);
- }
- TAstNode* VL(TAstNode** nodes, ui32 size, TPosition pos = {}) {
- return TAstNode::NewList(pos.Row ? pos : State.Positions.back(), nodes, size, *AstParseResults[StatementId].Pool);
- }
- TAstNode* VL(TArrayRef<TAstNode*> nodes, TPosition pos = {}) {
- return TAstNode::NewList(pos.Row ? pos : State.Positions.back(), nodes.data(), nodes.size(), *AstParseResults[StatementId].Pool);
- }
- TAstNode* QVL(TAstNode** nodes, ui32 size, TPosition pos = {}) {
- return Q(VL(nodes, size, pos), pos);
- }
- TAstNode* QVL(TAstNode* node, TPosition pos = {}) {
- return QVL(&node, 1, pos);
- }
- TAstNode* QVL(TArrayRef<TAstNode*> nodes, TPosition pos = {}) {
- return Q(VL(nodes, pos), pos);
- }
- TAstNode* A(const TStringBuf str, TPosition pos = {}, ui32 flags = 0) {
- return TAstNode::NewAtom(pos.Row ? pos : State.Positions.back(), str, *AstParseResults[StatementId].Pool, flags);
- }
- TAstNode* AX(const TString& str, TPosition pos = {}) {
- return A(str, pos.Row ? pos : State.Positions.back(), TNodeFlags::ArbitraryContent);
- }
- TAstNode* Q(TAstNode* node, TPosition pos = {}) {
- return L(A("quote", pos), node, pos);
- }
- TAstNode* QA(const TStringBuf str, TPosition pos = {}, ui32 flags = 0) {
- return Q(A(str, pos, flags), pos);
- }
- TAstNode* QAX(const TString& str, TPosition pos = {}) {
- return QA(str, pos, TNodeFlags::ArbitraryContent);
- }
- template <typename... TNodes>
- TAstNode* L(TNodes... nodes) {
- TLState state;
- LImpl(state, nodes...);
- return TAstNode::NewList(state.Position.Row ? state.Position : State.Positions.back(), state.Nodes.data(), state.Nodes.size(), *AstParseResults[StatementId].Pool);
- }
- template <typename... TNodes>
- TAstNode* QL(TNodes... nodes) {
- return Q(L(nodes...));
- }
- template <typename... TNodes>
- TAstNode* E(TAstNode* list, TNodes... nodes) {
- Y_ABORT_UNLESS(list->IsList());
- TVector<TAstNode*> nodes_vec;
- nodes_vec.reserve(list->GetChildrenCount() + sizeof...(nodes));
- auto children = list->GetChildren();
- if (children) {
- nodes_vec.assign(children.begin(), children.end());
- }
- nodes_vec.assign({nodes...});
- return VL(nodes_vec.data(), nodes_vec.size());
- }
- private:
- void AddError(const TString& value) {
- AstParseResults[StatementId].Issues.AddIssue(TIssue(State.Positions.back(), value));
- }
- void AddWarning(int code, const TString& value) {
- AstParseResults[StatementId].Issues.AddIssue(TIssue(State.Positions.back(), value).SetCode(code, ESeverity::TSeverityIds_ESeverityId_S_WARNING));
- }
- struct TLState {
- TPosition Position;
- TVector<TAstNode*> Nodes;
- };
- template <typename... TNodes>
- void LImpl(TLState& state, TNodes... nodes);
- void LImpl(TLState& state) {
- Y_UNUSED(state);
- }
- void LImpl(TLState& state, TPosition pos) {
- state.Position = pos;
- }
- void LImpl(TLState& state, TAstNode* node) {
- state.Nodes.push_back(node);
- }
- template <typename T, typename... TNodes>
- void LImpl(TLState& state, T node, TNodes... nodes) {
- state.Nodes.push_back(node);
- LImpl(state, nodes...);
- }
- void PushPosition(int location) {
- if (location == -1) {
- State.Positions.push_back(State.Positions.back());
- return;
- }
- State.Positions.push_back(Location2Position(location));
- };
- void PopPosition() {
- State.Positions.pop_back();
- }
- NYql::TPosition Location2Position(int location) const {
- if (!QuerySize) {
- return NYql::TPosition(0, 0);
- }
- if (location < 0) {
- return NYql::TPosition(0, 0);
- }
- auto it = LowerBound(RowStarts.begin(), RowStarts.end(), Min((ui32)location, QuerySize));
- Y_ENSURE(it != RowStarts.end());
- if (*it == (ui32)location) {
- auto row = 1 + it - RowStarts.begin();
- auto column = 1;
- return NYql::TPosition(column, row);
- } else {
- Y_ENSURE(it != RowStarts.begin());
- auto row = it - RowStarts.begin();
- auto column = 1 + location - *(it - 1);
- return NYql::TPosition(column, row);
- }
- }
- void ScanRows(const TString& query) {
- QuerySize = query.size();
- RowStarts.push_back(0);
- TPosition position(0, 1);
- TTextWalker walker(position, true);
- auto prevRow = position.Row;
- for (ui32 i = 0; i < query.size(); ++i) {
- walker.Advance(query[i]);
- while (position.Row != prevRow) {
- RowStarts.push_back(i);
- ++prevRow;
- }
- }
- RowStarts.push_back(QuerySize);
- }
- TAstNode* MakeProjectionRef(const TStringBuf& scope, const A_Const* aConst) {
- AT_LOCATION(aConst);
- auto num = IntVal(aConst->val);
- if (num <= 0) {
- AddError(TStringBuilder() << scope << ": position " << num << " is not in select list");
- return nullptr;
- }
- return L(A("PgProjectionRef"), QA(ToString(num - 1)));
- }
- private:
- TVector<TAstParseResult>& AstParseResults;
- NSQLTranslation::TTranslationSettings Settings;
- bool DqEngineEnabled = false;
- bool DqEngineForce = false;
- bool BlockEngineEnabled = false;
- bool BlockEngineForce = false;
- bool UnorderedResult = false;
- TString TablePathPrefix;
- TVector<ui32> RowStarts;
- ui32 QuerySize;
- TString Provider;
- static const THashMap<TStringBuf, TString> ProviderToInsertModeMap;
- TState State;
- ui32 StatementId = 0;
- TVector<TStmtParseInfo>* StmtParseInfo;
- bool PerStatementResult;
- TMaybe<ui32> SqlProcArgsCount;
- bool HasSelectInLimitedView = false;
- };
- const THashMap<TStringBuf, TString> TConverter::ProviderToInsertModeMap = {
- {NYql::KikimrProviderName, "insert_abort"},
- {NYql::YtProviderName, "append"}
- };
- NYql::TAstParseResult PGToYql(const TString& query, const NSQLTranslation::TTranslationSettings& settings, TStmtParseInfo* stmtParseInfo) {
- TVector<NYql::TAstParseResult> results;
- TVector<TStmtParseInfo> stmtParseInfos;
- TConverter converter(results, settings, query, &stmtParseInfos, false, Nothing());
- NYql::PGParse(query, converter);
- if (stmtParseInfo) {
- Y_ENSURE(!stmtParseInfos.empty());
- *stmtParseInfo = stmtParseInfos.back();
- }
- Y_ENSURE(!results.empty());
- results.back().ActualSyntaxType = NYql::ESyntaxType::Pg;
- return std::move(results.back());
- }
- TVector<NYql::TAstParseResult> PGToYqlStatements(const TString& query, const NSQLTranslation::TTranslationSettings& settings, TVector<TStmtParseInfo>* stmtParseInfo) {
- TVector<NYql::TAstParseResult> results;
- TConverter converter(results, settings, query, stmtParseInfo, true, Nothing());
- NYql::PGParse(query, converter);
- for (auto& res : results) {
- res.ActualSyntaxType = NYql::ESyntaxType::Pg;
- }
- return results;
- }
- bool ParseTypeName(const PG_TypeName* typeName, TString& value, bool* setOf = nullptr) {
- auto len = ListLength(typeName->names);
- if (len < 1 || len > 2) {
- return false;
- }
- if (len == 2) {
- auto schemaStr = to_lower(TString(StrVal(ListNodeNth(typeName->names, 0))));
- if (schemaStr != "pg_catalog") {
- return false;
- }
- }
- value = to_lower(TString(StrVal(ListNodeNth(typeName->names, len - 1))));
- if (ListLength(typeName->arrayBounds) && !value.StartsWith('_')) {
- value = "_" + value;
- }
- if (!setOf && typeName->setof) {
- return false;
- }
- if (setOf) {
- *setOf = typeName->setof;
- }
- return true;
- }
- bool ParseCreateFunctionStmtImpl(const CreateFunctionStmt* value, ui32 extensionIndex,
- NPg::IExtensionSqlBuilder* builder, NYql::NPg::TProcDesc& desc) {
- if (ListLength(value->funcname) != 1) {
- return false;
- }
- auto nameNode = ListNodeNth(value->funcname, 0);
- auto name = to_lower(TString(StrVal(nameNode)));
- desc.ExtensionIndex = extensionIndex;
- desc.Name = name;
- desc.IsStrict = false;
- if (value->returnType) {
- TString resultTypeStr;
- if (!ParseTypeName(value->returnType, resultTypeStr, &desc.ReturnSet)) {
- return false;
- }
- if (builder) {
- builder->PrepareType(extensionIndex, resultTypeStr);
- }
- desc.ResultType = NPg::LookupType(resultTypeStr).TypeId;
- } else {
- desc.ResultType = NPg::LookupType("record").TypeId;
- }
- for (ui32 pass = 0; pass < 2; ++pass) {
- for (int i = 0; i < ListLength(value->options); ++i) {
- auto node = LIST_CAST_NTH(DefElem, value->options, i);
- TString defnameStr(node->defname);
- if (pass == 1 && defnameStr == "as") {
- auto asList = CAST_NODE(List, node->arg);
- auto asListLen = ListLength(asList);
- if (desc.Lang == NPg::LangC) {
- if (asListLen < 1 || asListLen > 2) {
- return false;
- }
- auto extStr = TString(StrVal(ListNodeNth(asList, 0)));
- auto srcStr = asListLen > 1 ?
- TString(StrVal(ListNodeNth(asList, 1))) :
- name;
- Y_ENSURE(extensionIndex == NPg::LookupExtensionByInstallName(extStr));
- desc.Src = srcStr;
- } else if (desc.Lang == NPg::LangInternal || desc.Lang == NPg::LangSQL) {
- if (asListLen != 1) {
- return false;
- }
- auto srcStr = TString(StrVal(ListNodeNth(asList, 0)));
- desc.Src = srcStr;
- }
- } else if (pass == 0 && defnameStr == "strict") {
- desc.IsStrict = BoolVal(node->arg);
- } else if (pass == 0 && defnameStr == "language") {
- auto langStr = to_lower(TString(StrVal(node->arg)));
- if (langStr == "c") {
- desc.Lang = NPg::LangC;
- } else if (extensionIndex == 0 && langStr == "internal") {
- desc.Lang = NPg::LangInternal;
- } else if (langStr == "sql") {
- desc.Lang = NPg::LangSQL;
- } else {
- return false;
- }
- }
- }
- }
- bool hasArgNames = false;
- for (int i = 0; i < ListLength(value->parameters); ++i) {
- auto node = LIST_CAST_NTH(FunctionParameter, value->parameters, i);
- hasArgNames = hasArgNames || (node->name != nullptr);
- if (node->mode == FUNC_PARAM_IN || node->mode == FUNC_PARAM_DEFAULT) {
- if (node->defexpr) {
- desc.DefaultArgs.emplace_back();
- auto& value = desc.DefaultArgs.back();
- auto expr = node->defexpr;
- if (NodeTag(expr) == T_TypeCast) {
- expr = CAST_NODE(TypeCast, expr)->arg;
- }
- if (NodeTag(expr) != T_A_Const) {
- return false;
- }
- auto pgConst = GetValueNType(CAST_NODE(A_Const, expr));
- if (!pgConst) {
- return false;
- }
- value = pgConst->value;
- } else {
- Y_ENSURE(desc.DefaultArgs.empty());
- }
- desc.InputArgNames.push_back(node->name ? node->name : "");
- } else if (node->mode == FUNC_PARAM_OUT) {
- desc.OutputArgNames.push_back(node->name ? node->name : "");
- } else if (node->mode == FUNC_PARAM_VARIADIC) {
- desc.VariadicArgName = node->name ? node->name : "";
- } else {
- return false;
- }
- TString argTypeStr;
- if (!ParseTypeName(node->argType, argTypeStr)) {
- return false;
- }
- if (builder) {
- builder->PrepareType(extensionIndex, argTypeStr);
- }
- const auto& argTypeDesc = NPg::LookupType(argTypeStr);
- if (node->mode == FUNC_PARAM_IN || node->mode == FUNC_PARAM_DEFAULT) {
- desc.ArgTypes.push_back(argTypeDesc.TypeId);
- } else if (node->mode == FUNC_PARAM_VARIADIC) {
- desc.VariadicType = (argTypeDesc.ArrayTypeId == argTypeDesc.TypeId) ? argTypeDesc.ElementTypeId : argTypeDesc.TypeId;
- desc.VariadicArgType = argTypeDesc.TypeId;
- } else if (node->mode == FUNC_PARAM_OUT) {
- desc.OutputArgTypes.push_back(argTypeDesc.TypeId);
- }
- }
- if (!hasArgNames) {
- desc.InputArgNames.clear();
- desc.VariadicArgName.clear();
- desc.OutputArgNames.clear();
- }
- if (desc.Lang == NPg::LangSQL) {
- auto parser = NPg::GetSqlLanguageParser();
- if (!value->sql_body) {
- if (parser) {
- parser->Parse(desc.Src, desc);
- } else {
- return false;
- }
- } else {
- if (parser) {
- parser->ParseNode(value->sql_body, desc);
- } else {
- return false;
- }
- }
- if (!desc.ExprNode) {
- return false;
- }
- }
- return true;
- }
- class TExtensionHandler : public IPGParseEvents {
- public:
- TExtensionHandler(ui32 extensionIndex, NYql::NPg::IExtensionSqlBuilder& builder)
- : ExtensionIndex(extensionIndex)
- , Builder(builder)
- {}
- void OnResult(const List* raw) final {
- for (int i = 0; i < ListLength(raw); ++i) {
- if (!ParseRawStmt(LIST_CAST_NTH(RawStmt, raw, i))) {
- continue;
- }
- }
- }
- void OnError(const TIssue& issue) final {
- throw yexception() << "Can't parse extension DDL: " << issue.ToString();
- }
- [[nodiscard]]
- bool ParseRawStmt(const RawStmt* value) {
- auto node = value->stmt;
- switch (NodeTag(node)) {
- case T_CreateFunctionStmt:
- return ParseCreateFunctionStmt(CAST_NODE(CreateFunctionStmt, node));
- case T_DefineStmt:
- return ParseDefineStmt(CAST_NODE(DefineStmt, node));
- case T_CreateStmt:
- return ParseCreateStmt(CAST_NODE(CreateStmt, node));
- case T_InsertStmt:
- return ParseInsertStmt(CAST_NODE(InsertStmt, node));
- case T_CreateCastStmt:
- return ParseCreateCastStmt(CAST_NODE(CreateCastStmt, node));
- case T_CreateOpClassStmt:
- return ParseCreateOpClassStmt(CAST_NODE(CreateOpClassStmt, node));
- default:
- return false;
- }
- }
- [[nodiscard]]
- bool ParseDefineStmt(const DefineStmt* value) {
- switch (value->kind) {
- case OBJECT_TYPE:
- return ParseDefineType(value);
- case OBJECT_OPERATOR:
- return ParseDefineOperator(value);
- case OBJECT_AGGREGATE:
- return ParseDefineAggregate(value);
- default:
- return false;
- }
- }
- [[nodiscard]]
- bool ParseDefineType(const DefineStmt* value) {
- if (ListLength(value->defnames) != 1) {
- return false;
- }
- auto nameNode = ListNodeNth(value->defnames, 0);
- auto name = to_lower(TString(StrVal(nameNode)));
- Builder.PrepareType(ExtensionIndex, name);
- NPg::TTypeDesc desc = NPg::LookupType(name);
- for (int i = 0; i < ListLength(value->definition); ++i) {
- auto node = LIST_CAST_NTH(DefElem, value->definition, i);
- auto defnameStr = to_lower(TString(node->defname));
- if (defnameStr == "internallength") {
- if (NodeTag(node->arg) == T_Integer) {
- desc.TypeLen = IntVal(node->arg);
- } else if (NodeTag(node->arg) == T_TypeName) {
- TString value;
- if (!ParseTypeName(CAST_NODE_EXT(PG_TypeName, T_TypeName, node->arg), value)) {
- return false;
- }
- if (value == "variable") {
- desc.TypeLen = -1;
- } else {
- return false;
- }
- } else {
- return false;
- }
- } else if (defnameStr == "alignment") {
- if (NodeTag(node->arg) != T_TypeName) {
- return false;
- }
- TString value;
- if (!ParseTypeName(CAST_NODE_EXT(PG_TypeName, T_TypeName, node->arg), value)) {
- return false;
- }
- if (value == "double") {
- desc.TypeAlign = 'd';
- } else if (value == "int") {
- desc.TypeAlign = 'i';
- } else if (value == "short") {
- desc.TypeAlign = 's';
- } else if (value == "char") {
- desc.TypeAlign = 'c';
- } else {
- throw yexception() << "Unsupported alignment: " << value;
- }
- } else if (defnameStr == "input") {
- if (NodeTag(node->arg) != T_TypeName) {
- return false;
- }
- TString value;
- if (!ParseTypeName(CAST_NODE_EXT(PG_TypeName, T_TypeName, node->arg), value)) {
- return false;
- }
- try {
- desc.InFuncId = NPg::LookupProc(value, {NPg::LookupType("cstring").TypeId}).ProcId;
- } catch (const yexception&) {
- desc.InFuncId = NPg::LookupProc(value, {
- NPg::LookupType("cstring").TypeId,
- NPg::LookupType("oid").TypeId,
- NPg::LookupType("integer").TypeId
- }).ProcId;
- }
- } else if (defnameStr == "output") {
- if (NodeTag(node->arg) != T_TypeName) {
- return false;
- }
- TString value;
- if (!ParseTypeName(CAST_NODE_EXT(PG_TypeName, T_TypeName, node->arg), value)) {
- return false;
- }
- desc.OutFuncId = NPg::LookupProc(value, {desc.TypeId}).ProcId;
- } else if (defnameStr == "send") {
- if (NodeTag(node->arg) != T_TypeName) {
- return false;
- }
- TString value;
- if (!ParseTypeName(CAST_NODE_EXT(PG_TypeName, T_TypeName, node->arg), value)) {
- return false;
- }
- desc.SendFuncId = NPg::LookupProc(value, {desc.TypeId}).ProcId;
- } else if (defnameStr == "receive") {
- if (NodeTag(node->arg) != T_TypeName) {
- return false;
- }
- TString value;
- if (!ParseTypeName(CAST_NODE_EXT(PG_TypeName, T_TypeName, node->arg), value)) {
- return false;
- }
- try {
- desc.ReceiveFuncId = NPg::LookupProc(value, {NPg::LookupType("internal").TypeId}).ProcId;
- } catch (const yexception&) {
- desc.ReceiveFuncId = NPg::LookupProc(value, {
- NPg::LookupType("internal").TypeId,
- NPg::LookupType("oid").TypeId,
- NPg::LookupType("integer").TypeId
- }).ProcId;
- }
- } else if (defnameStr == "delimiter") {
- if (NodeTag(node->arg) != T_String) {
- return false;
- }
- TString value(StrVal(node->arg));
- Y_ENSURE(value.size() == 1);
- desc.TypeDelim = value[0];
- } else if (defnameStr == "typmod_in") {
- if (NodeTag(node->arg) != T_TypeName) {
- return false;
- }
- TString value;
- if (!ParseTypeName(CAST_NODE_EXT(PG_TypeName, T_TypeName, node->arg), value)) {
- return false;
- }
- desc.TypeModInFuncId = NPg::LookupProc(value, {NPg::LookupType("_cstring").TypeId}).ProcId;
- } else if (defnameStr == "typmod_out") {
- if (NodeTag(node->arg) != T_TypeName) {
- return false;
- }
- TString value;
- if (!ParseTypeName(CAST_NODE_EXT(PG_TypeName, T_TypeName, node->arg), value)) {
- return false;
- }
- desc.TypeModInFuncId = NPg::LookupProc(value, {NPg::LookupType("int4").TypeId}).ProcId;
- }
- }
- if (desc.TypeLen >= 0 && desc.TypeLen <= 8) {
- desc.PassByValue = true;
- }
- Builder.UpdateType(desc);
- return true;
- }
- [[nodiscard]]
- bool ParseDefineOperator(const DefineStmt* value) {
- if (ListLength(value->defnames) != 1) {
- return false;
- }
- auto nameNode = ListNodeNth(value->defnames, 0);
- auto name = to_lower(TString(StrVal(nameNode)));
- TString procedureName;
- TString commutator;
- TString negator;
- ui32 leftType = 0;
- ui32 rightType = 0;
- for (int i = 0; i < ListLength(value->definition); ++i) {
- auto node = LIST_CAST_NTH(DefElem, value->definition, i);
- auto defnameStr = to_lower(TString(node->defname));
- if (defnameStr == "leftarg") {
- if (NodeTag(node->arg) != T_TypeName) {
- return false;
- }
- TString value;
- if (!ParseTypeName(CAST_NODE_EXT(PG_TypeName, T_TypeName, node->arg), value)) {
- return false;
- }
- leftType = NPg::LookupType(value).TypeId;
- } else if (defnameStr == "rightarg") {
- if (NodeTag(node->arg) != T_TypeName) {
- return false;
- }
- TString value;
- if (!ParseTypeName(CAST_NODE_EXT(PG_TypeName, T_TypeName, node->arg), value)) {
- return false;
- }
- rightType = NPg::LookupType(value).TypeId;
- } else if (defnameStr == "procedure") {
- if (NodeTag(node->arg) != T_TypeName) {
- return false;
- }
- TString value;
- if (!ParseTypeName(CAST_NODE_EXT(PG_TypeName, T_TypeName, node->arg), value)) {
- return false;
- }
- procedureName = value;
- } else if (defnameStr == "commutator") {
- if (NodeTag(node->arg) != T_String) {
- return false;
- }
- commutator = StrVal(node->arg);
- } else if (defnameStr == "negator") {
- if (NodeTag(node->arg) != T_String) {
- return false;
- }
- negator = StrVal(node->arg);
- }
- }
- if (!leftType) {
- return false;
- }
- if (procedureName.empty()) {
- return false;
- }
- TVector<ui32> args;
- args.push_back(leftType);
- if (rightType) {
- args.push_back(rightType);
- }
- Builder.PrepareOper(ExtensionIndex, name, args);
- auto desc = NPg::LookupOper(name, args);
- if (!commutator.empty()) {
- TVector<ui32> commArgs;
- commArgs.push_back(rightType);
- commArgs.push_back(leftType);
- Builder.PrepareOper(ExtensionIndex, commutator, commArgs);
- desc.ComId = NPg::LookupOper(commutator, commArgs).OperId;
- }
- if (!negator.empty()) {
- Builder.PrepareOper(ExtensionIndex, negator, args);
- desc.NegateId = NPg::LookupOper(negator, args).OperId;
- }
- const auto& procDesc = NPg::LookupProc(procedureName, args);
- desc.ProcId = procDesc.ProcId;
- desc.ResultType = procDesc.ResultType;
- Builder.UpdateOper(desc);
- return true;
- }
- [[nodiscard]]
- bool ParseDefineAggregate(const DefineStmt* value) {
- if (ListLength(value->defnames) != 1) {
- return false;
- }
- auto nameNode = ListNodeNth(value->defnames, 0);
- auto name = to_lower(TString(StrVal(nameNode)));
- TString sfunc;
- ui32 stype = 0;
- TString combinefunc;
- TString finalfunc;
- TString serialfunc;
- TString deserialfunc;
- bool hypothetical = false;
- for (int i = 0; i < ListLength(value->definition); ++i) {
- auto node = LIST_CAST_NTH(DefElem, value->definition, i);
- auto defnameStr = to_lower(TString(node->defname));
- if (defnameStr == "sfunc") {
- if (NodeTag(node->arg) != T_TypeName) {
- return false;
- }
- TString value;
- if (!ParseTypeName(CAST_NODE_EXT(PG_TypeName, T_TypeName, node->arg), value)) {
- return false;
- }
- sfunc = value;
- } else if (defnameStr == "stype") {
- if (NodeTag(node->arg) != T_TypeName) {
- return false;
- }
- TString value;
- if (!ParseTypeName(CAST_NODE_EXT(PG_TypeName, T_TypeName, node->arg), value)) {
- return false;
- }
- stype = NPg::LookupType(value).TypeId;
- } else if (defnameStr == "combinefunc") {
- if (NodeTag(node->arg) != T_TypeName) {
- return false;
- }
- TString value;
- if (!ParseTypeName(CAST_NODE_EXT(PG_TypeName, T_TypeName, node->arg), value)) {
- return false;
- }
- combinefunc = value;
- } else if (defnameStr == "finalfunc") {
- if (NodeTag(node->arg) != T_TypeName) {
- return false;
- }
- TString value;
- if (!ParseTypeName(CAST_NODE_EXT(PG_TypeName, T_TypeName, node->arg), value)) {
- return false;
- }
- finalfunc = value;
- } else if (defnameStr == "serialfunc") {
- if (NodeTag(node->arg) != T_TypeName) {
- return false;
- }
- TString value;
- if (!ParseTypeName(CAST_NODE_EXT(PG_TypeName, T_TypeName, node->arg), value)) {
- return false;
- }
- serialfunc = value;
- } else if (defnameStr == "deserialfunc") {
- if (NodeTag(node->arg) != T_TypeName) {
- return false;
- }
- TString value;
- if (!ParseTypeName(CAST_NODE_EXT(PG_TypeName, T_TypeName, node->arg), value)) {
- return false;
- }
- deserialfunc = value;
- } else if (defnameStr == "hypothetical") {
- if (NodeTag(node->arg) != T_Boolean) {
- return false;
- }
- if (BoolVal(node->arg)) {
- hypothetical = true;
- }
- }
- }
- if (!sfunc || !stype) {
- return false;
- }
- NPg::TAggregateDesc desc;
- desc.Name = name;
- desc.ExtensionIndex = ExtensionIndex;
- if (ListLength(value->args) != 2) {
- return false;
- }
- auto numDirectArgs = intVal(lsecond(value->args));
- if (numDirectArgs >= 0) {
- desc.NumDirectArgs = numDirectArgs;
- desc.Kind = NPg::EAggKind::OrderedSet;
- Y_ENSURE(!hypothetical);
- } else if (hypothetical) {
- desc.Kind = NPg::EAggKind::Hypothetical;
- }
- auto args = linitial_node(List, value->args);
- for (int i = 0; i < ListLength(args); ++i) {
- auto node = LIST_CAST_NTH(FunctionParameter, args, i);
- if (node->mode == FUNC_PARAM_IN || node->mode == FUNC_PARAM_DEFAULT) {
- if (node->defexpr) {
- return false;
- }
- } else {
- return false;
- }
- TString argTypeStr;
- if (!ParseTypeName(node->argType, argTypeStr)) {
- return false;
- }
- Builder.PrepareType(ExtensionIndex, argTypeStr);
- auto argTypeId = NPg::LookupType(argTypeStr).TypeId;
- desc.ArgTypes.push_back(argTypeId);
- }
- desc.TransTypeId = stype;
- TVector<ui32> stateWithArgs;
- stateWithArgs.push_back(stype);
- stateWithArgs.insert(stateWithArgs.end(), desc.ArgTypes.begin(), desc.ArgTypes.end());
- desc.TransFuncId = NPg::LookupProc(sfunc, stateWithArgs).ProcId;
- if (!finalfunc.empty()) {
- desc.FinalFuncId = NPg::LookupProc(finalfunc, { stype }).ProcId;
- }
- if (!combinefunc.empty()) {
- desc.CombineFuncId = NPg::LookupProc(combinefunc, { stype, stype }).ProcId;
- }
- if (!serialfunc.empty()) {
- const auto& procDesc = NPg::LookupProc(serialfunc, { stype });
- Y_ENSURE(procDesc.ResultType == NPg::LookupType("bytea").TypeId);
- desc.SerializeFuncId = procDesc.ProcId;
- }
- if (!deserialfunc.empty()) {
- Y_ENSURE(!serialfunc.empty());
- const auto& procDesc = NPg::LookupProc(deserialfunc, { NPg::LookupType("bytea").TypeId, stype });
- Y_ENSURE(procDesc.ResultType == stype);
- desc.DeserializeFuncId = procDesc.ProcId;
- }
- Builder.CreateAggregate(desc);
- return true;
- }
- [[nodiscard]]
- bool ParseCreateFunctionStmt(const CreateFunctionStmt* value) {
- NYql::NPg::TProcDesc desc;
- if (!ParseCreateFunctionStmtImpl(value, ExtensionIndex, &Builder, desc)) {
- return false;
- }
- Builder.CreateProc(desc);
- return true;
- }
- [[nodiscard]]
- bool ParseCreateStmt(const CreateStmt* value) {
- NPg::TTableInfo table;
- table.Schema = "pg_catalog";
- table.Name = value->relation->relname;
- table.Kind = NPg::ERelKind::Relation;
- table.ExtensionIndex = ExtensionIndex;
- TVector<NPg::TColumnInfo> columns;
- for (int i = 0; i < ListLength(value->tableElts); ++i) {
- auto node = ListNodeNth(value->tableElts, i);
- if (NodeTag(node) != T_ColumnDef) {
- continue;
- }
- auto columnDef = CAST_NODE(ColumnDef, node);
- NPg::TColumnInfo column;
- column.Schema = table.Schema;
- column.TableName = table.Name;
- column.Name = columnDef->colname;
- column.ExtensionIndex = ExtensionIndex;
- Y_ENSURE(ParseTypeName(columnDef->typeName, column.UdtType));
- columns.push_back(column);
- }
- Builder.CreateTable(table, columns);
- return true;
- }
- [[nodiscard]]
- bool ParseInsertStmt(const InsertStmt* value) {
- TString tableName = value->relation->relname;
- TVector<TString> colNames;
- for (int i = 0; i < ListLength(value->cols); ++i) {
- auto node = LIST_CAST_NTH(ResTarget, value->cols, i);
- colNames.push_back(node->name);
- }
- auto select = CAST_NODE(SelectStmt, value->selectStmt);
- int rows = ListLength(select->valuesLists);
- if (!rows) {
- return false;
- }
- int cols = ListLength(CAST_NODE(List, ListNodeNth(select->valuesLists, 0)));
- TVector<TMaybe<TString>> data;
- data.reserve(rows * cols);
- for (int rowIdx = 0; rowIdx < rows; ++rowIdx) {
- const auto rawRow = CAST_NODE(List, ListNodeNth(select->valuesLists, rowIdx));
- for (int colIdx = 0; colIdx < ListLength(rawRow); ++colIdx) {
- const auto rawCell = ListNodeNth(rawRow, colIdx);
- if (NodeTag(rawCell) != T_A_Const) {
- return false;
- }
- auto pgConst = GetValueNType(CAST_NODE(A_Const, rawCell));
- if (!pgConst) {
- return false;
- }
- data.push_back(pgConst->value);
- }
- }
- Builder.InsertValues(NPg::TTableInfoKey{"pg_catalog", tableName}, colNames, data);
- return true;
- }
- [[nodiscard]]
- bool ParseCreateCastStmt(const CreateCastStmt* value) {
- TString sourceType;
- if (!ParseTypeName(value->sourcetype, sourceType)) {
- return false;
- }
- TString targetType;
- if (!ParseTypeName(value->targettype, targetType)) {
- return false;
- }
- NPg::TCastDesc desc;
- desc.ExtensionIndex = ExtensionIndex;
- desc.SourceId = NPg::LookupType(sourceType).TypeId;
- desc.TargetId = NPg::LookupType(targetType).TypeId;
- if (value->func) {
- if (ListLength(value->func->objname) != 1) {
- return false;
- }
- TString funcName = StrVal(ListNodeNth(value->func->objname, 0));
- TVector<ui32> argTypes;
- for (int i = 0; i < ListLength(value->func->objargs); ++i) {
- auto node = ListNodeNth(value->func->objargs, i);
- if (NodeTag(node) != T_TypeName) {
- return false;
- }
- TString value;
- if (!ParseTypeName(CAST_NODE_EXT(PG_TypeName, T_TypeName, node), value)) {
- return false;
- }
- argTypes.push_back(NPg::LookupType(value).TypeId);
- }
- desc.FunctionId = NPg::LookupProc(funcName, argTypes).ProcId;
- } else if (value->inout) {
- desc.Method = NPg::ECastMethod::InOut;
- } else {
- desc.Method = NPg::ECastMethod::Binary;
- }
- switch (value->context) {
- case COERCION_IMPLICIT:
- desc.CoercionCode = NPg::ECoercionCode::Implicit;
- break;
- case COERCION_ASSIGNMENT:
- desc.CoercionCode = NPg::ECoercionCode::Assignment;
- break;
- case COERCION_EXPLICIT:
- desc.CoercionCode = NPg::ECoercionCode::Explicit;
- break;
- default:
- return false;
- }
- Builder.CreateCast(desc);
- return true;
- }
- [[nodiscard]]
- bool ParseCreateOpClassStmt(const CreateOpClassStmt* value) {
- if (!value->isDefault) {
- return false;
- }
- if (ListLength(value->opclassname) != 1) {
- return false;
- }
- auto opClassName = to_lower(TString(StrVal(ListNodeNth(value->opclassname, 0))));
- if (ListLength(value->opfamilyname) > 1) {
- return false;
- }
- TString familyName;
- if (ListLength(value->opfamilyname) == 1) {
- familyName = to_lower(TString(StrVal(ListNodeNth(value->opfamilyname, 0))));
- }
- auto amName = to_lower(TString(value->amname));
- NPg::EOpClassMethod method;
- if (amName == "btree") {
- method = NPg::EOpClassMethod::Btree;
- } else if (amName == "hash") {
- method = NPg::EOpClassMethod::Hash;
- } else {
- return false;
- }
- TString dataType;
- if (!ParseTypeName(value->datatype, dataType)) {
- return false;
- }
- auto typeId = NPg::LookupType(dataType).TypeId;
- NPg::TOpClassDesc desc;
- desc.ExtensionIndex = ExtensionIndex;
- desc.Method = method;
- desc.TypeId = typeId;
- desc.Name = opClassName;
- if (familyName.empty()) {
- familyName = amName + "/" + opClassName;
- }
- desc.Family = familyName;
- TVector<NPg::TAmOpDesc> ops;
- TVector<NPg::TAmProcDesc> procs;
- for (int i = 0; i < ListLength(value->items); ++i) {
- auto node = LIST_CAST_NTH(CreateOpClassItem, value->items, i);
- if (node->itemtype != OPCLASS_ITEM_OPERATOR && node->itemtype != OPCLASS_ITEM_FUNCTION) {
- continue;
- }
- if (ListLength(node->name->objname) != 1) {
- return false;
- }
- TString funcName = StrVal(ListNodeNth(node->name->objname, 0));
- if (node->itemtype == OPCLASS_ITEM_OPERATOR) {
- NPg::TAmOpDesc amOpDesc;
- amOpDesc.ExtensionIndex = ExtensionIndex;
- amOpDesc.Family = familyName;
- amOpDesc.Strategy = node->number;
- amOpDesc.LeftType = typeId;
- amOpDesc.RightType = typeId;
- amOpDesc.OperId = NPg::LookupOper(funcName, {typeId,typeId}).OperId;
- ops.push_back(amOpDesc);
- } else {
- NPg::TAmProcDesc amProcDesc;
- amProcDesc.ExtensionIndex = ExtensionIndex;
- amProcDesc.Family = familyName;
- amProcDesc.ProcNum = node->number;
- amProcDesc.LeftType = typeId;
- amProcDesc.RightType = typeId;
- TVector<ui32> argTypes;
- for (int i = 0; i < ListLength(node->name->objargs); ++i) {
- auto typeName = ListNodeNth(node->name->objargs, i);
- if (NodeTag(typeName) != T_TypeName) {
- return false;
- }
- TString value;
- if (!ParseTypeName(CAST_NODE_EXT(PG_TypeName, T_TypeName, typeName), value)) {
- return false;
- }
- argTypes.push_back(NPg::LookupType(value).TypeId);
- }
- amProcDesc.ProcId = NPg::LookupProc(funcName, argTypes).ProcId;
- procs.push_back(amProcDesc);
- }
- }
- Builder.CreateOpClass(desc, ops, procs);
- return true;
- }
- private:
- const ui32 ExtensionIndex;
- NYql::NPg::IExtensionSqlBuilder& Builder;
- };
- class TExtensionSqlParser : public NYql::NPg::IExtensionSqlParser {
- public:
- void Parse(ui32 extensionIndex, const TVector<TString>& sqls, NYql::NPg::IExtensionSqlBuilder& builder) final {
- TExtensionHandler handler(extensionIndex, builder);
- for (const auto& sql : sqls) {
- NYql::PGParse(sql, handler);
- }
- NKikimr::NMiniKQL::RebuildTypeIndex();
- }
- };
- class TSystemFunctionsHandler : public IPGParseEvents {
- public:
- TSystemFunctionsHandler(TVector<NPg::TProcDesc>& procs)
- : Procs(procs)
- {}
- void OnResult(const List* raw) final {
- for (int i = 0; i < ListLength(raw); ++i) {
- if (!ParseRawStmt(LIST_CAST_NTH(RawStmt, raw, i))) {
- continue;
- }
- }
- }
- void OnError(const TIssue& issue) final {
- throw yexception() << "Can't parse system functions: " << issue.ToString();
- }
- [[nodiscard]]
- bool ParseRawStmt(const RawStmt* value) {
- auto node = value->stmt;
- switch (NodeTag(node)) {
- case T_CreateFunctionStmt:
- return ParseCreateFunctionStmt(CAST_NODE(CreateFunctionStmt, node));
- default:
- return false;
- }
- }
- [[nodiscard]]
- bool ParseCreateFunctionStmt(const CreateFunctionStmt* value) {
- NYql::NPg::TProcDesc desc;
- if (!ParseCreateFunctionStmtImpl(value, 0, nullptr, desc)) {
- return false;
- }
- Procs.push_back(desc);
- return true;
- }
- private:
- TVector<NPg::TProcDesc>& Procs;
- };
- class TSystemFunctionsParser : public NYql::NPg::ISystemFunctionsParser {
- public:
- void Parse(const TString& sql, TVector<NPg::TProcDesc>& procs) const final {
- TSystemFunctionsHandler handler(procs);
- NYql::PGParse(sql, handler);
- }
- };
- class TSqlLanguageParser : public NYql::NPg::ISqlLanguageParser, public IPGParseEvents {
- public:
- TSqlLanguageParser() {
- Settings.ClusterMapping["pg_catalog"] = TString(PgProviderName);
- Settings.Mode = NSQLTranslation::ESqlMode::LIMITED_VIEW;
- }
- void Parse(const TString& sql, NPg::TProcDesc& proc) final {
- Y_ENSURE(!FreezeGuard.Defined());
- CurrentProc = &proc;
- NYql::PGParse(sql, *this);
- CurrentProc = nullptr;
- }
- void ParseNode(const Node* stmt, NPg::TProcDesc& proc) final {
- Y_ENSURE(!FreezeGuard.Defined());
- proc.ExprNode = nullptr;
- if (proc.VariadicType) {
- // Can't be expressed as usual lambda
- return;
- }
- TVector<NYql::TAstParseResult> results(1);
- results[0].Pool = std::make_unique<TMemoryPool>(4096);
- TVector<TStmtParseInfo> stmtParseInfos(1);
- TConverter converter(results, Settings, "", &stmtParseInfos, false, proc.ArgTypes.size());
- converter.PrepareStatements();
- TAstNode* root = nullptr;
- switch (NodeTag(stmt)) {
- case T_SelectStmt:
- root = converter.ParseSelectStmt(CAST_NODE(SelectStmt, stmt), {.Inner = false});
- break;
- case T_ReturnStmt:
- root = converter.ParseReturnStmt(CAST_NODE(ReturnStmt, stmt));
- break;
- default:
- return;
- }
- if (!root) {
- //Cerr << "Can't parse SQL for function: " << proc.Name << ", " << results[0].Issues.ToString();
- return;
- }
- root = converter.L(converter.A("block"), converter.Q(converter.FinishStatements()));
- if (NodeTag(stmt) == T_SelectStmt) {
- root = converter.AsScalarContext(root);
- }
- TVector<TAstNode*> args;
- for (ui32 i = 0; i < proc.ArgTypes.size(); ++i) {
- args.push_back(converter.A("$p" + ToString(i + 1)));
- }
- root = converter.MakeLambda(args, root);
- auto program = converter.L(converter.L(converter.A("return"), root));
- TExprNode::TPtr graph;
- Ctx.IssueManager.Reset();
- if (!CompileExpr(*program, graph, Ctx, nullptr, nullptr, false, Max<ui32>(), 1)) {
- Cerr << "Can't compile SQL for function: " << proc.Name << ", " << Ctx.IssueManager.GetIssues().ToString();
- return;
- }
- SavedNodes.push_back(graph);
- proc.ExprNode = graph.Get();
- }
- void Freeze() final {
- Y_ENSURE(!FreezeGuard.Defined());
- FreezeGuard.ConstructInPlace(Ctx);
- }
- TExprContext& GetContext() final {
- Y_ENSURE(FreezeGuard.Defined());
- return Ctx;
- }
- void OnResult(const List* raw) final {
- if (ListLength(raw) == 1) {
- ParseNode(LIST_CAST_NTH(RawStmt, raw, 0)->stmt, *CurrentProc);
- }
- }
- void OnError(const TIssue& issue) final {
- throw yexception() << "Can't parse SQL for function: " << CurrentProc->Name << ", " << issue.ToString();
- }
- private:
- NSQLTranslation::TTranslationSettings Settings;
- TExprContext Ctx;
- TVector<TExprNode::TPtr> SavedNodes;
- TMaybe<TExprContext::TFreezeGuard> FreezeGuard;
- NPg::TProcDesc* CurrentProc = nullptr;
- };
- std::unique_ptr<NPg::IExtensionSqlParser> CreateExtensionSqlParser() {
- return std::make_unique<TExtensionSqlParser>();
- }
- std::unique_ptr<NYql::NPg::ISystemFunctionsParser> CreateSystemFunctionsParser() {
- return std::make_unique<TSystemFunctionsParser>();
- }
- std::unique_ptr<NYql::NPg::ISqlLanguageParser> CreateSqlLanguageParser() {
- return std::make_unique<TSqlLanguageParser>();
- }
- class TTranslator : public NSQLTranslation::ITranslator {
- public:
- NSQLTranslation::ILexer::TPtr MakeLexer(const NSQLTranslation::TTranslationSettings& settings) final {
- Y_UNUSED(settings);
- ythrow yexception() << "Unsupported method";
- }
- NYql::TAstParseResult TextToAst(const TString& query, const NSQLTranslation::TTranslationSettings& settings,
- NYql::TWarningRules* warningRules, NYql::TStmtParseInfo* stmtParseInfo) final {
- Y_UNUSED(warningRules);
- return PGToYql(query, settings, stmtParseInfo);
- }
- google::protobuf::Message* TextToMessage(const TString& query, const TString& queryName,
- NYql::TIssues& issues, size_t maxErrors, const NSQLTranslation::TTranslationSettings& settings) final {
- Y_UNUSED(query);
- Y_UNUSED(queryName);
- Y_UNUSED(issues);
- Y_UNUSED(maxErrors);
- Y_UNUSED(settings);
- ythrow yexception() << "Unsupported method";
- }
- NYql::TAstParseResult TextAndMessageToAst(const TString& query, const google::protobuf::Message& protoAst,
- const NSQLTranslation::TSQLHints& hints, const NSQLTranslation::TTranslationSettings& settings) final {
- Y_UNUSED(query);
- Y_UNUSED(protoAst);
- Y_UNUSED(hints);
- Y_UNUSED(settings);
- ythrow yexception() << "Unsupported method";
- }
- TVector<NYql::TAstParseResult> TextToManyAst(const TString& query, const NSQLTranslation::TTranslationSettings& settings,
- NYql::TWarningRules* warningRules, TVector<NYql::TStmtParseInfo>* stmtParseInfo) final {
- Y_UNUSED(warningRules);
- return PGToYqlStatements(query, settings, stmtParseInfo);
- }
- };
- NSQLTranslation::TTranslatorPtr MakeTranslator() {
- return MakeIntrusive<TTranslator>();
- }
- } // NSQLTranslationPG
|