compiler.py 264 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690
  1. # sql/compiler.py
  2. # Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
  3. # <see AUTHORS file>
  4. #
  5. # This module is part of SQLAlchemy and is released under
  6. # the MIT License: https://www.opensource.org/licenses/mit-license.php
  7. # mypy: allow-untyped-defs, allow-untyped-calls
  8. """Base SQL and DDL compiler implementations.
  9. Classes provided include:
  10. :class:`.compiler.SQLCompiler` - renders SQL
  11. strings
  12. :class:`.compiler.DDLCompiler` - renders DDL
  13. (data definition language) strings
  14. :class:`.compiler.GenericTypeCompiler` - renders
  15. type specification strings.
  16. To generate user-defined SQL strings, see
  17. :doc:`/ext/compiler`.
  18. """
  19. from __future__ import annotations
  20. import collections
  21. import collections.abc as collections_abc
  22. import contextlib
  23. from enum import IntEnum
  24. import itertools
  25. import operator
  26. import re
  27. from time import perf_counter
  28. import typing
  29. from typing import Any
  30. from typing import Callable
  31. from typing import cast
  32. from typing import ClassVar
  33. from typing import Dict
  34. from typing import FrozenSet
  35. from typing import Iterable
  36. from typing import Iterator
  37. from typing import List
  38. from typing import Mapping
  39. from typing import MutableMapping
  40. from typing import NamedTuple
  41. from typing import NoReturn
  42. from typing import Optional
  43. from typing import Pattern
  44. from typing import Sequence
  45. from typing import Set
  46. from typing import Tuple
  47. from typing import Type
  48. from typing import TYPE_CHECKING
  49. from typing import Union
  50. from . import base
  51. from . import coercions
  52. from . import crud
  53. from . import elements
  54. from . import functions
  55. from . import operators
  56. from . import roles
  57. from . import schema
  58. from . import selectable
  59. from . import sqltypes
  60. from . import util as sql_util
  61. from ._typing import is_column_element
  62. from ._typing import is_dml
  63. from .base import _de_clone
  64. from .base import _from_objects
  65. from .base import _NONE_NAME
  66. from .base import _SentinelDefaultCharacterization
  67. from .base import Executable
  68. from .base import NO_ARG
  69. from .elements import ClauseElement
  70. from .elements import quoted_name
  71. from .schema import Column
  72. from .sqltypes import TupleType
  73. from .type_api import TypeEngine
  74. from .visitors import prefix_anon_map
  75. from .visitors import Visitable
  76. from .. import exc
  77. from .. import util
  78. from ..util import FastIntFlag
  79. from ..util.typing import Literal
  80. from ..util.typing import Protocol
  81. from ..util.typing import TypedDict
  82. if typing.TYPE_CHECKING:
  83. from .annotation import _AnnotationDict
  84. from .base import _AmbiguousTableNameMap
  85. from .base import CompileState
  86. from .cache_key import CacheKey
  87. from .ddl import ExecutableDDLElement
  88. from .dml import Insert
  89. from .dml import UpdateBase
  90. from .dml import ValuesBase
  91. from .elements import _truncated_label
  92. from .elements import BindParameter
  93. from .elements import ColumnClause
  94. from .elements import ColumnElement
  95. from .elements import Label
  96. from .functions import Function
  97. from .schema import Table
  98. from .selectable import AliasedReturnsRows
  99. from .selectable import CompoundSelectState
  100. from .selectable import CTE
  101. from .selectable import FromClause
  102. from .selectable import NamedFromClause
  103. from .selectable import ReturnsRows
  104. from .selectable import Select
  105. from .selectable import SelectState
  106. from .type_api import _BindProcessorType
  107. from .type_api import _SentinelProcessorType
  108. from ..engine.cursor import CursorResultMetaData
  109. from ..engine.interfaces import _CoreSingleExecuteParams
  110. from ..engine.interfaces import _DBAPIAnyExecuteParams
  111. from ..engine.interfaces import _DBAPIMultiExecuteParams
  112. from ..engine.interfaces import _DBAPISingleExecuteParams
  113. from ..engine.interfaces import _ExecuteOptions
  114. from ..engine.interfaces import _GenericSetInputSizesType
  115. from ..engine.interfaces import _MutableCoreSingleExecuteParams
  116. from ..engine.interfaces import Dialect
  117. from ..engine.interfaces import SchemaTranslateMapType
  118. _FromHintsType = Dict["FromClause", str]
  119. RESERVED_WORDS = {
  120. "all",
  121. "analyse",
  122. "analyze",
  123. "and",
  124. "any",
  125. "array",
  126. "as",
  127. "asc",
  128. "asymmetric",
  129. "authorization",
  130. "between",
  131. "binary",
  132. "both",
  133. "case",
  134. "cast",
  135. "check",
  136. "collate",
  137. "column",
  138. "constraint",
  139. "create",
  140. "cross",
  141. "current_date",
  142. "current_role",
  143. "current_time",
  144. "current_timestamp",
  145. "current_user",
  146. "default",
  147. "deferrable",
  148. "desc",
  149. "distinct",
  150. "do",
  151. "else",
  152. "end",
  153. "except",
  154. "false",
  155. "for",
  156. "foreign",
  157. "freeze",
  158. "from",
  159. "full",
  160. "grant",
  161. "group",
  162. "having",
  163. "ilike",
  164. "in",
  165. "initially",
  166. "inner",
  167. "intersect",
  168. "into",
  169. "is",
  170. "isnull",
  171. "join",
  172. "leading",
  173. "left",
  174. "like",
  175. "limit",
  176. "localtime",
  177. "localtimestamp",
  178. "natural",
  179. "new",
  180. "not",
  181. "notnull",
  182. "null",
  183. "off",
  184. "offset",
  185. "old",
  186. "on",
  187. "only",
  188. "or",
  189. "order",
  190. "outer",
  191. "overlaps",
  192. "placing",
  193. "primary",
  194. "references",
  195. "right",
  196. "select",
  197. "session_user",
  198. "set",
  199. "similar",
  200. "some",
  201. "symmetric",
  202. "table",
  203. "then",
  204. "to",
  205. "trailing",
  206. "true",
  207. "union",
  208. "unique",
  209. "user",
  210. "using",
  211. "verbose",
  212. "when",
  213. "where",
  214. }
  215. LEGAL_CHARACTERS = re.compile(r"^[A-Z0-9_$]+$", re.I)
  216. LEGAL_CHARACTERS_PLUS_SPACE = re.compile(r"^[A-Z0-9_ $]+$", re.I)
  217. ILLEGAL_INITIAL_CHARACTERS = {str(x) for x in range(0, 10)}.union(["$"])
  218. FK_ON_DELETE = re.compile(
  219. r"^(?:RESTRICT|CASCADE|SET NULL|NO ACTION|SET DEFAULT)$", re.I
  220. )
  221. FK_ON_UPDATE = re.compile(
  222. r"^(?:RESTRICT|CASCADE|SET NULL|NO ACTION|SET DEFAULT)$", re.I
  223. )
  224. FK_INITIALLY = re.compile(r"^(?:DEFERRED|IMMEDIATE)$", re.I)
  225. BIND_PARAMS = re.compile(r"(?<![:\w\$\x5c]):([\w\$]+)(?![:\w\$])", re.UNICODE)
  226. BIND_PARAMS_ESC = re.compile(r"\x5c(:[\w\$]*)(?![:\w\$])", re.UNICODE)
  227. _pyformat_template = "%%(%(name)s)s"
  228. BIND_TEMPLATES = {
  229. "pyformat": _pyformat_template,
  230. "qmark": "?",
  231. "format": "%%s",
  232. "numeric": ":[_POSITION]",
  233. "numeric_dollar": "$[_POSITION]",
  234. "named": ":%(name)s",
  235. }
  236. OPERATORS = {
  237. # binary
  238. operators.and_: " AND ",
  239. operators.or_: " OR ",
  240. operators.add: " + ",
  241. operators.mul: " * ",
  242. operators.sub: " - ",
  243. operators.mod: " % ",
  244. operators.neg: "-",
  245. operators.lt: " < ",
  246. operators.le: " <= ",
  247. operators.ne: " != ",
  248. operators.gt: " > ",
  249. operators.ge: " >= ",
  250. operators.eq: " = ",
  251. operators.is_distinct_from: " IS DISTINCT FROM ",
  252. operators.is_not_distinct_from: " IS NOT DISTINCT FROM ",
  253. operators.concat_op: " || ",
  254. operators.match_op: " MATCH ",
  255. operators.not_match_op: " NOT MATCH ",
  256. operators.in_op: " IN ",
  257. operators.not_in_op: " NOT IN ",
  258. operators.comma_op: ", ",
  259. operators.from_: " FROM ",
  260. operators.as_: " AS ",
  261. operators.is_: " IS ",
  262. operators.is_not: " IS NOT ",
  263. operators.collate: " COLLATE ",
  264. # unary
  265. operators.exists: "EXISTS ",
  266. operators.distinct_op: "DISTINCT ",
  267. operators.inv: "NOT ",
  268. operators.any_op: "ANY ",
  269. operators.all_op: "ALL ",
  270. # modifiers
  271. operators.desc_op: " DESC",
  272. operators.asc_op: " ASC",
  273. operators.nulls_first_op: " NULLS FIRST",
  274. operators.nulls_last_op: " NULLS LAST",
  275. # bitwise
  276. operators.bitwise_xor_op: " ^ ",
  277. operators.bitwise_or_op: " | ",
  278. operators.bitwise_and_op: " & ",
  279. operators.bitwise_not_op: "~",
  280. operators.bitwise_lshift_op: " << ",
  281. operators.bitwise_rshift_op: " >> ",
  282. }
  283. FUNCTIONS: Dict[Type[Function[Any]], str] = {
  284. functions.coalesce: "coalesce",
  285. functions.current_date: "CURRENT_DATE",
  286. functions.current_time: "CURRENT_TIME",
  287. functions.current_timestamp: "CURRENT_TIMESTAMP",
  288. functions.current_user: "CURRENT_USER",
  289. functions.localtime: "LOCALTIME",
  290. functions.localtimestamp: "LOCALTIMESTAMP",
  291. functions.random: "random",
  292. functions.sysdate: "sysdate",
  293. functions.session_user: "SESSION_USER",
  294. functions.user: "USER",
  295. functions.cube: "CUBE",
  296. functions.rollup: "ROLLUP",
  297. functions.grouping_sets: "GROUPING SETS",
  298. }
  299. EXTRACT_MAP = {
  300. "month": "month",
  301. "day": "day",
  302. "year": "year",
  303. "second": "second",
  304. "hour": "hour",
  305. "doy": "doy",
  306. "minute": "minute",
  307. "quarter": "quarter",
  308. "dow": "dow",
  309. "week": "week",
  310. "epoch": "epoch",
  311. "milliseconds": "milliseconds",
  312. "microseconds": "microseconds",
  313. "timezone_hour": "timezone_hour",
  314. "timezone_minute": "timezone_minute",
  315. }
  316. COMPOUND_KEYWORDS = {
  317. selectable._CompoundSelectKeyword.UNION: "UNION",
  318. selectable._CompoundSelectKeyword.UNION_ALL: "UNION ALL",
  319. selectable._CompoundSelectKeyword.EXCEPT: "EXCEPT",
  320. selectable._CompoundSelectKeyword.EXCEPT_ALL: "EXCEPT ALL",
  321. selectable._CompoundSelectKeyword.INTERSECT: "INTERSECT",
  322. selectable._CompoundSelectKeyword.INTERSECT_ALL: "INTERSECT ALL",
  323. }
  324. class ResultColumnsEntry(NamedTuple):
  325. """Tracks a column expression that is expected to be represented
  326. in the result rows for this statement.
  327. This normally refers to the columns clause of a SELECT statement
  328. but may also refer to a RETURNING clause, as well as for dialect-specific
  329. emulations.
  330. """
  331. keyname: str
  332. """string name that's expected in cursor.description"""
  333. name: str
  334. """column name, may be labeled"""
  335. objects: Tuple[Any, ...]
  336. """sequence of objects that should be able to locate this column
  337. in a RowMapping. This is typically string names and aliases
  338. as well as Column objects.
  339. """
  340. type: TypeEngine[Any]
  341. """Datatype to be associated with this column. This is where
  342. the "result processing" logic directly links the compiled statement
  343. to the rows that come back from the cursor.
  344. """
  345. class _ResultMapAppender(Protocol):
  346. def __call__(
  347. self,
  348. keyname: str,
  349. name: str,
  350. objects: Sequence[Any],
  351. type_: TypeEngine[Any],
  352. ) -> None:
  353. ...
  354. # integer indexes into ResultColumnsEntry used by cursor.py.
  355. # some profiling showed integer access faster than named tuple
  356. RM_RENDERED_NAME: Literal[0] = 0
  357. RM_NAME: Literal[1] = 1
  358. RM_OBJECTS: Literal[2] = 2
  359. RM_TYPE: Literal[3] = 3
  360. class _BaseCompilerStackEntry(TypedDict):
  361. asfrom_froms: Set[FromClause]
  362. correlate_froms: Set[FromClause]
  363. selectable: ReturnsRows
  364. class _CompilerStackEntry(_BaseCompilerStackEntry, total=False):
  365. compile_state: CompileState
  366. need_result_map_for_nested: bool
  367. need_result_map_for_compound: bool
  368. select_0: ReturnsRows
  369. insert_from_select: Select[Any]
  370. class ExpandedState(NamedTuple):
  371. """represents state to use when producing "expanded" and
  372. "post compile" bound parameters for a statement.
  373. "expanded" parameters are parameters that are generated at
  374. statement execution time to suit a number of parameters passed, the most
  375. prominent example being the individual elements inside of an IN expression.
  376. "post compile" parameters are parameters where the SQL literal value
  377. will be rendered into the SQL statement at execution time, rather than
  378. being passed as separate parameters to the driver.
  379. To create an :class:`.ExpandedState` instance, use the
  380. :meth:`.SQLCompiler.construct_expanded_state` method on any
  381. :class:`.SQLCompiler` instance.
  382. """
  383. statement: str
  384. """String SQL statement with parameters fully expanded"""
  385. parameters: _CoreSingleExecuteParams
  386. """Parameter dictionary with parameters fully expanded.
  387. For a statement that uses named parameters, this dictionary will map
  388. exactly to the names in the statement. For a statement that uses
  389. positional parameters, the :attr:`.ExpandedState.positional_parameters`
  390. will yield a tuple with the positional parameter set.
  391. """
  392. processors: Mapping[str, _BindProcessorType[Any]]
  393. """mapping of bound value processors"""
  394. positiontup: Optional[Sequence[str]]
  395. """Sequence of string names indicating the order of positional
  396. parameters"""
  397. parameter_expansion: Mapping[str, List[str]]
  398. """Mapping representing the intermediary link from original parameter
  399. name to list of "expanded" parameter names, for those parameters that
  400. were expanded."""
  401. @property
  402. def positional_parameters(self) -> Tuple[Any, ...]:
  403. """Tuple of positional parameters, for statements that were compiled
  404. using a positional paramstyle.
  405. """
  406. if self.positiontup is None:
  407. raise exc.InvalidRequestError(
  408. "statement does not use a positional paramstyle"
  409. )
  410. return tuple(self.parameters[key] for key in self.positiontup)
  411. @property
  412. def additional_parameters(self) -> _CoreSingleExecuteParams:
  413. """synonym for :attr:`.ExpandedState.parameters`."""
  414. return self.parameters
  415. class _InsertManyValues(NamedTuple):
  416. """represents state to use for executing an "insertmanyvalues" statement.
  417. The primary consumers of this object are the
  418. :meth:`.SQLCompiler._deliver_insertmanyvalues_batches` and
  419. :meth:`.DefaultDialect._deliver_insertmanyvalues_batches` methods.
  420. .. versionadded:: 2.0
  421. """
  422. is_default_expr: bool
  423. """if True, the statement is of the form
  424. ``INSERT INTO TABLE DEFAULT VALUES``, and can't be rewritten as a "batch"
  425. """
  426. single_values_expr: str
  427. """The rendered "values" clause of the INSERT statement.
  428. This is typically the parenthesized section e.g. "(?, ?, ?)" or similar.
  429. The insertmanyvalues logic uses this string as a search and replace
  430. target.
  431. """
  432. insert_crud_params: List[crud._CrudParamElementStr]
  433. """List of Column / bind names etc. used while rewriting the statement"""
  434. num_positional_params_counted: int
  435. """the number of bound parameters in a single-row statement.
  436. This count may be larger or smaller than the actual number of columns
  437. targeted in the INSERT, as it accommodates for SQL expressions
  438. in the values list that may have zero or more parameters embedded
  439. within them.
  440. This count is part of what's used to organize rewritten parameter lists
  441. when batching.
  442. """
  443. sort_by_parameter_order: bool = False
  444. """if the deterministic_returnined_order parameter were used on the
  445. insert.
  446. All of the attributes following this will only be used if this is True.
  447. """
  448. includes_upsert_behaviors: bool = False
  449. """if True, we have to accommodate for upsert behaviors.
  450. This will in some cases downgrade "insertmanyvalues" that requests
  451. deterministic ordering.
  452. """
  453. sentinel_columns: Optional[Sequence[Column[Any]]] = None
  454. """List of sentinel columns that were located.
  455. This list is only here if the INSERT asked for
  456. sort_by_parameter_order=True,
  457. and dialect-appropriate sentinel columns were located.
  458. .. versionadded:: 2.0.10
  459. """
  460. num_sentinel_columns: int = 0
  461. """how many sentinel columns are in the above list, if any.
  462. This is the same as
  463. ``len(sentinel_columns) if sentinel_columns is not None else 0``
  464. """
  465. sentinel_param_keys: Optional[Sequence[Union[str, int]]] = None
  466. """parameter str keys / int indexes in each param dictionary / tuple
  467. that would link to the client side "sentinel" values for that row, which
  468. we can use to match up parameter sets to result rows.
  469. This is only present if sentinel_columns is present and the INSERT
  470. statement actually refers to client side values for these sentinel
  471. columns.
  472. .. versionadded:: 2.0.10
  473. """
  474. implicit_sentinel: bool = False
  475. """if True, we have exactly one sentinel column and it uses a server side
  476. value, currently has to generate an incrementing integer value.
  477. The dialect in question would have asserted that it supports receiving
  478. these values back and sorting on that value as a means of guaranteeing
  479. correlation with the incoming parameter list.
  480. .. versionadded:: 2.0.10
  481. """
  482. embed_values_counter: bool = False
  483. """Whether to embed an incrementing integer counter in each parameter
  484. set within the VALUES clause as parameters are batched over.
  485. This is only used for a specific INSERT..SELECT..VALUES..RETURNING syntax
  486. where a subquery is used to produce value tuples. Current support
  487. includes PostgreSQL, Microsoft SQL Server.
  488. .. versionadded:: 2.0.10
  489. """
  490. class _InsertManyValuesBatch(NamedTuple):
  491. """represents an individual batch SQL statement for insertmanyvalues.
  492. This is passed through the
  493. :meth:`.SQLCompiler._deliver_insertmanyvalues_batches` and
  494. :meth:`.DefaultDialect._deliver_insertmanyvalues_batches` methods out
  495. to the :class:`.Connection` within the
  496. :meth:`.Connection._exec_insertmany_context` method.
  497. .. versionadded:: 2.0.10
  498. """
  499. replaced_statement: str
  500. replaced_parameters: _DBAPIAnyExecuteParams
  501. processed_setinputsizes: Optional[_GenericSetInputSizesType]
  502. batch: Sequence[_DBAPISingleExecuteParams]
  503. batch_size: int
  504. batchnum: int
  505. total_batches: int
  506. rows_sorted: bool
  507. is_downgraded: bool
  508. class InsertmanyvaluesSentinelOpts(FastIntFlag):
  509. """bitflag enum indicating styles of PK defaults
  510. which can work as implicit sentinel columns
  511. """
  512. NOT_SUPPORTED = 1
  513. AUTOINCREMENT = 2
  514. IDENTITY = 4
  515. SEQUENCE = 8
  516. ANY_AUTOINCREMENT = AUTOINCREMENT | IDENTITY | SEQUENCE
  517. _SUPPORTED_OR_NOT = NOT_SUPPORTED | ANY_AUTOINCREMENT
  518. USE_INSERT_FROM_SELECT = 16
  519. RENDER_SELECT_COL_CASTS = 64
  520. class CompilerState(IntEnum):
  521. COMPILING = 0
  522. """statement is present, compilation phase in progress"""
  523. STRING_APPLIED = 1
  524. """statement is present, string form of the statement has been applied.
  525. Additional processors by subclasses may still be pending.
  526. """
  527. NO_STATEMENT = 2
  528. """compiler does not have a statement to compile, is used
  529. for method access"""
  530. class Linting(IntEnum):
  531. """represent preferences for the 'SQL linting' feature.
  532. this feature currently includes support for flagging cartesian products
  533. in SQL statements.
  534. """
  535. NO_LINTING = 0
  536. "Disable all linting."
  537. COLLECT_CARTESIAN_PRODUCTS = 1
  538. """Collect data on FROMs and cartesian products and gather into
  539. 'self.from_linter'"""
  540. WARN_LINTING = 2
  541. "Emit warnings for linters that find problems"
  542. FROM_LINTING = COLLECT_CARTESIAN_PRODUCTS | WARN_LINTING
  543. """Warn for cartesian products; combines COLLECT_CARTESIAN_PRODUCTS
  544. and WARN_LINTING"""
  545. NO_LINTING, COLLECT_CARTESIAN_PRODUCTS, WARN_LINTING, FROM_LINTING = tuple(
  546. Linting
  547. )
  548. class FromLinter(collections.namedtuple("FromLinter", ["froms", "edges"])):
  549. """represents current state for the "cartesian product" detection
  550. feature."""
  551. def lint(self, start=None):
  552. froms = self.froms
  553. if not froms:
  554. return None, None
  555. edges = set(self.edges)
  556. the_rest = set(froms)
  557. if start is not None:
  558. start_with = start
  559. the_rest.remove(start_with)
  560. else:
  561. start_with = the_rest.pop()
  562. stack = collections.deque([start_with])
  563. while stack and the_rest:
  564. node = stack.popleft()
  565. the_rest.discard(node)
  566. # comparison of nodes in edges here is based on hash equality, as
  567. # there are "annotated" elements that match the non-annotated ones.
  568. # to remove the need for in-python hash() calls, use native
  569. # containment routines (e.g. "node in edge", "edge.index(node)")
  570. to_remove = {edge for edge in edges if node in edge}
  571. # appendleft the node in each edge that is not
  572. # the one that matched.
  573. stack.extendleft(edge[not edge.index(node)] for edge in to_remove)
  574. edges.difference_update(to_remove)
  575. # FROMS left over? boom
  576. if the_rest:
  577. return the_rest, start_with
  578. else:
  579. return None, None
  580. def warn(self, stmt_type="SELECT"):
  581. the_rest, start_with = self.lint()
  582. # FROMS left over? boom
  583. if the_rest:
  584. froms = the_rest
  585. if froms:
  586. template = (
  587. "{stmt_type} statement has a cartesian product between "
  588. "FROM element(s) {froms} and "
  589. 'FROM element "{start}". Apply join condition(s) '
  590. "between each element to resolve."
  591. )
  592. froms_str = ", ".join(
  593. f'"{self.froms[from_]}"' for from_ in froms
  594. )
  595. message = template.format(
  596. stmt_type=stmt_type,
  597. froms=froms_str,
  598. start=self.froms[start_with],
  599. )
  600. util.warn(message)
  601. class Compiled:
  602. """Represent a compiled SQL or DDL expression.
  603. The ``__str__`` method of the ``Compiled`` object should produce
  604. the actual text of the statement. ``Compiled`` objects are
  605. specific to their underlying database dialect, and also may
  606. or may not be specific to the columns referenced within a
  607. particular set of bind parameters. In no case should the
  608. ``Compiled`` object be dependent on the actual values of those
  609. bind parameters, even though it may reference those values as
  610. defaults.
  611. """
  612. statement: Optional[ClauseElement] = None
  613. "The statement to compile."
  614. string: str = ""
  615. "The string representation of the ``statement``"
  616. state: CompilerState
  617. """description of the compiler's state"""
  618. is_sql = False
  619. is_ddl = False
  620. _cached_metadata: Optional[CursorResultMetaData] = None
  621. _result_columns: Optional[List[ResultColumnsEntry]] = None
  622. schema_translate_map: Optional[SchemaTranslateMapType] = None
  623. execution_options: _ExecuteOptions = util.EMPTY_DICT
  624. """
  625. Execution options propagated from the statement. In some cases,
  626. sub-elements of the statement can modify these.
  627. """
  628. preparer: IdentifierPreparer
  629. _annotations: _AnnotationDict = util.EMPTY_DICT
  630. compile_state: Optional[CompileState] = None
  631. """Optional :class:`.CompileState` object that maintains additional
  632. state used by the compiler.
  633. Major executable objects such as :class:`_expression.Insert`,
  634. :class:`_expression.Update`, :class:`_expression.Delete`,
  635. :class:`_expression.Select` will generate this
  636. state when compiled in order to calculate additional information about the
  637. object. For the top level object that is to be executed, the state can be
  638. stored here where it can also have applicability towards result set
  639. processing.
  640. .. versionadded:: 1.4
  641. """
  642. dml_compile_state: Optional[CompileState] = None
  643. """Optional :class:`.CompileState` assigned at the same point that
  644. .isinsert, .isupdate, or .isdelete is assigned.
  645. This will normally be the same object as .compile_state, with the
  646. exception of cases like the :class:`.ORMFromStatementCompileState`
  647. object.
  648. .. versionadded:: 1.4.40
  649. """
  650. cache_key: Optional[CacheKey] = None
  651. """The :class:`.CacheKey` that was generated ahead of creating this
  652. :class:`.Compiled` object.
  653. This is used for routines that need access to the original
  654. :class:`.CacheKey` instance generated when the :class:`.Compiled`
  655. instance was first cached, typically in order to reconcile
  656. the original list of :class:`.BindParameter` objects with a
  657. per-statement list that's generated on each call.
  658. """
  659. _gen_time: float
  660. """Generation time of this :class:`.Compiled`, used for reporting
  661. cache stats."""
  662. def __init__(
  663. self,
  664. dialect: Dialect,
  665. statement: Optional[ClauseElement],
  666. schema_translate_map: Optional[SchemaTranslateMapType] = None,
  667. render_schema_translate: bool = False,
  668. compile_kwargs: Mapping[str, Any] = util.immutabledict(),
  669. ):
  670. """Construct a new :class:`.Compiled` object.
  671. :param dialect: :class:`.Dialect` to compile against.
  672. :param statement: :class:`_expression.ClauseElement` to be compiled.
  673. :param schema_translate_map: dictionary of schema names to be
  674. translated when forming the resultant SQL
  675. .. seealso::
  676. :ref:`schema_translating`
  677. :param compile_kwargs: additional kwargs that will be
  678. passed to the initial call to :meth:`.Compiled.process`.
  679. """
  680. self.dialect = dialect
  681. self.preparer = self.dialect.identifier_preparer
  682. if schema_translate_map:
  683. self.schema_translate_map = schema_translate_map
  684. self.preparer = self.preparer._with_schema_translate(
  685. schema_translate_map
  686. )
  687. if statement is not None:
  688. self.state = CompilerState.COMPILING
  689. self.statement = statement
  690. self.can_execute = statement.supports_execution
  691. self._annotations = statement._annotations
  692. if self.can_execute:
  693. if TYPE_CHECKING:
  694. assert isinstance(statement, Executable)
  695. self.execution_options = statement._execution_options
  696. self.string = self.process(self.statement, **compile_kwargs)
  697. if render_schema_translate:
  698. self.string = self.preparer._render_schema_translates(
  699. self.string, schema_translate_map
  700. )
  701. self.state = CompilerState.STRING_APPLIED
  702. else:
  703. self.state = CompilerState.NO_STATEMENT
  704. self._gen_time = perf_counter()
  705. def __init_subclass__(cls) -> None:
  706. cls._init_compiler_cls()
  707. return super().__init_subclass__()
  708. @classmethod
  709. def _init_compiler_cls(cls):
  710. pass
  711. def _execute_on_connection(
  712. self, connection, distilled_params, execution_options
  713. ):
  714. if self.can_execute:
  715. return connection._execute_compiled(
  716. self, distilled_params, execution_options
  717. )
  718. else:
  719. raise exc.ObjectNotExecutableError(self.statement)
  720. def visit_unsupported_compilation(self, element, err, **kw):
  721. raise exc.UnsupportedCompilationError(self, type(element)) from err
  722. @property
  723. def sql_compiler(self):
  724. """Return a Compiled that is capable of processing SQL expressions.
  725. If this compiler is one, it would likely just return 'self'.
  726. """
  727. raise NotImplementedError()
  728. def process(self, obj: Visitable, **kwargs: Any) -> str:
  729. return obj._compiler_dispatch(self, **kwargs)
  730. def __str__(self) -> str:
  731. """Return the string text of the generated SQL or DDL."""
  732. if self.state is CompilerState.STRING_APPLIED:
  733. return self.string
  734. else:
  735. return ""
  736. def construct_params(
  737. self,
  738. params: Optional[_CoreSingleExecuteParams] = None,
  739. extracted_parameters: Optional[Sequence[BindParameter[Any]]] = None,
  740. escape_names: bool = True,
  741. ) -> Optional[_MutableCoreSingleExecuteParams]:
  742. """Return the bind params for this compiled object.
  743. :param params: a dict of string/object pairs whose values will
  744. override bind values compiled in to the
  745. statement.
  746. """
  747. raise NotImplementedError()
  748. @property
  749. def params(self):
  750. """Return the bind params for this compiled object."""
  751. return self.construct_params()
  752. class TypeCompiler(util.EnsureKWArg):
  753. """Produces DDL specification for TypeEngine objects."""
  754. ensure_kwarg = r"visit_\w+"
  755. def __init__(self, dialect: Dialect):
  756. self.dialect = dialect
  757. def process(self, type_: TypeEngine[Any], **kw: Any) -> str:
  758. if (
  759. type_._variant_mapping
  760. and self.dialect.name in type_._variant_mapping
  761. ):
  762. type_ = type_._variant_mapping[self.dialect.name]
  763. return type_._compiler_dispatch(self, **kw)
  764. def visit_unsupported_compilation(
  765. self, element: Any, err: Exception, **kw: Any
  766. ) -> NoReturn:
  767. raise exc.UnsupportedCompilationError(self, element) from err
  768. # this was a Visitable, but to allow accurate detection of
  769. # column elements this is actually a column element
  770. class _CompileLabel(
  771. roles.BinaryElementRole[Any], elements.CompilerColumnElement
  772. ):
  773. """lightweight label object which acts as an expression.Label."""
  774. __visit_name__ = "label"
  775. __slots__ = "element", "name", "_alt_names"
  776. def __init__(self, col, name, alt_names=()):
  777. self.element = col
  778. self.name = name
  779. self._alt_names = (col,) + alt_names
  780. @property
  781. def proxy_set(self):
  782. return self.element.proxy_set
  783. @property
  784. def type(self):
  785. return self.element.type
  786. def self_group(self, **kw):
  787. return self
  788. class ilike_case_insensitive(
  789. roles.BinaryElementRole[Any], elements.CompilerColumnElement
  790. ):
  791. """produce a wrapping element for a case-insensitive portion of
  792. an ILIKE construct.
  793. The construct usually renders the ``lower()`` function, but on
  794. PostgreSQL will pass silently with the assumption that "ILIKE"
  795. is being used.
  796. .. versionadded:: 2.0
  797. """
  798. __visit_name__ = "ilike_case_insensitive_operand"
  799. __slots__ = "element", "comparator"
  800. def __init__(self, element):
  801. self.element = element
  802. self.comparator = element.comparator
  803. @property
  804. def proxy_set(self):
  805. return self.element.proxy_set
  806. @property
  807. def type(self):
  808. return self.element.type
  809. def self_group(self, **kw):
  810. return self
  811. def _with_binary_element_type(self, type_):
  812. return ilike_case_insensitive(
  813. self.element._with_binary_element_type(type_)
  814. )
  815. class SQLCompiler(Compiled):
  816. """Default implementation of :class:`.Compiled`.
  817. Compiles :class:`_expression.ClauseElement` objects into SQL strings.
  818. """
  819. extract_map = EXTRACT_MAP
  820. bindname_escape_characters: ClassVar[
  821. Mapping[str, str]
  822. ] = util.immutabledict(
  823. {
  824. "%": "P",
  825. "(": "A",
  826. ")": "Z",
  827. ":": "C",
  828. ".": "_",
  829. "[": "_",
  830. "]": "_",
  831. " ": "_",
  832. }
  833. )
  834. """A mapping (e.g. dict or similar) containing a lookup of
  835. characters keyed to replacement characters which will be applied to all
  836. 'bind names' used in SQL statements as a form of 'escaping'; the given
  837. characters are replaced entirely with the 'replacement' character when
  838. rendered in the SQL statement, and a similar translation is performed
  839. on the incoming names used in parameter dictionaries passed to methods
  840. like :meth:`_engine.Connection.execute`.
  841. This allows bound parameter names used in :func:`_sql.bindparam` and
  842. other constructs to have any arbitrary characters present without any
  843. concern for characters that aren't allowed at all on the target database.
  844. Third party dialects can establish their own dictionary here to replace the
  845. default mapping, which will ensure that the particular characters in the
  846. mapping will never appear in a bound parameter name.
  847. The dictionary is evaluated at **class creation time**, so cannot be
  848. modified at runtime; it must be present on the class when the class
  849. is first declared.
  850. Note that for dialects that have additional bound parameter rules such
  851. as additional restrictions on leading characters, the
  852. :meth:`_sql.SQLCompiler.bindparam_string` method may need to be augmented.
  853. See the cx_Oracle compiler for an example of this.
  854. .. versionadded:: 2.0.0rc1
  855. """
  856. _bind_translate_re: ClassVar[Pattern[str]]
  857. _bind_translate_chars: ClassVar[Mapping[str, str]]
  858. is_sql = True
  859. compound_keywords = COMPOUND_KEYWORDS
  860. isdelete: bool = False
  861. isinsert: bool = False
  862. isupdate: bool = False
  863. """class-level defaults which can be set at the instance
  864. level to define if this Compiled instance represents
  865. INSERT/UPDATE/DELETE
  866. """
  867. postfetch: Optional[List[Column[Any]]]
  868. """list of columns that can be post-fetched after INSERT or UPDATE to
  869. receive server-updated values"""
  870. insert_prefetch: Sequence[Column[Any]] = ()
  871. """list of columns for which default values should be evaluated before
  872. an INSERT takes place"""
  873. update_prefetch: Sequence[Column[Any]] = ()
  874. """list of columns for which onupdate default values should be evaluated
  875. before an UPDATE takes place"""
  876. implicit_returning: Optional[Sequence[ColumnElement[Any]]] = None
  877. """list of "implicit" returning columns for a toplevel INSERT or UPDATE
  878. statement, used to receive newly generated values of columns.
  879. .. versionadded:: 2.0 ``implicit_returning`` replaces the previous
  880. ``returning`` collection, which was not a generalized RETURNING
  881. collection and instead was in fact specific to the "implicit returning"
  882. feature.
  883. """
  884. isplaintext: bool = False
  885. binds: Dict[str, BindParameter[Any]]
  886. """a dictionary of bind parameter keys to BindParameter instances."""
  887. bind_names: Dict[BindParameter[Any], str]
  888. """a dictionary of BindParameter instances to "compiled" names
  889. that are actually present in the generated SQL"""
  890. stack: List[_CompilerStackEntry]
  891. """major statements such as SELECT, INSERT, UPDATE, DELETE are
  892. tracked in this stack using an entry format."""
  893. returning_precedes_values: bool = False
  894. """set to True classwide to generate RETURNING
  895. clauses before the VALUES or WHERE clause (i.e. MSSQL)
  896. """
  897. render_table_with_column_in_update_from: bool = False
  898. """set to True classwide to indicate the SET clause
  899. in a multi-table UPDATE statement should qualify
  900. columns with the table name (i.e. MySQL only)
  901. """
  902. ansi_bind_rules: bool = False
  903. """SQL 92 doesn't allow bind parameters to be used
  904. in the columns clause of a SELECT, nor does it allow
  905. ambiguous expressions like "? = ?". A compiler
  906. subclass can set this flag to False if the target
  907. driver/DB enforces this
  908. """
  909. bindtemplate: str
  910. """template to render bound parameters based on paramstyle."""
  911. compilation_bindtemplate: str
  912. """template used by compiler to render parameters before positional
  913. paramstyle application"""
  914. _numeric_binds_identifier_char: str
  915. """Character that's used to as the identifier of a numerical bind param.
  916. For example if this char is set to ``$``, numerical binds will be rendered
  917. in the form ``$1, $2, $3``.
  918. """
  919. _result_columns: List[ResultColumnsEntry]
  920. """relates label names in the final SQL to a tuple of local
  921. column/label name, ColumnElement object (if any) and
  922. TypeEngine. CursorResult uses this for type processing and
  923. column targeting"""
  924. _textual_ordered_columns: bool = False
  925. """tell the result object that the column names as rendered are important,
  926. but they are also "ordered" vs. what is in the compiled object here.
  927. As of 1.4.42 this condition is only present when the statement is a
  928. TextualSelect, e.g. text("....").columns(...), where it is required
  929. that the columns are considered positionally and not by name.
  930. """
  931. _ad_hoc_textual: bool = False
  932. """tell the result that we encountered text() or '*' constructs in the
  933. middle of the result columns, but we also have compiled columns, so
  934. if the number of columns in cursor.description does not match how many
  935. expressions we have, that means we can't rely on positional at all and
  936. should match on name.
  937. """
  938. _ordered_columns: bool = True
  939. """
  940. if False, means we can't be sure the list of entries
  941. in _result_columns is actually the rendered order. Usually
  942. True unless using an unordered TextualSelect.
  943. """
  944. _loose_column_name_matching: bool = False
  945. """tell the result object that the SQL statement is textual, wants to match
  946. up to Column objects, and may be using the ._tq_label in the SELECT rather
  947. than the base name.
  948. """
  949. _numeric_binds: bool = False
  950. """
  951. True if paramstyle is "numeric". This paramstyle is trickier than
  952. all the others.
  953. """
  954. _render_postcompile: bool = False
  955. """
  956. whether to render out POSTCOMPILE params during the compile phase.
  957. This attribute is used only for end-user invocation of stmt.compile();
  958. it's never used for actual statement execution, where instead the
  959. dialect internals access and render the internal postcompile structure
  960. directly.
  961. """
  962. _post_compile_expanded_state: Optional[ExpandedState] = None
  963. """When render_postcompile is used, the ``ExpandedState`` used to create
  964. the "expanded" SQL is assigned here, and then used by the ``.params``
  965. accessor and ``.construct_params()`` methods for their return values.
  966. .. versionadded:: 2.0.0rc1
  967. """
  968. _pre_expanded_string: Optional[str] = None
  969. """Stores the original string SQL before 'post_compile' is applied,
  970. for cases where 'post_compile' were used.
  971. """
  972. _pre_expanded_positiontup: Optional[List[str]] = None
  973. _insertmanyvalues: Optional[_InsertManyValues] = None
  974. _insert_crud_params: Optional[crud._CrudParamSequence] = None
  975. literal_execute_params: FrozenSet[BindParameter[Any]] = frozenset()
  976. """bindparameter objects that are rendered as literal values at statement
  977. execution time.
  978. """
  979. post_compile_params: FrozenSet[BindParameter[Any]] = frozenset()
  980. """bindparameter objects that are rendered as bound parameter placeholders
  981. at statement execution time.
  982. """
  983. escaped_bind_names: util.immutabledict[str, str] = util.EMPTY_DICT
  984. """Late escaping of bound parameter names that has to be converted
  985. to the original name when looking in the parameter dictionary.
  986. """
  987. has_out_parameters = False
  988. """if True, there are bindparam() objects that have the isoutparam
  989. flag set."""
  990. postfetch_lastrowid = False
  991. """if True, and this in insert, use cursor.lastrowid to populate
  992. result.inserted_primary_key. """
  993. _cache_key_bind_match: Optional[
  994. Tuple[
  995. Dict[
  996. BindParameter[Any],
  997. List[BindParameter[Any]],
  998. ],
  999. Dict[
  1000. str,
  1001. BindParameter[Any],
  1002. ],
  1003. ]
  1004. ] = None
  1005. """a mapping that will relate the BindParameter object we compile
  1006. to those that are part of the extracted collection of parameters
  1007. in the cache key, if we were given a cache key.
  1008. """
  1009. positiontup: Optional[List[str]] = None
  1010. """for a compiled construct that uses a positional paramstyle, will be
  1011. a sequence of strings, indicating the names of bound parameters in order.
  1012. This is used in order to render bound parameters in their correct order,
  1013. and is combined with the :attr:`_sql.Compiled.params` dictionary to
  1014. render parameters.
  1015. This sequence always contains the unescaped name of the parameters.
  1016. .. seealso::
  1017. :ref:`faq_sql_expression_string` - includes a usage example for
  1018. debugging use cases.
  1019. """
  1020. _values_bindparam: Optional[List[str]] = None
  1021. _visited_bindparam: Optional[List[str]] = None
  1022. inline: bool = False
  1023. ctes: Optional[MutableMapping[CTE, str]]
  1024. # Detect same CTE references - Dict[(level, name), cte]
  1025. # Level is required for supporting nesting
  1026. ctes_by_level_name: Dict[Tuple[int, str], CTE]
  1027. # To retrieve key/level in ctes_by_level_name -
  1028. # Dict[cte_reference, (level, cte_name, cte_opts)]
  1029. level_name_by_cte: Dict[CTE, Tuple[int, str, selectable._CTEOpts]]
  1030. ctes_recursive: bool
  1031. _post_compile_pattern = re.compile(r"__\[POSTCOMPILE_(\S+?)(~~.+?~~)?\]")
  1032. _pyformat_pattern = re.compile(r"%\(([^)]+?)\)s")
  1033. _positional_pattern = re.compile(
  1034. f"{_pyformat_pattern.pattern}|{_post_compile_pattern.pattern}"
  1035. )
  1036. @classmethod
  1037. def _init_compiler_cls(cls):
  1038. cls._init_bind_translate()
  1039. @classmethod
  1040. def _init_bind_translate(cls):
  1041. reg = re.escape("".join(cls.bindname_escape_characters))
  1042. cls._bind_translate_re = re.compile(f"[{reg}]")
  1043. cls._bind_translate_chars = cls.bindname_escape_characters
  1044. def __init__(
  1045. self,
  1046. dialect: Dialect,
  1047. statement: Optional[ClauseElement],
  1048. cache_key: Optional[CacheKey] = None,
  1049. column_keys: Optional[Sequence[str]] = None,
  1050. for_executemany: bool = False,
  1051. linting: Linting = NO_LINTING,
  1052. _supporting_against: Optional[SQLCompiler] = None,
  1053. **kwargs: Any,
  1054. ):
  1055. """Construct a new :class:`.SQLCompiler` object.
  1056. :param dialect: :class:`.Dialect` to be used
  1057. :param statement: :class:`_expression.ClauseElement` to be compiled
  1058. :param column_keys: a list of column names to be compiled into an
  1059. INSERT or UPDATE statement.
  1060. :param for_executemany: whether INSERT / UPDATE statements should
  1061. expect that they are to be invoked in an "executemany" style,
  1062. which may impact how the statement will be expected to return the
  1063. values of defaults and autoincrement / sequences and similar.
  1064. Depending on the backend and driver in use, support for retrieving
  1065. these values may be disabled which means SQL expressions may
  1066. be rendered inline, RETURNING may not be rendered, etc.
  1067. :param kwargs: additional keyword arguments to be consumed by the
  1068. superclass.
  1069. """
  1070. self.column_keys = column_keys
  1071. self.cache_key = cache_key
  1072. if cache_key:
  1073. cksm = {b.key: b for b in cache_key[1]}
  1074. ckbm = {b: [b] for b in cache_key[1]}
  1075. self._cache_key_bind_match = (ckbm, cksm)
  1076. # compile INSERT/UPDATE defaults/sequences to expect executemany
  1077. # style execution, which may mean no pre-execute of defaults,
  1078. # or no RETURNING
  1079. self.for_executemany = for_executemany
  1080. self.linting = linting
  1081. # a dictionary of bind parameter keys to BindParameter
  1082. # instances.
  1083. self.binds = {}
  1084. # a dictionary of BindParameter instances to "compiled" names
  1085. # that are actually present in the generated SQL
  1086. self.bind_names = util.column_dict()
  1087. # stack which keeps track of nested SELECT statements
  1088. self.stack = []
  1089. self._result_columns = []
  1090. # true if the paramstyle is positional
  1091. self.positional = dialect.positional
  1092. if self.positional:
  1093. self._numeric_binds = nb = dialect.paramstyle.startswith("numeric")
  1094. if nb:
  1095. self._numeric_binds_identifier_char = (
  1096. "$" if dialect.paramstyle == "numeric_dollar" else ":"
  1097. )
  1098. self.compilation_bindtemplate = _pyformat_template
  1099. else:
  1100. self.compilation_bindtemplate = BIND_TEMPLATES[dialect.paramstyle]
  1101. self.ctes = None
  1102. self.label_length = (
  1103. dialect.label_length or dialect.max_identifier_length
  1104. )
  1105. # a map which tracks "anonymous" identifiers that are created on
  1106. # the fly here
  1107. self.anon_map = prefix_anon_map()
  1108. # a map which tracks "truncated" names based on
  1109. # dialect.label_length or dialect.max_identifier_length
  1110. self.truncated_names: Dict[Tuple[str, str], str] = {}
  1111. self._truncated_counters: Dict[str, int] = {}
  1112. Compiled.__init__(self, dialect, statement, **kwargs)
  1113. if self.isinsert or self.isupdate or self.isdelete:
  1114. if TYPE_CHECKING:
  1115. assert isinstance(statement, UpdateBase)
  1116. if self.isinsert or self.isupdate:
  1117. if TYPE_CHECKING:
  1118. assert isinstance(statement, ValuesBase)
  1119. if statement._inline:
  1120. self.inline = True
  1121. elif self.for_executemany and (
  1122. not self.isinsert
  1123. or (
  1124. self.dialect.insert_executemany_returning
  1125. and statement._return_defaults
  1126. )
  1127. ):
  1128. self.inline = True
  1129. self.bindtemplate = BIND_TEMPLATES[dialect.paramstyle]
  1130. if _supporting_against:
  1131. self.__dict__.update(
  1132. {
  1133. k: v
  1134. for k, v in _supporting_against.__dict__.items()
  1135. if k
  1136. not in {
  1137. "state",
  1138. "dialect",
  1139. "preparer",
  1140. "positional",
  1141. "_numeric_binds",
  1142. "compilation_bindtemplate",
  1143. "bindtemplate",
  1144. }
  1145. }
  1146. )
  1147. if self.state is CompilerState.STRING_APPLIED:
  1148. if self.positional:
  1149. if self._numeric_binds:
  1150. self._process_numeric()
  1151. else:
  1152. self._process_positional()
  1153. if self._render_postcompile:
  1154. parameters = self.construct_params(
  1155. escape_names=False,
  1156. _no_postcompile=True,
  1157. )
  1158. self._process_parameters_for_postcompile(
  1159. parameters, _populate_self=True
  1160. )
  1161. @property
  1162. def insert_single_values_expr(self) -> Optional[str]:
  1163. """When an INSERT is compiled with a single set of parameters inside
  1164. a VALUES expression, the string is assigned here, where it can be
  1165. used for insert batching schemes to rewrite the VALUES expression.
  1166. .. versionadded:: 1.3.8
  1167. .. versionchanged:: 2.0 This collection is no longer used by
  1168. SQLAlchemy's built-in dialects, in favor of the currently
  1169. internal ``_insertmanyvalues`` collection that is used only by
  1170. :class:`.SQLCompiler`.
  1171. """
  1172. if self._insertmanyvalues is None:
  1173. return None
  1174. else:
  1175. return self._insertmanyvalues.single_values_expr
  1176. @util.ro_memoized_property
  1177. def effective_returning(self) -> Optional[Sequence[ColumnElement[Any]]]:
  1178. """The effective "returning" columns for INSERT, UPDATE or DELETE.
  1179. This is either the so-called "implicit returning" columns which are
  1180. calculated by the compiler on the fly, or those present based on what's
  1181. present in ``self.statement._returning`` (expanded into individual
  1182. columns using the ``._all_selected_columns`` attribute) i.e. those set
  1183. explicitly using the :meth:`.UpdateBase.returning` method.
  1184. .. versionadded:: 2.0
  1185. """
  1186. if self.implicit_returning:
  1187. return self.implicit_returning
  1188. elif self.statement is not None and is_dml(self.statement):
  1189. return [
  1190. c
  1191. for c in self.statement._all_selected_columns
  1192. if is_column_element(c)
  1193. ]
  1194. else:
  1195. return None
  1196. @property
  1197. def returning(self):
  1198. """backwards compatibility; returns the
  1199. effective_returning collection.
  1200. """
  1201. return self.effective_returning
  1202. @property
  1203. def current_executable(self):
  1204. """Return the current 'executable' that is being compiled.
  1205. This is currently the :class:`_sql.Select`, :class:`_sql.Insert`,
  1206. :class:`_sql.Update`, :class:`_sql.Delete`,
  1207. :class:`_sql.CompoundSelect` object that is being compiled.
  1208. Specifically it's assigned to the ``self.stack`` list of elements.
  1209. When a statement like the above is being compiled, it normally
  1210. is also assigned to the ``.statement`` attribute of the
  1211. :class:`_sql.Compiler` object. However, all SQL constructs are
  1212. ultimately nestable, and this attribute should never be consulted
  1213. by a ``visit_`` method, as it is not guaranteed to be assigned
  1214. nor guaranteed to correspond to the current statement being compiled.
  1215. .. versionadded:: 1.3.21
  1216. For compatibility with previous versions, use the following
  1217. recipe::
  1218. statement = getattr(self, "current_executable", False)
  1219. if statement is False:
  1220. statement = self.stack[-1]["selectable"]
  1221. For versions 1.4 and above, ensure only .current_executable
  1222. is used; the format of "self.stack" may change.
  1223. """
  1224. try:
  1225. return self.stack[-1]["selectable"]
  1226. except IndexError as ie:
  1227. raise IndexError("Compiler does not have a stack entry") from ie
  1228. @property
  1229. def prefetch(self):
  1230. return list(self.insert_prefetch) + list(self.update_prefetch)
  1231. @util.memoized_property
  1232. def _global_attributes(self) -> Dict[Any, Any]:
  1233. return {}
  1234. @util.memoized_instancemethod
  1235. def _init_cte_state(self) -> MutableMapping[CTE, str]:
  1236. """Initialize collections related to CTEs only if
  1237. a CTE is located, to save on the overhead of
  1238. these collections otherwise.
  1239. """
  1240. # collect CTEs to tack on top of a SELECT
  1241. # To store the query to print - Dict[cte, text_query]
  1242. ctes: MutableMapping[CTE, str] = util.OrderedDict()
  1243. self.ctes = ctes
  1244. # Detect same CTE references - Dict[(level, name), cte]
  1245. # Level is required for supporting nesting
  1246. self.ctes_by_level_name = {}
  1247. # To retrieve key/level in ctes_by_level_name -
  1248. # Dict[cte_reference, (level, cte_name, cte_opts)]
  1249. self.level_name_by_cte = {}
  1250. self.ctes_recursive = False
  1251. return ctes
  1252. @contextlib.contextmanager
  1253. def _nested_result(self):
  1254. """special API to support the use case of 'nested result sets'"""
  1255. result_columns, ordered_columns = (
  1256. self._result_columns,
  1257. self._ordered_columns,
  1258. )
  1259. self._result_columns, self._ordered_columns = [], False
  1260. try:
  1261. if self.stack:
  1262. entry = self.stack[-1]
  1263. entry["need_result_map_for_nested"] = True
  1264. else:
  1265. entry = None
  1266. yield self._result_columns, self._ordered_columns
  1267. finally:
  1268. if entry:
  1269. entry.pop("need_result_map_for_nested")
  1270. self._result_columns, self._ordered_columns = (
  1271. result_columns,
  1272. ordered_columns,
  1273. )
  1274. def _process_positional(self):
  1275. assert not self.positiontup
  1276. assert self.state is CompilerState.STRING_APPLIED
  1277. assert not self._numeric_binds
  1278. if self.dialect.paramstyle == "format":
  1279. placeholder = "%s"
  1280. else:
  1281. assert self.dialect.paramstyle == "qmark"
  1282. placeholder = "?"
  1283. positions = []
  1284. def find_position(m: re.Match[str]) -> str:
  1285. normal_bind = m.group(1)
  1286. if normal_bind:
  1287. positions.append(normal_bind)
  1288. return placeholder
  1289. else:
  1290. # this a post-compile bind
  1291. positions.append(m.group(2))
  1292. return m.group(0)
  1293. self.string = re.sub(
  1294. self._positional_pattern, find_position, self.string
  1295. )
  1296. if self.escaped_bind_names:
  1297. reverse_escape = {v: k for k, v in self.escaped_bind_names.items()}
  1298. assert len(self.escaped_bind_names) == len(reverse_escape)
  1299. self.positiontup = [
  1300. reverse_escape.get(name, name) for name in positions
  1301. ]
  1302. else:
  1303. self.positiontup = positions
  1304. if self._insertmanyvalues:
  1305. positions = []
  1306. single_values_expr = re.sub(
  1307. self._positional_pattern,
  1308. find_position,
  1309. self._insertmanyvalues.single_values_expr,
  1310. )
  1311. insert_crud_params = [
  1312. (
  1313. v[0],
  1314. v[1],
  1315. re.sub(self._positional_pattern, find_position, v[2]),
  1316. v[3],
  1317. )
  1318. for v in self._insertmanyvalues.insert_crud_params
  1319. ]
  1320. sentinel_param_int_idxs = (
  1321. [
  1322. self.positiontup.index(cast(str, _param_key))
  1323. for _param_key in self._insertmanyvalues.sentinel_param_keys # noqa: E501
  1324. ]
  1325. if self._insertmanyvalues.sentinel_param_keys is not None
  1326. else None
  1327. )
  1328. self._insertmanyvalues = self._insertmanyvalues._replace(
  1329. single_values_expr=single_values_expr,
  1330. insert_crud_params=insert_crud_params,
  1331. sentinel_param_keys=sentinel_param_int_idxs,
  1332. )
  1333. def _process_numeric(self):
  1334. assert self._numeric_binds
  1335. assert self.state is CompilerState.STRING_APPLIED
  1336. num = 1
  1337. param_pos: Dict[str, str] = {}
  1338. order: Iterable[str]
  1339. if self._insertmanyvalues and self._values_bindparam is not None:
  1340. # bindparams that are not in values are always placed first.
  1341. # this avoids the need of changing them when using executemany
  1342. # values () ()
  1343. order = itertools.chain(
  1344. (
  1345. name
  1346. for name in self.bind_names.values()
  1347. if name not in self._values_bindparam
  1348. ),
  1349. self.bind_names.values(),
  1350. )
  1351. else:
  1352. order = self.bind_names.values()
  1353. for bind_name in order:
  1354. if bind_name in param_pos:
  1355. continue
  1356. bind = self.binds[bind_name]
  1357. if (
  1358. bind in self.post_compile_params
  1359. or bind in self.literal_execute_params
  1360. ):
  1361. # set to None to just mark the in positiontup, it will not
  1362. # be replaced below.
  1363. param_pos[bind_name] = None # type: ignore
  1364. else:
  1365. ph = f"{self._numeric_binds_identifier_char}{num}"
  1366. num += 1
  1367. param_pos[bind_name] = ph
  1368. self.next_numeric_pos = num
  1369. self.positiontup = list(param_pos)
  1370. if self.escaped_bind_names:
  1371. len_before = len(param_pos)
  1372. param_pos = {
  1373. self.escaped_bind_names.get(name, name): pos
  1374. for name, pos in param_pos.items()
  1375. }
  1376. assert len(param_pos) == len_before
  1377. # Can't use format here since % chars are not escaped.
  1378. self.string = self._pyformat_pattern.sub(
  1379. lambda m: param_pos[m.group(1)], self.string
  1380. )
  1381. if self._insertmanyvalues:
  1382. single_values_expr = (
  1383. # format is ok here since single_values_expr includes only
  1384. # place-holders
  1385. self._insertmanyvalues.single_values_expr
  1386. % param_pos
  1387. )
  1388. insert_crud_params = [
  1389. (v[0], v[1], "%s", v[3])
  1390. for v in self._insertmanyvalues.insert_crud_params
  1391. ]
  1392. sentinel_param_int_idxs = (
  1393. [
  1394. self.positiontup.index(cast(str, _param_key))
  1395. for _param_key in self._insertmanyvalues.sentinel_param_keys # noqa: E501
  1396. ]
  1397. if self._insertmanyvalues.sentinel_param_keys is not None
  1398. else None
  1399. )
  1400. self._insertmanyvalues = self._insertmanyvalues._replace(
  1401. # This has the numbers (:1, :2)
  1402. single_values_expr=single_values_expr,
  1403. # The single binds are instead %s so they can be formatted
  1404. insert_crud_params=insert_crud_params,
  1405. sentinel_param_keys=sentinel_param_int_idxs,
  1406. )
  1407. @util.memoized_property
  1408. def _bind_processors(
  1409. self,
  1410. ) -> MutableMapping[
  1411. str, Union[_BindProcessorType[Any], Sequence[_BindProcessorType[Any]]]
  1412. ]:
  1413. # mypy is not able to see the two value types as the above Union,
  1414. # it just sees "object". don't know how to resolve
  1415. return {
  1416. key: value # type: ignore
  1417. for key, value in (
  1418. (
  1419. self.bind_names[bindparam],
  1420. bindparam.type._cached_bind_processor(self.dialect)
  1421. if not bindparam.type._is_tuple_type
  1422. else tuple(
  1423. elem_type._cached_bind_processor(self.dialect)
  1424. for elem_type in cast(TupleType, bindparam.type).types
  1425. ),
  1426. )
  1427. for bindparam in self.bind_names
  1428. )
  1429. if value is not None
  1430. }
  1431. @util.memoized_property
  1432. def _imv_sentinel_value_resolvers(
  1433. self,
  1434. ) -> Optional[Sequence[Optional[_SentinelProcessorType[Any]]]]:
  1435. imv = self._insertmanyvalues
  1436. if imv is None or imv.sentinel_columns is None:
  1437. return None
  1438. sentinel_value_resolvers = [
  1439. _scol.type._cached_sentinel_value_processor(self.dialect)
  1440. for _scol in imv.sentinel_columns
  1441. ]
  1442. if util.NONE_SET.issuperset(sentinel_value_resolvers):
  1443. return None
  1444. else:
  1445. return sentinel_value_resolvers
  1446. def is_subquery(self):
  1447. return len(self.stack) > 1
  1448. @property
  1449. def sql_compiler(self):
  1450. return self
  1451. def construct_expanded_state(
  1452. self,
  1453. params: Optional[_CoreSingleExecuteParams] = None,
  1454. escape_names: bool = True,
  1455. ) -> ExpandedState:
  1456. """Return a new :class:`.ExpandedState` for a given parameter set.
  1457. For queries that use "expanding" or other late-rendered parameters,
  1458. this method will provide for both the finalized SQL string as well
  1459. as the parameters that would be used for a particular parameter set.
  1460. .. versionadded:: 2.0.0rc1
  1461. """
  1462. parameters = self.construct_params(
  1463. params,
  1464. escape_names=escape_names,
  1465. _no_postcompile=True,
  1466. )
  1467. return self._process_parameters_for_postcompile(
  1468. parameters,
  1469. )
  1470. def construct_params(
  1471. self,
  1472. params: Optional[_CoreSingleExecuteParams] = None,
  1473. extracted_parameters: Optional[Sequence[BindParameter[Any]]] = None,
  1474. escape_names: bool = True,
  1475. _group_number: Optional[int] = None,
  1476. _check: bool = True,
  1477. _no_postcompile: bool = False,
  1478. ) -> _MutableCoreSingleExecuteParams:
  1479. """return a dictionary of bind parameter keys and values"""
  1480. if self._render_postcompile and not _no_postcompile:
  1481. assert self._post_compile_expanded_state is not None
  1482. if not params:
  1483. return dict(self._post_compile_expanded_state.parameters)
  1484. else:
  1485. raise exc.InvalidRequestError(
  1486. "can't construct new parameters when render_postcompile "
  1487. "is used; the statement is hard-linked to the original "
  1488. "parameters. Use construct_expanded_state to generate a "
  1489. "new statement and parameters."
  1490. )
  1491. has_escaped_names = escape_names and bool(self.escaped_bind_names)
  1492. if extracted_parameters:
  1493. # related the bound parameters collected in the original cache key
  1494. # to those collected in the incoming cache key. They will not have
  1495. # matching names but they will line up positionally in the same
  1496. # way. The parameters present in self.bind_names may be clones of
  1497. # these original cache key params in the case of DML but the .key
  1498. # will be guaranteed to match.
  1499. if self.cache_key is None:
  1500. raise exc.CompileError(
  1501. "This compiled object has no original cache key; "
  1502. "can't pass extracted_parameters to construct_params"
  1503. )
  1504. else:
  1505. orig_extracted = self.cache_key[1]
  1506. ckbm_tuple = self._cache_key_bind_match
  1507. assert ckbm_tuple is not None
  1508. ckbm, _ = ckbm_tuple
  1509. resolved_extracted = {
  1510. bind: extracted
  1511. for b, extracted in zip(orig_extracted, extracted_parameters)
  1512. for bind in ckbm[b]
  1513. }
  1514. else:
  1515. resolved_extracted = None
  1516. if params:
  1517. pd = {}
  1518. for bindparam, name in self.bind_names.items():
  1519. escaped_name = (
  1520. self.escaped_bind_names.get(name, name)
  1521. if has_escaped_names
  1522. else name
  1523. )
  1524. if bindparam.key in params:
  1525. pd[escaped_name] = params[bindparam.key]
  1526. elif name in params:
  1527. pd[escaped_name] = params[name]
  1528. elif _check and bindparam.required:
  1529. if _group_number:
  1530. raise exc.InvalidRequestError(
  1531. "A value is required for bind parameter %r, "
  1532. "in parameter group %d"
  1533. % (bindparam.key, _group_number),
  1534. code="cd3x",
  1535. )
  1536. else:
  1537. raise exc.InvalidRequestError(
  1538. "A value is required for bind parameter %r"
  1539. % bindparam.key,
  1540. code="cd3x",
  1541. )
  1542. else:
  1543. if resolved_extracted:
  1544. value_param = resolved_extracted.get(
  1545. bindparam, bindparam
  1546. )
  1547. else:
  1548. value_param = bindparam
  1549. if bindparam.callable:
  1550. pd[escaped_name] = value_param.effective_value
  1551. else:
  1552. pd[escaped_name] = value_param.value
  1553. return pd
  1554. else:
  1555. pd = {}
  1556. for bindparam, name in self.bind_names.items():
  1557. escaped_name = (
  1558. self.escaped_bind_names.get(name, name)
  1559. if has_escaped_names
  1560. else name
  1561. )
  1562. if _check and bindparam.required:
  1563. if _group_number:
  1564. raise exc.InvalidRequestError(
  1565. "A value is required for bind parameter %r, "
  1566. "in parameter group %d"
  1567. % (bindparam.key, _group_number),
  1568. code="cd3x",
  1569. )
  1570. else:
  1571. raise exc.InvalidRequestError(
  1572. "A value is required for bind parameter %r"
  1573. % bindparam.key,
  1574. code="cd3x",
  1575. )
  1576. if resolved_extracted:
  1577. value_param = resolved_extracted.get(bindparam, bindparam)
  1578. else:
  1579. value_param = bindparam
  1580. if bindparam.callable:
  1581. pd[escaped_name] = value_param.effective_value
  1582. else:
  1583. pd[escaped_name] = value_param.value
  1584. return pd
  1585. @util.memoized_instancemethod
  1586. def _get_set_input_sizes_lookup(self):
  1587. dialect = self.dialect
  1588. include_types = dialect.include_set_input_sizes
  1589. exclude_types = dialect.exclude_set_input_sizes
  1590. dbapi = dialect.dbapi
  1591. def lookup_type(typ):
  1592. dbtype = typ._unwrapped_dialect_impl(dialect).get_dbapi_type(dbapi)
  1593. if (
  1594. dbtype is not None
  1595. and (exclude_types is None or dbtype not in exclude_types)
  1596. and (include_types is None or dbtype in include_types)
  1597. ):
  1598. return dbtype
  1599. else:
  1600. return None
  1601. inputsizes = {}
  1602. literal_execute_params = self.literal_execute_params
  1603. for bindparam in self.bind_names:
  1604. if bindparam in literal_execute_params:
  1605. continue
  1606. if bindparam.type._is_tuple_type:
  1607. inputsizes[bindparam] = [
  1608. lookup_type(typ)
  1609. for typ in cast(TupleType, bindparam.type).types
  1610. ]
  1611. else:
  1612. inputsizes[bindparam] = lookup_type(bindparam.type)
  1613. return inputsizes
  1614. @property
  1615. def params(self):
  1616. """Return the bind param dictionary embedded into this
  1617. compiled object, for those values that are present.
  1618. .. seealso::
  1619. :ref:`faq_sql_expression_string` - includes a usage example for
  1620. debugging use cases.
  1621. """
  1622. return self.construct_params(_check=False)
  1623. def _process_parameters_for_postcompile(
  1624. self,
  1625. parameters: _MutableCoreSingleExecuteParams,
  1626. _populate_self: bool = False,
  1627. ) -> ExpandedState:
  1628. """handle special post compile parameters.
  1629. These include:
  1630. * "expanding" parameters -typically IN tuples that are rendered
  1631. on a per-parameter basis for an otherwise fixed SQL statement string.
  1632. * literal_binds compiled with the literal_execute flag. Used for
  1633. things like SQL Server "TOP N" where the driver does not accommodate
  1634. N as a bound parameter.
  1635. """
  1636. expanded_parameters = {}
  1637. new_positiontup: Optional[List[str]]
  1638. pre_expanded_string = self._pre_expanded_string
  1639. if pre_expanded_string is None:
  1640. pre_expanded_string = self.string
  1641. if self.positional:
  1642. new_positiontup = []
  1643. pre_expanded_positiontup = self._pre_expanded_positiontup
  1644. if pre_expanded_positiontup is None:
  1645. pre_expanded_positiontup = self.positiontup
  1646. else:
  1647. new_positiontup = pre_expanded_positiontup = None
  1648. processors = self._bind_processors
  1649. single_processors = cast(
  1650. "Mapping[str, _BindProcessorType[Any]]", processors
  1651. )
  1652. tuple_processors = cast(
  1653. "Mapping[str, Sequence[_BindProcessorType[Any]]]", processors
  1654. )
  1655. new_processors: Dict[str, _BindProcessorType[Any]] = {}
  1656. replacement_expressions: Dict[str, Any] = {}
  1657. to_update_sets: Dict[str, Any] = {}
  1658. # notes:
  1659. # *unescaped* parameter names in:
  1660. # self.bind_names, self.binds, self._bind_processors, self.positiontup
  1661. #
  1662. # *escaped* parameter names in:
  1663. # construct_params(), replacement_expressions
  1664. numeric_positiontup: Optional[List[str]] = None
  1665. if self.positional and pre_expanded_positiontup is not None:
  1666. names: Iterable[str] = pre_expanded_positiontup
  1667. if self._numeric_binds:
  1668. numeric_positiontup = []
  1669. else:
  1670. names = self.bind_names.values()
  1671. ebn = self.escaped_bind_names
  1672. for name in names:
  1673. escaped_name = ebn.get(name, name) if ebn else name
  1674. parameter = self.binds[name]
  1675. if parameter in self.literal_execute_params:
  1676. if escaped_name not in replacement_expressions:
  1677. replacement_expressions[
  1678. escaped_name
  1679. ] = self.render_literal_bindparam(
  1680. parameter,
  1681. render_literal_value=parameters.pop(escaped_name),
  1682. )
  1683. continue
  1684. if parameter in self.post_compile_params:
  1685. if escaped_name in replacement_expressions:
  1686. to_update = to_update_sets[escaped_name]
  1687. values = None
  1688. else:
  1689. # we are removing the parameter from parameters
  1690. # because it is a list value, which is not expected by
  1691. # TypeEngine objects that would otherwise be asked to
  1692. # process it. the single name is being replaced with
  1693. # individual numbered parameters for each value in the
  1694. # param.
  1695. #
  1696. # note we are also inserting *escaped* parameter names
  1697. # into the given dictionary. default dialect will
  1698. # use these param names directly as they will not be
  1699. # in the escaped_bind_names dictionary.
  1700. values = parameters.pop(name)
  1701. leep_res = self._literal_execute_expanding_parameter(
  1702. escaped_name, parameter, values
  1703. )
  1704. (to_update, replacement_expr) = leep_res
  1705. to_update_sets[escaped_name] = to_update
  1706. replacement_expressions[escaped_name] = replacement_expr
  1707. if not parameter.literal_execute:
  1708. parameters.update(to_update)
  1709. if parameter.type._is_tuple_type:
  1710. assert values is not None
  1711. new_processors.update(
  1712. (
  1713. "%s_%s_%s" % (name, i, j),
  1714. tuple_processors[name][j - 1],
  1715. )
  1716. for i, tuple_element in enumerate(values, 1)
  1717. for j, _ in enumerate(tuple_element, 1)
  1718. if name in tuple_processors
  1719. and tuple_processors[name][j - 1] is not None
  1720. )
  1721. else:
  1722. new_processors.update(
  1723. (key, single_processors[name])
  1724. for key, _ in to_update
  1725. if name in single_processors
  1726. )
  1727. if numeric_positiontup is not None:
  1728. numeric_positiontup.extend(
  1729. name for name, _ in to_update
  1730. )
  1731. elif new_positiontup is not None:
  1732. # to_update has escaped names, but that's ok since
  1733. # these are new names, that aren't in the
  1734. # escaped_bind_names dict.
  1735. new_positiontup.extend(name for name, _ in to_update)
  1736. expanded_parameters[name] = [
  1737. expand_key for expand_key, _ in to_update
  1738. ]
  1739. elif new_positiontup is not None:
  1740. new_positiontup.append(name)
  1741. def process_expanding(m):
  1742. key = m.group(1)
  1743. expr = replacement_expressions[key]
  1744. # if POSTCOMPILE included a bind_expression, render that
  1745. # around each element
  1746. if m.group(2):
  1747. tok = m.group(2).split("~~")
  1748. be_left, be_right = tok[1], tok[3]
  1749. expr = ", ".join(
  1750. "%s%s%s" % (be_left, exp, be_right)
  1751. for exp in expr.split(", ")
  1752. )
  1753. return expr
  1754. statement = re.sub(
  1755. self._post_compile_pattern, process_expanding, pre_expanded_string
  1756. )
  1757. if numeric_positiontup is not None:
  1758. assert new_positiontup is not None
  1759. param_pos = {
  1760. key: f"{self._numeric_binds_identifier_char}{num}"
  1761. for num, key in enumerate(
  1762. numeric_positiontup, self.next_numeric_pos
  1763. )
  1764. }
  1765. # Can't use format here since % chars are not escaped.
  1766. statement = self._pyformat_pattern.sub(
  1767. lambda m: param_pos[m.group(1)], statement
  1768. )
  1769. new_positiontup.extend(numeric_positiontup)
  1770. expanded_state = ExpandedState(
  1771. statement,
  1772. parameters,
  1773. new_processors,
  1774. new_positiontup,
  1775. expanded_parameters,
  1776. )
  1777. if _populate_self:
  1778. # this is for the "render_postcompile" flag, which is not
  1779. # otherwise used internally and is for end-user debugging and
  1780. # special use cases.
  1781. self._pre_expanded_string = pre_expanded_string
  1782. self._pre_expanded_positiontup = pre_expanded_positiontup
  1783. self.string = expanded_state.statement
  1784. self.positiontup = (
  1785. list(expanded_state.positiontup or ())
  1786. if self.positional
  1787. else None
  1788. )
  1789. self._post_compile_expanded_state = expanded_state
  1790. return expanded_state
  1791. @util.preload_module("sqlalchemy.engine.cursor")
  1792. def _create_result_map(self):
  1793. """utility method used for unit tests only."""
  1794. cursor = util.preloaded.engine_cursor
  1795. return cursor.CursorResultMetaData._create_description_match_map(
  1796. self._result_columns
  1797. )
  1798. # assigned by crud.py for insert/update statements
  1799. _get_bind_name_for_col: _BindNameForColProtocol
  1800. @util.memoized_property
  1801. def _within_exec_param_key_getter(self) -> Callable[[Any], str]:
  1802. getter = self._get_bind_name_for_col
  1803. return getter
  1804. @util.memoized_property
  1805. @util.preload_module("sqlalchemy.engine.result")
  1806. def _inserted_primary_key_from_lastrowid_getter(self):
  1807. result = util.preloaded.engine_result
  1808. param_key_getter = self._within_exec_param_key_getter
  1809. assert self.compile_state is not None
  1810. statement = self.compile_state.statement
  1811. if TYPE_CHECKING:
  1812. assert isinstance(statement, Insert)
  1813. table = statement.table
  1814. getters = [
  1815. (operator.methodcaller("get", param_key_getter(col), None), col)
  1816. for col in table.primary_key
  1817. ]
  1818. autoinc_getter = None
  1819. autoinc_col = table._autoincrement_column
  1820. if autoinc_col is not None:
  1821. # apply type post processors to the lastrowid
  1822. lastrowid_processor = autoinc_col.type._cached_result_processor(
  1823. self.dialect, None
  1824. )
  1825. autoinc_key = param_key_getter(autoinc_col)
  1826. # if a bind value is present for the autoincrement column
  1827. # in the parameters, we need to do the logic dictated by
  1828. # #7998; honor a non-None user-passed parameter over lastrowid.
  1829. # previously in the 1.4 series we weren't fetching lastrowid
  1830. # at all if the key were present in the parameters
  1831. if autoinc_key in self.binds:
  1832. def _autoinc_getter(lastrowid, parameters):
  1833. param_value = parameters.get(autoinc_key, lastrowid)
  1834. if param_value is not None:
  1835. # they supplied non-None parameter, use that.
  1836. # SQLite at least is observed to return the wrong
  1837. # cursor.lastrowid for INSERT..ON CONFLICT so it
  1838. # can't be used in all cases
  1839. return param_value
  1840. else:
  1841. # use lastrowid
  1842. return lastrowid
  1843. # work around mypy https://github.com/python/mypy/issues/14027
  1844. autoinc_getter = _autoinc_getter
  1845. else:
  1846. lastrowid_processor = None
  1847. row_fn = result.result_tuple([col.key for col in table.primary_key])
  1848. def get(lastrowid, parameters):
  1849. """given cursor.lastrowid value and the parameters used for INSERT,
  1850. return a "row" that represents the primary key, either by
  1851. using the "lastrowid" or by extracting values from the parameters
  1852. that were sent along with the INSERT.
  1853. """
  1854. if lastrowid_processor is not None:
  1855. lastrowid = lastrowid_processor(lastrowid)
  1856. if lastrowid is None:
  1857. return row_fn(getter(parameters) for getter, col in getters)
  1858. else:
  1859. return row_fn(
  1860. (
  1861. autoinc_getter(lastrowid, parameters)
  1862. if autoinc_getter is not None
  1863. else lastrowid
  1864. )
  1865. if col is autoinc_col
  1866. else getter(parameters)
  1867. for getter, col in getters
  1868. )
  1869. return get
  1870. @util.memoized_property
  1871. @util.preload_module("sqlalchemy.engine.result")
  1872. def _inserted_primary_key_from_returning_getter(self):
  1873. if typing.TYPE_CHECKING:
  1874. from ..engine import result
  1875. else:
  1876. result = util.preloaded.engine_result
  1877. assert self.compile_state is not None
  1878. statement = self.compile_state.statement
  1879. if TYPE_CHECKING:
  1880. assert isinstance(statement, Insert)
  1881. param_key_getter = self._within_exec_param_key_getter
  1882. table = statement.table
  1883. returning = self.implicit_returning
  1884. assert returning is not None
  1885. ret = {col: idx for idx, col in enumerate(returning)}
  1886. getters = cast(
  1887. "List[Tuple[Callable[[Any], Any], bool]]",
  1888. [
  1889. (operator.itemgetter(ret[col]), True)
  1890. if col in ret
  1891. else (
  1892. operator.methodcaller("get", param_key_getter(col), None),
  1893. False,
  1894. )
  1895. for col in table.primary_key
  1896. ],
  1897. )
  1898. row_fn = result.result_tuple([col.key for col in table.primary_key])
  1899. def get(row, parameters):
  1900. return row_fn(
  1901. getter(row) if use_row else getter(parameters)
  1902. for getter, use_row in getters
  1903. )
  1904. return get
  1905. def default_from(self):
  1906. """Called when a SELECT statement has no froms, and no FROM clause is
  1907. to be appended.
  1908. Gives Oracle a chance to tack on a ``FROM DUAL`` to the string output.
  1909. """
  1910. return ""
  1911. def visit_grouping(self, grouping, asfrom=False, **kwargs):
  1912. return "(" + grouping.element._compiler_dispatch(self, **kwargs) + ")"
  1913. def visit_select_statement_grouping(self, grouping, **kwargs):
  1914. return "(" + grouping.element._compiler_dispatch(self, **kwargs) + ")"
  1915. def visit_label_reference(
  1916. self, element, within_columns_clause=False, **kwargs
  1917. ):
  1918. if self.stack and self.dialect.supports_simple_order_by_label:
  1919. try:
  1920. compile_state = cast(
  1921. "Union[SelectState, CompoundSelectState]",
  1922. self.stack[-1]["compile_state"],
  1923. )
  1924. except KeyError as ke:
  1925. raise exc.CompileError(
  1926. "Can't resolve label reference for ORDER BY / "
  1927. "GROUP BY / DISTINCT etc."
  1928. ) from ke
  1929. (
  1930. with_cols,
  1931. only_froms,
  1932. only_cols,
  1933. ) = compile_state._label_resolve_dict
  1934. if within_columns_clause:
  1935. resolve_dict = only_froms
  1936. else:
  1937. resolve_dict = only_cols
  1938. # this can be None in the case that a _label_reference()
  1939. # were subject to a replacement operation, in which case
  1940. # the replacement of the Label element may have changed
  1941. # to something else like a ColumnClause expression.
  1942. order_by_elem = element.element._order_by_label_element
  1943. if (
  1944. order_by_elem is not None
  1945. and order_by_elem.name in resolve_dict
  1946. and order_by_elem.shares_lineage(
  1947. resolve_dict[order_by_elem.name]
  1948. )
  1949. ):
  1950. kwargs[
  1951. "render_label_as_label"
  1952. ] = element.element._order_by_label_element
  1953. return self.process(
  1954. element.element,
  1955. within_columns_clause=within_columns_clause,
  1956. **kwargs,
  1957. )
  1958. def visit_textual_label_reference(
  1959. self, element, within_columns_clause=False, **kwargs
  1960. ):
  1961. if not self.stack:
  1962. # compiling the element outside of the context of a SELECT
  1963. return self.process(element._text_clause)
  1964. try:
  1965. compile_state = cast(
  1966. "Union[SelectState, CompoundSelectState]",
  1967. self.stack[-1]["compile_state"],
  1968. )
  1969. except KeyError as ke:
  1970. coercions._no_text_coercion(
  1971. element.element,
  1972. extra=(
  1973. "Can't resolve label reference for ORDER BY / "
  1974. "GROUP BY / DISTINCT etc."
  1975. ),
  1976. exc_cls=exc.CompileError,
  1977. err=ke,
  1978. )
  1979. with_cols, only_froms, only_cols = compile_state._label_resolve_dict
  1980. try:
  1981. if within_columns_clause:
  1982. col = only_froms[element.element]
  1983. else:
  1984. col = with_cols[element.element]
  1985. except KeyError as err:
  1986. coercions._no_text_coercion(
  1987. element.element,
  1988. extra=(
  1989. "Can't resolve label reference for ORDER BY / "
  1990. "GROUP BY / DISTINCT etc."
  1991. ),
  1992. exc_cls=exc.CompileError,
  1993. err=err,
  1994. )
  1995. else:
  1996. kwargs["render_label_as_label"] = col
  1997. return self.process(
  1998. col, within_columns_clause=within_columns_clause, **kwargs
  1999. )
  2000. def visit_label(
  2001. self,
  2002. label,
  2003. add_to_result_map=None,
  2004. within_label_clause=False,
  2005. within_columns_clause=False,
  2006. render_label_as_label=None,
  2007. result_map_targets=(),
  2008. **kw,
  2009. ):
  2010. # only render labels within the columns clause
  2011. # or ORDER BY clause of a select. dialect-specific compilers
  2012. # can modify this behavior.
  2013. render_label_with_as = (
  2014. within_columns_clause and not within_label_clause
  2015. )
  2016. render_label_only = render_label_as_label is label
  2017. if render_label_only or render_label_with_as:
  2018. if isinstance(label.name, elements._truncated_label):
  2019. labelname = self._truncated_identifier("colident", label.name)
  2020. else:
  2021. labelname = label.name
  2022. if render_label_with_as:
  2023. if add_to_result_map is not None:
  2024. add_to_result_map(
  2025. labelname,
  2026. label.name,
  2027. (label, labelname) + label._alt_names + result_map_targets,
  2028. label.type,
  2029. )
  2030. return (
  2031. label.element._compiler_dispatch(
  2032. self,
  2033. within_columns_clause=True,
  2034. within_label_clause=True,
  2035. **kw,
  2036. )
  2037. + OPERATORS[operators.as_]
  2038. + self.preparer.format_label(label, labelname)
  2039. )
  2040. elif render_label_only:
  2041. return self.preparer.format_label(label, labelname)
  2042. else:
  2043. return label.element._compiler_dispatch(
  2044. self, within_columns_clause=False, **kw
  2045. )
  2046. def _fallback_column_name(self, column):
  2047. raise exc.CompileError(
  2048. "Cannot compile Column object until " "its 'name' is assigned."
  2049. )
  2050. def visit_lambda_element(self, element, **kw):
  2051. sql_element = element._resolved
  2052. return self.process(sql_element, **kw)
  2053. def visit_column(
  2054. self,
  2055. column: ColumnClause[Any],
  2056. add_to_result_map: Optional[_ResultMapAppender] = None,
  2057. include_table: bool = True,
  2058. result_map_targets: Tuple[Any, ...] = (),
  2059. ambiguous_table_name_map: Optional[_AmbiguousTableNameMap] = None,
  2060. **kwargs: Any,
  2061. ) -> str:
  2062. name = orig_name = column.name
  2063. if name is None:
  2064. name = self._fallback_column_name(column)
  2065. is_literal = column.is_literal
  2066. if not is_literal and isinstance(name, elements._truncated_label):
  2067. name = self._truncated_identifier("colident", name)
  2068. if add_to_result_map is not None:
  2069. targets = (column, name, column.key) + result_map_targets
  2070. if column._tq_label:
  2071. targets += (column._tq_label,)
  2072. add_to_result_map(name, orig_name, targets, column.type)
  2073. if is_literal:
  2074. # note we are not currently accommodating for
  2075. # literal_column(quoted_name('ident', True)) here
  2076. name = self.escape_literal_column(name)
  2077. else:
  2078. name = self.preparer.quote(name)
  2079. table = column.table
  2080. if table is None or not include_table or not table.named_with_column:
  2081. return name
  2082. else:
  2083. effective_schema = self.preparer.schema_for_object(table)
  2084. if effective_schema:
  2085. schema_prefix = (
  2086. self.preparer.quote_schema(effective_schema) + "."
  2087. )
  2088. else:
  2089. schema_prefix = ""
  2090. if TYPE_CHECKING:
  2091. assert isinstance(table, NamedFromClause)
  2092. tablename = table.name
  2093. if (
  2094. not effective_schema
  2095. and ambiguous_table_name_map
  2096. and tablename in ambiguous_table_name_map
  2097. ):
  2098. tablename = ambiguous_table_name_map[tablename]
  2099. if isinstance(tablename, elements._truncated_label):
  2100. tablename = self._truncated_identifier("alias", tablename)
  2101. return schema_prefix + self.preparer.quote(tablename) + "." + name
  2102. def visit_collation(self, element, **kw):
  2103. return self.preparer.format_collation(element.collation)
  2104. def visit_fromclause(self, fromclause, **kwargs):
  2105. return fromclause.name
  2106. def visit_index(self, index, **kwargs):
  2107. return index.name
  2108. def visit_typeclause(self, typeclause, **kw):
  2109. kw["type_expression"] = typeclause
  2110. kw["identifier_preparer"] = self.preparer
  2111. return self.dialect.type_compiler_instance.process(
  2112. typeclause.type, **kw
  2113. )
  2114. def post_process_text(self, text):
  2115. if self.preparer._double_percents:
  2116. text = text.replace("%", "%%")
  2117. return text
  2118. def escape_literal_column(self, text):
  2119. if self.preparer._double_percents:
  2120. text = text.replace("%", "%%")
  2121. return text
  2122. def visit_textclause(self, textclause, add_to_result_map=None, **kw):
  2123. def do_bindparam(m):
  2124. name = m.group(1)
  2125. if name in textclause._bindparams:
  2126. return self.process(textclause._bindparams[name], **kw)
  2127. else:
  2128. return self.bindparam_string(name, **kw)
  2129. if not self.stack:
  2130. self.isplaintext = True
  2131. if add_to_result_map:
  2132. # text() object is present in the columns clause of a
  2133. # select(). Add a no-name entry to the result map so that
  2134. # row[text()] produces a result
  2135. add_to_result_map(None, None, (textclause,), sqltypes.NULLTYPE)
  2136. # un-escape any \:params
  2137. return BIND_PARAMS_ESC.sub(
  2138. lambda m: m.group(1),
  2139. BIND_PARAMS.sub(
  2140. do_bindparam, self.post_process_text(textclause.text)
  2141. ),
  2142. )
  2143. def visit_textual_select(
  2144. self, taf, compound_index=None, asfrom=False, **kw
  2145. ):
  2146. toplevel = not self.stack
  2147. entry = self._default_stack_entry if toplevel else self.stack[-1]
  2148. new_entry: _CompilerStackEntry = {
  2149. "correlate_froms": set(),
  2150. "asfrom_froms": set(),
  2151. "selectable": taf,
  2152. }
  2153. self.stack.append(new_entry)
  2154. if taf._independent_ctes:
  2155. self._dispatch_independent_ctes(taf, kw)
  2156. populate_result_map = (
  2157. toplevel
  2158. or (
  2159. compound_index == 0
  2160. and entry.get("need_result_map_for_compound", False)
  2161. )
  2162. or entry.get("need_result_map_for_nested", False)
  2163. )
  2164. if populate_result_map:
  2165. self._ordered_columns = (
  2166. self._textual_ordered_columns
  2167. ) = taf.positional
  2168. # enable looser result column matching when the SQL text links to
  2169. # Column objects by name only
  2170. self._loose_column_name_matching = not taf.positional and bool(
  2171. taf.column_args
  2172. )
  2173. for c in taf.column_args:
  2174. self.process(
  2175. c,
  2176. within_columns_clause=True,
  2177. add_to_result_map=self._add_to_result_map,
  2178. )
  2179. text = self.process(taf.element, **kw)
  2180. if self.ctes:
  2181. nesting_level = len(self.stack) if not toplevel else None
  2182. text = self._render_cte_clause(nesting_level=nesting_level) + text
  2183. self.stack.pop(-1)
  2184. return text
  2185. def visit_null(self, expr, **kw):
  2186. return "NULL"
  2187. def visit_true(self, expr, **kw):
  2188. if self.dialect.supports_native_boolean:
  2189. return "true"
  2190. else:
  2191. return "1"
  2192. def visit_false(self, expr, **kw):
  2193. if self.dialect.supports_native_boolean:
  2194. return "false"
  2195. else:
  2196. return "0"
  2197. def _generate_delimited_list(self, elements, separator, **kw):
  2198. return separator.join(
  2199. s
  2200. for s in (c._compiler_dispatch(self, **kw) for c in elements)
  2201. if s
  2202. )
  2203. def _generate_delimited_and_list(self, clauses, **kw):
  2204. lcc, clauses = elements.BooleanClauseList._process_clauses_for_boolean(
  2205. operators.and_,
  2206. elements.True_._singleton,
  2207. elements.False_._singleton,
  2208. clauses,
  2209. )
  2210. if lcc == 1:
  2211. return clauses[0]._compiler_dispatch(self, **kw)
  2212. else:
  2213. separator = OPERATORS[operators.and_]
  2214. return separator.join(
  2215. s
  2216. for s in (c._compiler_dispatch(self, **kw) for c in clauses)
  2217. if s
  2218. )
  2219. def visit_tuple(self, clauselist, **kw):
  2220. return "(%s)" % self.visit_clauselist(clauselist, **kw)
  2221. def visit_clauselist(self, clauselist, **kw):
  2222. sep = clauselist.operator
  2223. if sep is None:
  2224. sep = " "
  2225. else:
  2226. sep = OPERATORS[clauselist.operator]
  2227. return self._generate_delimited_list(clauselist.clauses, sep, **kw)
  2228. def visit_expression_clauselist(self, clauselist, **kw):
  2229. operator_ = clauselist.operator
  2230. disp = self._get_operator_dispatch(
  2231. operator_, "expression_clauselist", None
  2232. )
  2233. if disp:
  2234. return disp(clauselist, operator_, **kw)
  2235. try:
  2236. opstring = OPERATORS[operator_]
  2237. except KeyError as err:
  2238. raise exc.UnsupportedCompilationError(self, operator_) from err
  2239. else:
  2240. kw["_in_operator_expression"] = True
  2241. return self._generate_delimited_list(
  2242. clauselist.clauses, opstring, **kw
  2243. )
  2244. def visit_case(self, clause, **kwargs):
  2245. x = "CASE "
  2246. if clause.value is not None:
  2247. x += clause.value._compiler_dispatch(self, **kwargs) + " "
  2248. for cond, result in clause.whens:
  2249. x += (
  2250. "WHEN "
  2251. + cond._compiler_dispatch(self, **kwargs)
  2252. + " THEN "
  2253. + result._compiler_dispatch(self, **kwargs)
  2254. + " "
  2255. )
  2256. if clause.else_ is not None:
  2257. x += (
  2258. "ELSE " + clause.else_._compiler_dispatch(self, **kwargs) + " "
  2259. )
  2260. x += "END"
  2261. return x
  2262. def visit_type_coerce(self, type_coerce, **kw):
  2263. return type_coerce.typed_expression._compiler_dispatch(self, **kw)
  2264. def visit_cast(self, cast, **kwargs):
  2265. type_clause = cast.typeclause._compiler_dispatch(self, **kwargs)
  2266. match = re.match("(.*)( COLLATE .*)", type_clause)
  2267. return "CAST(%s AS %s)%s" % (
  2268. cast.clause._compiler_dispatch(self, **kwargs),
  2269. match.group(1) if match else type_clause,
  2270. match.group(2) if match else "",
  2271. )
  2272. def _format_frame_clause(self, range_, **kw):
  2273. return "%s AND %s" % (
  2274. "UNBOUNDED PRECEDING"
  2275. if range_[0] is elements.RANGE_UNBOUNDED
  2276. else "CURRENT ROW"
  2277. if range_[0] is elements.RANGE_CURRENT
  2278. else "%s PRECEDING"
  2279. % (self.process(elements.literal(abs(range_[0])), **kw),)
  2280. if range_[0] < 0
  2281. else "%s FOLLOWING"
  2282. % (self.process(elements.literal(range_[0]), **kw),),
  2283. "UNBOUNDED FOLLOWING"
  2284. if range_[1] is elements.RANGE_UNBOUNDED
  2285. else "CURRENT ROW"
  2286. if range_[1] is elements.RANGE_CURRENT
  2287. else "%s PRECEDING"
  2288. % (self.process(elements.literal(abs(range_[1])), **kw),)
  2289. if range_[1] < 0
  2290. else "%s FOLLOWING"
  2291. % (self.process(elements.literal(range_[1]), **kw),),
  2292. )
  2293. def visit_over(self, over, **kwargs):
  2294. text = over.element._compiler_dispatch(self, **kwargs)
  2295. if over.range_:
  2296. range_ = "RANGE BETWEEN %s" % self._format_frame_clause(
  2297. over.range_, **kwargs
  2298. )
  2299. elif over.rows:
  2300. range_ = "ROWS BETWEEN %s" % self._format_frame_clause(
  2301. over.rows, **kwargs
  2302. )
  2303. else:
  2304. range_ = None
  2305. return "%s OVER (%s)" % (
  2306. text,
  2307. " ".join(
  2308. [
  2309. "%s BY %s"
  2310. % (word, clause._compiler_dispatch(self, **kwargs))
  2311. for word, clause in (
  2312. ("PARTITION", over.partition_by),
  2313. ("ORDER", over.order_by),
  2314. )
  2315. if clause is not None and len(clause)
  2316. ]
  2317. + ([range_] if range_ else [])
  2318. ),
  2319. )
  2320. def visit_withingroup(self, withingroup, **kwargs):
  2321. return "%s WITHIN GROUP (ORDER BY %s)" % (
  2322. withingroup.element._compiler_dispatch(self, **kwargs),
  2323. withingroup.order_by._compiler_dispatch(self, **kwargs),
  2324. )
  2325. def visit_funcfilter(self, funcfilter, **kwargs):
  2326. return "%s FILTER (WHERE %s)" % (
  2327. funcfilter.func._compiler_dispatch(self, **kwargs),
  2328. funcfilter.criterion._compiler_dispatch(self, **kwargs),
  2329. )
  2330. def visit_extract(self, extract, **kwargs):
  2331. field = self.extract_map.get(extract.field, extract.field)
  2332. return "EXTRACT(%s FROM %s)" % (
  2333. field,
  2334. extract.expr._compiler_dispatch(self, **kwargs),
  2335. )
  2336. def visit_scalar_function_column(self, element, **kw):
  2337. compiled_fn = self.visit_function(element.fn, **kw)
  2338. compiled_col = self.visit_column(element, **kw)
  2339. return "(%s).%s" % (compiled_fn, compiled_col)
  2340. def visit_function(
  2341. self,
  2342. func: Function[Any],
  2343. add_to_result_map: Optional[_ResultMapAppender] = None,
  2344. **kwargs: Any,
  2345. ) -> str:
  2346. if add_to_result_map is not None:
  2347. add_to_result_map(func.name, func.name, (), func.type)
  2348. disp = getattr(self, "visit_%s_func" % func.name.lower(), None)
  2349. text: str
  2350. if disp:
  2351. text = disp(func, **kwargs)
  2352. else:
  2353. name = FUNCTIONS.get(func._deannotate().__class__, None)
  2354. if name:
  2355. if func._has_args:
  2356. name += "%(expr)s"
  2357. else:
  2358. name = func.name
  2359. name = (
  2360. self.preparer.quote(name)
  2361. if self.preparer._requires_quotes_illegal_chars(name)
  2362. or isinstance(name, elements.quoted_name)
  2363. else name
  2364. )
  2365. name = name + "%(expr)s"
  2366. text = ".".join(
  2367. [
  2368. (
  2369. self.preparer.quote(tok)
  2370. if self.preparer._requires_quotes_illegal_chars(tok)
  2371. or isinstance(name, elements.quoted_name)
  2372. else tok
  2373. )
  2374. for tok in func.packagenames
  2375. ]
  2376. + [name]
  2377. ) % {"expr": self.function_argspec(func, **kwargs)}
  2378. if func._with_ordinality:
  2379. text += " WITH ORDINALITY"
  2380. return text
  2381. def visit_next_value_func(self, next_value, **kw):
  2382. return self.visit_sequence(next_value.sequence)
  2383. def visit_sequence(self, sequence, **kw):
  2384. raise NotImplementedError(
  2385. "Dialect '%s' does not support sequence increments."
  2386. % self.dialect.name
  2387. )
  2388. def function_argspec(self, func, **kwargs):
  2389. return func.clause_expr._compiler_dispatch(self, **kwargs)
  2390. def visit_compound_select(
  2391. self, cs, asfrom=False, compound_index=None, **kwargs
  2392. ):
  2393. toplevel = not self.stack
  2394. compile_state = cs._compile_state_factory(cs, self, **kwargs)
  2395. if toplevel and not self.compile_state:
  2396. self.compile_state = compile_state
  2397. compound_stmt = compile_state.statement
  2398. entry = self._default_stack_entry if toplevel else self.stack[-1]
  2399. need_result_map = toplevel or (
  2400. not compound_index
  2401. and entry.get("need_result_map_for_compound", False)
  2402. )
  2403. # indicates there is already a CompoundSelect in play
  2404. if compound_index == 0:
  2405. entry["select_0"] = cs
  2406. self.stack.append(
  2407. {
  2408. "correlate_froms": entry["correlate_froms"],
  2409. "asfrom_froms": entry["asfrom_froms"],
  2410. "selectable": cs,
  2411. "compile_state": compile_state,
  2412. "need_result_map_for_compound": need_result_map,
  2413. }
  2414. )
  2415. if compound_stmt._independent_ctes:
  2416. self._dispatch_independent_ctes(compound_stmt, kwargs)
  2417. keyword = self.compound_keywords[cs.keyword]
  2418. text = (" " + keyword + " ").join(
  2419. (
  2420. c._compiler_dispatch(
  2421. self, asfrom=asfrom, compound_index=i, **kwargs
  2422. )
  2423. for i, c in enumerate(cs.selects)
  2424. )
  2425. )
  2426. kwargs["include_table"] = False
  2427. text += self.group_by_clause(cs, **dict(asfrom=asfrom, **kwargs))
  2428. text += self.order_by_clause(cs, **kwargs)
  2429. if cs._has_row_limiting_clause:
  2430. text += self._row_limit_clause(cs, **kwargs)
  2431. if self.ctes:
  2432. nesting_level = len(self.stack) if not toplevel else None
  2433. text = (
  2434. self._render_cte_clause(
  2435. nesting_level=nesting_level,
  2436. include_following_stack=True,
  2437. )
  2438. + text
  2439. )
  2440. self.stack.pop(-1)
  2441. return text
  2442. def _row_limit_clause(self, cs, **kwargs):
  2443. if cs._fetch_clause is not None:
  2444. return self.fetch_clause(cs, **kwargs)
  2445. else:
  2446. return self.limit_clause(cs, **kwargs)
  2447. def _get_operator_dispatch(self, operator_, qualifier1, qualifier2):
  2448. attrname = "visit_%s_%s%s" % (
  2449. operator_.__name__,
  2450. qualifier1,
  2451. "_" + qualifier2 if qualifier2 else "",
  2452. )
  2453. return getattr(self, attrname, None)
  2454. def visit_unary(
  2455. self, unary, add_to_result_map=None, result_map_targets=(), **kw
  2456. ):
  2457. if add_to_result_map is not None:
  2458. result_map_targets += (unary,)
  2459. kw["add_to_result_map"] = add_to_result_map
  2460. kw["result_map_targets"] = result_map_targets
  2461. if unary.operator:
  2462. if unary.modifier:
  2463. raise exc.CompileError(
  2464. "Unary expression does not support operator "
  2465. "and modifier simultaneously"
  2466. )
  2467. disp = self._get_operator_dispatch(
  2468. unary.operator, "unary", "operator"
  2469. )
  2470. if disp:
  2471. return disp(unary, unary.operator, **kw)
  2472. else:
  2473. return self._generate_generic_unary_operator(
  2474. unary, OPERATORS[unary.operator], **kw
  2475. )
  2476. elif unary.modifier:
  2477. disp = self._get_operator_dispatch(
  2478. unary.modifier, "unary", "modifier"
  2479. )
  2480. if disp:
  2481. return disp(unary, unary.modifier, **kw)
  2482. else:
  2483. return self._generate_generic_unary_modifier(
  2484. unary, OPERATORS[unary.modifier], **kw
  2485. )
  2486. else:
  2487. raise exc.CompileError(
  2488. "Unary expression has no operator or modifier"
  2489. )
  2490. def visit_truediv_binary(self, binary, operator, **kw):
  2491. if self.dialect.div_is_floordiv:
  2492. return (
  2493. self.process(binary.left, **kw)
  2494. + " / "
  2495. # TODO: would need a fast cast again here,
  2496. # unless we want to use an implicit cast like "+ 0.0"
  2497. + self.process(
  2498. elements.Cast(
  2499. binary.right,
  2500. binary.right.type
  2501. if binary.right.type._type_affinity is sqltypes.Numeric
  2502. else sqltypes.Numeric(),
  2503. ),
  2504. **kw,
  2505. )
  2506. )
  2507. else:
  2508. return (
  2509. self.process(binary.left, **kw)
  2510. + " / "
  2511. + self.process(binary.right, **kw)
  2512. )
  2513. def visit_floordiv_binary(self, binary, operator, **kw):
  2514. if (
  2515. self.dialect.div_is_floordiv
  2516. and binary.right.type._type_affinity is sqltypes.Integer
  2517. ):
  2518. return (
  2519. self.process(binary.left, **kw)
  2520. + " / "
  2521. + self.process(binary.right, **kw)
  2522. )
  2523. else:
  2524. return "FLOOR(%s)" % (
  2525. self.process(binary.left, **kw)
  2526. + " / "
  2527. + self.process(binary.right, **kw)
  2528. )
  2529. def visit_is_true_unary_operator(self, element, operator, **kw):
  2530. if (
  2531. element._is_implicitly_boolean
  2532. or self.dialect.supports_native_boolean
  2533. ):
  2534. return self.process(element.element, **kw)
  2535. else:
  2536. return "%s = 1" % self.process(element.element, **kw)
  2537. def visit_is_false_unary_operator(self, element, operator, **kw):
  2538. if (
  2539. element._is_implicitly_boolean
  2540. or self.dialect.supports_native_boolean
  2541. ):
  2542. return "NOT %s" % self.process(element.element, **kw)
  2543. else:
  2544. return "%s = 0" % self.process(element.element, **kw)
  2545. def visit_not_match_op_binary(self, binary, operator, **kw):
  2546. return "NOT %s" % self.visit_binary(
  2547. binary, override_operator=operators.match_op
  2548. )
  2549. def visit_not_in_op_binary(self, binary, operator, **kw):
  2550. # The brackets are required in the NOT IN operation because the empty
  2551. # case is handled using the form "(col NOT IN (null) OR 1 = 1)".
  2552. # The presence of the OR makes the brackets required.
  2553. return "(%s)" % self._generate_generic_binary(
  2554. binary, OPERATORS[operator], **kw
  2555. )
  2556. def visit_empty_set_op_expr(self, type_, expand_op, **kw):
  2557. if expand_op is operators.not_in_op:
  2558. if len(type_) > 1:
  2559. return "(%s)) OR (1 = 1" % (
  2560. ", ".join("NULL" for element in type_)
  2561. )
  2562. else:
  2563. return "NULL) OR (1 = 1"
  2564. elif expand_op is operators.in_op:
  2565. if len(type_) > 1:
  2566. return "(%s)) AND (1 != 1" % (
  2567. ", ".join("NULL" for element in type_)
  2568. )
  2569. else:
  2570. return "NULL) AND (1 != 1"
  2571. else:
  2572. return self.visit_empty_set_expr(type_)
  2573. def visit_empty_set_expr(self, element_types, **kw):
  2574. raise NotImplementedError(
  2575. "Dialect '%s' does not support empty set expression."
  2576. % self.dialect.name
  2577. )
  2578. def _literal_execute_expanding_parameter_literal_binds(
  2579. self, parameter, values, bind_expression_template=None
  2580. ):
  2581. typ_dialect_impl = parameter.type._unwrapped_dialect_impl(self.dialect)
  2582. if not values:
  2583. # empty IN expression. note we don't need to use
  2584. # bind_expression_template here because there are no
  2585. # expressions to render.
  2586. if typ_dialect_impl._is_tuple_type:
  2587. replacement_expression = (
  2588. "VALUES " if self.dialect.tuple_in_values else ""
  2589. ) + self.visit_empty_set_op_expr(
  2590. parameter.type.types, parameter.expand_op
  2591. )
  2592. else:
  2593. replacement_expression = self.visit_empty_set_op_expr(
  2594. [parameter.type], parameter.expand_op
  2595. )
  2596. elif typ_dialect_impl._is_tuple_type or (
  2597. typ_dialect_impl._isnull
  2598. and isinstance(values[0], collections_abc.Sequence)
  2599. and not isinstance(values[0], (str, bytes))
  2600. ):
  2601. if typ_dialect_impl._has_bind_expression:
  2602. raise NotImplementedError(
  2603. "bind_expression() on TupleType not supported with "
  2604. "literal_binds"
  2605. )
  2606. replacement_expression = (
  2607. "VALUES " if self.dialect.tuple_in_values else ""
  2608. ) + ", ".join(
  2609. "(%s)"
  2610. % (
  2611. ", ".join(
  2612. self.render_literal_value(value, param_type)
  2613. for value, param_type in zip(
  2614. tuple_element, parameter.type.types
  2615. )
  2616. )
  2617. )
  2618. for i, tuple_element in enumerate(values)
  2619. )
  2620. else:
  2621. if bind_expression_template:
  2622. post_compile_pattern = self._post_compile_pattern
  2623. m = post_compile_pattern.search(bind_expression_template)
  2624. assert m and m.group(
  2625. 2
  2626. ), "unexpected format for expanding parameter"
  2627. tok = m.group(2).split("~~")
  2628. be_left, be_right = tok[1], tok[3]
  2629. replacement_expression = ", ".join(
  2630. "%s%s%s"
  2631. % (
  2632. be_left,
  2633. self.render_literal_value(value, parameter.type),
  2634. be_right,
  2635. )
  2636. for value in values
  2637. )
  2638. else:
  2639. replacement_expression = ", ".join(
  2640. self.render_literal_value(value, parameter.type)
  2641. for value in values
  2642. )
  2643. return (), replacement_expression
  2644. def _literal_execute_expanding_parameter(self, name, parameter, values):
  2645. if parameter.literal_execute:
  2646. return self._literal_execute_expanding_parameter_literal_binds(
  2647. parameter, values
  2648. )
  2649. dialect = self.dialect
  2650. typ_dialect_impl = parameter.type._unwrapped_dialect_impl(dialect)
  2651. if self._numeric_binds:
  2652. bind_template = self.compilation_bindtemplate
  2653. else:
  2654. bind_template = self.bindtemplate
  2655. if (
  2656. self.dialect._bind_typing_render_casts
  2657. and typ_dialect_impl.render_bind_cast
  2658. ):
  2659. def _render_bindtemplate(name):
  2660. return self.render_bind_cast(
  2661. parameter.type,
  2662. typ_dialect_impl,
  2663. bind_template % {"name": name},
  2664. )
  2665. else:
  2666. def _render_bindtemplate(name):
  2667. return bind_template % {"name": name}
  2668. if not values:
  2669. to_update = []
  2670. if typ_dialect_impl._is_tuple_type:
  2671. replacement_expression = self.visit_empty_set_op_expr(
  2672. parameter.type.types, parameter.expand_op
  2673. )
  2674. else:
  2675. replacement_expression = self.visit_empty_set_op_expr(
  2676. [parameter.type], parameter.expand_op
  2677. )
  2678. elif typ_dialect_impl._is_tuple_type or (
  2679. typ_dialect_impl._isnull
  2680. and isinstance(values[0], collections_abc.Sequence)
  2681. and not isinstance(values[0], (str, bytes))
  2682. ):
  2683. assert not typ_dialect_impl._is_array
  2684. to_update = [
  2685. ("%s_%s_%s" % (name, i, j), value)
  2686. for i, tuple_element in enumerate(values, 1)
  2687. for j, value in enumerate(tuple_element, 1)
  2688. ]
  2689. replacement_expression = (
  2690. "VALUES " if dialect.tuple_in_values else ""
  2691. ) + ", ".join(
  2692. "(%s)"
  2693. % (
  2694. ", ".join(
  2695. _render_bindtemplate(
  2696. to_update[i * len(tuple_element) + j][0]
  2697. )
  2698. for j, value in enumerate(tuple_element)
  2699. )
  2700. )
  2701. for i, tuple_element in enumerate(values)
  2702. )
  2703. else:
  2704. to_update = [
  2705. ("%s_%s" % (name, i), value)
  2706. for i, value in enumerate(values, 1)
  2707. ]
  2708. replacement_expression = ", ".join(
  2709. _render_bindtemplate(key) for key, value in to_update
  2710. )
  2711. return to_update, replacement_expression
  2712. def visit_binary(
  2713. self,
  2714. binary,
  2715. override_operator=None,
  2716. eager_grouping=False,
  2717. from_linter=None,
  2718. lateral_from_linter=None,
  2719. **kw,
  2720. ):
  2721. if from_linter and operators.is_comparison(binary.operator):
  2722. if lateral_from_linter is not None:
  2723. enclosing_lateral = kw["enclosing_lateral"]
  2724. lateral_from_linter.edges.update(
  2725. itertools.product(
  2726. _de_clone(
  2727. binary.left._from_objects + [enclosing_lateral]
  2728. ),
  2729. _de_clone(
  2730. binary.right._from_objects + [enclosing_lateral]
  2731. ),
  2732. )
  2733. )
  2734. else:
  2735. from_linter.edges.update(
  2736. itertools.product(
  2737. _de_clone(binary.left._from_objects),
  2738. _de_clone(binary.right._from_objects),
  2739. )
  2740. )
  2741. # don't allow "? = ?" to render
  2742. if (
  2743. self.ansi_bind_rules
  2744. and isinstance(binary.left, elements.BindParameter)
  2745. and isinstance(binary.right, elements.BindParameter)
  2746. ):
  2747. kw["literal_execute"] = True
  2748. operator_ = override_operator or binary.operator
  2749. disp = self._get_operator_dispatch(operator_, "binary", None)
  2750. if disp:
  2751. return disp(binary, operator_, **kw)
  2752. else:
  2753. try:
  2754. opstring = OPERATORS[operator_]
  2755. except KeyError as err:
  2756. raise exc.UnsupportedCompilationError(self, operator_) from err
  2757. else:
  2758. return self._generate_generic_binary(
  2759. binary,
  2760. opstring,
  2761. from_linter=from_linter,
  2762. lateral_from_linter=lateral_from_linter,
  2763. **kw,
  2764. )
  2765. def visit_function_as_comparison_op_binary(self, element, operator, **kw):
  2766. return self.process(element.sql_function, **kw)
  2767. def visit_mod_binary(self, binary, operator, **kw):
  2768. if self.preparer._double_percents:
  2769. return (
  2770. self.process(binary.left, **kw)
  2771. + " %% "
  2772. + self.process(binary.right, **kw)
  2773. )
  2774. else:
  2775. return (
  2776. self.process(binary.left, **kw)
  2777. + " % "
  2778. + self.process(binary.right, **kw)
  2779. )
  2780. def visit_custom_op_binary(self, element, operator, **kw):
  2781. kw["eager_grouping"] = operator.eager_grouping
  2782. return self._generate_generic_binary(
  2783. element,
  2784. " " + self.escape_literal_column(operator.opstring) + " ",
  2785. **kw,
  2786. )
  2787. def visit_custom_op_unary_operator(self, element, operator, **kw):
  2788. return self._generate_generic_unary_operator(
  2789. element, self.escape_literal_column(operator.opstring) + " ", **kw
  2790. )
  2791. def visit_custom_op_unary_modifier(self, element, operator, **kw):
  2792. return self._generate_generic_unary_modifier(
  2793. element, " " + self.escape_literal_column(operator.opstring), **kw
  2794. )
  2795. def _generate_generic_binary(
  2796. self, binary, opstring, eager_grouping=False, **kw
  2797. ):
  2798. _in_operator_expression = kw.get("_in_operator_expression", False)
  2799. kw["_in_operator_expression"] = True
  2800. kw["_binary_op"] = binary.operator
  2801. text = (
  2802. binary.left._compiler_dispatch(
  2803. self, eager_grouping=eager_grouping, **kw
  2804. )
  2805. + opstring
  2806. + binary.right._compiler_dispatch(
  2807. self, eager_grouping=eager_grouping, **kw
  2808. )
  2809. )
  2810. if _in_operator_expression and eager_grouping:
  2811. text = "(%s)" % text
  2812. return text
  2813. def _generate_generic_unary_operator(self, unary, opstring, **kw):
  2814. return opstring + unary.element._compiler_dispatch(self, **kw)
  2815. def _generate_generic_unary_modifier(self, unary, opstring, **kw):
  2816. return unary.element._compiler_dispatch(self, **kw) + opstring
  2817. @util.memoized_property
  2818. def _like_percent_literal(self):
  2819. return elements.literal_column("'%'", type_=sqltypes.STRINGTYPE)
  2820. def visit_ilike_case_insensitive_operand(self, element, **kw):
  2821. return f"lower({element.element._compiler_dispatch(self, **kw)})"
  2822. def visit_contains_op_binary(self, binary, operator, **kw):
  2823. binary = binary._clone()
  2824. percent = self._like_percent_literal
  2825. binary.right = percent.concat(binary.right).concat(percent)
  2826. return self.visit_like_op_binary(binary, operator, **kw)
  2827. def visit_not_contains_op_binary(self, binary, operator, **kw):
  2828. binary = binary._clone()
  2829. percent = self._like_percent_literal
  2830. binary.right = percent.concat(binary.right).concat(percent)
  2831. return self.visit_not_like_op_binary(binary, operator, **kw)
  2832. def visit_icontains_op_binary(self, binary, operator, **kw):
  2833. binary = binary._clone()
  2834. percent = self._like_percent_literal
  2835. binary.left = ilike_case_insensitive(binary.left)
  2836. binary.right = percent.concat(
  2837. ilike_case_insensitive(binary.right)
  2838. ).concat(percent)
  2839. return self.visit_ilike_op_binary(binary, operator, **kw)
  2840. def visit_not_icontains_op_binary(self, binary, operator, **kw):
  2841. binary = binary._clone()
  2842. percent = self._like_percent_literal
  2843. binary.left = ilike_case_insensitive(binary.left)
  2844. binary.right = percent.concat(
  2845. ilike_case_insensitive(binary.right)
  2846. ).concat(percent)
  2847. return self.visit_not_ilike_op_binary(binary, operator, **kw)
  2848. def visit_startswith_op_binary(self, binary, operator, **kw):
  2849. binary = binary._clone()
  2850. percent = self._like_percent_literal
  2851. binary.right = percent._rconcat(binary.right)
  2852. return self.visit_like_op_binary(binary, operator, **kw)
  2853. def visit_not_startswith_op_binary(self, binary, operator, **kw):
  2854. binary = binary._clone()
  2855. percent = self._like_percent_literal
  2856. binary.right = percent._rconcat(binary.right)
  2857. return self.visit_not_like_op_binary(binary, operator, **kw)
  2858. def visit_istartswith_op_binary(self, binary, operator, **kw):
  2859. binary = binary._clone()
  2860. percent = self._like_percent_literal
  2861. binary.left = ilike_case_insensitive(binary.left)
  2862. binary.right = percent._rconcat(ilike_case_insensitive(binary.right))
  2863. return self.visit_ilike_op_binary(binary, operator, **kw)
  2864. def visit_not_istartswith_op_binary(self, binary, operator, **kw):
  2865. binary = binary._clone()
  2866. percent = self._like_percent_literal
  2867. binary.left = ilike_case_insensitive(binary.left)
  2868. binary.right = percent._rconcat(ilike_case_insensitive(binary.right))
  2869. return self.visit_not_ilike_op_binary(binary, operator, **kw)
  2870. def visit_endswith_op_binary(self, binary, operator, **kw):
  2871. binary = binary._clone()
  2872. percent = self._like_percent_literal
  2873. binary.right = percent.concat(binary.right)
  2874. return self.visit_like_op_binary(binary, operator, **kw)
  2875. def visit_not_endswith_op_binary(self, binary, operator, **kw):
  2876. binary = binary._clone()
  2877. percent = self._like_percent_literal
  2878. binary.right = percent.concat(binary.right)
  2879. return self.visit_not_like_op_binary(binary, operator, **kw)
  2880. def visit_iendswith_op_binary(self, binary, operator, **kw):
  2881. binary = binary._clone()
  2882. percent = self._like_percent_literal
  2883. binary.left = ilike_case_insensitive(binary.left)
  2884. binary.right = percent.concat(ilike_case_insensitive(binary.right))
  2885. return self.visit_ilike_op_binary(binary, operator, **kw)
  2886. def visit_not_iendswith_op_binary(self, binary, operator, **kw):
  2887. binary = binary._clone()
  2888. percent = self._like_percent_literal
  2889. binary.left = ilike_case_insensitive(binary.left)
  2890. binary.right = percent.concat(ilike_case_insensitive(binary.right))
  2891. return self.visit_not_ilike_op_binary(binary, operator, **kw)
  2892. def visit_like_op_binary(self, binary, operator, **kw):
  2893. escape = binary.modifiers.get("escape", None)
  2894. return "%s LIKE %s" % (
  2895. binary.left._compiler_dispatch(self, **kw),
  2896. binary.right._compiler_dispatch(self, **kw),
  2897. ) + (
  2898. " ESCAPE " + self.render_literal_value(escape, sqltypes.STRINGTYPE)
  2899. if escape is not None
  2900. else ""
  2901. )
  2902. def visit_not_like_op_binary(self, binary, operator, **kw):
  2903. escape = binary.modifiers.get("escape", None)
  2904. return "%s NOT LIKE %s" % (
  2905. binary.left._compiler_dispatch(self, **kw),
  2906. binary.right._compiler_dispatch(self, **kw),
  2907. ) + (
  2908. " ESCAPE " + self.render_literal_value(escape, sqltypes.STRINGTYPE)
  2909. if escape is not None
  2910. else ""
  2911. )
  2912. def visit_ilike_op_binary(self, binary, operator, **kw):
  2913. if operator is operators.ilike_op:
  2914. binary = binary._clone()
  2915. binary.left = ilike_case_insensitive(binary.left)
  2916. binary.right = ilike_case_insensitive(binary.right)
  2917. # else we assume ilower() has been applied
  2918. return self.visit_like_op_binary(binary, operator, **kw)
  2919. def visit_not_ilike_op_binary(self, binary, operator, **kw):
  2920. if operator is operators.not_ilike_op:
  2921. binary = binary._clone()
  2922. binary.left = ilike_case_insensitive(binary.left)
  2923. binary.right = ilike_case_insensitive(binary.right)
  2924. # else we assume ilower() has been applied
  2925. return self.visit_not_like_op_binary(binary, operator, **kw)
  2926. def visit_between_op_binary(self, binary, operator, **kw):
  2927. symmetric = binary.modifiers.get("symmetric", False)
  2928. return self._generate_generic_binary(
  2929. binary, " BETWEEN SYMMETRIC " if symmetric else " BETWEEN ", **kw
  2930. )
  2931. def visit_not_between_op_binary(self, binary, operator, **kw):
  2932. symmetric = binary.modifiers.get("symmetric", False)
  2933. return self._generate_generic_binary(
  2934. binary,
  2935. " NOT BETWEEN SYMMETRIC " if symmetric else " NOT BETWEEN ",
  2936. **kw,
  2937. )
  2938. def visit_regexp_match_op_binary(self, binary, operator, **kw):
  2939. raise exc.CompileError(
  2940. "%s dialect does not support regular expressions"
  2941. % self.dialect.name
  2942. )
  2943. def visit_not_regexp_match_op_binary(self, binary, operator, **kw):
  2944. raise exc.CompileError(
  2945. "%s dialect does not support regular expressions"
  2946. % self.dialect.name
  2947. )
  2948. def visit_regexp_replace_op_binary(self, binary, operator, **kw):
  2949. raise exc.CompileError(
  2950. "%s dialect does not support regular expression replacements"
  2951. % self.dialect.name
  2952. )
  2953. def visit_bindparam(
  2954. self,
  2955. bindparam,
  2956. within_columns_clause=False,
  2957. literal_binds=False,
  2958. skip_bind_expression=False,
  2959. literal_execute=False,
  2960. render_postcompile=False,
  2961. **kwargs,
  2962. ):
  2963. if not skip_bind_expression:
  2964. impl = bindparam.type.dialect_impl(self.dialect)
  2965. if impl._has_bind_expression:
  2966. bind_expression = impl.bind_expression(bindparam)
  2967. wrapped = self.process(
  2968. bind_expression,
  2969. skip_bind_expression=True,
  2970. within_columns_clause=within_columns_clause,
  2971. literal_binds=literal_binds and not bindparam.expanding,
  2972. literal_execute=literal_execute,
  2973. render_postcompile=render_postcompile,
  2974. **kwargs,
  2975. )
  2976. if bindparam.expanding:
  2977. # for postcompile w/ expanding, move the "wrapped" part
  2978. # of this into the inside
  2979. m = re.match(
  2980. r"^(.*)\(__\[POSTCOMPILE_(\S+?)\]\)(.*)$", wrapped
  2981. )
  2982. assert m, "unexpected format for expanding parameter"
  2983. wrapped = "(__[POSTCOMPILE_%s~~%s~~REPL~~%s~~])" % (
  2984. m.group(2),
  2985. m.group(1),
  2986. m.group(3),
  2987. )
  2988. if literal_binds:
  2989. ret = self.render_literal_bindparam(
  2990. bindparam,
  2991. within_columns_clause=True,
  2992. bind_expression_template=wrapped,
  2993. **kwargs,
  2994. )
  2995. return "(%s)" % ret
  2996. return wrapped
  2997. if not literal_binds:
  2998. literal_execute = (
  2999. literal_execute
  3000. or bindparam.literal_execute
  3001. or (within_columns_clause and self.ansi_bind_rules)
  3002. )
  3003. post_compile = literal_execute or bindparam.expanding
  3004. else:
  3005. post_compile = False
  3006. if literal_binds:
  3007. ret = self.render_literal_bindparam(
  3008. bindparam, within_columns_clause=True, **kwargs
  3009. )
  3010. if bindparam.expanding:
  3011. ret = "(%s)" % ret
  3012. return ret
  3013. name = self._truncate_bindparam(bindparam)
  3014. if name in self.binds:
  3015. existing = self.binds[name]
  3016. if existing is not bindparam:
  3017. if (
  3018. (existing.unique or bindparam.unique)
  3019. and not existing.proxy_set.intersection(
  3020. bindparam.proxy_set
  3021. )
  3022. and not existing._cloned_set.intersection(
  3023. bindparam._cloned_set
  3024. )
  3025. ):
  3026. raise exc.CompileError(
  3027. "Bind parameter '%s' conflicts with "
  3028. "unique bind parameter of the same name" % name
  3029. )
  3030. elif existing.expanding != bindparam.expanding:
  3031. raise exc.CompileError(
  3032. "Can't reuse bound parameter name '%s' in both "
  3033. "'expanding' (e.g. within an IN expression) and "
  3034. "non-expanding contexts. If this parameter is to "
  3035. "receive a list/array value, set 'expanding=True' on "
  3036. "it for expressions that aren't IN, otherwise use "
  3037. "a different parameter name." % (name,)
  3038. )
  3039. elif existing._is_crud or bindparam._is_crud:
  3040. if existing._is_crud and bindparam._is_crud:
  3041. # TODO: this condition is not well understood.
  3042. # see tests in test/sql/test_update.py
  3043. raise exc.CompileError(
  3044. "Encountered unsupported case when compiling an "
  3045. "INSERT or UPDATE statement. If this is a "
  3046. "multi-table "
  3047. "UPDATE statement, please provide string-named "
  3048. "arguments to the "
  3049. "values() method with distinct names; support for "
  3050. "multi-table UPDATE statements that "
  3051. "target multiple tables for UPDATE is very "
  3052. "limited",
  3053. )
  3054. else:
  3055. raise exc.CompileError(
  3056. f"bindparam() name '{bindparam.key}' is reserved "
  3057. "for automatic usage in the VALUES or SET "
  3058. "clause of this "
  3059. "insert/update statement. Please use a "
  3060. "name other than column name when using "
  3061. "bindparam() "
  3062. "with insert() or update() (for example, "
  3063. f"'b_{bindparam.key}')."
  3064. )
  3065. self.binds[bindparam.key] = self.binds[name] = bindparam
  3066. # if we are given a cache key that we're going to match against,
  3067. # relate the bindparam here to one that is most likely present
  3068. # in the "extracted params" portion of the cache key. this is used
  3069. # to set up a positional mapping that is used to determine the
  3070. # correct parameters for a subsequent use of this compiled with
  3071. # a different set of parameter values. here, we accommodate for
  3072. # parameters that may have been cloned both before and after the cache
  3073. # key was been generated.
  3074. ckbm_tuple = self._cache_key_bind_match
  3075. if ckbm_tuple:
  3076. ckbm, cksm = ckbm_tuple
  3077. for bp in bindparam._cloned_set:
  3078. if bp.key in cksm:
  3079. cb = cksm[bp.key]
  3080. ckbm[cb].append(bindparam)
  3081. if bindparam.isoutparam:
  3082. self.has_out_parameters = True
  3083. if post_compile:
  3084. if render_postcompile:
  3085. self._render_postcompile = True
  3086. if literal_execute:
  3087. self.literal_execute_params |= {bindparam}
  3088. else:
  3089. self.post_compile_params |= {bindparam}
  3090. ret = self.bindparam_string(
  3091. name,
  3092. post_compile=post_compile,
  3093. expanding=bindparam.expanding,
  3094. bindparam_type=bindparam.type,
  3095. **kwargs,
  3096. )
  3097. if bindparam.expanding:
  3098. ret = "(%s)" % ret
  3099. return ret
  3100. def render_bind_cast(self, type_, dbapi_type, sqltext):
  3101. raise NotImplementedError()
  3102. def render_literal_bindparam(
  3103. self,
  3104. bindparam,
  3105. render_literal_value=NO_ARG,
  3106. bind_expression_template=None,
  3107. **kw,
  3108. ):
  3109. if render_literal_value is not NO_ARG:
  3110. value = render_literal_value
  3111. else:
  3112. if bindparam.value is None and bindparam.callable is None:
  3113. op = kw.get("_binary_op", None)
  3114. if op and op not in (operators.is_, operators.is_not):
  3115. util.warn_limited(
  3116. "Bound parameter '%s' rendering literal NULL in a SQL "
  3117. "expression; comparisons to NULL should not use "
  3118. "operators outside of 'is' or 'is not'",
  3119. (bindparam.key,),
  3120. )
  3121. return self.process(sqltypes.NULLTYPE, **kw)
  3122. value = bindparam.effective_value
  3123. if bindparam.expanding:
  3124. leep = self._literal_execute_expanding_parameter_literal_binds
  3125. to_update, replacement_expr = leep(
  3126. bindparam,
  3127. value,
  3128. bind_expression_template=bind_expression_template,
  3129. )
  3130. return replacement_expr
  3131. else:
  3132. return self.render_literal_value(value, bindparam.type)
  3133. def render_literal_value(self, value, type_):
  3134. """Render the value of a bind parameter as a quoted literal.
  3135. This is used for statement sections that do not accept bind parameters
  3136. on the target driver/database.
  3137. This should be implemented by subclasses using the quoting services
  3138. of the DBAPI.
  3139. """
  3140. if value is None and not type_.should_evaluate_none:
  3141. # issue #10535 - handle NULL in the compiler without placing
  3142. # this onto each type, except for "evaluate None" types
  3143. # (e.g. JSON)
  3144. return self.process(elements.Null._instance())
  3145. processor = type_._cached_literal_processor(self.dialect)
  3146. if processor:
  3147. try:
  3148. return processor(value)
  3149. except Exception as e:
  3150. raise exc.CompileError(
  3151. f"Could not render literal value "
  3152. f'"{sql_util._repr_single_value(value)}" '
  3153. f"with datatype "
  3154. f"{type_}; see parent stack trace for "
  3155. "more detail."
  3156. ) from e
  3157. else:
  3158. raise exc.CompileError(
  3159. f"No literal value renderer is available for literal value "
  3160. f'"{sql_util._repr_single_value(value)}" '
  3161. f"with datatype {type_}"
  3162. )
  3163. def _truncate_bindparam(self, bindparam):
  3164. if bindparam in self.bind_names:
  3165. return self.bind_names[bindparam]
  3166. bind_name = bindparam.key
  3167. if isinstance(bind_name, elements._truncated_label):
  3168. bind_name = self._truncated_identifier("bindparam", bind_name)
  3169. # add to bind_names for translation
  3170. self.bind_names[bindparam] = bind_name
  3171. return bind_name
  3172. def _truncated_identifier(
  3173. self, ident_class: str, name: _truncated_label
  3174. ) -> str:
  3175. if (ident_class, name) in self.truncated_names:
  3176. return self.truncated_names[(ident_class, name)]
  3177. anonname = name.apply_map(self.anon_map)
  3178. if len(anonname) > self.label_length - 6:
  3179. counter = self._truncated_counters.get(ident_class, 1)
  3180. truncname = (
  3181. anonname[0 : max(self.label_length - 6, 0)]
  3182. + "_"
  3183. + hex(counter)[2:]
  3184. )
  3185. self._truncated_counters[ident_class] = counter + 1
  3186. else:
  3187. truncname = anonname
  3188. self.truncated_names[(ident_class, name)] = truncname
  3189. return truncname
  3190. def _anonymize(self, name: str) -> str:
  3191. return name % self.anon_map
  3192. def bindparam_string(
  3193. self,
  3194. name: str,
  3195. post_compile: bool = False,
  3196. expanding: bool = False,
  3197. escaped_from: Optional[str] = None,
  3198. bindparam_type: Optional[TypeEngine[Any]] = None,
  3199. accumulate_bind_names: Optional[Set[str]] = None,
  3200. visited_bindparam: Optional[List[str]] = None,
  3201. **kw: Any,
  3202. ) -> str:
  3203. # TODO: accumulate_bind_names is passed by crud.py to gather
  3204. # names on a per-value basis, visited_bindparam is passed by
  3205. # visit_insert() to collect all parameters in the statement.
  3206. # see if this gathering can be simplified somehow
  3207. if accumulate_bind_names is not None:
  3208. accumulate_bind_names.add(name)
  3209. if visited_bindparam is not None:
  3210. visited_bindparam.append(name)
  3211. if not escaped_from:
  3212. if self._bind_translate_re.search(name):
  3213. # not quite the translate use case as we want to
  3214. # also get a quick boolean if we even found
  3215. # unusual characters in the name
  3216. new_name = self._bind_translate_re.sub(
  3217. lambda m: self._bind_translate_chars[m.group(0)],
  3218. name,
  3219. )
  3220. escaped_from = name
  3221. name = new_name
  3222. if escaped_from:
  3223. self.escaped_bind_names = self.escaped_bind_names.union(
  3224. {escaped_from: name}
  3225. )
  3226. if post_compile:
  3227. ret = "__[POSTCOMPILE_%s]" % name
  3228. if expanding:
  3229. # for expanding, bound parameters or literal values will be
  3230. # rendered per item
  3231. return ret
  3232. # otherwise, for non-expanding "literal execute", apply
  3233. # bind casts as determined by the datatype
  3234. if bindparam_type is not None:
  3235. type_impl = bindparam_type._unwrapped_dialect_impl(
  3236. self.dialect
  3237. )
  3238. if type_impl.render_literal_cast:
  3239. ret = self.render_bind_cast(bindparam_type, type_impl, ret)
  3240. return ret
  3241. elif self.state is CompilerState.COMPILING:
  3242. ret = self.compilation_bindtemplate % {"name": name}
  3243. else:
  3244. ret = self.bindtemplate % {"name": name}
  3245. if (
  3246. bindparam_type is not None
  3247. and self.dialect._bind_typing_render_casts
  3248. ):
  3249. type_impl = bindparam_type._unwrapped_dialect_impl(self.dialect)
  3250. if type_impl.render_bind_cast:
  3251. ret = self.render_bind_cast(bindparam_type, type_impl, ret)
  3252. return ret
  3253. def _dispatch_independent_ctes(self, stmt, kw):
  3254. local_kw = kw.copy()
  3255. local_kw.pop("cte_opts", None)
  3256. for cte, opt in zip(
  3257. stmt._independent_ctes, stmt._independent_ctes_opts
  3258. ):
  3259. cte._compiler_dispatch(self, cte_opts=opt, **local_kw)
  3260. def visit_cte(
  3261. self,
  3262. cte: CTE,
  3263. asfrom: bool = False,
  3264. ashint: bool = False,
  3265. fromhints: Optional[_FromHintsType] = None,
  3266. visiting_cte: Optional[CTE] = None,
  3267. from_linter: Optional[FromLinter] = None,
  3268. cte_opts: selectable._CTEOpts = selectable._CTEOpts(False),
  3269. **kwargs: Any,
  3270. ) -> Optional[str]:
  3271. self_ctes = self._init_cte_state()
  3272. assert self_ctes is self.ctes
  3273. kwargs["visiting_cte"] = cte
  3274. cte_name = cte.name
  3275. if isinstance(cte_name, elements._truncated_label):
  3276. cte_name = self._truncated_identifier("alias", cte_name)
  3277. is_new_cte = True
  3278. embedded_in_current_named_cte = False
  3279. _reference_cte = cte._get_reference_cte()
  3280. nesting = cte.nesting or cte_opts.nesting
  3281. # check for CTE already encountered
  3282. if _reference_cte in self.level_name_by_cte:
  3283. cte_level, _, existing_cte_opts = self.level_name_by_cte[
  3284. _reference_cte
  3285. ]
  3286. assert _ == cte_name
  3287. cte_level_name = (cte_level, cte_name)
  3288. existing_cte = self.ctes_by_level_name[cte_level_name]
  3289. # check if we are receiving it here with a specific
  3290. # "nest_here" location; if so, move it to this location
  3291. if cte_opts.nesting:
  3292. if existing_cte_opts.nesting:
  3293. raise exc.CompileError(
  3294. "CTE is stated as 'nest_here' in "
  3295. "more than one location"
  3296. )
  3297. old_level_name = (cte_level, cte_name)
  3298. cte_level = len(self.stack) if nesting else 1
  3299. cte_level_name = new_level_name = (cte_level, cte_name)
  3300. del self.ctes_by_level_name[old_level_name]
  3301. self.ctes_by_level_name[new_level_name] = existing_cte
  3302. self.level_name_by_cte[_reference_cte] = new_level_name + (
  3303. cte_opts,
  3304. )
  3305. else:
  3306. cte_level = len(self.stack) if nesting else 1
  3307. cte_level_name = (cte_level, cte_name)
  3308. if cte_level_name in self.ctes_by_level_name:
  3309. existing_cte = self.ctes_by_level_name[cte_level_name]
  3310. else:
  3311. existing_cte = None
  3312. if existing_cte is not None:
  3313. embedded_in_current_named_cte = visiting_cte is existing_cte
  3314. # we've generated a same-named CTE that we are enclosed in,
  3315. # or this is the same CTE. just return the name.
  3316. if cte is existing_cte._restates or cte is existing_cte:
  3317. is_new_cte = False
  3318. elif existing_cte is cte._restates:
  3319. # we've generated a same-named CTE that is
  3320. # enclosed in us - we take precedence, so
  3321. # discard the text for the "inner".
  3322. del self_ctes[existing_cte]
  3323. existing_cte_reference_cte = existing_cte._get_reference_cte()
  3324. assert existing_cte_reference_cte is _reference_cte
  3325. assert existing_cte_reference_cte is existing_cte
  3326. del self.level_name_by_cte[existing_cte_reference_cte]
  3327. else:
  3328. # if the two CTEs are deep-copy identical, consider them
  3329. # the same, **if** they are clones, that is, they came from
  3330. # the ORM or other visit method
  3331. if (
  3332. cte._is_clone_of is not None
  3333. or existing_cte._is_clone_of is not None
  3334. ) and cte.compare(existing_cte):
  3335. is_new_cte = False
  3336. else:
  3337. raise exc.CompileError(
  3338. "Multiple, unrelated CTEs found with "
  3339. "the same name: %r" % cte_name
  3340. )
  3341. if not asfrom and not is_new_cte:
  3342. return None
  3343. if cte._cte_alias is not None:
  3344. pre_alias_cte = cte._cte_alias
  3345. cte_pre_alias_name = cte._cte_alias.name
  3346. if isinstance(cte_pre_alias_name, elements._truncated_label):
  3347. cte_pre_alias_name = self._truncated_identifier(
  3348. "alias", cte_pre_alias_name
  3349. )
  3350. else:
  3351. pre_alias_cte = cte
  3352. cte_pre_alias_name = None
  3353. if is_new_cte:
  3354. self.ctes_by_level_name[cte_level_name] = cte
  3355. self.level_name_by_cte[_reference_cte] = cte_level_name + (
  3356. cte_opts,
  3357. )
  3358. if pre_alias_cte not in self.ctes:
  3359. self.visit_cte(pre_alias_cte, **kwargs)
  3360. if not cte_pre_alias_name and cte not in self_ctes:
  3361. if cte.recursive:
  3362. self.ctes_recursive = True
  3363. text = self.preparer.format_alias(cte, cte_name)
  3364. if cte.recursive:
  3365. col_source = cte.element
  3366. # TODO: can we get at the .columns_plus_names collection
  3367. # that is already (or will be?) generated for the SELECT
  3368. # rather than calling twice?
  3369. recur_cols = [
  3370. # TODO: proxy_name is not technically safe,
  3371. # see test_cte->
  3372. # test_with_recursive_no_name_currently_buggy. not
  3373. # clear what should be done with such a case
  3374. fallback_label_name or proxy_name
  3375. for (
  3376. _,
  3377. proxy_name,
  3378. fallback_label_name,
  3379. c,
  3380. repeated,
  3381. ) in (col_source._generate_columns_plus_names(True))
  3382. if not repeated
  3383. ]
  3384. text += "(%s)" % (
  3385. ", ".join(
  3386. self.preparer.format_label_name(
  3387. ident, anon_map=self.anon_map
  3388. )
  3389. for ident in recur_cols
  3390. )
  3391. )
  3392. assert kwargs.get("subquery", False) is False
  3393. if not self.stack:
  3394. # toplevel, this is a stringify of the
  3395. # cte directly. just compile the inner
  3396. # the way alias() does.
  3397. return cte.element._compiler_dispatch(
  3398. self, asfrom=asfrom, **kwargs
  3399. )
  3400. else:
  3401. prefixes = self._generate_prefixes(
  3402. cte, cte._prefixes, **kwargs
  3403. )
  3404. inner = cte.element._compiler_dispatch(
  3405. self, asfrom=True, **kwargs
  3406. )
  3407. text += " AS %s\n(%s)" % (prefixes, inner)
  3408. if cte._suffixes:
  3409. text += " " + self._generate_prefixes(
  3410. cte, cte._suffixes, **kwargs
  3411. )
  3412. self_ctes[cte] = text
  3413. if asfrom:
  3414. if from_linter:
  3415. from_linter.froms[cte._de_clone()] = cte_name
  3416. if not is_new_cte and embedded_in_current_named_cte:
  3417. return self.preparer.format_alias(cte, cte_name)
  3418. if cte_pre_alias_name:
  3419. text = self.preparer.format_alias(cte, cte_pre_alias_name)
  3420. if self.preparer._requires_quotes(cte_name):
  3421. cte_name = self.preparer.quote(cte_name)
  3422. text += self.get_render_as_alias_suffix(cte_name)
  3423. return text
  3424. else:
  3425. return self.preparer.format_alias(cte, cte_name)
  3426. return None
  3427. def visit_table_valued_alias(self, element, **kw):
  3428. if element.joins_implicitly:
  3429. kw["from_linter"] = None
  3430. if element._is_lateral:
  3431. return self.visit_lateral(element, **kw)
  3432. else:
  3433. return self.visit_alias(element, **kw)
  3434. def visit_table_valued_column(self, element, **kw):
  3435. return self.visit_column(element, **kw)
  3436. def visit_alias(
  3437. self,
  3438. alias,
  3439. asfrom=False,
  3440. ashint=False,
  3441. iscrud=False,
  3442. fromhints=None,
  3443. subquery=False,
  3444. lateral=False,
  3445. enclosing_alias=None,
  3446. from_linter=None,
  3447. **kwargs,
  3448. ):
  3449. if lateral:
  3450. if "enclosing_lateral" not in kwargs:
  3451. # if lateral is set and enclosing_lateral is not
  3452. # present, we assume we are being called directly
  3453. # from visit_lateral() and we need to set enclosing_lateral.
  3454. assert alias._is_lateral
  3455. kwargs["enclosing_lateral"] = alias
  3456. # for lateral objects, we track a second from_linter that is...
  3457. # lateral! to the level above us.
  3458. if (
  3459. from_linter
  3460. and "lateral_from_linter" not in kwargs
  3461. and "enclosing_lateral" in kwargs
  3462. ):
  3463. kwargs["lateral_from_linter"] = from_linter
  3464. if enclosing_alias is not None and enclosing_alias.element is alias:
  3465. inner = alias.element._compiler_dispatch(
  3466. self,
  3467. asfrom=asfrom,
  3468. ashint=ashint,
  3469. iscrud=iscrud,
  3470. fromhints=fromhints,
  3471. lateral=lateral,
  3472. enclosing_alias=alias,
  3473. **kwargs,
  3474. )
  3475. if subquery and (asfrom or lateral):
  3476. inner = "(%s)" % (inner,)
  3477. return inner
  3478. else:
  3479. enclosing_alias = kwargs["enclosing_alias"] = alias
  3480. if asfrom or ashint:
  3481. if isinstance(alias.name, elements._truncated_label):
  3482. alias_name = self._truncated_identifier("alias", alias.name)
  3483. else:
  3484. alias_name = alias.name
  3485. if ashint:
  3486. return self.preparer.format_alias(alias, alias_name)
  3487. elif asfrom:
  3488. if from_linter:
  3489. from_linter.froms[alias._de_clone()] = alias_name
  3490. inner = alias.element._compiler_dispatch(
  3491. self, asfrom=True, lateral=lateral, **kwargs
  3492. )
  3493. if subquery:
  3494. inner = "(%s)" % (inner,)
  3495. ret = inner + self.get_render_as_alias_suffix(
  3496. self.preparer.format_alias(alias, alias_name)
  3497. )
  3498. if alias._supports_derived_columns and alias._render_derived:
  3499. ret += "(%s)" % (
  3500. ", ".join(
  3501. "%s%s"
  3502. % (
  3503. self.preparer.quote(col.name),
  3504. " %s"
  3505. % self.dialect.type_compiler_instance.process(
  3506. col.type, **kwargs
  3507. )
  3508. if alias._render_derived_w_types
  3509. else "",
  3510. )
  3511. for col in alias.c
  3512. )
  3513. )
  3514. if fromhints and alias in fromhints:
  3515. ret = self.format_from_hint_text(
  3516. ret, alias, fromhints[alias], iscrud
  3517. )
  3518. return ret
  3519. else:
  3520. # note we cancel the "subquery" flag here as well
  3521. return alias.element._compiler_dispatch(
  3522. self, lateral=lateral, **kwargs
  3523. )
  3524. def visit_subquery(self, subquery, **kw):
  3525. kw["subquery"] = True
  3526. return self.visit_alias(subquery, **kw)
  3527. def visit_lateral(self, lateral_, **kw):
  3528. kw["lateral"] = True
  3529. return "LATERAL %s" % self.visit_alias(lateral_, **kw)
  3530. def visit_tablesample(self, tablesample, asfrom=False, **kw):
  3531. text = "%s TABLESAMPLE %s" % (
  3532. self.visit_alias(tablesample, asfrom=True, **kw),
  3533. tablesample._get_method()._compiler_dispatch(self, **kw),
  3534. )
  3535. if tablesample.seed is not None:
  3536. text += " REPEATABLE (%s)" % (
  3537. tablesample.seed._compiler_dispatch(self, **kw)
  3538. )
  3539. return text
  3540. def _render_values(self, element, **kw):
  3541. kw.setdefault("literal_binds", element.literal_binds)
  3542. tuples = ", ".join(
  3543. self.process(
  3544. elements.Tuple(
  3545. types=element._column_types, *elem
  3546. ).self_group(),
  3547. **kw,
  3548. )
  3549. for chunk in element._data
  3550. for elem in chunk
  3551. )
  3552. return f"VALUES {tuples}"
  3553. def visit_values(self, element, asfrom=False, from_linter=None, **kw):
  3554. v = self._render_values(element, **kw)
  3555. if element._unnamed:
  3556. name = None
  3557. elif isinstance(element.name, elements._truncated_label):
  3558. name = self._truncated_identifier("values", element.name)
  3559. else:
  3560. name = element.name
  3561. if element._is_lateral:
  3562. lateral = "LATERAL "
  3563. else:
  3564. lateral = ""
  3565. if asfrom:
  3566. if from_linter:
  3567. from_linter.froms[element._de_clone()] = (
  3568. name if name is not None else "(unnamed VALUES element)"
  3569. )
  3570. if name:
  3571. kw["include_table"] = False
  3572. v = "%s(%s)%s (%s)" % (
  3573. lateral,
  3574. v,
  3575. self.get_render_as_alias_suffix(self.preparer.quote(name)),
  3576. (
  3577. ", ".join(
  3578. c._compiler_dispatch(self, **kw)
  3579. for c in element.columns
  3580. )
  3581. ),
  3582. )
  3583. else:
  3584. v = "%s(%s)" % (lateral, v)
  3585. return v
  3586. def visit_scalar_values(self, element, **kw):
  3587. return f"({self._render_values(element, **kw)})"
  3588. def get_render_as_alias_suffix(self, alias_name_text):
  3589. return " AS " + alias_name_text
  3590. def _add_to_result_map(
  3591. self,
  3592. keyname: str,
  3593. name: str,
  3594. objects: Tuple[Any, ...],
  3595. type_: TypeEngine[Any],
  3596. ) -> None:
  3597. if keyname is None or keyname == "*":
  3598. self._ordered_columns = False
  3599. self._ad_hoc_textual = True
  3600. if type_._is_tuple_type:
  3601. raise exc.CompileError(
  3602. "Most backends don't support SELECTing "
  3603. "from a tuple() object. If this is an ORM query, "
  3604. "consider using the Bundle object."
  3605. )
  3606. self._result_columns.append(
  3607. ResultColumnsEntry(keyname, name, objects, type_)
  3608. )
  3609. def _label_returning_column(
  3610. self, stmt, column, populate_result_map, column_clause_args=None, **kw
  3611. ):
  3612. """Render a column with necessary labels inside of a RETURNING clause.
  3613. This method is provided for individual dialects in place of calling
  3614. the _label_select_column method directly, so that the two use cases
  3615. of RETURNING vs. SELECT can be disambiguated going forward.
  3616. .. versionadded:: 1.4.21
  3617. """
  3618. return self._label_select_column(
  3619. None,
  3620. column,
  3621. populate_result_map,
  3622. False,
  3623. {} if column_clause_args is None else column_clause_args,
  3624. **kw,
  3625. )
  3626. def _label_select_column(
  3627. self,
  3628. select,
  3629. column,
  3630. populate_result_map,
  3631. asfrom,
  3632. column_clause_args,
  3633. name=None,
  3634. proxy_name=None,
  3635. fallback_label_name=None,
  3636. within_columns_clause=True,
  3637. column_is_repeated=False,
  3638. need_column_expressions=False,
  3639. include_table=True,
  3640. ):
  3641. """produce labeled columns present in a select()."""
  3642. impl = column.type.dialect_impl(self.dialect)
  3643. if impl._has_column_expression and (
  3644. need_column_expressions or populate_result_map
  3645. ):
  3646. col_expr = impl.column_expression(column)
  3647. else:
  3648. col_expr = column
  3649. if populate_result_map:
  3650. # pass an "add_to_result_map" callable into the compilation
  3651. # of embedded columns. this collects information about the
  3652. # column as it will be fetched in the result and is coordinated
  3653. # with cursor.description when the query is executed.
  3654. add_to_result_map = self._add_to_result_map
  3655. # if the SELECT statement told us this column is a repeat,
  3656. # wrap the callable with one that prevents the addition of the
  3657. # targets
  3658. if column_is_repeated:
  3659. _add_to_result_map = add_to_result_map
  3660. def add_to_result_map(keyname, name, objects, type_):
  3661. _add_to_result_map(keyname, name, (), type_)
  3662. # if we redefined col_expr for type expressions, wrap the
  3663. # callable with one that adds the original column to the targets
  3664. elif col_expr is not column:
  3665. _add_to_result_map = add_to_result_map
  3666. def add_to_result_map(keyname, name, objects, type_):
  3667. _add_to_result_map(
  3668. keyname, name, (column,) + objects, type_
  3669. )
  3670. else:
  3671. add_to_result_map = None
  3672. # this method is used by some of the dialects for RETURNING,
  3673. # which has different inputs. _label_returning_column was added
  3674. # as the better target for this now however for 1.4 we will keep
  3675. # _label_select_column directly compatible with this use case.
  3676. # these assertions right now set up the current expected inputs
  3677. assert within_columns_clause, (
  3678. "_label_select_column is only relevant within "
  3679. "the columns clause of a SELECT or RETURNING"
  3680. )
  3681. if isinstance(column, elements.Label):
  3682. if col_expr is not column:
  3683. result_expr = _CompileLabel(
  3684. col_expr, column.name, alt_names=(column.element,)
  3685. )
  3686. else:
  3687. result_expr = col_expr
  3688. elif name:
  3689. # here, _columns_plus_names has determined there's an explicit
  3690. # label name we need to use. this is the default for
  3691. # tablenames_plus_columnnames as well as when columns are being
  3692. # deduplicated on name
  3693. assert (
  3694. proxy_name is not None
  3695. ), "proxy_name is required if 'name' is passed"
  3696. result_expr = _CompileLabel(
  3697. col_expr,
  3698. name,
  3699. alt_names=(
  3700. proxy_name,
  3701. # this is a hack to allow legacy result column lookups
  3702. # to work as they did before; this goes away in 2.0.
  3703. # TODO: this only seems to be tested indirectly
  3704. # via test/orm/test_deprecations.py. should be a
  3705. # resultset test for this
  3706. column._tq_label,
  3707. ),
  3708. )
  3709. else:
  3710. # determine here whether this column should be rendered in
  3711. # a labelled context or not, as we were given no required label
  3712. # name from the caller. Here we apply heuristics based on the kind
  3713. # of SQL expression involved.
  3714. if col_expr is not column:
  3715. # type-specific expression wrapping the given column,
  3716. # so we render a label
  3717. render_with_label = True
  3718. elif isinstance(column, elements.ColumnClause):
  3719. # table-bound column, we render its name as a label if we are
  3720. # inside of a subquery only
  3721. render_with_label = (
  3722. asfrom
  3723. and not column.is_literal
  3724. and column.table is not None
  3725. )
  3726. elif isinstance(column, elements.TextClause):
  3727. render_with_label = False
  3728. elif isinstance(column, elements.UnaryExpression):
  3729. render_with_label = column.wraps_column_expression or asfrom
  3730. elif (
  3731. # general class of expressions that don't have a SQL-column
  3732. # addressible name. includes scalar selects, bind parameters,
  3733. # SQL functions, others
  3734. not isinstance(column, elements.NamedColumn)
  3735. # deeper check that indicates there's no natural "name" to
  3736. # this element, which accommodates for custom SQL constructs
  3737. # that might have a ".name" attribute (but aren't SQL
  3738. # functions) but are not implementing this more recently added
  3739. # base class. in theory the "NamedColumn" check should be
  3740. # enough, however here we seek to maintain legacy behaviors
  3741. # as well.
  3742. and column._non_anon_label is None
  3743. ):
  3744. render_with_label = True
  3745. else:
  3746. render_with_label = False
  3747. if render_with_label:
  3748. if not fallback_label_name:
  3749. # used by the RETURNING case right now. we generate it
  3750. # here as 3rd party dialects may be referring to
  3751. # _label_select_column method directly instead of the
  3752. # just-added _label_returning_column method
  3753. assert not column_is_repeated
  3754. fallback_label_name = column._anon_name_label
  3755. fallback_label_name = (
  3756. elements._truncated_label(fallback_label_name)
  3757. if not isinstance(
  3758. fallback_label_name, elements._truncated_label
  3759. )
  3760. else fallback_label_name
  3761. )
  3762. result_expr = _CompileLabel(
  3763. col_expr, fallback_label_name, alt_names=(proxy_name,)
  3764. )
  3765. else:
  3766. result_expr = col_expr
  3767. column_clause_args.update(
  3768. within_columns_clause=within_columns_clause,
  3769. add_to_result_map=add_to_result_map,
  3770. include_table=include_table,
  3771. )
  3772. return result_expr._compiler_dispatch(self, **column_clause_args)
  3773. def format_from_hint_text(self, sqltext, table, hint, iscrud):
  3774. hinttext = self.get_from_hint_text(table, hint)
  3775. if hinttext:
  3776. sqltext += " " + hinttext
  3777. return sqltext
  3778. def get_select_hint_text(self, byfroms):
  3779. return None
  3780. def get_from_hint_text(self, table, text):
  3781. return None
  3782. def get_crud_hint_text(self, table, text):
  3783. return None
  3784. def get_statement_hint_text(self, hint_texts):
  3785. return " ".join(hint_texts)
  3786. _default_stack_entry: _CompilerStackEntry
  3787. if not typing.TYPE_CHECKING:
  3788. _default_stack_entry = util.immutabledict(
  3789. [("correlate_froms", frozenset()), ("asfrom_froms", frozenset())]
  3790. )
  3791. def _display_froms_for_select(
  3792. self, select_stmt, asfrom, lateral=False, **kw
  3793. ):
  3794. # utility method to help external dialects
  3795. # get the correct from list for a select.
  3796. # specifically the oracle dialect needs this feature
  3797. # right now.
  3798. toplevel = not self.stack
  3799. entry = self._default_stack_entry if toplevel else self.stack[-1]
  3800. compile_state = select_stmt._compile_state_factory(select_stmt, self)
  3801. correlate_froms = entry["correlate_froms"]
  3802. asfrom_froms = entry["asfrom_froms"]
  3803. if asfrom and not lateral:
  3804. froms = compile_state._get_display_froms(
  3805. explicit_correlate_froms=correlate_froms.difference(
  3806. asfrom_froms
  3807. ),
  3808. implicit_correlate_froms=(),
  3809. )
  3810. else:
  3811. froms = compile_state._get_display_froms(
  3812. explicit_correlate_froms=correlate_froms,
  3813. implicit_correlate_froms=asfrom_froms,
  3814. )
  3815. return froms
  3816. translate_select_structure: Any = None
  3817. """if not ``None``, should be a callable which accepts ``(select_stmt,
  3818. **kw)`` and returns a select object. this is used for structural changes
  3819. mostly to accommodate for LIMIT/OFFSET schemes
  3820. """
  3821. def visit_select(
  3822. self,
  3823. select_stmt,
  3824. asfrom=False,
  3825. insert_into=False,
  3826. fromhints=None,
  3827. compound_index=None,
  3828. select_wraps_for=None,
  3829. lateral=False,
  3830. from_linter=None,
  3831. **kwargs,
  3832. ):
  3833. assert select_wraps_for is None, (
  3834. "SQLAlchemy 1.4 requires use of "
  3835. "the translate_select_structure hook for structural "
  3836. "translations of SELECT objects"
  3837. )
  3838. # initial setup of SELECT. the compile_state_factory may now
  3839. # be creating a totally different SELECT from the one that was
  3840. # passed in. for ORM use this will convert from an ORM-state
  3841. # SELECT to a regular "Core" SELECT. other composed operations
  3842. # such as computation of joins will be performed.
  3843. kwargs["within_columns_clause"] = False
  3844. compile_state = select_stmt._compile_state_factory(
  3845. select_stmt, self, **kwargs
  3846. )
  3847. kwargs[
  3848. "ambiguous_table_name_map"
  3849. ] = compile_state._ambiguous_table_name_map
  3850. select_stmt = compile_state.statement
  3851. toplevel = not self.stack
  3852. if toplevel and not self.compile_state:
  3853. self.compile_state = compile_state
  3854. is_embedded_select = compound_index is not None or insert_into
  3855. # translate step for Oracle, SQL Server which often need to
  3856. # restructure the SELECT to allow for LIMIT/OFFSET and possibly
  3857. # other conditions
  3858. if self.translate_select_structure:
  3859. new_select_stmt = self.translate_select_structure(
  3860. select_stmt, asfrom=asfrom, **kwargs
  3861. )
  3862. # if SELECT was restructured, maintain a link to the originals
  3863. # and assemble a new compile state
  3864. if new_select_stmt is not select_stmt:
  3865. compile_state_wraps_for = compile_state
  3866. select_wraps_for = select_stmt
  3867. select_stmt = new_select_stmt
  3868. compile_state = select_stmt._compile_state_factory(
  3869. select_stmt, self, **kwargs
  3870. )
  3871. select_stmt = compile_state.statement
  3872. entry = self._default_stack_entry if toplevel else self.stack[-1]
  3873. populate_result_map = need_column_expressions = (
  3874. toplevel
  3875. or entry.get("need_result_map_for_compound", False)
  3876. or entry.get("need_result_map_for_nested", False)
  3877. )
  3878. # indicates there is a CompoundSelect in play and we are not the
  3879. # first select
  3880. if compound_index:
  3881. populate_result_map = False
  3882. # this was first proposed as part of #3372; however, it is not
  3883. # reached in current tests and could possibly be an assertion
  3884. # instead.
  3885. if not populate_result_map and "add_to_result_map" in kwargs:
  3886. del kwargs["add_to_result_map"]
  3887. froms = self._setup_select_stack(
  3888. select_stmt, compile_state, entry, asfrom, lateral, compound_index
  3889. )
  3890. column_clause_args = kwargs.copy()
  3891. column_clause_args.update(
  3892. {"within_label_clause": False, "within_columns_clause": False}
  3893. )
  3894. text = "SELECT " # we're off to a good start !
  3895. if select_stmt._hints:
  3896. hint_text, byfrom = self._setup_select_hints(select_stmt)
  3897. if hint_text:
  3898. text += hint_text + " "
  3899. else:
  3900. byfrom = None
  3901. if select_stmt._independent_ctes:
  3902. self._dispatch_independent_ctes(select_stmt, kwargs)
  3903. if select_stmt._prefixes:
  3904. text += self._generate_prefixes(
  3905. select_stmt, select_stmt._prefixes, **kwargs
  3906. )
  3907. text += self.get_select_precolumns(select_stmt, **kwargs)
  3908. # the actual list of columns to print in the SELECT column list.
  3909. inner_columns = [
  3910. c
  3911. for c in [
  3912. self._label_select_column(
  3913. select_stmt,
  3914. column,
  3915. populate_result_map,
  3916. asfrom,
  3917. column_clause_args,
  3918. name=name,
  3919. proxy_name=proxy_name,
  3920. fallback_label_name=fallback_label_name,
  3921. column_is_repeated=repeated,
  3922. need_column_expressions=need_column_expressions,
  3923. )
  3924. for (
  3925. name,
  3926. proxy_name,
  3927. fallback_label_name,
  3928. column,
  3929. repeated,
  3930. ) in compile_state.columns_plus_names
  3931. ]
  3932. if c is not None
  3933. ]
  3934. if populate_result_map and select_wraps_for is not None:
  3935. # if this select was generated from translate_select,
  3936. # rewrite the targeted columns in the result map
  3937. translate = dict(
  3938. zip(
  3939. [
  3940. name
  3941. for (
  3942. key,
  3943. proxy_name,
  3944. fallback_label_name,
  3945. name,
  3946. repeated,
  3947. ) in compile_state.columns_plus_names
  3948. ],
  3949. [
  3950. name
  3951. for (
  3952. key,
  3953. proxy_name,
  3954. fallback_label_name,
  3955. name,
  3956. repeated,
  3957. ) in compile_state_wraps_for.columns_plus_names
  3958. ],
  3959. )
  3960. )
  3961. self._result_columns = [
  3962. ResultColumnsEntry(
  3963. key, name, tuple(translate.get(o, o) for o in obj), type_
  3964. )
  3965. for key, name, obj, type_ in self._result_columns
  3966. ]
  3967. text = self._compose_select_body(
  3968. text,
  3969. select_stmt,
  3970. compile_state,
  3971. inner_columns,
  3972. froms,
  3973. byfrom,
  3974. toplevel,
  3975. kwargs,
  3976. )
  3977. if select_stmt._statement_hints:
  3978. per_dialect = [
  3979. ht
  3980. for (dialect_name, ht) in select_stmt._statement_hints
  3981. if dialect_name in ("*", self.dialect.name)
  3982. ]
  3983. if per_dialect:
  3984. text += " " + self.get_statement_hint_text(per_dialect)
  3985. # In compound query, CTEs are shared at the compound level
  3986. if self.ctes and (not is_embedded_select or toplevel):
  3987. nesting_level = len(self.stack) if not toplevel else None
  3988. text = self._render_cte_clause(nesting_level=nesting_level) + text
  3989. if select_stmt._suffixes:
  3990. text += " " + self._generate_prefixes(
  3991. select_stmt, select_stmt._suffixes, **kwargs
  3992. )
  3993. self.stack.pop(-1)
  3994. return text
  3995. def _setup_select_hints(
  3996. self, select: Select[Any]
  3997. ) -> Tuple[str, _FromHintsType]:
  3998. byfrom = {
  3999. from_: hinttext
  4000. % {"name": from_._compiler_dispatch(self, ashint=True)}
  4001. for (from_, dialect), hinttext in select._hints.items()
  4002. if dialect in ("*", self.dialect.name)
  4003. }
  4004. hint_text = self.get_select_hint_text(byfrom)
  4005. return hint_text, byfrom
  4006. def _setup_select_stack(
  4007. self, select, compile_state, entry, asfrom, lateral, compound_index
  4008. ):
  4009. correlate_froms = entry["correlate_froms"]
  4010. asfrom_froms = entry["asfrom_froms"]
  4011. if compound_index == 0:
  4012. entry["select_0"] = select
  4013. elif compound_index:
  4014. select_0 = entry["select_0"]
  4015. numcols = len(select_0._all_selected_columns)
  4016. if len(compile_state.columns_plus_names) != numcols:
  4017. raise exc.CompileError(
  4018. "All selectables passed to "
  4019. "CompoundSelect must have identical numbers of "
  4020. "columns; select #%d has %d columns, select "
  4021. "#%d has %d"
  4022. % (
  4023. 1,
  4024. numcols,
  4025. compound_index + 1,
  4026. len(select._all_selected_columns),
  4027. )
  4028. )
  4029. if asfrom and not lateral:
  4030. froms = compile_state._get_display_froms(
  4031. explicit_correlate_froms=correlate_froms.difference(
  4032. asfrom_froms
  4033. ),
  4034. implicit_correlate_froms=(),
  4035. )
  4036. else:
  4037. froms = compile_state._get_display_froms(
  4038. explicit_correlate_froms=correlate_froms,
  4039. implicit_correlate_froms=asfrom_froms,
  4040. )
  4041. new_correlate_froms = set(_from_objects(*froms))
  4042. all_correlate_froms = new_correlate_froms.union(correlate_froms)
  4043. new_entry: _CompilerStackEntry = {
  4044. "asfrom_froms": new_correlate_froms,
  4045. "correlate_froms": all_correlate_froms,
  4046. "selectable": select,
  4047. "compile_state": compile_state,
  4048. }
  4049. self.stack.append(new_entry)
  4050. return froms
  4051. def _compose_select_body(
  4052. self,
  4053. text,
  4054. select,
  4055. compile_state,
  4056. inner_columns,
  4057. froms,
  4058. byfrom,
  4059. toplevel,
  4060. kwargs,
  4061. ):
  4062. text += ", ".join(inner_columns)
  4063. if self.linting & COLLECT_CARTESIAN_PRODUCTS:
  4064. from_linter = FromLinter({}, set())
  4065. warn_linting = self.linting & WARN_LINTING
  4066. if toplevel:
  4067. self.from_linter = from_linter
  4068. else:
  4069. from_linter = None
  4070. warn_linting = False
  4071. # adjust the whitespace for no inner columns, part of #9440,
  4072. # so that a no-col SELECT comes out as "SELECT WHERE..." or
  4073. # "SELECT FROM ...".
  4074. # while it would be better to have built the SELECT starting string
  4075. # without trailing whitespace first, then add whitespace only if inner
  4076. # cols were present, this breaks compatibility with various custom
  4077. # compilation schemes that are currently being tested.
  4078. if not inner_columns:
  4079. text = text.rstrip()
  4080. if froms:
  4081. text += " \nFROM "
  4082. if select._hints:
  4083. text += ", ".join(
  4084. [
  4085. f._compiler_dispatch(
  4086. self,
  4087. asfrom=True,
  4088. fromhints=byfrom,
  4089. from_linter=from_linter,
  4090. **kwargs,
  4091. )
  4092. for f in froms
  4093. ]
  4094. )
  4095. else:
  4096. text += ", ".join(
  4097. [
  4098. f._compiler_dispatch(
  4099. self,
  4100. asfrom=True,
  4101. from_linter=from_linter,
  4102. **kwargs,
  4103. )
  4104. for f in froms
  4105. ]
  4106. )
  4107. else:
  4108. text += self.default_from()
  4109. if select._where_criteria:
  4110. t = self._generate_delimited_and_list(
  4111. select._where_criteria, from_linter=from_linter, **kwargs
  4112. )
  4113. if t:
  4114. text += " \nWHERE " + t
  4115. if warn_linting:
  4116. assert from_linter is not None
  4117. from_linter.warn()
  4118. if select._group_by_clauses:
  4119. text += self.group_by_clause(select, **kwargs)
  4120. if select._having_criteria:
  4121. t = self._generate_delimited_and_list(
  4122. select._having_criteria, **kwargs
  4123. )
  4124. if t:
  4125. text += " \nHAVING " + t
  4126. if select._order_by_clauses:
  4127. text += self.order_by_clause(select, **kwargs)
  4128. if select._has_row_limiting_clause:
  4129. text += self._row_limit_clause(select, **kwargs)
  4130. if select._for_update_arg is not None:
  4131. text += self.for_update_clause(select, **kwargs)
  4132. return text
  4133. def _generate_prefixes(self, stmt, prefixes, **kw):
  4134. clause = " ".join(
  4135. prefix._compiler_dispatch(self, **kw)
  4136. for prefix, dialect_name in prefixes
  4137. if dialect_name in (None, "*") or dialect_name == self.dialect.name
  4138. )
  4139. if clause:
  4140. clause += " "
  4141. return clause
  4142. def _render_cte_clause(
  4143. self,
  4144. nesting_level=None,
  4145. include_following_stack=False,
  4146. ):
  4147. """
  4148. include_following_stack
  4149. Also render the nesting CTEs on the next stack. Useful for
  4150. SQL structures like UNION or INSERT that can wrap SELECT
  4151. statements containing nesting CTEs.
  4152. """
  4153. if not self.ctes:
  4154. return ""
  4155. ctes: MutableMapping[CTE, str]
  4156. if nesting_level and nesting_level > 1:
  4157. ctes = util.OrderedDict()
  4158. for cte in list(self.ctes.keys()):
  4159. cte_level, cte_name, cte_opts = self.level_name_by_cte[
  4160. cte._get_reference_cte()
  4161. ]
  4162. nesting = cte.nesting or cte_opts.nesting
  4163. is_rendered_level = cte_level == nesting_level or (
  4164. include_following_stack and cte_level == nesting_level + 1
  4165. )
  4166. if not (nesting and is_rendered_level):
  4167. continue
  4168. ctes[cte] = self.ctes[cte]
  4169. else:
  4170. ctes = self.ctes
  4171. if not ctes:
  4172. return ""
  4173. ctes_recursive = any([cte.recursive for cte in ctes])
  4174. cte_text = self.get_cte_preamble(ctes_recursive) + " "
  4175. cte_text += ", \n".join([txt for txt in ctes.values()])
  4176. cte_text += "\n "
  4177. if nesting_level and nesting_level > 1:
  4178. for cte in list(ctes.keys()):
  4179. cte_level, cte_name, cte_opts = self.level_name_by_cte[
  4180. cte._get_reference_cte()
  4181. ]
  4182. del self.ctes[cte]
  4183. del self.ctes_by_level_name[(cte_level, cte_name)]
  4184. del self.level_name_by_cte[cte._get_reference_cte()]
  4185. return cte_text
  4186. def get_cte_preamble(self, recursive):
  4187. if recursive:
  4188. return "WITH RECURSIVE"
  4189. else:
  4190. return "WITH"
  4191. def get_select_precolumns(self, select, **kw):
  4192. """Called when building a ``SELECT`` statement, position is just
  4193. before column list.
  4194. """
  4195. if select._distinct_on:
  4196. util.warn_deprecated(
  4197. "DISTINCT ON is currently supported only by the PostgreSQL "
  4198. "dialect. Use of DISTINCT ON for other backends is currently "
  4199. "silently ignored, however this usage is deprecated, and will "
  4200. "raise CompileError in a future release for all backends "
  4201. "that do not support this syntax.",
  4202. version="1.4",
  4203. )
  4204. return "DISTINCT " if select._distinct else ""
  4205. def group_by_clause(self, select, **kw):
  4206. """allow dialects to customize how GROUP BY is rendered."""
  4207. group_by = self._generate_delimited_list(
  4208. select._group_by_clauses, OPERATORS[operators.comma_op], **kw
  4209. )
  4210. if group_by:
  4211. return " GROUP BY " + group_by
  4212. else:
  4213. return ""
  4214. def order_by_clause(self, select, **kw):
  4215. """allow dialects to customize how ORDER BY is rendered."""
  4216. order_by = self._generate_delimited_list(
  4217. select._order_by_clauses, OPERATORS[operators.comma_op], **kw
  4218. )
  4219. if order_by:
  4220. return " ORDER BY " + order_by
  4221. else:
  4222. return ""
  4223. def for_update_clause(self, select, **kw):
  4224. return " FOR UPDATE"
  4225. def returning_clause(
  4226. self,
  4227. stmt: UpdateBase,
  4228. returning_cols: Sequence[ColumnElement[Any]],
  4229. *,
  4230. populate_result_map: bool,
  4231. **kw: Any,
  4232. ) -> str:
  4233. columns = [
  4234. self._label_returning_column(
  4235. stmt,
  4236. column,
  4237. populate_result_map,
  4238. fallback_label_name=fallback_label_name,
  4239. column_is_repeated=repeated,
  4240. name=name,
  4241. proxy_name=proxy_name,
  4242. **kw,
  4243. )
  4244. for (
  4245. name,
  4246. proxy_name,
  4247. fallback_label_name,
  4248. column,
  4249. repeated,
  4250. ) in stmt._generate_columns_plus_names(
  4251. True, cols=base._select_iterables(returning_cols)
  4252. )
  4253. ]
  4254. return "RETURNING " + ", ".join(columns)
  4255. def limit_clause(self, select, **kw):
  4256. text = ""
  4257. if select._limit_clause is not None:
  4258. text += "\n LIMIT " + self.process(select._limit_clause, **kw)
  4259. if select._offset_clause is not None:
  4260. if select._limit_clause is None:
  4261. text += "\n LIMIT -1"
  4262. text += " OFFSET " + self.process(select._offset_clause, **kw)
  4263. return text
  4264. def fetch_clause(
  4265. self,
  4266. select,
  4267. fetch_clause=None,
  4268. require_offset=False,
  4269. use_literal_execute_for_simple_int=False,
  4270. **kw,
  4271. ):
  4272. if fetch_clause is None:
  4273. fetch_clause = select._fetch_clause
  4274. fetch_clause_options = select._fetch_clause_options
  4275. else:
  4276. fetch_clause_options = {"percent": False, "with_ties": False}
  4277. text = ""
  4278. if select._offset_clause is not None:
  4279. offset_clause = select._offset_clause
  4280. if (
  4281. use_literal_execute_for_simple_int
  4282. and select._simple_int_clause(offset_clause)
  4283. ):
  4284. offset_clause = offset_clause.render_literal_execute()
  4285. offset_str = self.process(offset_clause, **kw)
  4286. text += "\n OFFSET %s ROWS" % offset_str
  4287. elif require_offset:
  4288. text += "\n OFFSET 0 ROWS"
  4289. if fetch_clause is not None:
  4290. if (
  4291. use_literal_execute_for_simple_int
  4292. and select._simple_int_clause(fetch_clause)
  4293. ):
  4294. fetch_clause = fetch_clause.render_literal_execute()
  4295. text += "\n FETCH FIRST %s%s ROWS %s" % (
  4296. self.process(fetch_clause, **kw),
  4297. " PERCENT" if fetch_clause_options["percent"] else "",
  4298. "WITH TIES" if fetch_clause_options["with_ties"] else "ONLY",
  4299. )
  4300. return text
  4301. def visit_table(
  4302. self,
  4303. table,
  4304. asfrom=False,
  4305. iscrud=False,
  4306. ashint=False,
  4307. fromhints=None,
  4308. use_schema=True,
  4309. from_linter=None,
  4310. ambiguous_table_name_map=None,
  4311. **kwargs,
  4312. ):
  4313. if from_linter:
  4314. from_linter.froms[table] = table.fullname
  4315. if asfrom or ashint:
  4316. effective_schema = self.preparer.schema_for_object(table)
  4317. if use_schema and effective_schema:
  4318. ret = (
  4319. self.preparer.quote_schema(effective_schema)
  4320. + "."
  4321. + self.preparer.quote(table.name)
  4322. )
  4323. else:
  4324. ret = self.preparer.quote(table.name)
  4325. if (
  4326. not effective_schema
  4327. and ambiguous_table_name_map
  4328. and table.name in ambiguous_table_name_map
  4329. ):
  4330. anon_name = self._truncated_identifier(
  4331. "alias", ambiguous_table_name_map[table.name]
  4332. )
  4333. ret = ret + self.get_render_as_alias_suffix(
  4334. self.preparer.format_alias(None, anon_name)
  4335. )
  4336. if fromhints and table in fromhints:
  4337. ret = self.format_from_hint_text(
  4338. ret, table, fromhints[table], iscrud
  4339. )
  4340. return ret
  4341. else:
  4342. return ""
  4343. def visit_join(self, join, asfrom=False, from_linter=None, **kwargs):
  4344. if from_linter:
  4345. from_linter.edges.update(
  4346. itertools.product(
  4347. _de_clone(join.left._from_objects),
  4348. _de_clone(join.right._from_objects),
  4349. )
  4350. )
  4351. if join.full:
  4352. join_type = " FULL OUTER JOIN "
  4353. elif join.isouter:
  4354. join_type = " LEFT OUTER JOIN "
  4355. else:
  4356. join_type = " JOIN "
  4357. return (
  4358. join.left._compiler_dispatch(
  4359. self, asfrom=True, from_linter=from_linter, **kwargs
  4360. )
  4361. + join_type
  4362. + join.right._compiler_dispatch(
  4363. self, asfrom=True, from_linter=from_linter, **kwargs
  4364. )
  4365. + " ON "
  4366. # TODO: likely need asfrom=True here?
  4367. + join.onclause._compiler_dispatch(
  4368. self, from_linter=from_linter, **kwargs
  4369. )
  4370. )
  4371. def _setup_crud_hints(self, stmt, table_text):
  4372. dialect_hints = {
  4373. table: hint_text
  4374. for (table, dialect), hint_text in stmt._hints.items()
  4375. if dialect in ("*", self.dialect.name)
  4376. }
  4377. if stmt.table in dialect_hints:
  4378. table_text = self.format_from_hint_text(
  4379. table_text, stmt.table, dialect_hints[stmt.table], True
  4380. )
  4381. return dialect_hints, table_text
  4382. # within the realm of "insertmanyvalues sentinel columns",
  4383. # these lookups match different kinds of Column() configurations
  4384. # to specific backend capabilities. they are broken into two
  4385. # lookups, one for autoincrement columns and the other for non
  4386. # autoincrement columns
  4387. _sentinel_col_non_autoinc_lookup = util.immutabledict(
  4388. {
  4389. _SentinelDefaultCharacterization.CLIENTSIDE: (
  4390. InsertmanyvaluesSentinelOpts._SUPPORTED_OR_NOT
  4391. ),
  4392. _SentinelDefaultCharacterization.SENTINEL_DEFAULT: (
  4393. InsertmanyvaluesSentinelOpts._SUPPORTED_OR_NOT
  4394. ),
  4395. _SentinelDefaultCharacterization.NONE: (
  4396. InsertmanyvaluesSentinelOpts._SUPPORTED_OR_NOT
  4397. ),
  4398. _SentinelDefaultCharacterization.IDENTITY: (
  4399. InsertmanyvaluesSentinelOpts.IDENTITY
  4400. ),
  4401. _SentinelDefaultCharacterization.SEQUENCE: (
  4402. InsertmanyvaluesSentinelOpts.SEQUENCE
  4403. ),
  4404. }
  4405. )
  4406. _sentinel_col_autoinc_lookup = _sentinel_col_non_autoinc_lookup.union(
  4407. {
  4408. _SentinelDefaultCharacterization.NONE: (
  4409. InsertmanyvaluesSentinelOpts.AUTOINCREMENT
  4410. ),
  4411. }
  4412. )
  4413. def _get_sentinel_column_for_table(
  4414. self, table: Table
  4415. ) -> Optional[Sequence[Column[Any]]]:
  4416. """given a :class:`.Table`, return a usable sentinel column or
  4417. columns for this dialect if any.
  4418. Return None if no sentinel columns could be identified, or raise an
  4419. error if a column was marked as a sentinel explicitly but isn't
  4420. compatible with this dialect.
  4421. """
  4422. sentinel_opts = self.dialect.insertmanyvalues_implicit_sentinel
  4423. sentinel_characteristics = table._sentinel_column_characteristics
  4424. sent_cols = sentinel_characteristics.columns
  4425. if sent_cols is None:
  4426. return None
  4427. if sentinel_characteristics.is_autoinc:
  4428. bitmask = self._sentinel_col_autoinc_lookup.get(
  4429. sentinel_characteristics.default_characterization, 0
  4430. )
  4431. else:
  4432. bitmask = self._sentinel_col_non_autoinc_lookup.get(
  4433. sentinel_characteristics.default_characterization, 0
  4434. )
  4435. if sentinel_opts & bitmask:
  4436. return sent_cols
  4437. if sentinel_characteristics.is_explicit:
  4438. # a column was explicitly marked as insert_sentinel=True,
  4439. # however it is not compatible with this dialect. they should
  4440. # not indicate this column as a sentinel if they need to include
  4441. # this dialect.
  4442. # TODO: do we want non-primary key explicit sentinel cols
  4443. # that can gracefully degrade for some backends?
  4444. # insert_sentinel="degrade" perhaps. not for the initial release.
  4445. # I am hoping people are generally not dealing with this sentinel
  4446. # business at all.
  4447. # if is_explicit is True, there will be only one sentinel column.
  4448. raise exc.InvalidRequestError(
  4449. f"Column {sent_cols[0]} can't be explicitly "
  4450. "marked as a sentinel column when using the "
  4451. f"{self.dialect.name} dialect, as the "
  4452. "particular type of default generation on this column is "
  4453. "not currently compatible with this dialect's specific "
  4454. f"INSERT..RETURNING syntax which can receive the "
  4455. "server-generated value in "
  4456. "a deterministic way. To remove this error, remove "
  4457. "insert_sentinel=True from primary key autoincrement "
  4458. "columns; these columns are automatically used as "
  4459. "sentinels for supported dialects in any case."
  4460. )
  4461. return None
  4462. def _deliver_insertmanyvalues_batches(
  4463. self,
  4464. statement: str,
  4465. parameters: _DBAPIMultiExecuteParams,
  4466. generic_setinputsizes: Optional[_GenericSetInputSizesType],
  4467. batch_size: int,
  4468. sort_by_parameter_order: bool,
  4469. ) -> Iterator[_InsertManyValuesBatch]:
  4470. imv = self._insertmanyvalues
  4471. assert imv is not None
  4472. lenparams = len(parameters)
  4473. if imv.is_default_expr and not self.dialect.supports_default_metavalue:
  4474. # backend doesn't support
  4475. # INSERT INTO table (pk_col) VALUES (DEFAULT), (DEFAULT), ...
  4476. # at the moment this is basically SQL Server due to
  4477. # not being able to use DEFAULT for identity column
  4478. # just yield out that many single statements! still
  4479. # faster than a whole connection.execute() call ;)
  4480. #
  4481. # note we still are taking advantage of the fact that we know
  4482. # we are using RETURNING. The generalized approach of fetching
  4483. # cursor.lastrowid etc. still goes through the more heavyweight
  4484. # "ExecutionContext per statement" system as it isn't usable
  4485. # as a generic "RETURNING" approach
  4486. use_row_at_a_time = True
  4487. downgraded = False
  4488. elif not self.dialect.supports_multivalues_insert or (
  4489. sort_by_parameter_order
  4490. and self._result_columns
  4491. and (imv.sentinel_columns is None or imv.includes_upsert_behaviors)
  4492. ):
  4493. # deterministic order was requested and the compiler could
  4494. # not organize sentinel columns for this dialect/statement.
  4495. # use row at a time
  4496. use_row_at_a_time = True
  4497. downgraded = True
  4498. else:
  4499. use_row_at_a_time = False
  4500. downgraded = False
  4501. if use_row_at_a_time:
  4502. for batchnum, param in enumerate(
  4503. cast("Sequence[_DBAPISingleExecuteParams]", parameters), 1
  4504. ):
  4505. yield _InsertManyValuesBatch(
  4506. statement,
  4507. param,
  4508. generic_setinputsizes,
  4509. [param],
  4510. batch_size,
  4511. batchnum,
  4512. lenparams,
  4513. sort_by_parameter_order,
  4514. downgraded,
  4515. )
  4516. return
  4517. executemany_values = f"({imv.single_values_expr})"
  4518. statement = statement.replace(executemany_values, "__EXECMANY_TOKEN__")
  4519. # Use optional insertmanyvalues_max_parameters
  4520. # to further shrink the batch size so that there are no more than
  4521. # insertmanyvalues_max_parameters params.
  4522. # Currently used by SQL Server, which limits statements to 2100 bound
  4523. # parameters (actually 2099).
  4524. max_params = self.dialect.insertmanyvalues_max_parameters
  4525. if max_params:
  4526. total_num_of_params = len(self.bind_names)
  4527. num_params_per_batch = len(imv.insert_crud_params)
  4528. num_params_outside_of_batch = (
  4529. total_num_of_params - num_params_per_batch
  4530. )
  4531. batch_size = min(
  4532. batch_size,
  4533. (
  4534. (max_params - num_params_outside_of_batch)
  4535. // num_params_per_batch
  4536. ),
  4537. )
  4538. batches = list(parameters)
  4539. processed_setinputsizes: Optional[_GenericSetInputSizesType] = None
  4540. batchnum = 1
  4541. total_batches = lenparams // batch_size + (
  4542. 1 if lenparams % batch_size else 0
  4543. )
  4544. insert_crud_params = imv.insert_crud_params
  4545. assert insert_crud_params is not None
  4546. escaped_bind_names: Mapping[str, str]
  4547. expand_pos_lower_index = expand_pos_upper_index = 0
  4548. if not self.positional:
  4549. if self.escaped_bind_names:
  4550. escaped_bind_names = self.escaped_bind_names
  4551. else:
  4552. escaped_bind_names = {}
  4553. all_keys = set(parameters[0])
  4554. def apply_placeholders(keys, formatted):
  4555. for key in keys:
  4556. key = escaped_bind_names.get(key, key)
  4557. formatted = formatted.replace(
  4558. self.bindtemplate % {"name": key},
  4559. self.bindtemplate
  4560. % {"name": f"{key}__EXECMANY_INDEX__"},
  4561. )
  4562. return formatted
  4563. if imv.embed_values_counter:
  4564. imv_values_counter = ", _IMV_VALUES_COUNTER"
  4565. else:
  4566. imv_values_counter = ""
  4567. formatted_values_clause = f"""({', '.join(
  4568. apply_placeholders(bind_keys, formatted)
  4569. for _, _, formatted, bind_keys in insert_crud_params
  4570. )}{imv_values_counter})"""
  4571. keys_to_replace = all_keys.intersection(
  4572. escaped_bind_names.get(key, key)
  4573. for _, _, _, bind_keys in insert_crud_params
  4574. for key in bind_keys
  4575. )
  4576. base_parameters = {
  4577. key: parameters[0][key]
  4578. for key in all_keys.difference(keys_to_replace)
  4579. }
  4580. executemany_values_w_comma = ""
  4581. else:
  4582. formatted_values_clause = ""
  4583. keys_to_replace = set()
  4584. base_parameters = {}
  4585. if imv.embed_values_counter:
  4586. executemany_values_w_comma = (
  4587. f"({imv.single_values_expr}, _IMV_VALUES_COUNTER), "
  4588. )
  4589. else:
  4590. executemany_values_w_comma = f"({imv.single_values_expr}), "
  4591. all_names_we_will_expand: Set[str] = set()
  4592. for elem in imv.insert_crud_params:
  4593. all_names_we_will_expand.update(elem[3])
  4594. # get the start and end position in a particular list
  4595. # of parameters where we will be doing the "expanding".
  4596. # statements can have params on either side or both sides,
  4597. # given RETURNING and CTEs
  4598. if all_names_we_will_expand:
  4599. positiontup = self.positiontup
  4600. assert positiontup is not None
  4601. all_expand_positions = {
  4602. idx
  4603. for idx, name in enumerate(positiontup)
  4604. if name in all_names_we_will_expand
  4605. }
  4606. expand_pos_lower_index = min(all_expand_positions)
  4607. expand_pos_upper_index = max(all_expand_positions) + 1
  4608. assert (
  4609. len(all_expand_positions)
  4610. == expand_pos_upper_index - expand_pos_lower_index
  4611. )
  4612. if self._numeric_binds:
  4613. escaped = re.escape(self._numeric_binds_identifier_char)
  4614. executemany_values_w_comma = re.sub(
  4615. rf"{escaped}\d+", "%s", executemany_values_w_comma
  4616. )
  4617. while batches:
  4618. batch = cast("Sequence[Any]", batches[0:batch_size])
  4619. batches[0:batch_size] = []
  4620. if generic_setinputsizes:
  4621. # if setinputsizes is present, expand this collection to
  4622. # suit the batch length as well
  4623. # currently this will be mssql+pyodbc for internal dialects
  4624. processed_setinputsizes = [
  4625. (new_key, len_, typ)
  4626. for new_key, len_, typ in (
  4627. (f"{key}_{index}", len_, typ)
  4628. for index in range(len(batch))
  4629. for key, len_, typ in generic_setinputsizes
  4630. )
  4631. ]
  4632. replaced_parameters: Any
  4633. if self.positional:
  4634. num_ins_params = imv.num_positional_params_counted
  4635. batch_iterator: Iterable[Sequence[Any]]
  4636. if num_ins_params == len(batch[0]):
  4637. extra_params_left = extra_params_right = ()
  4638. batch_iterator = batch
  4639. else:
  4640. extra_params_left = batch[0][:expand_pos_lower_index]
  4641. extra_params_right = batch[0][expand_pos_upper_index:]
  4642. batch_iterator = (
  4643. b[expand_pos_lower_index:expand_pos_upper_index]
  4644. for b in batch
  4645. )
  4646. if imv.embed_values_counter:
  4647. expanded_values_string = (
  4648. "".join(
  4649. executemany_values_w_comma.replace(
  4650. "_IMV_VALUES_COUNTER", str(i)
  4651. )
  4652. for i, _ in enumerate(batch)
  4653. )
  4654. )[:-2]
  4655. else:
  4656. expanded_values_string = (
  4657. (executemany_values_w_comma * len(batch))
  4658. )[:-2]
  4659. if self._numeric_binds and num_ins_params > 0:
  4660. # numeric will always number the parameters inside of
  4661. # VALUES (and thus order self.positiontup) to be higher
  4662. # than non-VALUES parameters, no matter where in the
  4663. # statement those non-VALUES parameters appear (this is
  4664. # ensured in _process_numeric by numbering first all
  4665. # params that are not in _values_bindparam)
  4666. # therefore all extra params are always
  4667. # on the left side and numbered lower than the VALUES
  4668. # parameters
  4669. assert not extra_params_right
  4670. start = expand_pos_lower_index + 1
  4671. end = num_ins_params * (len(batch)) + start
  4672. # need to format here, since statement may contain
  4673. # unescaped %, while values_string contains just (%s, %s)
  4674. positions = tuple(
  4675. f"{self._numeric_binds_identifier_char}{i}"
  4676. for i in range(start, end)
  4677. )
  4678. expanded_values_string = expanded_values_string % positions
  4679. replaced_statement = statement.replace(
  4680. "__EXECMANY_TOKEN__", expanded_values_string
  4681. )
  4682. replaced_parameters = tuple(
  4683. itertools.chain.from_iterable(batch_iterator)
  4684. )
  4685. replaced_parameters = (
  4686. extra_params_left
  4687. + replaced_parameters
  4688. + extra_params_right
  4689. )
  4690. else:
  4691. replaced_values_clauses = []
  4692. replaced_parameters = base_parameters.copy()
  4693. for i, param in enumerate(batch):
  4694. fmv = formatted_values_clause.replace(
  4695. "EXECMANY_INDEX__", str(i)
  4696. )
  4697. if imv.embed_values_counter:
  4698. fmv = fmv.replace("_IMV_VALUES_COUNTER", str(i))
  4699. replaced_values_clauses.append(fmv)
  4700. replaced_parameters.update(
  4701. {f"{key}__{i}": param[key] for key in keys_to_replace}
  4702. )
  4703. replaced_statement = statement.replace(
  4704. "__EXECMANY_TOKEN__",
  4705. ", ".join(replaced_values_clauses),
  4706. )
  4707. yield _InsertManyValuesBatch(
  4708. replaced_statement,
  4709. replaced_parameters,
  4710. processed_setinputsizes,
  4711. batch,
  4712. batch_size,
  4713. batchnum,
  4714. total_batches,
  4715. sort_by_parameter_order,
  4716. False,
  4717. )
  4718. batchnum += 1
  4719. def visit_insert(
  4720. self, insert_stmt, visited_bindparam=None, visiting_cte=None, **kw
  4721. ):
  4722. compile_state = insert_stmt._compile_state_factory(
  4723. insert_stmt, self, **kw
  4724. )
  4725. insert_stmt = compile_state.statement
  4726. if visiting_cte is not None:
  4727. kw["visiting_cte"] = visiting_cte
  4728. toplevel = False
  4729. else:
  4730. toplevel = not self.stack
  4731. if toplevel:
  4732. self.isinsert = True
  4733. if not self.dml_compile_state:
  4734. self.dml_compile_state = compile_state
  4735. if not self.compile_state:
  4736. self.compile_state = compile_state
  4737. self.stack.append(
  4738. {
  4739. "correlate_froms": set(),
  4740. "asfrom_froms": set(),
  4741. "selectable": insert_stmt,
  4742. }
  4743. )
  4744. counted_bindparam = 0
  4745. # reset any incoming "visited_bindparam" collection
  4746. visited_bindparam = None
  4747. # for positional, insertmanyvalues needs to know how many
  4748. # bound parameters are in the VALUES sequence; there's no simple
  4749. # rule because default expressions etc. can have zero or more
  4750. # params inside them. After multiple attempts to figure this out,
  4751. # this very simplistic "count after" works and is
  4752. # likely the least amount of callcounts, though looks clumsy
  4753. if self.positional and visiting_cte is None:
  4754. # if we are inside a CTE, don't count parameters
  4755. # here since they wont be for insertmanyvalues. keep
  4756. # visited_bindparam at None so no counting happens.
  4757. # see #9173
  4758. visited_bindparam = []
  4759. crud_params_struct = crud._get_crud_params(
  4760. self,
  4761. insert_stmt,
  4762. compile_state,
  4763. toplevel,
  4764. visited_bindparam=visited_bindparam,
  4765. **kw,
  4766. )
  4767. if self.positional and visited_bindparam is not None:
  4768. counted_bindparam = len(visited_bindparam)
  4769. if self._numeric_binds:
  4770. if self._values_bindparam is not None:
  4771. self._values_bindparam += visited_bindparam
  4772. else:
  4773. self._values_bindparam = visited_bindparam
  4774. crud_params_single = crud_params_struct.single_params
  4775. if (
  4776. not crud_params_single
  4777. and not self.dialect.supports_default_values
  4778. and not self.dialect.supports_default_metavalue
  4779. and not self.dialect.supports_empty_insert
  4780. ):
  4781. raise exc.CompileError(
  4782. "The '%s' dialect with current database "
  4783. "version settings does not support empty "
  4784. "inserts." % self.dialect.name
  4785. )
  4786. if compile_state._has_multi_parameters:
  4787. if not self.dialect.supports_multivalues_insert:
  4788. raise exc.CompileError(
  4789. "The '%s' dialect with current database "
  4790. "version settings does not support "
  4791. "in-place multirow inserts." % self.dialect.name
  4792. )
  4793. elif (
  4794. self.implicit_returning or insert_stmt._returning
  4795. ) and insert_stmt._sort_by_parameter_order:
  4796. raise exc.CompileError(
  4797. "RETURNING cannot be determinstically sorted when "
  4798. "using an INSERT which includes multi-row values()."
  4799. )
  4800. crud_params_single = crud_params_struct.single_params
  4801. else:
  4802. crud_params_single = crud_params_struct.single_params
  4803. preparer = self.preparer
  4804. supports_default_values = self.dialect.supports_default_values
  4805. text = "INSERT "
  4806. if insert_stmt._prefixes:
  4807. text += self._generate_prefixes(
  4808. insert_stmt, insert_stmt._prefixes, **kw
  4809. )
  4810. text += "INTO "
  4811. table_text = preparer.format_table(insert_stmt.table)
  4812. if insert_stmt._hints:
  4813. _, table_text = self._setup_crud_hints(insert_stmt, table_text)
  4814. if insert_stmt._independent_ctes:
  4815. self._dispatch_independent_ctes(insert_stmt, kw)
  4816. text += table_text
  4817. if crud_params_single or not supports_default_values:
  4818. text += " (%s)" % ", ".join(
  4819. [expr for _, expr, _, _ in crud_params_single]
  4820. )
  4821. # look for insertmanyvalues attributes that would have been configured
  4822. # by crud.py as it scanned through the columns to be part of the
  4823. # INSERT
  4824. use_insertmanyvalues = crud_params_struct.use_insertmanyvalues
  4825. named_sentinel_params: Optional[Sequence[str]] = None
  4826. add_sentinel_cols = None
  4827. implicit_sentinel = False
  4828. returning_cols = self.implicit_returning or insert_stmt._returning
  4829. if returning_cols:
  4830. add_sentinel_cols = crud_params_struct.use_sentinel_columns
  4831. if add_sentinel_cols is not None:
  4832. assert use_insertmanyvalues
  4833. # search for the sentinel column explicitly present
  4834. # in the INSERT columns list, and additionally check that
  4835. # this column has a bound parameter name set up that's in the
  4836. # parameter list. If both of these cases are present, it means
  4837. # we will have a client side value for the sentinel in each
  4838. # parameter set.
  4839. _params_by_col = {
  4840. col: param_names
  4841. for col, _, _, param_names in crud_params_single
  4842. }
  4843. named_sentinel_params = []
  4844. for _add_sentinel_col in add_sentinel_cols:
  4845. if _add_sentinel_col not in _params_by_col:
  4846. named_sentinel_params = None
  4847. break
  4848. param_name = self._within_exec_param_key_getter(
  4849. _add_sentinel_col
  4850. )
  4851. if param_name not in _params_by_col[_add_sentinel_col]:
  4852. named_sentinel_params = None
  4853. break
  4854. named_sentinel_params.append(param_name)
  4855. if named_sentinel_params is None:
  4856. # if we are not going to have a client side value for
  4857. # the sentinel in the parameter set, that means it's
  4858. # an autoincrement, an IDENTITY, or a server-side SQL
  4859. # expression like nextval('seqname'). So this is
  4860. # an "implicit" sentinel; we will look for it in
  4861. # RETURNING
  4862. # only, and then sort on it. For this case on PG,
  4863. # SQL Server we have to use a special INSERT form
  4864. # that guarantees the server side function lines up with
  4865. # the entries in the VALUES.
  4866. if (
  4867. self.dialect.insertmanyvalues_implicit_sentinel
  4868. & InsertmanyvaluesSentinelOpts.ANY_AUTOINCREMENT
  4869. ):
  4870. implicit_sentinel = True
  4871. else:
  4872. # here, we are not using a sentinel at all
  4873. # and we are likely the SQLite dialect.
  4874. # The first add_sentinel_col that we have should not
  4875. # be marked as "insert_sentinel=True". if it was,
  4876. # an error should have been raised in
  4877. # _get_sentinel_column_for_table.
  4878. assert not add_sentinel_cols[0]._insert_sentinel, (
  4879. "sentinel selection rules should have prevented "
  4880. "us from getting here for this dialect"
  4881. )
  4882. # always put the sentinel columns last. even if they are
  4883. # in the returning list already, they will be there twice
  4884. # then.
  4885. returning_cols = list(returning_cols) + list(add_sentinel_cols)
  4886. returning_clause = self.returning_clause(
  4887. insert_stmt,
  4888. returning_cols,
  4889. populate_result_map=toplevel,
  4890. )
  4891. if self.returning_precedes_values:
  4892. text += " " + returning_clause
  4893. else:
  4894. returning_clause = None
  4895. if insert_stmt.select is not None:
  4896. # placed here by crud.py
  4897. select_text = self.process(
  4898. self.stack[-1]["insert_from_select"], insert_into=True, **kw
  4899. )
  4900. if self.ctes and self.dialect.cte_follows_insert:
  4901. nesting_level = len(self.stack) if not toplevel else None
  4902. text += " %s%s" % (
  4903. self._render_cte_clause(
  4904. nesting_level=nesting_level,
  4905. include_following_stack=True,
  4906. ),
  4907. select_text,
  4908. )
  4909. else:
  4910. text += " %s" % select_text
  4911. elif not crud_params_single and supports_default_values:
  4912. text += " DEFAULT VALUES"
  4913. if use_insertmanyvalues:
  4914. self._insertmanyvalues = _InsertManyValues(
  4915. True,
  4916. self.dialect.default_metavalue_token,
  4917. cast(
  4918. "List[crud._CrudParamElementStr]", crud_params_single
  4919. ),
  4920. counted_bindparam,
  4921. sort_by_parameter_order=(
  4922. insert_stmt._sort_by_parameter_order
  4923. ),
  4924. includes_upsert_behaviors=(
  4925. insert_stmt._post_values_clause is not None
  4926. ),
  4927. sentinel_columns=add_sentinel_cols,
  4928. num_sentinel_columns=len(add_sentinel_cols)
  4929. if add_sentinel_cols
  4930. else 0,
  4931. implicit_sentinel=implicit_sentinel,
  4932. )
  4933. elif compile_state._has_multi_parameters:
  4934. text += " VALUES %s" % (
  4935. ", ".join(
  4936. "(%s)"
  4937. % (", ".join(value for _, _, value, _ in crud_param_set))
  4938. for crud_param_set in crud_params_struct.all_multi_params
  4939. ),
  4940. )
  4941. else:
  4942. insert_single_values_expr = ", ".join(
  4943. [
  4944. value
  4945. for _, _, value, _ in cast(
  4946. "List[crud._CrudParamElementStr]",
  4947. crud_params_single,
  4948. )
  4949. ]
  4950. )
  4951. if use_insertmanyvalues:
  4952. if (
  4953. implicit_sentinel
  4954. and (
  4955. self.dialect.insertmanyvalues_implicit_sentinel
  4956. & InsertmanyvaluesSentinelOpts.USE_INSERT_FROM_SELECT
  4957. )
  4958. # this is checking if we have
  4959. # INSERT INTO table (id) VALUES (DEFAULT).
  4960. and not (crud_params_struct.is_default_metavalue_only)
  4961. ):
  4962. # if we have a sentinel column that is server generated,
  4963. # then for selected backends render the VALUES list as a
  4964. # subquery. This is the orderable form supported by
  4965. # PostgreSQL and SQL Server.
  4966. embed_sentinel_value = True
  4967. render_bind_casts = (
  4968. self.dialect.insertmanyvalues_implicit_sentinel
  4969. & InsertmanyvaluesSentinelOpts.RENDER_SELECT_COL_CASTS
  4970. )
  4971. colnames = ", ".join(
  4972. f"p{i}" for i, _ in enumerate(crud_params_single)
  4973. )
  4974. if render_bind_casts:
  4975. # render casts for the SELECT list. For PG, we are
  4976. # already rendering bind casts in the parameter list,
  4977. # selectively for the more "tricky" types like ARRAY.
  4978. # however, even for the "easy" types, if the parameter
  4979. # is NULL for every entry, PG gives up and says
  4980. # "it must be TEXT", which fails for other easy types
  4981. # like ints. So we cast on this side too.
  4982. colnames_w_cast = ", ".join(
  4983. self.render_bind_cast(
  4984. col.type,
  4985. col.type._unwrapped_dialect_impl(self.dialect),
  4986. f"p{i}",
  4987. )
  4988. for i, (col, *_) in enumerate(crud_params_single)
  4989. )
  4990. else:
  4991. colnames_w_cast = colnames
  4992. text += (
  4993. f" SELECT {colnames_w_cast} FROM "
  4994. f"(VALUES ({insert_single_values_expr})) "
  4995. f"AS imp_sen({colnames}, sen_counter) "
  4996. "ORDER BY sen_counter"
  4997. )
  4998. else:
  4999. # otherwise, if no sentinel or backend doesn't support
  5000. # orderable subquery form, use a plain VALUES list
  5001. embed_sentinel_value = False
  5002. text += f" VALUES ({insert_single_values_expr})"
  5003. self._insertmanyvalues = _InsertManyValues(
  5004. is_default_expr=False,
  5005. single_values_expr=insert_single_values_expr,
  5006. insert_crud_params=cast(
  5007. "List[crud._CrudParamElementStr]",
  5008. crud_params_single,
  5009. ),
  5010. num_positional_params_counted=counted_bindparam,
  5011. sort_by_parameter_order=(
  5012. insert_stmt._sort_by_parameter_order
  5013. ),
  5014. includes_upsert_behaviors=(
  5015. insert_stmt._post_values_clause is not None
  5016. ),
  5017. sentinel_columns=add_sentinel_cols,
  5018. num_sentinel_columns=len(add_sentinel_cols)
  5019. if add_sentinel_cols
  5020. else 0,
  5021. sentinel_param_keys=named_sentinel_params,
  5022. implicit_sentinel=implicit_sentinel,
  5023. embed_values_counter=embed_sentinel_value,
  5024. )
  5025. else:
  5026. text += f" VALUES ({insert_single_values_expr})"
  5027. if insert_stmt._post_values_clause is not None:
  5028. post_values_clause = self.process(
  5029. insert_stmt._post_values_clause, **kw
  5030. )
  5031. if post_values_clause:
  5032. text += " " + post_values_clause
  5033. if returning_clause and not self.returning_precedes_values:
  5034. text += " " + returning_clause
  5035. if self.ctes and not self.dialect.cte_follows_insert:
  5036. nesting_level = len(self.stack) if not toplevel else None
  5037. text = (
  5038. self._render_cte_clause(
  5039. nesting_level=nesting_level,
  5040. include_following_stack=True,
  5041. )
  5042. + text
  5043. )
  5044. self.stack.pop(-1)
  5045. return text
  5046. def update_limit_clause(self, update_stmt):
  5047. """Provide a hook for MySQL to add LIMIT to the UPDATE"""
  5048. return None
  5049. def update_tables_clause(self, update_stmt, from_table, extra_froms, **kw):
  5050. """Provide a hook to override the initial table clause
  5051. in an UPDATE statement.
  5052. MySQL overrides this.
  5053. """
  5054. kw["asfrom"] = True
  5055. return from_table._compiler_dispatch(self, iscrud=True, **kw)
  5056. def update_from_clause(
  5057. self, update_stmt, from_table, extra_froms, from_hints, **kw
  5058. ):
  5059. """Provide a hook to override the generation of an
  5060. UPDATE..FROM clause.
  5061. MySQL and MSSQL override this.
  5062. """
  5063. raise NotImplementedError(
  5064. "This backend does not support multiple-table "
  5065. "criteria within UPDATE"
  5066. )
  5067. def visit_update(self, update_stmt, visiting_cte=None, **kw):
  5068. compile_state = update_stmt._compile_state_factory(
  5069. update_stmt, self, **kw
  5070. )
  5071. update_stmt = compile_state.statement
  5072. if visiting_cte is not None:
  5073. kw["visiting_cte"] = visiting_cte
  5074. toplevel = False
  5075. else:
  5076. toplevel = not self.stack
  5077. if toplevel:
  5078. self.isupdate = True
  5079. if not self.dml_compile_state:
  5080. self.dml_compile_state = compile_state
  5081. if not self.compile_state:
  5082. self.compile_state = compile_state
  5083. if self.linting & COLLECT_CARTESIAN_PRODUCTS:
  5084. from_linter = FromLinter({}, set())
  5085. warn_linting = self.linting & WARN_LINTING
  5086. if toplevel:
  5087. self.from_linter = from_linter
  5088. else:
  5089. from_linter = None
  5090. warn_linting = False
  5091. extra_froms = compile_state._extra_froms
  5092. is_multitable = bool(extra_froms)
  5093. if is_multitable:
  5094. # main table might be a JOIN
  5095. main_froms = set(_from_objects(update_stmt.table))
  5096. render_extra_froms = [
  5097. f for f in extra_froms if f not in main_froms
  5098. ]
  5099. correlate_froms = main_froms.union(extra_froms)
  5100. else:
  5101. render_extra_froms = []
  5102. correlate_froms = {update_stmt.table}
  5103. self.stack.append(
  5104. {
  5105. "correlate_froms": correlate_froms,
  5106. "asfrom_froms": correlate_froms,
  5107. "selectable": update_stmt,
  5108. }
  5109. )
  5110. text = "UPDATE "
  5111. if update_stmt._prefixes:
  5112. text += self._generate_prefixes(
  5113. update_stmt, update_stmt._prefixes, **kw
  5114. )
  5115. table_text = self.update_tables_clause(
  5116. update_stmt,
  5117. update_stmt.table,
  5118. render_extra_froms,
  5119. from_linter=from_linter,
  5120. **kw,
  5121. )
  5122. crud_params_struct = crud._get_crud_params(
  5123. self, update_stmt, compile_state, toplevel, **kw
  5124. )
  5125. crud_params = crud_params_struct.single_params
  5126. if update_stmt._hints:
  5127. dialect_hints, table_text = self._setup_crud_hints(
  5128. update_stmt, table_text
  5129. )
  5130. else:
  5131. dialect_hints = None
  5132. if update_stmt._independent_ctes:
  5133. self._dispatch_independent_ctes(update_stmt, kw)
  5134. text += table_text
  5135. text += " SET "
  5136. text += ", ".join(
  5137. expr + "=" + value
  5138. for _, expr, value, _ in cast(
  5139. "List[Tuple[Any, str, str, Any]]", crud_params
  5140. )
  5141. )
  5142. if self.implicit_returning or update_stmt._returning:
  5143. if self.returning_precedes_values:
  5144. text += " " + self.returning_clause(
  5145. update_stmt,
  5146. self.implicit_returning or update_stmt._returning,
  5147. populate_result_map=toplevel,
  5148. )
  5149. if extra_froms:
  5150. extra_from_text = self.update_from_clause(
  5151. update_stmt,
  5152. update_stmt.table,
  5153. render_extra_froms,
  5154. dialect_hints,
  5155. from_linter=from_linter,
  5156. **kw,
  5157. )
  5158. if extra_from_text:
  5159. text += " " + extra_from_text
  5160. if update_stmt._where_criteria:
  5161. t = self._generate_delimited_and_list(
  5162. update_stmt._where_criteria, from_linter=from_linter, **kw
  5163. )
  5164. if t:
  5165. text += " WHERE " + t
  5166. limit_clause = self.update_limit_clause(update_stmt)
  5167. if limit_clause:
  5168. text += " " + limit_clause
  5169. if (
  5170. self.implicit_returning or update_stmt._returning
  5171. ) and not self.returning_precedes_values:
  5172. text += " " + self.returning_clause(
  5173. update_stmt,
  5174. self.implicit_returning or update_stmt._returning,
  5175. populate_result_map=toplevel,
  5176. )
  5177. if self.ctes:
  5178. nesting_level = len(self.stack) if not toplevel else None
  5179. text = self._render_cte_clause(nesting_level=nesting_level) + text
  5180. if warn_linting:
  5181. assert from_linter is not None
  5182. from_linter.warn(stmt_type="UPDATE")
  5183. self.stack.pop(-1)
  5184. return text
  5185. def delete_extra_from_clause(
  5186. self, update_stmt, from_table, extra_froms, from_hints, **kw
  5187. ):
  5188. """Provide a hook to override the generation of an
  5189. DELETE..FROM clause.
  5190. This can be used to implement DELETE..USING for example.
  5191. MySQL and MSSQL override this.
  5192. """
  5193. raise NotImplementedError(
  5194. "This backend does not support multiple-table "
  5195. "criteria within DELETE"
  5196. )
  5197. def delete_table_clause(self, delete_stmt, from_table, extra_froms, **kw):
  5198. return from_table._compiler_dispatch(
  5199. self, asfrom=True, iscrud=True, **kw
  5200. )
  5201. def visit_delete(self, delete_stmt, visiting_cte=None, **kw):
  5202. compile_state = delete_stmt._compile_state_factory(
  5203. delete_stmt, self, **kw
  5204. )
  5205. delete_stmt = compile_state.statement
  5206. if visiting_cte is not None:
  5207. kw["visiting_cte"] = visiting_cte
  5208. toplevel = False
  5209. else:
  5210. toplevel = not self.stack
  5211. if toplevel:
  5212. self.isdelete = True
  5213. if not self.dml_compile_state:
  5214. self.dml_compile_state = compile_state
  5215. if not self.compile_state:
  5216. self.compile_state = compile_state
  5217. if self.linting & COLLECT_CARTESIAN_PRODUCTS:
  5218. from_linter = FromLinter({}, set())
  5219. warn_linting = self.linting & WARN_LINTING
  5220. if toplevel:
  5221. self.from_linter = from_linter
  5222. else:
  5223. from_linter = None
  5224. warn_linting = False
  5225. extra_froms = compile_state._extra_froms
  5226. correlate_froms = {delete_stmt.table}.union(extra_froms)
  5227. self.stack.append(
  5228. {
  5229. "correlate_froms": correlate_froms,
  5230. "asfrom_froms": correlate_froms,
  5231. "selectable": delete_stmt,
  5232. }
  5233. )
  5234. text = "DELETE "
  5235. if delete_stmt._prefixes:
  5236. text += self._generate_prefixes(
  5237. delete_stmt, delete_stmt._prefixes, **kw
  5238. )
  5239. text += "FROM "
  5240. try:
  5241. table_text = self.delete_table_clause(
  5242. delete_stmt,
  5243. delete_stmt.table,
  5244. extra_froms,
  5245. from_linter=from_linter,
  5246. )
  5247. except TypeError:
  5248. # anticipate 3rd party dialects that don't include **kw
  5249. # TODO: remove in 2.1
  5250. table_text = self.delete_table_clause(
  5251. delete_stmt, delete_stmt.table, extra_froms
  5252. )
  5253. if from_linter:
  5254. _ = self.process(delete_stmt.table, from_linter=from_linter)
  5255. crud._get_crud_params(self, delete_stmt, compile_state, toplevel, **kw)
  5256. if delete_stmt._hints:
  5257. dialect_hints, table_text = self._setup_crud_hints(
  5258. delete_stmt, table_text
  5259. )
  5260. else:
  5261. dialect_hints = None
  5262. if delete_stmt._independent_ctes:
  5263. self._dispatch_independent_ctes(delete_stmt, kw)
  5264. text += table_text
  5265. if (
  5266. self.implicit_returning or delete_stmt._returning
  5267. ) and self.returning_precedes_values:
  5268. text += " " + self.returning_clause(
  5269. delete_stmt,
  5270. self.implicit_returning or delete_stmt._returning,
  5271. populate_result_map=toplevel,
  5272. )
  5273. if extra_froms:
  5274. extra_from_text = self.delete_extra_from_clause(
  5275. delete_stmt,
  5276. delete_stmt.table,
  5277. extra_froms,
  5278. dialect_hints,
  5279. from_linter=from_linter,
  5280. **kw,
  5281. )
  5282. if extra_from_text:
  5283. text += " " + extra_from_text
  5284. if delete_stmt._where_criteria:
  5285. t = self._generate_delimited_and_list(
  5286. delete_stmt._where_criteria, from_linter=from_linter, **kw
  5287. )
  5288. if t:
  5289. text += " WHERE " + t
  5290. if (
  5291. self.implicit_returning or delete_stmt._returning
  5292. ) and not self.returning_precedes_values:
  5293. text += " " + self.returning_clause(
  5294. delete_stmt,
  5295. self.implicit_returning or delete_stmt._returning,
  5296. populate_result_map=toplevel,
  5297. )
  5298. if self.ctes:
  5299. nesting_level = len(self.stack) if not toplevel else None
  5300. text = self._render_cte_clause(nesting_level=nesting_level) + text
  5301. if warn_linting:
  5302. assert from_linter is not None
  5303. from_linter.warn(stmt_type="DELETE")
  5304. self.stack.pop(-1)
  5305. return text
  5306. def visit_savepoint(self, savepoint_stmt, **kw):
  5307. return "SAVEPOINT %s" % self.preparer.format_savepoint(savepoint_stmt)
  5308. def visit_rollback_to_savepoint(self, savepoint_stmt, **kw):
  5309. return "ROLLBACK TO SAVEPOINT %s" % self.preparer.format_savepoint(
  5310. savepoint_stmt
  5311. )
  5312. def visit_release_savepoint(self, savepoint_stmt, **kw):
  5313. return "RELEASE SAVEPOINT %s" % self.preparer.format_savepoint(
  5314. savepoint_stmt
  5315. )
  5316. class StrSQLCompiler(SQLCompiler):
  5317. """A :class:`.SQLCompiler` subclass which allows a small selection
  5318. of non-standard SQL features to render into a string value.
  5319. The :class:`.StrSQLCompiler` is invoked whenever a Core expression
  5320. element is directly stringified without calling upon the
  5321. :meth:`_expression.ClauseElement.compile` method.
  5322. It can render a limited set
  5323. of non-standard SQL constructs to assist in basic stringification,
  5324. however for more substantial custom or dialect-specific SQL constructs,
  5325. it will be necessary to make use of
  5326. :meth:`_expression.ClauseElement.compile`
  5327. directly.
  5328. .. seealso::
  5329. :ref:`faq_sql_expression_string`
  5330. """
  5331. def _fallback_column_name(self, column):
  5332. return "<name unknown>"
  5333. @util.preload_module("sqlalchemy.engine.url")
  5334. def visit_unsupported_compilation(self, element, err, **kw):
  5335. if element.stringify_dialect != "default":
  5336. url = util.preloaded.engine_url
  5337. dialect = url.URL.create(element.stringify_dialect).get_dialect()()
  5338. compiler = dialect.statement_compiler(
  5339. dialect, None, _supporting_against=self
  5340. )
  5341. if not isinstance(compiler, StrSQLCompiler):
  5342. return compiler.process(element, **kw)
  5343. return super().visit_unsupported_compilation(element, err)
  5344. def visit_getitem_binary(self, binary, operator, **kw):
  5345. return "%s[%s]" % (
  5346. self.process(binary.left, **kw),
  5347. self.process(binary.right, **kw),
  5348. )
  5349. def visit_json_getitem_op_binary(self, binary, operator, **kw):
  5350. return self.visit_getitem_binary(binary, operator, **kw)
  5351. def visit_json_path_getitem_op_binary(self, binary, operator, **kw):
  5352. return self.visit_getitem_binary(binary, operator, **kw)
  5353. def visit_sequence(self, seq, **kw):
  5354. return "<next sequence value: %s>" % self.preparer.format_sequence(seq)
  5355. def returning_clause(
  5356. self,
  5357. stmt: UpdateBase,
  5358. returning_cols: Sequence[ColumnElement[Any]],
  5359. *,
  5360. populate_result_map: bool,
  5361. **kw: Any,
  5362. ) -> str:
  5363. columns = [
  5364. self._label_select_column(None, c, True, False, {})
  5365. for c in base._select_iterables(returning_cols)
  5366. ]
  5367. return "RETURNING " + ", ".join(columns)
  5368. def update_from_clause(
  5369. self, update_stmt, from_table, extra_froms, from_hints, **kw
  5370. ):
  5371. kw["asfrom"] = True
  5372. return "FROM " + ", ".join(
  5373. t._compiler_dispatch(self, fromhints=from_hints, **kw)
  5374. for t in extra_froms
  5375. )
  5376. def delete_extra_from_clause(
  5377. self, update_stmt, from_table, extra_froms, from_hints, **kw
  5378. ):
  5379. kw["asfrom"] = True
  5380. return ", " + ", ".join(
  5381. t._compiler_dispatch(self, fromhints=from_hints, **kw)
  5382. for t in extra_froms
  5383. )
  5384. def visit_empty_set_expr(self, type_, **kw):
  5385. return "SELECT 1 WHERE 1!=1"
  5386. def get_from_hint_text(self, table, text):
  5387. return "[%s]" % text
  5388. def visit_regexp_match_op_binary(self, binary, operator, **kw):
  5389. return self._generate_generic_binary(binary, " <regexp> ", **kw)
  5390. def visit_not_regexp_match_op_binary(self, binary, operator, **kw):
  5391. return self._generate_generic_binary(binary, " <not regexp> ", **kw)
  5392. def visit_regexp_replace_op_binary(self, binary, operator, **kw):
  5393. return "<regexp replace>(%s, %s)" % (
  5394. binary.left._compiler_dispatch(self, **kw),
  5395. binary.right._compiler_dispatch(self, **kw),
  5396. )
  5397. def visit_try_cast(self, cast, **kwargs):
  5398. return "TRY_CAST(%s AS %s)" % (
  5399. cast.clause._compiler_dispatch(self, **kwargs),
  5400. cast.typeclause._compiler_dispatch(self, **kwargs),
  5401. )
  5402. class DDLCompiler(Compiled):
  5403. is_ddl = True
  5404. if TYPE_CHECKING:
  5405. def __init__(
  5406. self,
  5407. dialect: Dialect,
  5408. statement: ExecutableDDLElement,
  5409. schema_translate_map: Optional[SchemaTranslateMapType] = ...,
  5410. render_schema_translate: bool = ...,
  5411. compile_kwargs: Mapping[str, Any] = ...,
  5412. ):
  5413. ...
  5414. @util.memoized_property
  5415. def sql_compiler(self):
  5416. return self.dialect.statement_compiler(
  5417. self.dialect, None, schema_translate_map=self.schema_translate_map
  5418. )
  5419. @util.memoized_property
  5420. def type_compiler(self):
  5421. return self.dialect.type_compiler_instance
  5422. def construct_params(
  5423. self,
  5424. params: Optional[_CoreSingleExecuteParams] = None,
  5425. extracted_parameters: Optional[Sequence[BindParameter[Any]]] = None,
  5426. escape_names: bool = True,
  5427. ) -> Optional[_MutableCoreSingleExecuteParams]:
  5428. return None
  5429. def visit_ddl(self, ddl, **kwargs):
  5430. # table events can substitute table and schema name
  5431. context = ddl.context
  5432. if isinstance(ddl.target, schema.Table):
  5433. context = context.copy()
  5434. preparer = self.preparer
  5435. path = preparer.format_table_seq(ddl.target)
  5436. if len(path) == 1:
  5437. table, sch = path[0], ""
  5438. else:
  5439. table, sch = path[-1], path[0]
  5440. context.setdefault("table", table)
  5441. context.setdefault("schema", sch)
  5442. context.setdefault("fullname", preparer.format_table(ddl.target))
  5443. return self.sql_compiler.post_process_text(ddl.statement % context)
  5444. def visit_create_schema(self, create, **kw):
  5445. text = "CREATE SCHEMA "
  5446. if create.if_not_exists:
  5447. text += "IF NOT EXISTS "
  5448. return text + self.preparer.format_schema(create.element)
  5449. def visit_drop_schema(self, drop, **kw):
  5450. text = "DROP SCHEMA "
  5451. if drop.if_exists:
  5452. text += "IF EXISTS "
  5453. text += self.preparer.format_schema(drop.element)
  5454. if drop.cascade:
  5455. text += " CASCADE"
  5456. return text
  5457. def visit_create_table(self, create, **kw):
  5458. table = create.element
  5459. preparer = self.preparer
  5460. text = "\nCREATE "
  5461. if table._prefixes:
  5462. text += " ".join(table._prefixes) + " "
  5463. text += "TABLE "
  5464. if create.if_not_exists:
  5465. text += "IF NOT EXISTS "
  5466. text += preparer.format_table(table) + " "
  5467. create_table_suffix = self.create_table_suffix(table)
  5468. if create_table_suffix:
  5469. text += create_table_suffix + " "
  5470. text += "("
  5471. separator = "\n"
  5472. # if only one primary key, specify it along with the column
  5473. first_pk = False
  5474. for create_column in create.columns:
  5475. column = create_column.element
  5476. try:
  5477. processed = self.process(
  5478. create_column, first_pk=column.primary_key and not first_pk
  5479. )
  5480. if processed is not None:
  5481. text += separator
  5482. separator = ", \n"
  5483. text += "\t" + processed
  5484. if column.primary_key:
  5485. first_pk = True
  5486. except exc.CompileError as ce:
  5487. raise exc.CompileError(
  5488. "(in table '%s', column '%s'): %s"
  5489. % (table.description, column.name, ce.args[0])
  5490. ) from ce
  5491. const = self.create_table_constraints(
  5492. table,
  5493. _include_foreign_key_constraints=create.include_foreign_key_constraints, # noqa
  5494. )
  5495. if const:
  5496. text += separator + "\t" + const
  5497. text += "\n)%s\n\n" % self.post_create_table(table)
  5498. return text
  5499. def visit_create_column(self, create, first_pk=False, **kw):
  5500. column = create.element
  5501. if column.system:
  5502. return None
  5503. text = self.get_column_specification(column, first_pk=first_pk)
  5504. const = " ".join(
  5505. self.process(constraint) for constraint in column.constraints
  5506. )
  5507. if const:
  5508. text += " " + const
  5509. return text
  5510. def create_table_constraints(
  5511. self, table, _include_foreign_key_constraints=None, **kw
  5512. ):
  5513. # On some DB order is significant: visit PK first, then the
  5514. # other constraints (engine.ReflectionTest.testbasic failed on FB2)
  5515. constraints = []
  5516. if table.primary_key:
  5517. constraints.append(table.primary_key)
  5518. all_fkcs = table.foreign_key_constraints
  5519. if _include_foreign_key_constraints is not None:
  5520. omit_fkcs = all_fkcs.difference(_include_foreign_key_constraints)
  5521. else:
  5522. omit_fkcs = set()
  5523. constraints.extend(
  5524. [
  5525. c
  5526. for c in table._sorted_constraints
  5527. if c is not table.primary_key and c not in omit_fkcs
  5528. ]
  5529. )
  5530. return ", \n\t".join(
  5531. p
  5532. for p in (
  5533. self.process(constraint)
  5534. for constraint in constraints
  5535. if (constraint._should_create_for_compiler(self))
  5536. and (
  5537. not self.dialect.supports_alter
  5538. or not getattr(constraint, "use_alter", False)
  5539. )
  5540. )
  5541. if p is not None
  5542. )
  5543. def visit_drop_table(self, drop, **kw):
  5544. text = "\nDROP TABLE "
  5545. if drop.if_exists:
  5546. text += "IF EXISTS "
  5547. return text + self.preparer.format_table(drop.element)
  5548. def visit_drop_view(self, drop, **kw):
  5549. return "\nDROP VIEW " + self.preparer.format_table(drop.element)
  5550. def _verify_index_table(self, index):
  5551. if index.table is None:
  5552. raise exc.CompileError(
  5553. "Index '%s' is not associated " "with any table." % index.name
  5554. )
  5555. def visit_create_index(
  5556. self, create, include_schema=False, include_table_schema=True, **kw
  5557. ):
  5558. index = create.element
  5559. self._verify_index_table(index)
  5560. preparer = self.preparer
  5561. text = "CREATE "
  5562. if index.unique:
  5563. text += "UNIQUE "
  5564. if index.name is None:
  5565. raise exc.CompileError(
  5566. "CREATE INDEX requires that the index have a name"
  5567. )
  5568. text += "INDEX "
  5569. if create.if_not_exists:
  5570. text += "IF NOT EXISTS "
  5571. text += "%s ON %s (%s)" % (
  5572. self._prepared_index_name(index, include_schema=include_schema),
  5573. preparer.format_table(
  5574. index.table, use_schema=include_table_schema
  5575. ),
  5576. ", ".join(
  5577. self.sql_compiler.process(
  5578. expr, include_table=False, literal_binds=True
  5579. )
  5580. for expr in index.expressions
  5581. ),
  5582. )
  5583. return text
  5584. def visit_drop_index(self, drop, **kw):
  5585. index = drop.element
  5586. if index.name is None:
  5587. raise exc.CompileError(
  5588. "DROP INDEX requires that the index have a name"
  5589. )
  5590. text = "\nDROP INDEX "
  5591. if drop.if_exists:
  5592. text += "IF EXISTS "
  5593. return text + self._prepared_index_name(index, include_schema=True)
  5594. def _prepared_index_name(self, index, include_schema=False):
  5595. if index.table is not None:
  5596. effective_schema = self.preparer.schema_for_object(index.table)
  5597. else:
  5598. effective_schema = None
  5599. if include_schema and effective_schema:
  5600. schema_name = self.preparer.quote_schema(effective_schema)
  5601. else:
  5602. schema_name = None
  5603. index_name = self.preparer.format_index(index)
  5604. if schema_name:
  5605. index_name = schema_name + "." + index_name
  5606. return index_name
  5607. def visit_add_constraint(self, create, **kw):
  5608. return "ALTER TABLE %s ADD %s" % (
  5609. self.preparer.format_table(create.element.table),
  5610. self.process(create.element),
  5611. )
  5612. def visit_set_table_comment(self, create, **kw):
  5613. return "COMMENT ON TABLE %s IS %s" % (
  5614. self.preparer.format_table(create.element),
  5615. self.sql_compiler.render_literal_value(
  5616. create.element.comment, sqltypes.String()
  5617. ),
  5618. )
  5619. def visit_drop_table_comment(self, drop, **kw):
  5620. return "COMMENT ON TABLE %s IS NULL" % self.preparer.format_table(
  5621. drop.element
  5622. )
  5623. def visit_set_column_comment(self, create, **kw):
  5624. return "COMMENT ON COLUMN %s IS %s" % (
  5625. self.preparer.format_column(
  5626. create.element, use_table=True, use_schema=True
  5627. ),
  5628. self.sql_compiler.render_literal_value(
  5629. create.element.comment, sqltypes.String()
  5630. ),
  5631. )
  5632. def visit_drop_column_comment(self, drop, **kw):
  5633. return "COMMENT ON COLUMN %s IS NULL" % self.preparer.format_column(
  5634. drop.element, use_table=True
  5635. )
  5636. def visit_set_constraint_comment(self, create, **kw):
  5637. raise exc.UnsupportedCompilationError(self, type(create))
  5638. def visit_drop_constraint_comment(self, drop, **kw):
  5639. raise exc.UnsupportedCompilationError(self, type(drop))
  5640. def get_identity_options(self, identity_options):
  5641. text = []
  5642. if identity_options.increment is not None:
  5643. text.append("INCREMENT BY %d" % identity_options.increment)
  5644. if identity_options.start is not None:
  5645. text.append("START WITH %d" % identity_options.start)
  5646. if identity_options.minvalue is not None:
  5647. text.append("MINVALUE %d" % identity_options.minvalue)
  5648. if identity_options.maxvalue is not None:
  5649. text.append("MAXVALUE %d" % identity_options.maxvalue)
  5650. if identity_options.nominvalue is not None:
  5651. text.append("NO MINVALUE")
  5652. if identity_options.nomaxvalue is not None:
  5653. text.append("NO MAXVALUE")
  5654. if identity_options.cache is not None:
  5655. text.append("CACHE %d" % identity_options.cache)
  5656. if identity_options.cycle is not None:
  5657. text.append("CYCLE" if identity_options.cycle else "NO CYCLE")
  5658. return " ".join(text)
  5659. def visit_create_sequence(self, create, prefix=None, **kw):
  5660. text = "CREATE SEQUENCE "
  5661. if create.if_not_exists:
  5662. text += "IF NOT EXISTS "
  5663. text += self.preparer.format_sequence(create.element)
  5664. if prefix:
  5665. text += prefix
  5666. options = self.get_identity_options(create.element)
  5667. if options:
  5668. text += " " + options
  5669. return text
  5670. def visit_drop_sequence(self, drop, **kw):
  5671. text = "DROP SEQUENCE "
  5672. if drop.if_exists:
  5673. text += "IF EXISTS "
  5674. return text + self.preparer.format_sequence(drop.element)
  5675. def visit_drop_constraint(self, drop, **kw):
  5676. constraint = drop.element
  5677. if constraint.name is not None:
  5678. formatted_name = self.preparer.format_constraint(constraint)
  5679. else:
  5680. formatted_name = None
  5681. if formatted_name is None:
  5682. raise exc.CompileError(
  5683. "Can't emit DROP CONSTRAINT for constraint %r; "
  5684. "it has no name" % drop.element
  5685. )
  5686. return "ALTER TABLE %s DROP CONSTRAINT %s%s%s" % (
  5687. self.preparer.format_table(drop.element.table),
  5688. "IF EXISTS " if drop.if_exists else "",
  5689. formatted_name,
  5690. " CASCADE" if drop.cascade else "",
  5691. )
  5692. def get_column_specification(self, column, **kwargs):
  5693. colspec = (
  5694. self.preparer.format_column(column)
  5695. + " "
  5696. + self.dialect.type_compiler_instance.process(
  5697. column.type, type_expression=column
  5698. )
  5699. )
  5700. default = self.get_column_default_string(column)
  5701. if default is not None:
  5702. colspec += " DEFAULT " + default
  5703. if column.computed is not None:
  5704. colspec += " " + self.process(column.computed)
  5705. if (
  5706. column.identity is not None
  5707. and self.dialect.supports_identity_columns
  5708. ):
  5709. colspec += " " + self.process(column.identity)
  5710. if not column.nullable and (
  5711. not column.identity or not self.dialect.supports_identity_columns
  5712. ):
  5713. colspec += " NOT NULL"
  5714. return colspec
  5715. def create_table_suffix(self, table):
  5716. return ""
  5717. def post_create_table(self, table):
  5718. return ""
  5719. def get_column_default_string(self, column):
  5720. if isinstance(column.server_default, schema.DefaultClause):
  5721. return self.render_default_string(column.server_default.arg)
  5722. else:
  5723. return None
  5724. def render_default_string(self, default):
  5725. if isinstance(default, str):
  5726. return self.sql_compiler.render_literal_value(
  5727. default, sqltypes.STRINGTYPE
  5728. )
  5729. else:
  5730. return self.sql_compiler.process(default, literal_binds=True)
  5731. def visit_table_or_column_check_constraint(self, constraint, **kw):
  5732. if constraint.is_column_level:
  5733. return self.visit_column_check_constraint(constraint)
  5734. else:
  5735. return self.visit_check_constraint(constraint)
  5736. def visit_check_constraint(self, constraint, **kw):
  5737. text = ""
  5738. if constraint.name is not None:
  5739. formatted_name = self.preparer.format_constraint(constraint)
  5740. if formatted_name is not None:
  5741. text += "CONSTRAINT %s " % formatted_name
  5742. text += "CHECK (%s)" % self.sql_compiler.process(
  5743. constraint.sqltext, include_table=False, literal_binds=True
  5744. )
  5745. text += self.define_constraint_deferrability(constraint)
  5746. return text
  5747. def visit_column_check_constraint(self, constraint, **kw):
  5748. text = ""
  5749. if constraint.name is not None:
  5750. formatted_name = self.preparer.format_constraint(constraint)
  5751. if formatted_name is not None:
  5752. text += "CONSTRAINT %s " % formatted_name
  5753. text += "CHECK (%s)" % self.sql_compiler.process(
  5754. constraint.sqltext, include_table=False, literal_binds=True
  5755. )
  5756. text += self.define_constraint_deferrability(constraint)
  5757. return text
  5758. def visit_primary_key_constraint(self, constraint, **kw):
  5759. if len(constraint) == 0:
  5760. return ""
  5761. text = ""
  5762. if constraint.name is not None:
  5763. formatted_name = self.preparer.format_constraint(constraint)
  5764. if formatted_name is not None:
  5765. text += "CONSTRAINT %s " % formatted_name
  5766. text += "PRIMARY KEY "
  5767. text += "(%s)" % ", ".join(
  5768. self.preparer.quote(c.name)
  5769. for c in (
  5770. constraint.columns_autoinc_first
  5771. if constraint._implicit_generated
  5772. else constraint.columns
  5773. )
  5774. )
  5775. text += self.define_constraint_deferrability(constraint)
  5776. return text
  5777. def visit_foreign_key_constraint(self, constraint, **kw):
  5778. preparer = self.preparer
  5779. text = ""
  5780. if constraint.name is not None:
  5781. formatted_name = self.preparer.format_constraint(constraint)
  5782. if formatted_name is not None:
  5783. text += "CONSTRAINT %s " % formatted_name
  5784. remote_table = list(constraint.elements)[0].column.table
  5785. text += "FOREIGN KEY(%s) REFERENCES %s (%s)" % (
  5786. ", ".join(
  5787. preparer.quote(f.parent.name) for f in constraint.elements
  5788. ),
  5789. self.define_constraint_remote_table(
  5790. constraint, remote_table, preparer
  5791. ),
  5792. ", ".join(
  5793. preparer.quote(f.column.name) for f in constraint.elements
  5794. ),
  5795. )
  5796. text += self.define_constraint_match(constraint)
  5797. text += self.define_constraint_cascades(constraint)
  5798. text += self.define_constraint_deferrability(constraint)
  5799. return text
  5800. def define_constraint_remote_table(self, constraint, table, preparer):
  5801. """Format the remote table clause of a CREATE CONSTRAINT clause."""
  5802. return preparer.format_table(table)
  5803. def visit_unique_constraint(self, constraint, **kw):
  5804. if len(constraint) == 0:
  5805. return ""
  5806. text = ""
  5807. if constraint.name is not None:
  5808. formatted_name = self.preparer.format_constraint(constraint)
  5809. if formatted_name is not None:
  5810. text += "CONSTRAINT %s " % formatted_name
  5811. text += "UNIQUE %s(%s)" % (
  5812. self.define_unique_constraint_distinct(constraint, **kw),
  5813. ", ".join(self.preparer.quote(c.name) for c in constraint),
  5814. )
  5815. text += self.define_constraint_deferrability(constraint)
  5816. return text
  5817. def define_unique_constraint_distinct(self, constraint, **kw):
  5818. return ""
  5819. def define_constraint_cascades(self, constraint):
  5820. text = ""
  5821. if constraint.ondelete is not None:
  5822. text += " ON DELETE %s" % self.preparer.validate_sql_phrase(
  5823. constraint.ondelete, FK_ON_DELETE
  5824. )
  5825. if constraint.onupdate is not None:
  5826. text += " ON UPDATE %s" % self.preparer.validate_sql_phrase(
  5827. constraint.onupdate, FK_ON_UPDATE
  5828. )
  5829. return text
  5830. def define_constraint_deferrability(self, constraint):
  5831. text = ""
  5832. if constraint.deferrable is not None:
  5833. if constraint.deferrable:
  5834. text += " DEFERRABLE"
  5835. else:
  5836. text += " NOT DEFERRABLE"
  5837. if constraint.initially is not None:
  5838. text += " INITIALLY %s" % self.preparer.validate_sql_phrase(
  5839. constraint.initially, FK_INITIALLY
  5840. )
  5841. return text
  5842. def define_constraint_match(self, constraint):
  5843. text = ""
  5844. if constraint.match is not None:
  5845. text += " MATCH %s" % constraint.match
  5846. return text
  5847. def visit_computed_column(self, generated, **kw):
  5848. text = "GENERATED ALWAYS AS (%s)" % self.sql_compiler.process(
  5849. generated.sqltext, include_table=False, literal_binds=True
  5850. )
  5851. if generated.persisted is True:
  5852. text += " STORED"
  5853. elif generated.persisted is False:
  5854. text += " VIRTUAL"
  5855. return text
  5856. def visit_identity_column(self, identity, **kw):
  5857. text = "GENERATED %s AS IDENTITY" % (
  5858. "ALWAYS" if identity.always else "BY DEFAULT",
  5859. )
  5860. options = self.get_identity_options(identity)
  5861. if options:
  5862. text += " (%s)" % options
  5863. return text
  5864. class GenericTypeCompiler(TypeCompiler):
  5865. def visit_FLOAT(self, type_, **kw):
  5866. return "FLOAT"
  5867. def visit_DOUBLE(self, type_, **kw):
  5868. return "DOUBLE"
  5869. def visit_DOUBLE_PRECISION(self, type_, **kw):
  5870. return "DOUBLE PRECISION"
  5871. def visit_REAL(self, type_, **kw):
  5872. return "REAL"
  5873. def visit_NUMERIC(self, type_, **kw):
  5874. if type_.precision is None:
  5875. return "NUMERIC"
  5876. elif type_.scale is None:
  5877. return "NUMERIC(%(precision)s)" % {"precision": type_.precision}
  5878. else:
  5879. return "NUMERIC(%(precision)s, %(scale)s)" % {
  5880. "precision": type_.precision,
  5881. "scale": type_.scale,
  5882. }
  5883. def visit_DECIMAL(self, type_, **kw):
  5884. if type_.precision is None:
  5885. return "DECIMAL"
  5886. elif type_.scale is None:
  5887. return "DECIMAL(%(precision)s)" % {"precision": type_.precision}
  5888. else:
  5889. return "DECIMAL(%(precision)s, %(scale)s)" % {
  5890. "precision": type_.precision,
  5891. "scale": type_.scale,
  5892. }
  5893. def visit_INTEGER(self, type_, **kw):
  5894. return "INTEGER"
  5895. def visit_SMALLINT(self, type_, **kw):
  5896. return "SMALLINT"
  5897. def visit_BIGINT(self, type_, **kw):
  5898. return "BIGINT"
  5899. def visit_TIMESTAMP(self, type_, **kw):
  5900. return "TIMESTAMP"
  5901. def visit_DATETIME(self, type_, **kw):
  5902. return "DATETIME"
  5903. def visit_DATE(self, type_, **kw):
  5904. return "DATE"
  5905. def visit_TIME(self, type_, **kw):
  5906. return "TIME"
  5907. def visit_CLOB(self, type_, **kw):
  5908. return "CLOB"
  5909. def visit_NCLOB(self, type_, **kw):
  5910. return "NCLOB"
  5911. def _render_string_type(self, type_, name, length_override=None):
  5912. text = name
  5913. if length_override:
  5914. text += "(%d)" % length_override
  5915. elif type_.length:
  5916. text += "(%d)" % type_.length
  5917. if type_.collation:
  5918. text += ' COLLATE "%s"' % type_.collation
  5919. return text
  5920. def visit_CHAR(self, type_, **kw):
  5921. return self._render_string_type(type_, "CHAR")
  5922. def visit_NCHAR(self, type_, **kw):
  5923. return self._render_string_type(type_, "NCHAR")
  5924. def visit_VARCHAR(self, type_, **kw):
  5925. return self._render_string_type(type_, "VARCHAR")
  5926. def visit_NVARCHAR(self, type_, **kw):
  5927. return self._render_string_type(type_, "NVARCHAR")
  5928. def visit_TEXT(self, type_, **kw):
  5929. return self._render_string_type(type_, "TEXT")
  5930. def visit_BLOB(self, type_, **kw):
  5931. return "BLOB"
  5932. def visit_BINARY(self, type_, **kw):
  5933. return "BINARY" + (type_.length and "(%d)" % type_.length or "")
  5934. def visit_VARBINARY(self, type_, **kw):
  5935. return "VARBINARY" + (type_.length and "(%d)" % type_.length or "")
  5936. def visit_BOOLEAN(self, type_, **kw):
  5937. return "BOOLEAN"
  5938. def visit_uuid(self, type_, **kw):
  5939. return self._render_string_type(type_, "CHAR", length_override=32)
  5940. def visit_large_binary(self, type_, **kw):
  5941. return self.visit_BLOB(type_, **kw)
  5942. def visit_boolean(self, type_, **kw):
  5943. return self.visit_BOOLEAN(type_, **kw)
  5944. def visit_time(self, type_, **kw):
  5945. return self.visit_TIME(type_, **kw)
  5946. def visit_datetime(self, type_, **kw):
  5947. return self.visit_DATETIME(type_, **kw)
  5948. def visit_date(self, type_, **kw):
  5949. return self.visit_DATE(type_, **kw)
  5950. def visit_big_integer(self, type_, **kw):
  5951. return self.visit_BIGINT(type_, **kw)
  5952. def visit_small_integer(self, type_, **kw):
  5953. return self.visit_SMALLINT(type_, **kw)
  5954. def visit_integer(self, type_, **kw):
  5955. return self.visit_INTEGER(type_, **kw)
  5956. def visit_real(self, type_, **kw):
  5957. return self.visit_REAL(type_, **kw)
  5958. def visit_float(self, type_, **kw):
  5959. return self.visit_FLOAT(type_, **kw)
  5960. def visit_double(self, type_, **kw):
  5961. return self.visit_DOUBLE(type_, **kw)
  5962. def visit_numeric(self, type_, **kw):
  5963. return self.visit_NUMERIC(type_, **kw)
  5964. def visit_string(self, type_, **kw):
  5965. return self.visit_VARCHAR(type_, **kw)
  5966. def visit_unicode(self, type_, **kw):
  5967. return self.visit_VARCHAR(type_, **kw)
  5968. def visit_text(self, type_, **kw):
  5969. return self.visit_TEXT(type_, **kw)
  5970. def visit_unicode_text(self, type_, **kw):
  5971. return self.visit_TEXT(type_, **kw)
  5972. def visit_enum(self, type_, **kw):
  5973. return self.visit_VARCHAR(type_, **kw)
  5974. def visit_null(self, type_, **kw):
  5975. raise exc.CompileError(
  5976. "Can't generate DDL for %r; "
  5977. "did you forget to specify a "
  5978. "type on this Column?" % type_
  5979. )
  5980. def visit_type_decorator(self, type_, **kw):
  5981. return self.process(type_.type_engine(self.dialect), **kw)
  5982. def visit_user_defined(self, type_, **kw):
  5983. return type_.get_col_spec(**kw)
  5984. class StrSQLTypeCompiler(GenericTypeCompiler):
  5985. def process(self, type_, **kw):
  5986. try:
  5987. _compiler_dispatch = type_._compiler_dispatch
  5988. except AttributeError:
  5989. return self._visit_unknown(type_, **kw)
  5990. else:
  5991. return _compiler_dispatch(self, **kw)
  5992. def __getattr__(self, key):
  5993. if key.startswith("visit_"):
  5994. return self._visit_unknown
  5995. else:
  5996. raise AttributeError(key)
  5997. def _visit_unknown(self, type_, **kw):
  5998. if type_.__class__.__name__ == type_.__class__.__name__.upper():
  5999. return type_.__class__.__name__
  6000. else:
  6001. return repr(type_)
  6002. def visit_null(self, type_, **kw):
  6003. return "NULL"
  6004. def visit_user_defined(self, type_, **kw):
  6005. try:
  6006. get_col_spec = type_.get_col_spec
  6007. except AttributeError:
  6008. return repr(type_)
  6009. else:
  6010. return get_col_spec(**kw)
  6011. class _SchemaForObjectCallable(Protocol):
  6012. def __call__(self, obj: Any) -> str:
  6013. ...
  6014. class _BindNameForColProtocol(Protocol):
  6015. def __call__(self, col: ColumnClause[Any]) -> str:
  6016. ...
  6017. class IdentifierPreparer:
  6018. """Handle quoting and case-folding of identifiers based on options."""
  6019. reserved_words = RESERVED_WORDS
  6020. legal_characters = LEGAL_CHARACTERS
  6021. illegal_initial_characters = ILLEGAL_INITIAL_CHARACTERS
  6022. initial_quote: str
  6023. final_quote: str
  6024. _strings: MutableMapping[str, str]
  6025. schema_for_object: _SchemaForObjectCallable = operator.attrgetter("schema")
  6026. """Return the .schema attribute for an object.
  6027. For the default IdentifierPreparer, the schema for an object is always
  6028. the value of the ".schema" attribute. if the preparer is replaced
  6029. with one that has a non-empty schema_translate_map, the value of the
  6030. ".schema" attribute is rendered a symbol that will be converted to a
  6031. real schema name from the mapping post-compile.
  6032. """
  6033. _includes_none_schema_translate: bool = False
  6034. def __init__(
  6035. self,
  6036. dialect,
  6037. initial_quote='"',
  6038. final_quote=None,
  6039. escape_quote='"',
  6040. quote_case_sensitive_collations=True,
  6041. omit_schema=False,
  6042. ):
  6043. """Construct a new ``IdentifierPreparer`` object.
  6044. initial_quote
  6045. Character that begins a delimited identifier.
  6046. final_quote
  6047. Character that ends a delimited identifier. Defaults to
  6048. `initial_quote`.
  6049. omit_schema
  6050. Prevent prepending schema name. Useful for databases that do
  6051. not support schemae.
  6052. """
  6053. self.dialect = dialect
  6054. self.initial_quote = initial_quote
  6055. self.final_quote = final_quote or self.initial_quote
  6056. self.escape_quote = escape_quote
  6057. self.escape_to_quote = self.escape_quote * 2
  6058. self.omit_schema = omit_schema
  6059. self.quote_case_sensitive_collations = quote_case_sensitive_collations
  6060. self._strings = {}
  6061. self._double_percents = self.dialect.paramstyle in (
  6062. "format",
  6063. "pyformat",
  6064. )
  6065. def _with_schema_translate(self, schema_translate_map):
  6066. prep = self.__class__.__new__(self.__class__)
  6067. prep.__dict__.update(self.__dict__)
  6068. includes_none = None in schema_translate_map
  6069. def symbol_getter(obj):
  6070. name = obj.schema
  6071. if obj._use_schema_map and (name is not None or includes_none):
  6072. if name is not None and ("[" in name or "]" in name):
  6073. raise exc.CompileError(
  6074. "Square bracket characters ([]) not supported "
  6075. "in schema translate name '%s'" % name
  6076. )
  6077. return quoted_name(
  6078. "__[SCHEMA_%s]" % (name or "_none"), quote=False
  6079. )
  6080. else:
  6081. return obj.schema
  6082. prep.schema_for_object = symbol_getter
  6083. prep._includes_none_schema_translate = includes_none
  6084. return prep
  6085. def _render_schema_translates(self, statement, schema_translate_map):
  6086. d = schema_translate_map
  6087. if None in d:
  6088. if not self._includes_none_schema_translate:
  6089. raise exc.InvalidRequestError(
  6090. "schema translate map which previously did not have "
  6091. "`None` present as a key now has `None` present; compiled "
  6092. "statement may lack adequate placeholders. Please use "
  6093. "consistent keys in successive "
  6094. "schema_translate_map dictionaries."
  6095. )
  6096. d["_none"] = d[None]
  6097. def replace(m):
  6098. name = m.group(2)
  6099. if name in d:
  6100. effective_schema = d[name]
  6101. else:
  6102. if name in (None, "_none"):
  6103. raise exc.InvalidRequestError(
  6104. "schema translate map which previously had `None` "
  6105. "present as a key now no longer has it present; don't "
  6106. "know how to apply schema for compiled statement. "
  6107. "Please use consistent keys in successive "
  6108. "schema_translate_map dictionaries."
  6109. )
  6110. effective_schema = name
  6111. if not effective_schema:
  6112. effective_schema = self.dialect.default_schema_name
  6113. if not effective_schema:
  6114. # TODO: no coverage here
  6115. raise exc.CompileError(
  6116. "Dialect has no default schema name; can't "
  6117. "use None as dynamic schema target."
  6118. )
  6119. return self.quote_schema(effective_schema)
  6120. return re.sub(r"(__\[SCHEMA_([^\]]+)\])", replace, statement)
  6121. def _escape_identifier(self, value: str) -> str:
  6122. """Escape an identifier.
  6123. Subclasses should override this to provide database-dependent
  6124. escaping behavior.
  6125. """
  6126. value = value.replace(self.escape_quote, self.escape_to_quote)
  6127. if self._double_percents:
  6128. value = value.replace("%", "%%")
  6129. return value
  6130. def _unescape_identifier(self, value: str) -> str:
  6131. """Canonicalize an escaped identifier.
  6132. Subclasses should override this to provide database-dependent
  6133. unescaping behavior that reverses _escape_identifier.
  6134. """
  6135. return value.replace(self.escape_to_quote, self.escape_quote)
  6136. def validate_sql_phrase(self, element, reg):
  6137. """keyword sequence filter.
  6138. a filter for elements that are intended to represent keyword sequences,
  6139. such as "INITIALLY", "INITIALLY DEFERRED", etc. no special characters
  6140. should be present.
  6141. .. versionadded:: 1.3
  6142. """
  6143. if element is not None and not reg.match(element):
  6144. raise exc.CompileError(
  6145. "Unexpected SQL phrase: %r (matching against %r)"
  6146. % (element, reg.pattern)
  6147. )
  6148. return element
  6149. def quote_identifier(self, value: str) -> str:
  6150. """Quote an identifier.
  6151. Subclasses should override this to provide database-dependent
  6152. quoting behavior.
  6153. """
  6154. return (
  6155. self.initial_quote
  6156. + self._escape_identifier(value)
  6157. + self.final_quote
  6158. )
  6159. def _requires_quotes(self, value: str) -> bool:
  6160. """Return True if the given identifier requires quoting."""
  6161. lc_value = value.lower()
  6162. return (
  6163. lc_value in self.reserved_words
  6164. or value[0] in self.illegal_initial_characters
  6165. or not self.legal_characters.match(str(value))
  6166. or (lc_value != value)
  6167. )
  6168. def _requires_quotes_illegal_chars(self, value):
  6169. """Return True if the given identifier requires quoting, but
  6170. not taking case convention into account."""
  6171. return not self.legal_characters.match(str(value))
  6172. def quote_schema(self, schema: str, force: Any = None) -> str:
  6173. """Conditionally quote a schema name.
  6174. The name is quoted if it is a reserved word, contains quote-necessary
  6175. characters, or is an instance of :class:`.quoted_name` which includes
  6176. ``quote`` set to ``True``.
  6177. Subclasses can override this to provide database-dependent
  6178. quoting behavior for schema names.
  6179. :param schema: string schema name
  6180. :param force: unused
  6181. .. deprecated:: 0.9
  6182. The :paramref:`.IdentifierPreparer.quote_schema.force`
  6183. parameter is deprecated and will be removed in a future
  6184. release. This flag has no effect on the behavior of the
  6185. :meth:`.IdentifierPreparer.quote` method; please refer to
  6186. :class:`.quoted_name`.
  6187. """
  6188. if force is not None:
  6189. # not using the util.deprecated_params() decorator in this
  6190. # case because of the additional function call overhead on this
  6191. # very performance-critical spot.
  6192. util.warn_deprecated(
  6193. "The IdentifierPreparer.quote_schema.force parameter is "
  6194. "deprecated and will be removed in a future release. This "
  6195. "flag has no effect on the behavior of the "
  6196. "IdentifierPreparer.quote method; please refer to "
  6197. "quoted_name().",
  6198. # deprecated 0.9. warning from 1.3
  6199. version="0.9",
  6200. )
  6201. return self.quote(schema)
  6202. def quote(self, ident: str, force: Any = None) -> str:
  6203. """Conditionally quote an identifier.
  6204. The identifier is quoted if it is a reserved word, contains
  6205. quote-necessary characters, or is an instance of
  6206. :class:`.quoted_name` which includes ``quote`` set to ``True``.
  6207. Subclasses can override this to provide database-dependent
  6208. quoting behavior for identifier names.
  6209. :param ident: string identifier
  6210. :param force: unused
  6211. .. deprecated:: 0.9
  6212. The :paramref:`.IdentifierPreparer.quote.force`
  6213. parameter is deprecated and will be removed in a future
  6214. release. This flag has no effect on the behavior of the
  6215. :meth:`.IdentifierPreparer.quote` method; please refer to
  6216. :class:`.quoted_name`.
  6217. """
  6218. if force is not None:
  6219. # not using the util.deprecated_params() decorator in this
  6220. # case because of the additional function call overhead on this
  6221. # very performance-critical spot.
  6222. util.warn_deprecated(
  6223. "The IdentifierPreparer.quote.force parameter is "
  6224. "deprecated and will be removed in a future release. This "
  6225. "flag has no effect on the behavior of the "
  6226. "IdentifierPreparer.quote method; please refer to "
  6227. "quoted_name().",
  6228. # deprecated 0.9. warning from 1.3
  6229. version="0.9",
  6230. )
  6231. force = getattr(ident, "quote", None)
  6232. if force is None:
  6233. if ident in self._strings:
  6234. return self._strings[ident]
  6235. else:
  6236. if self._requires_quotes(ident):
  6237. self._strings[ident] = self.quote_identifier(ident)
  6238. else:
  6239. self._strings[ident] = ident
  6240. return self._strings[ident]
  6241. elif force:
  6242. return self.quote_identifier(ident)
  6243. else:
  6244. return ident
  6245. def format_collation(self, collation_name):
  6246. if self.quote_case_sensitive_collations:
  6247. return self.quote(collation_name)
  6248. else:
  6249. return collation_name
  6250. def format_sequence(self, sequence, use_schema=True):
  6251. name = self.quote(sequence.name)
  6252. effective_schema = self.schema_for_object(sequence)
  6253. if (
  6254. not self.omit_schema
  6255. and use_schema
  6256. and effective_schema is not None
  6257. ):
  6258. name = self.quote_schema(effective_schema) + "." + name
  6259. return name
  6260. def format_label(
  6261. self, label: Label[Any], name: Optional[str] = None
  6262. ) -> str:
  6263. return self.quote(name or label.name)
  6264. def format_alias(
  6265. self, alias: Optional[AliasedReturnsRows], name: Optional[str] = None
  6266. ) -> str:
  6267. if name is None:
  6268. assert alias is not None
  6269. return self.quote(alias.name)
  6270. else:
  6271. return self.quote(name)
  6272. def format_savepoint(self, savepoint, name=None):
  6273. # Running the savepoint name through quoting is unnecessary
  6274. # for all known dialects. This is here to support potential
  6275. # third party use cases
  6276. ident = name or savepoint.ident
  6277. if self._requires_quotes(ident):
  6278. ident = self.quote_identifier(ident)
  6279. return ident
  6280. @util.preload_module("sqlalchemy.sql.naming")
  6281. def format_constraint(self, constraint, _alembic_quote=True):
  6282. naming = util.preloaded.sql_naming
  6283. if constraint.name is _NONE_NAME:
  6284. name = naming._constraint_name_for_table(
  6285. constraint, constraint.table
  6286. )
  6287. if name is None:
  6288. return None
  6289. else:
  6290. name = constraint.name
  6291. if constraint.__visit_name__ == "index":
  6292. return self.truncate_and_render_index_name(
  6293. name, _alembic_quote=_alembic_quote
  6294. )
  6295. else:
  6296. return self.truncate_and_render_constraint_name(
  6297. name, _alembic_quote=_alembic_quote
  6298. )
  6299. def truncate_and_render_index_name(self, name, _alembic_quote=True):
  6300. # calculate these at format time so that ad-hoc changes
  6301. # to dialect.max_identifier_length etc. can be reflected
  6302. # as IdentifierPreparer is long lived
  6303. max_ = (
  6304. self.dialect.max_index_name_length
  6305. or self.dialect.max_identifier_length
  6306. )
  6307. return self._truncate_and_render_maxlen_name(
  6308. name, max_, _alembic_quote
  6309. )
  6310. def truncate_and_render_constraint_name(self, name, _alembic_quote=True):
  6311. # calculate these at format time so that ad-hoc changes
  6312. # to dialect.max_identifier_length etc. can be reflected
  6313. # as IdentifierPreparer is long lived
  6314. max_ = (
  6315. self.dialect.max_constraint_name_length
  6316. or self.dialect.max_identifier_length
  6317. )
  6318. return self._truncate_and_render_maxlen_name(
  6319. name, max_, _alembic_quote
  6320. )
  6321. def _truncate_and_render_maxlen_name(self, name, max_, _alembic_quote):
  6322. if isinstance(name, elements._truncated_label):
  6323. if len(name) > max_:
  6324. name = name[0 : max_ - 8] + "_" + util.md5_hex(name)[-4:]
  6325. else:
  6326. self.dialect.validate_identifier(name)
  6327. if not _alembic_quote:
  6328. return name
  6329. else:
  6330. return self.quote(name)
  6331. def format_index(self, index):
  6332. return self.format_constraint(index)
  6333. def format_table(self, table, use_schema=True, name=None):
  6334. """Prepare a quoted table and schema name."""
  6335. if name is None:
  6336. name = table.name
  6337. result = self.quote(name)
  6338. effective_schema = self.schema_for_object(table)
  6339. if not self.omit_schema and use_schema and effective_schema:
  6340. result = self.quote_schema(effective_schema) + "." + result
  6341. return result
  6342. def format_schema(self, name):
  6343. """Prepare a quoted schema name."""
  6344. return self.quote(name)
  6345. def format_label_name(
  6346. self,
  6347. name,
  6348. anon_map=None,
  6349. ):
  6350. """Prepare a quoted column name."""
  6351. if anon_map is not None and isinstance(
  6352. name, elements._truncated_label
  6353. ):
  6354. name = name.apply_map(anon_map)
  6355. return self.quote(name)
  6356. def format_column(
  6357. self,
  6358. column,
  6359. use_table=False,
  6360. name=None,
  6361. table_name=None,
  6362. use_schema=False,
  6363. anon_map=None,
  6364. ):
  6365. """Prepare a quoted column name."""
  6366. if name is None:
  6367. name = column.name
  6368. if anon_map is not None and isinstance(
  6369. name, elements._truncated_label
  6370. ):
  6371. name = name.apply_map(anon_map)
  6372. if not getattr(column, "is_literal", False):
  6373. if use_table:
  6374. return (
  6375. self.format_table(
  6376. column.table, use_schema=use_schema, name=table_name
  6377. )
  6378. + "."
  6379. + self.quote(name)
  6380. )
  6381. else:
  6382. return self.quote(name)
  6383. else:
  6384. # literal textual elements get stuck into ColumnClause a lot,
  6385. # which shouldn't get quoted
  6386. if use_table:
  6387. return (
  6388. self.format_table(
  6389. column.table, use_schema=use_schema, name=table_name
  6390. )
  6391. + "."
  6392. + name
  6393. )
  6394. else:
  6395. return name
  6396. def format_table_seq(self, table, use_schema=True):
  6397. """Format table name and schema as a tuple."""
  6398. # Dialects with more levels in their fully qualified references
  6399. # ('database', 'owner', etc.) could override this and return
  6400. # a longer sequence.
  6401. effective_schema = self.schema_for_object(table)
  6402. if not self.omit_schema and use_schema and effective_schema:
  6403. return (
  6404. self.quote_schema(effective_schema),
  6405. self.format_table(table, use_schema=False),
  6406. )
  6407. else:
  6408. return (self.format_table(table, use_schema=False),)
  6409. @util.memoized_property
  6410. def _r_identifiers(self):
  6411. initial, final, escaped_final = (
  6412. re.escape(s)
  6413. for s in (
  6414. self.initial_quote,
  6415. self.final_quote,
  6416. self._escape_identifier(self.final_quote),
  6417. )
  6418. )
  6419. r = re.compile(
  6420. r"(?:"
  6421. r"(?:%(initial)s((?:%(escaped)s|[^%(final)s])+)%(final)s"
  6422. r"|([^\.]+))(?=\.|$))+"
  6423. % {"initial": initial, "final": final, "escaped": escaped_final}
  6424. )
  6425. return r
  6426. def unformat_identifiers(self, identifiers):
  6427. """Unpack 'schema.table.column'-like strings into components."""
  6428. r = self._r_identifiers
  6429. return [
  6430. self._unescape_identifier(i)
  6431. for i in [a or b for a, b in r.findall(identifiers)]
  6432. ]