12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425 |
- #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/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>();
- }
- } // NSQLTranslationPG
|