compiler.py 186 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446
  1. # sql/compiler.py
  2. # Copyright (C) 2005-2022 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. """Base SQL and DDL compiler implementations.
  8. Classes provided include:
  9. :class:`.compiler.SQLCompiler` - renders SQL
  10. strings
  11. :class:`.compiler.DDLCompiler` - renders DDL
  12. (data definition language) strings
  13. :class:`.compiler.GenericTypeCompiler` - renders
  14. type specification strings.
  15. To generate user-defined SQL strings, see
  16. :doc:`/ext/compiler`.
  17. """
  18. import collections
  19. import contextlib
  20. import itertools
  21. import operator
  22. import re
  23. from . import base
  24. from . import coercions
  25. from . import crud
  26. from . import elements
  27. from . import functions
  28. from . import operators
  29. from . import schema
  30. from . import selectable
  31. from . import sqltypes
  32. from .base import NO_ARG
  33. from .base import prefix_anon_map
  34. from .elements import quoted_name
  35. from .. import exc
  36. from .. import util
  37. RESERVED_WORDS = set(
  38. [
  39. "all",
  40. "analyse",
  41. "analyze",
  42. "and",
  43. "any",
  44. "array",
  45. "as",
  46. "asc",
  47. "asymmetric",
  48. "authorization",
  49. "between",
  50. "binary",
  51. "both",
  52. "case",
  53. "cast",
  54. "check",
  55. "collate",
  56. "column",
  57. "constraint",
  58. "create",
  59. "cross",
  60. "current_date",
  61. "current_role",
  62. "current_time",
  63. "current_timestamp",
  64. "current_user",
  65. "default",
  66. "deferrable",
  67. "desc",
  68. "distinct",
  69. "do",
  70. "else",
  71. "end",
  72. "except",
  73. "false",
  74. "for",
  75. "foreign",
  76. "freeze",
  77. "from",
  78. "full",
  79. "grant",
  80. "group",
  81. "having",
  82. "ilike",
  83. "in",
  84. "initially",
  85. "inner",
  86. "intersect",
  87. "into",
  88. "is",
  89. "isnull",
  90. "join",
  91. "leading",
  92. "left",
  93. "like",
  94. "limit",
  95. "localtime",
  96. "localtimestamp",
  97. "natural",
  98. "new",
  99. "not",
  100. "notnull",
  101. "null",
  102. "off",
  103. "offset",
  104. "old",
  105. "on",
  106. "only",
  107. "or",
  108. "order",
  109. "outer",
  110. "overlaps",
  111. "placing",
  112. "primary",
  113. "references",
  114. "right",
  115. "select",
  116. "session_user",
  117. "set",
  118. "similar",
  119. "some",
  120. "symmetric",
  121. "table",
  122. "then",
  123. "to",
  124. "trailing",
  125. "true",
  126. "union",
  127. "unique",
  128. "user",
  129. "using",
  130. "verbose",
  131. "when",
  132. "where",
  133. ]
  134. )
  135. LEGAL_CHARACTERS = re.compile(r"^[A-Z0-9_$]+$", re.I)
  136. LEGAL_CHARACTERS_PLUS_SPACE = re.compile(r"^[A-Z0-9_ $]+$", re.I)
  137. ILLEGAL_INITIAL_CHARACTERS = {str(x) for x in range(0, 10)}.union(["$"])
  138. FK_ON_DELETE = re.compile(
  139. r"^(?:RESTRICT|CASCADE|SET NULL|NO ACTION|SET DEFAULT)$", re.I
  140. )
  141. FK_ON_UPDATE = re.compile(
  142. r"^(?:RESTRICT|CASCADE|SET NULL|NO ACTION|SET DEFAULT)$", re.I
  143. )
  144. FK_INITIALLY = re.compile(r"^(?:DEFERRED|IMMEDIATE)$", re.I)
  145. BIND_PARAMS = re.compile(r"(?<![:\w\$\x5c]):([\w\$]+)(?![:\w\$])", re.UNICODE)
  146. BIND_PARAMS_ESC = re.compile(r"\x5c(:[\w\$]*)(?![:\w\$])", re.UNICODE)
  147. BIND_TEMPLATES = {
  148. "pyformat": "%%(%(name)s)s",
  149. "qmark": "?",
  150. "format": "%%s",
  151. "numeric": ":[_POSITION]",
  152. "named": ":%(name)s",
  153. }
  154. _BIND_TRANSLATE_RE = re.compile(r"[%\(\):\[\]]")
  155. _BIND_TRANSLATE_CHARS = dict(zip("%():[]", "PAZC__"))
  156. OPERATORS = {
  157. # binary
  158. operators.and_: " AND ",
  159. operators.or_: " OR ",
  160. operators.add: " + ",
  161. operators.mul: " * ",
  162. operators.sub: " - ",
  163. operators.div: " / ",
  164. operators.mod: " % ",
  165. operators.truediv: " / ",
  166. operators.neg: "-",
  167. operators.lt: " < ",
  168. operators.le: " <= ",
  169. operators.ne: " != ",
  170. operators.gt: " > ",
  171. operators.ge: " >= ",
  172. operators.eq: " = ",
  173. operators.is_distinct_from: " IS DISTINCT FROM ",
  174. operators.is_not_distinct_from: " IS NOT DISTINCT FROM ",
  175. operators.concat_op: " || ",
  176. operators.match_op: " MATCH ",
  177. operators.not_match_op: " NOT MATCH ",
  178. operators.in_op: " IN ",
  179. operators.not_in_op: " NOT IN ",
  180. operators.comma_op: ", ",
  181. operators.from_: " FROM ",
  182. operators.as_: " AS ",
  183. operators.is_: " IS ",
  184. operators.is_not: " IS NOT ",
  185. operators.collate: " COLLATE ",
  186. # unary
  187. operators.exists: "EXISTS ",
  188. operators.distinct_op: "DISTINCT ",
  189. operators.inv: "NOT ",
  190. operators.any_op: "ANY ",
  191. operators.all_op: "ALL ",
  192. # modifiers
  193. operators.desc_op: " DESC",
  194. operators.asc_op: " ASC",
  195. operators.nulls_first_op: " NULLS FIRST",
  196. operators.nulls_last_op: " NULLS LAST",
  197. }
  198. FUNCTIONS = {
  199. functions.coalesce: "coalesce",
  200. functions.current_date: "CURRENT_DATE",
  201. functions.current_time: "CURRENT_TIME",
  202. functions.current_timestamp: "CURRENT_TIMESTAMP",
  203. functions.current_user: "CURRENT_USER",
  204. functions.localtime: "LOCALTIME",
  205. functions.localtimestamp: "LOCALTIMESTAMP",
  206. functions.random: "random",
  207. functions.sysdate: "sysdate",
  208. functions.session_user: "SESSION_USER",
  209. functions.user: "USER",
  210. functions.cube: "CUBE",
  211. functions.rollup: "ROLLUP",
  212. functions.grouping_sets: "GROUPING SETS",
  213. }
  214. EXTRACT_MAP = {
  215. "month": "month",
  216. "day": "day",
  217. "year": "year",
  218. "second": "second",
  219. "hour": "hour",
  220. "doy": "doy",
  221. "minute": "minute",
  222. "quarter": "quarter",
  223. "dow": "dow",
  224. "week": "week",
  225. "epoch": "epoch",
  226. "milliseconds": "milliseconds",
  227. "microseconds": "microseconds",
  228. "timezone_hour": "timezone_hour",
  229. "timezone_minute": "timezone_minute",
  230. }
  231. COMPOUND_KEYWORDS = {
  232. selectable.CompoundSelect.UNION: "UNION",
  233. selectable.CompoundSelect.UNION_ALL: "UNION ALL",
  234. selectable.CompoundSelect.EXCEPT: "EXCEPT",
  235. selectable.CompoundSelect.EXCEPT_ALL: "EXCEPT ALL",
  236. selectable.CompoundSelect.INTERSECT: "INTERSECT",
  237. selectable.CompoundSelect.INTERSECT_ALL: "INTERSECT ALL",
  238. }
  239. RM_RENDERED_NAME = 0
  240. RM_NAME = 1
  241. RM_OBJECTS = 2
  242. RM_TYPE = 3
  243. ExpandedState = collections.namedtuple(
  244. "ExpandedState",
  245. [
  246. "statement",
  247. "additional_parameters",
  248. "processors",
  249. "positiontup",
  250. "parameter_expansion",
  251. ],
  252. )
  253. NO_LINTING = util.symbol("NO_LINTING", "Disable all linting.", canonical=0)
  254. COLLECT_CARTESIAN_PRODUCTS = util.symbol(
  255. "COLLECT_CARTESIAN_PRODUCTS",
  256. "Collect data on FROMs and cartesian products and gather "
  257. "into 'self.from_linter'",
  258. canonical=1,
  259. )
  260. WARN_LINTING = util.symbol(
  261. "WARN_LINTING", "Emit warnings for linters that find problems", canonical=2
  262. )
  263. FROM_LINTING = util.symbol(
  264. "FROM_LINTING",
  265. "Warn for cartesian products; "
  266. "combines COLLECT_CARTESIAN_PRODUCTS and WARN_LINTING",
  267. canonical=COLLECT_CARTESIAN_PRODUCTS | WARN_LINTING,
  268. )
  269. class FromLinter(collections.namedtuple("FromLinter", ["froms", "edges"])):
  270. def lint(self, start=None):
  271. froms = self.froms
  272. if not froms:
  273. return None, None
  274. edges = set(self.edges)
  275. the_rest = set(froms)
  276. if start is not None:
  277. start_with = start
  278. the_rest.remove(start_with)
  279. else:
  280. start_with = the_rest.pop()
  281. stack = collections.deque([start_with])
  282. while stack and the_rest:
  283. node = stack.popleft()
  284. the_rest.discard(node)
  285. # comparison of nodes in edges here is based on hash equality, as
  286. # there are "annotated" elements that match the non-annotated ones.
  287. # to remove the need for in-python hash() calls, use native
  288. # containment routines (e.g. "node in edge", "edge.index(node)")
  289. to_remove = {edge for edge in edges if node in edge}
  290. # appendleft the node in each edge that is not
  291. # the one that matched.
  292. stack.extendleft(edge[not edge.index(node)] for edge in to_remove)
  293. edges.difference_update(to_remove)
  294. # FROMS left over? boom
  295. if the_rest:
  296. return the_rest, start_with
  297. else:
  298. return None, None
  299. def warn(self):
  300. the_rest, start_with = self.lint()
  301. # FROMS left over? boom
  302. if the_rest:
  303. froms = the_rest
  304. if froms:
  305. template = (
  306. "SELECT statement has a cartesian product between "
  307. "FROM element(s) {froms} and "
  308. 'FROM element "{start}". Apply join condition(s) '
  309. "between each element to resolve."
  310. )
  311. froms_str = ", ".join(
  312. '"{elem}"'.format(elem=self.froms[from_])
  313. for from_ in froms
  314. )
  315. message = template.format(
  316. froms=froms_str, start=self.froms[start_with]
  317. )
  318. util.warn(message)
  319. class Compiled(object):
  320. """Represent a compiled SQL or DDL expression.
  321. The ``__str__`` method of the ``Compiled`` object should produce
  322. the actual text of the statement. ``Compiled`` objects are
  323. specific to their underlying database dialect, and also may
  324. or may not be specific to the columns referenced within a
  325. particular set of bind parameters. In no case should the
  326. ``Compiled`` object be dependent on the actual values of those
  327. bind parameters, even though it may reference those values as
  328. defaults.
  329. """
  330. _cached_metadata = None
  331. _result_columns = None
  332. schema_translate_map = None
  333. execution_options = util.EMPTY_DICT
  334. """
  335. Execution options propagated from the statement. In some cases,
  336. sub-elements of the statement can modify these.
  337. """
  338. _annotations = util.EMPTY_DICT
  339. compile_state = None
  340. """Optional :class:`.CompileState` object that maintains additional
  341. state used by the compiler.
  342. Major executable objects such as :class:`_expression.Insert`,
  343. :class:`_expression.Update`, :class:`_expression.Delete`,
  344. :class:`_expression.Select` will generate this
  345. state when compiled in order to calculate additional information about the
  346. object. For the top level object that is to be executed, the state can be
  347. stored here where it can also have applicability towards result set
  348. processing.
  349. .. versionadded:: 1.4
  350. """
  351. cache_key = None
  352. _gen_time = None
  353. def __init__(
  354. self,
  355. dialect,
  356. statement,
  357. schema_translate_map=None,
  358. render_schema_translate=False,
  359. compile_kwargs=util.immutabledict(),
  360. ):
  361. """Construct a new :class:`.Compiled` object.
  362. :param dialect: :class:`.Dialect` to compile against.
  363. :param statement: :class:`_expression.ClauseElement` to be compiled.
  364. :param schema_translate_map: dictionary of schema names to be
  365. translated when forming the resultant SQL
  366. .. versionadded:: 1.1
  367. .. seealso::
  368. :ref:`schema_translating`
  369. :param compile_kwargs: additional kwargs that will be
  370. passed to the initial call to :meth:`.Compiled.process`.
  371. """
  372. self.dialect = dialect
  373. self.preparer = self.dialect.identifier_preparer
  374. if schema_translate_map:
  375. self.schema_translate_map = schema_translate_map
  376. self.preparer = self.preparer._with_schema_translate(
  377. schema_translate_map
  378. )
  379. if statement is not None:
  380. self.statement = statement
  381. self.can_execute = statement.supports_execution
  382. self._annotations = statement._annotations
  383. if self.can_execute:
  384. self.execution_options = statement._execution_options
  385. self.string = self.process(self.statement, **compile_kwargs)
  386. if render_schema_translate:
  387. self.string = self.preparer._render_schema_translates(
  388. self.string, schema_translate_map
  389. )
  390. self._gen_time = util.perf_counter()
  391. def _execute_on_connection(
  392. self, connection, multiparams, params, execution_options
  393. ):
  394. if self.can_execute:
  395. return connection._execute_compiled(
  396. self, multiparams, params, execution_options
  397. )
  398. else:
  399. raise exc.ObjectNotExecutableError(self.statement)
  400. def visit_unsupported_compilation(self, element, err):
  401. util.raise_(
  402. exc.UnsupportedCompilationError(self, type(element)),
  403. replace_context=err,
  404. )
  405. @property
  406. def sql_compiler(self):
  407. """Return a Compiled that is capable of processing SQL expressions.
  408. If this compiler is one, it would likely just return 'self'.
  409. """
  410. raise NotImplementedError()
  411. def process(self, obj, **kwargs):
  412. return obj._compiler_dispatch(self, **kwargs)
  413. def __str__(self):
  414. """Return the string text of the generated SQL or DDL."""
  415. return self.string or ""
  416. def construct_params(self, params=None, extracted_parameters=None):
  417. """Return the bind params for this compiled object.
  418. :param params: a dict of string/object pairs whose values will
  419. override bind values compiled in to the
  420. statement.
  421. """
  422. raise NotImplementedError()
  423. @property
  424. def params(self):
  425. """Return the bind params for this compiled object."""
  426. return self.construct_params()
  427. class TypeCompiler(util.with_metaclass(util.EnsureKWArgType, object)):
  428. """Produces DDL specification for TypeEngine objects."""
  429. ensure_kwarg = r"visit_\w+"
  430. def __init__(self, dialect):
  431. self.dialect = dialect
  432. def process(self, type_, **kw):
  433. return type_._compiler_dispatch(self, **kw)
  434. def visit_unsupported_compilation(self, element, err, **kw):
  435. util.raise_(
  436. exc.UnsupportedCompilationError(self, element),
  437. replace_context=err,
  438. )
  439. # this was a Visitable, but to allow accurate detection of
  440. # column elements this is actually a column element
  441. class _CompileLabel(elements.ColumnElement):
  442. """lightweight label object which acts as an expression.Label."""
  443. __visit_name__ = "label"
  444. __slots__ = "element", "name"
  445. def __init__(self, col, name, alt_names=()):
  446. self.element = col
  447. self.name = name
  448. self._alt_names = (col,) + alt_names
  449. @property
  450. def proxy_set(self):
  451. return self.element.proxy_set
  452. @property
  453. def type(self):
  454. return self.element.type
  455. def self_group(self, **kw):
  456. return self
  457. class SQLCompiler(Compiled):
  458. """Default implementation of :class:`.Compiled`.
  459. Compiles :class:`_expression.ClauseElement` objects into SQL strings.
  460. """
  461. extract_map = EXTRACT_MAP
  462. compound_keywords = COMPOUND_KEYWORDS
  463. isdelete = isinsert = isupdate = False
  464. """class-level defaults which can be set at the instance
  465. level to define if this Compiled instance represents
  466. INSERT/UPDATE/DELETE
  467. """
  468. isplaintext = False
  469. returning = None
  470. """holds the "returning" collection of columns if
  471. the statement is CRUD and defines returning columns
  472. either implicitly or explicitly
  473. """
  474. returning_precedes_values = False
  475. """set to True classwide to generate RETURNING
  476. clauses before the VALUES or WHERE clause (i.e. MSSQL)
  477. """
  478. render_table_with_column_in_update_from = False
  479. """set to True classwide to indicate the SET clause
  480. in a multi-table UPDATE statement should qualify
  481. columns with the table name (i.e. MySQL only)
  482. """
  483. ansi_bind_rules = False
  484. """SQL 92 doesn't allow bind parameters to be used
  485. in the columns clause of a SELECT, nor does it allow
  486. ambiguous expressions like "? = ?". A compiler
  487. subclass can set this flag to False if the target
  488. driver/DB enforces this
  489. """
  490. _textual_ordered_columns = False
  491. """tell the result object that the column names as rendered are important,
  492. but they are also "ordered" vs. what is in the compiled object here.
  493. """
  494. _ordered_columns = True
  495. """
  496. if False, means we can't be sure the list of entries
  497. in _result_columns is actually the rendered order. Usually
  498. True unless using an unordered TextualSelect.
  499. """
  500. _loose_column_name_matching = False
  501. """tell the result object that the SQL statement is textual, wants to match
  502. up to Column objects, and may be using the ._tq_label in the SELECT rather
  503. than the base name.
  504. """
  505. _numeric_binds = False
  506. """
  507. True if paramstyle is "numeric". This paramstyle is trickier than
  508. all the others.
  509. """
  510. _render_postcompile = False
  511. """
  512. whether to render out POSTCOMPILE params during the compile phase.
  513. """
  514. insert_single_values_expr = None
  515. """When an INSERT is compiled with a single set of parameters inside
  516. a VALUES expression, the string is assigned here, where it can be
  517. used for insert batching schemes to rewrite the VALUES expression.
  518. .. versionadded:: 1.3.8
  519. """
  520. literal_execute_params = frozenset()
  521. """bindparameter objects that are rendered as literal values at statement
  522. execution time.
  523. """
  524. post_compile_params = frozenset()
  525. """bindparameter objects that are rendered as bound parameter placeholders
  526. at statement execution time.
  527. """
  528. escaped_bind_names = util.EMPTY_DICT
  529. """Late escaping of bound parameter names that has to be converted
  530. to the original name when looking in the parameter dictionary.
  531. """
  532. has_out_parameters = False
  533. """if True, there are bindparam() objects that have the isoutparam
  534. flag set."""
  535. insert_prefetch = update_prefetch = ()
  536. postfetch_lastrowid = False
  537. """if True, and this in insert, use cursor.lastrowid to populate
  538. result.inserted_primary_key. """
  539. _cache_key_bind_match = None
  540. """a mapping that will relate the BindParameter object we compile
  541. to those that are part of the extracted collection of parameters
  542. in the cache key, if we were given a cache key.
  543. """
  544. positiontup = None
  545. """for a compiled construct that uses a positional paramstyle, will be
  546. a sequence of strings, indicating the names of bound parameters in order.
  547. This is used in order to render bound parameters in their correct order,
  548. and is combined with the :attr:`_sql.Compiled.params` dictionary to
  549. render parameters.
  550. .. seealso::
  551. :ref:`faq_sql_expression_string` - includes a usage example for
  552. debugging use cases.
  553. """
  554. inline = False
  555. def __init__(
  556. self,
  557. dialect,
  558. statement,
  559. cache_key=None,
  560. column_keys=None,
  561. for_executemany=False,
  562. linting=NO_LINTING,
  563. **kwargs
  564. ):
  565. """Construct a new :class:`.SQLCompiler` object.
  566. :param dialect: :class:`.Dialect` to be used
  567. :param statement: :class:`_expression.ClauseElement` to be compiled
  568. :param column_keys: a list of column names to be compiled into an
  569. INSERT or UPDATE statement.
  570. :param for_executemany: whether INSERT / UPDATE statements should
  571. expect that they are to be invoked in an "executemany" style,
  572. which may impact how the statement will be expected to return the
  573. values of defaults and autoincrement / sequences and similar.
  574. Depending on the backend and driver in use, support for retrieving
  575. these values may be disabled which means SQL expressions may
  576. be rendered inline, RETURNING may not be rendered, etc.
  577. :param kwargs: additional keyword arguments to be consumed by the
  578. superclass.
  579. """
  580. self.column_keys = column_keys
  581. self.cache_key = cache_key
  582. if cache_key:
  583. self._cache_key_bind_match = ckbm = {
  584. b.key: b for b in cache_key[1]
  585. }
  586. ckbm.update({b: [b] for b in cache_key[1]})
  587. # compile INSERT/UPDATE defaults/sequences to expect executemany
  588. # style execution, which may mean no pre-execute of defaults,
  589. # or no RETURNING
  590. self.for_executemany = for_executemany
  591. self.linting = linting
  592. # a dictionary of bind parameter keys to BindParameter
  593. # instances.
  594. self.binds = {}
  595. # a dictionary of BindParameter instances to "compiled" names
  596. # that are actually present in the generated SQL
  597. self.bind_names = util.column_dict()
  598. # stack which keeps track of nested SELECT statements
  599. self.stack = []
  600. # relates label names in the final SQL to a tuple of local
  601. # column/label name, ColumnElement object (if any) and
  602. # TypeEngine. CursorResult uses this for type processing and
  603. # column targeting
  604. self._result_columns = []
  605. # true if the paramstyle is positional
  606. self.positional = dialect.positional
  607. if self.positional:
  608. self.positiontup = []
  609. self._numeric_binds = dialect.paramstyle == "numeric"
  610. self.bindtemplate = BIND_TEMPLATES[dialect.paramstyle]
  611. self.ctes = None
  612. self.label_length = (
  613. dialect.label_length or dialect.max_identifier_length
  614. )
  615. # a map which tracks "anonymous" identifiers that are created on
  616. # the fly here
  617. self.anon_map = prefix_anon_map()
  618. # a map which tracks "truncated" names based on
  619. # dialect.label_length or dialect.max_identifier_length
  620. self.truncated_names = {}
  621. Compiled.__init__(self, dialect, statement, **kwargs)
  622. if self.isinsert or self.isupdate or self.isdelete:
  623. if statement._returning:
  624. self.returning = statement._returning
  625. if self.isinsert or self.isupdate:
  626. if statement._inline:
  627. self.inline = True
  628. elif self.for_executemany and (
  629. not self.isinsert
  630. or (
  631. self.dialect.insert_executemany_returning
  632. and statement._return_defaults
  633. )
  634. ):
  635. self.inline = True
  636. if self.positional and self._numeric_binds:
  637. self._apply_numbered_params()
  638. if self._render_postcompile:
  639. self._process_parameters_for_postcompile(_populate_self=True)
  640. @property
  641. def current_executable(self):
  642. """Return the current 'executable' that is being compiled.
  643. This is currently the :class:`_sql.Select`, :class:`_sql.Insert`,
  644. :class:`_sql.Update`, :class:`_sql.Delete`,
  645. :class:`_sql.CompoundSelect` object that is being compiled.
  646. Specifically it's assigned to the ``self.stack`` list of elements.
  647. When a statement like the above is being compiled, it normally
  648. is also assigned to the ``.statement`` attribute of the
  649. :class:`_sql.Compiler` object. However, all SQL constructs are
  650. ultimately nestable, and this attribute should never be consulted
  651. by a ``visit_`` method, as it is not guaranteed to be assigned
  652. nor guaranteed to correspond to the current statement being compiled.
  653. .. versionadded:: 1.3.21
  654. For compatibility with previous versions, use the following
  655. recipe::
  656. statement = getattr(self, "current_executable", False)
  657. if statement is False:
  658. statement = self.stack[-1]["selectable"]
  659. For versions 1.4 and above, ensure only .current_executable
  660. is used; the format of "self.stack" may change.
  661. """
  662. try:
  663. return self.stack[-1]["selectable"]
  664. except IndexError as ie:
  665. util.raise_(
  666. IndexError("Compiler does not have a stack entry"),
  667. replace_context=ie,
  668. )
  669. @property
  670. def prefetch(self):
  671. return list(self.insert_prefetch + self.update_prefetch)
  672. @util.memoized_property
  673. def _global_attributes(self):
  674. return {}
  675. @util.memoized_instancemethod
  676. def _init_cte_state(self):
  677. """Initialize collections related to CTEs only if
  678. a CTE is located, to save on the overhead of
  679. these collections otherwise.
  680. """
  681. # collect CTEs to tack on top of a SELECT
  682. # To store the query to print - Dict[cte, text_query]
  683. self.ctes = util.OrderedDict()
  684. # Detect same CTE references - Dict[(level, name), cte]
  685. # Level is required for supporting nesting
  686. self.ctes_by_level_name = {}
  687. # To retrieve key/level in ctes_by_level_name -
  688. # Dict[cte_reference, (level, cte_name)]
  689. self.level_name_by_cte = {}
  690. self.ctes_recursive = False
  691. if self.positional:
  692. self.cte_positional = {}
  693. @contextlib.contextmanager
  694. def _nested_result(self):
  695. """special API to support the use case of 'nested result sets'"""
  696. result_columns, ordered_columns = (
  697. self._result_columns,
  698. self._ordered_columns,
  699. )
  700. self._result_columns, self._ordered_columns = [], False
  701. try:
  702. if self.stack:
  703. entry = self.stack[-1]
  704. entry["need_result_map_for_nested"] = True
  705. else:
  706. entry = None
  707. yield self._result_columns, self._ordered_columns
  708. finally:
  709. if entry:
  710. entry.pop("need_result_map_for_nested")
  711. self._result_columns, self._ordered_columns = (
  712. result_columns,
  713. ordered_columns,
  714. )
  715. def _apply_numbered_params(self):
  716. poscount = itertools.count(1)
  717. self.string = re.sub(
  718. r"\[_POSITION\]", lambda m: str(util.next(poscount)), self.string
  719. )
  720. @util.memoized_property
  721. def _bind_processors(self):
  722. return dict(
  723. (key, value)
  724. for key, value in (
  725. (
  726. self.bind_names[bindparam],
  727. bindparam.type._cached_bind_processor(self.dialect)
  728. if not bindparam.type._is_tuple_type
  729. else tuple(
  730. elem_type._cached_bind_processor(self.dialect)
  731. for elem_type in bindparam.type.types
  732. ),
  733. )
  734. for bindparam in self.bind_names
  735. )
  736. if value is not None
  737. )
  738. def is_subquery(self):
  739. return len(self.stack) > 1
  740. @property
  741. def sql_compiler(self):
  742. return self
  743. def construct_params(
  744. self,
  745. params=None,
  746. _group_number=None,
  747. _check=True,
  748. extracted_parameters=None,
  749. ):
  750. """return a dictionary of bind parameter keys and values"""
  751. has_escaped_names = bool(self.escaped_bind_names)
  752. if extracted_parameters:
  753. # related the bound parameters collected in the original cache key
  754. # to those collected in the incoming cache key. They will not have
  755. # matching names but they will line up positionally in the same
  756. # way. The parameters present in self.bind_names may be clones of
  757. # these original cache key params in the case of DML but the .key
  758. # will be guaranteed to match.
  759. try:
  760. orig_extracted = self.cache_key[1]
  761. except TypeError as err:
  762. util.raise_(
  763. exc.CompileError(
  764. "This compiled object has no original cache key; "
  765. "can't pass extracted_parameters to construct_params"
  766. ),
  767. replace_context=err,
  768. )
  769. ckbm = self._cache_key_bind_match
  770. resolved_extracted = {
  771. bind: extracted
  772. for b, extracted in zip(orig_extracted, extracted_parameters)
  773. for bind in ckbm[b]
  774. }
  775. else:
  776. resolved_extracted = None
  777. if params:
  778. pd = {}
  779. for bindparam, name in self.bind_names.items():
  780. escaped_name = (
  781. self.escaped_bind_names.get(name, name)
  782. if has_escaped_names
  783. else name
  784. )
  785. if bindparam.key in params:
  786. pd[escaped_name] = params[bindparam.key]
  787. elif name in params:
  788. pd[escaped_name] = params[name]
  789. elif _check and bindparam.required:
  790. if _group_number:
  791. raise exc.InvalidRequestError(
  792. "A value is required for bind parameter %r, "
  793. "in parameter group %d"
  794. % (bindparam.key, _group_number),
  795. code="cd3x",
  796. )
  797. else:
  798. raise exc.InvalidRequestError(
  799. "A value is required for bind parameter %r"
  800. % bindparam.key,
  801. code="cd3x",
  802. )
  803. else:
  804. if resolved_extracted:
  805. value_param = resolved_extracted.get(
  806. bindparam, bindparam
  807. )
  808. else:
  809. value_param = bindparam
  810. if bindparam.callable:
  811. pd[escaped_name] = value_param.effective_value
  812. else:
  813. pd[escaped_name] = value_param.value
  814. return pd
  815. else:
  816. pd = {}
  817. for bindparam, name in self.bind_names.items():
  818. escaped_name = (
  819. self.escaped_bind_names.get(name, name)
  820. if has_escaped_names
  821. else name
  822. )
  823. if _check and bindparam.required:
  824. if _group_number:
  825. raise exc.InvalidRequestError(
  826. "A value is required for bind parameter %r, "
  827. "in parameter group %d"
  828. % (bindparam.key, _group_number),
  829. code="cd3x",
  830. )
  831. else:
  832. raise exc.InvalidRequestError(
  833. "A value is required for bind parameter %r"
  834. % bindparam.key,
  835. code="cd3x",
  836. )
  837. if resolved_extracted:
  838. value_param = resolved_extracted.get(bindparam, bindparam)
  839. else:
  840. value_param = bindparam
  841. if bindparam.callable:
  842. pd[escaped_name] = value_param.effective_value
  843. else:
  844. pd[escaped_name] = value_param.value
  845. return pd
  846. @util.memoized_instancemethod
  847. def _get_set_input_sizes_lookup(
  848. self, include_types=None, exclude_types=None
  849. ):
  850. if not hasattr(self, "bind_names"):
  851. return None
  852. dialect = self.dialect
  853. dbapi = self.dialect.dbapi
  854. # _unwrapped_dialect_impl() is necessary so that we get the
  855. # correct dialect type for a custom TypeDecorator, or a Variant,
  856. # which is also a TypeDecorator. Special types like Interval,
  857. # that use TypeDecorator but also might be mapped directly
  858. # for a dialect impl, also subclass Emulated first which overrides
  859. # this behavior in those cases to behave like the default.
  860. if include_types is None and exclude_types is None:
  861. def _lookup_type(typ):
  862. dbtype = typ.dialect_impl(dialect).get_dbapi_type(dbapi)
  863. return dbtype
  864. else:
  865. def _lookup_type(typ):
  866. # note we get dbtype from the possibly TypeDecorator-wrapped
  867. # dialect_impl, but the dialect_impl itself that we use for
  868. # include/exclude is the unwrapped version.
  869. dialect_impl = typ._unwrapped_dialect_impl(dialect)
  870. dbtype = typ.dialect_impl(dialect).get_dbapi_type(dbapi)
  871. if (
  872. dbtype is not None
  873. and (
  874. exclude_types is None
  875. or dbtype not in exclude_types
  876. and type(dialect_impl) not in exclude_types
  877. )
  878. and (
  879. include_types is None
  880. or dbtype in include_types
  881. or type(dialect_impl) in include_types
  882. )
  883. ):
  884. return dbtype
  885. else:
  886. return None
  887. inputsizes = {}
  888. literal_execute_params = self.literal_execute_params
  889. for bindparam in self.bind_names:
  890. if bindparam in literal_execute_params:
  891. continue
  892. if bindparam.type._is_tuple_type:
  893. inputsizes[bindparam] = [
  894. _lookup_type(typ) for typ in bindparam.type.types
  895. ]
  896. else:
  897. inputsizes[bindparam] = _lookup_type(bindparam.type)
  898. return inputsizes
  899. @property
  900. def params(self):
  901. """Return the bind param dictionary embedded into this
  902. compiled object, for those values that are present.
  903. .. seealso::
  904. :ref:`faq_sql_expression_string` - includes a usage example for
  905. debugging use cases.
  906. """
  907. return self.construct_params(_check=False)
  908. def _process_parameters_for_postcompile(
  909. self, parameters=None, _populate_self=False
  910. ):
  911. """handle special post compile parameters.
  912. These include:
  913. * "expanding" parameters -typically IN tuples that are rendered
  914. on a per-parameter basis for an otherwise fixed SQL statement string.
  915. * literal_binds compiled with the literal_execute flag. Used for
  916. things like SQL Server "TOP N" where the driver does not accommodate
  917. N as a bound parameter.
  918. """
  919. if parameters is None:
  920. parameters = self.construct_params()
  921. expanded_parameters = {}
  922. if self.positional:
  923. positiontup = []
  924. else:
  925. positiontup = None
  926. processors = self._bind_processors
  927. new_processors = {}
  928. if self.positional and self._numeric_binds:
  929. # I'm not familiar with any DBAPI that uses 'numeric'.
  930. # strategy would likely be to make use of numbers greater than
  931. # the highest number present; then for expanding parameters,
  932. # append them to the end of the parameter list. that way
  933. # we avoid having to renumber all the existing parameters.
  934. raise NotImplementedError(
  935. "'post-compile' bind parameters are not supported with "
  936. "the 'numeric' paramstyle at this time."
  937. )
  938. replacement_expressions = {}
  939. to_update_sets = {}
  940. # notes:
  941. # *unescaped* parameter names in:
  942. # self.bind_names, self.binds, self._bind_processors
  943. #
  944. # *escaped* parameter names in:
  945. # construct_params(), replacement_expressions
  946. for name in (
  947. self.positiontup if self.positional else self.bind_names.values()
  948. ):
  949. escaped_name = (
  950. self.escaped_bind_names.get(name, name)
  951. if self.escaped_bind_names
  952. else name
  953. )
  954. parameter = self.binds[name]
  955. if parameter in self.literal_execute_params:
  956. if escaped_name not in replacement_expressions:
  957. value = parameters.pop(escaped_name)
  958. replacement_expressions[
  959. escaped_name
  960. ] = self.render_literal_bindparam(
  961. parameter, render_literal_value=value
  962. )
  963. continue
  964. if parameter in self.post_compile_params:
  965. if escaped_name in replacement_expressions:
  966. to_update = to_update_sets[escaped_name]
  967. else:
  968. # we are removing the parameter from parameters
  969. # because it is a list value, which is not expected by
  970. # TypeEngine objects that would otherwise be asked to
  971. # process it. the single name is being replaced with
  972. # individual numbered parameters for each value in the
  973. # param.
  974. values = parameters.pop(escaped_name)
  975. leep = self._literal_execute_expanding_parameter
  976. to_update, replacement_expr = leep(
  977. escaped_name, parameter, values
  978. )
  979. to_update_sets[escaped_name] = to_update
  980. replacement_expressions[escaped_name] = replacement_expr
  981. if not parameter.literal_execute:
  982. parameters.update(to_update)
  983. if parameter.type._is_tuple_type:
  984. new_processors.update(
  985. (
  986. "%s_%s_%s" % (name, i, j),
  987. processors[name][j - 1],
  988. )
  989. for i, tuple_element in enumerate(values, 1)
  990. for j, value in enumerate(tuple_element, 1)
  991. if name in processors
  992. and processors[name][j - 1] is not None
  993. )
  994. else:
  995. new_processors.update(
  996. (key, processors[name])
  997. for key, value in to_update
  998. if name in processors
  999. )
  1000. if self.positional:
  1001. positiontup.extend(name for name, value in to_update)
  1002. expanded_parameters[name] = [
  1003. expand_key for expand_key, value in to_update
  1004. ]
  1005. elif self.positional:
  1006. positiontup.append(name)
  1007. def process_expanding(m):
  1008. key = m.group(1)
  1009. expr = replacement_expressions[key]
  1010. # if POSTCOMPILE included a bind_expression, render that
  1011. # around each element
  1012. if m.group(2):
  1013. tok = m.group(2).split("~~")
  1014. be_left, be_right = tok[1], tok[3]
  1015. expr = ", ".join(
  1016. "%s%s%s" % (be_left, exp, be_right)
  1017. for exp in expr.split(", ")
  1018. )
  1019. return expr
  1020. statement = re.sub(
  1021. r"__\[POSTCOMPILE_(\S+?)(~~.+?~~)?\]",
  1022. process_expanding,
  1023. self.string,
  1024. )
  1025. expanded_state = ExpandedState(
  1026. statement,
  1027. parameters,
  1028. new_processors,
  1029. positiontup,
  1030. expanded_parameters,
  1031. )
  1032. if _populate_self:
  1033. # this is for the "render_postcompile" flag, which is not
  1034. # otherwise used internally and is for end-user debugging and
  1035. # special use cases.
  1036. self.string = expanded_state.statement
  1037. self._bind_processors.update(expanded_state.processors)
  1038. self.positiontup = expanded_state.positiontup
  1039. self.post_compile_params = frozenset()
  1040. for key in expanded_state.parameter_expansion:
  1041. bind = self.binds.pop(key)
  1042. self.bind_names.pop(bind)
  1043. for value, expanded_key in zip(
  1044. bind.value, expanded_state.parameter_expansion[key]
  1045. ):
  1046. self.binds[expanded_key] = new_param = bind._with_value(
  1047. value
  1048. )
  1049. self.bind_names[new_param] = expanded_key
  1050. return expanded_state
  1051. @util.preload_module("sqlalchemy.engine.cursor")
  1052. def _create_result_map(self):
  1053. """utility method used for unit tests only."""
  1054. cursor = util.preloaded.engine_cursor
  1055. return cursor.CursorResultMetaData._create_description_match_map(
  1056. self._result_columns
  1057. )
  1058. @util.memoized_property
  1059. @util.preload_module("sqlalchemy.engine.result")
  1060. def _inserted_primary_key_from_lastrowid_getter(self):
  1061. result = util.preloaded.engine_result
  1062. key_getter = self._key_getters_for_crud_column[2]
  1063. table = self.statement.table
  1064. getters = [
  1065. (operator.methodcaller("get", key_getter(col), None), col)
  1066. for col in table.primary_key
  1067. ]
  1068. autoinc_col = table._autoincrement_column
  1069. if autoinc_col is not None:
  1070. # apply type post processors to the lastrowid
  1071. proc = autoinc_col.type._cached_result_processor(
  1072. self.dialect, None
  1073. )
  1074. else:
  1075. proc = None
  1076. row_fn = result.result_tuple([col.key for col in table.primary_key])
  1077. def get(lastrowid, parameters):
  1078. if proc is not None:
  1079. lastrowid = proc(lastrowid)
  1080. if lastrowid is None:
  1081. return row_fn(getter(parameters) for getter, col in getters)
  1082. else:
  1083. return row_fn(
  1084. lastrowid if col is autoinc_col else getter(parameters)
  1085. for getter, col in getters
  1086. )
  1087. return get
  1088. @util.memoized_property
  1089. @util.preload_module("sqlalchemy.engine.result")
  1090. def _inserted_primary_key_from_returning_getter(self):
  1091. result = util.preloaded.engine_result
  1092. key_getter = self._key_getters_for_crud_column[2]
  1093. table = self.statement.table
  1094. ret = {col: idx for idx, col in enumerate(self.returning)}
  1095. getters = [
  1096. (operator.itemgetter(ret[col]), True)
  1097. if col in ret
  1098. else (operator.methodcaller("get", key_getter(col), None), False)
  1099. for col in table.primary_key
  1100. ]
  1101. row_fn = result.result_tuple([col.key for col in table.primary_key])
  1102. def get(row, parameters):
  1103. return row_fn(
  1104. getter(row) if use_row else getter(parameters)
  1105. for getter, use_row in getters
  1106. )
  1107. return get
  1108. def default_from(self):
  1109. """Called when a SELECT statement has no froms, and no FROM clause is
  1110. to be appended.
  1111. Gives Oracle a chance to tack on a ``FROM DUAL`` to the string output.
  1112. """
  1113. return ""
  1114. def visit_grouping(self, grouping, asfrom=False, **kwargs):
  1115. return "(" + grouping.element._compiler_dispatch(self, **kwargs) + ")"
  1116. def visit_select_statement_grouping(self, grouping, **kwargs):
  1117. return "(" + grouping.element._compiler_dispatch(self, **kwargs) + ")"
  1118. def visit_label_reference(
  1119. self, element, within_columns_clause=False, **kwargs
  1120. ):
  1121. if self.stack and self.dialect.supports_simple_order_by_label:
  1122. compile_state = self.stack[-1]["compile_state"]
  1123. (
  1124. with_cols,
  1125. only_froms,
  1126. only_cols,
  1127. ) = compile_state._label_resolve_dict
  1128. if within_columns_clause:
  1129. resolve_dict = only_froms
  1130. else:
  1131. resolve_dict = only_cols
  1132. # this can be None in the case that a _label_reference()
  1133. # were subject to a replacement operation, in which case
  1134. # the replacement of the Label element may have changed
  1135. # to something else like a ColumnClause expression.
  1136. order_by_elem = element.element._order_by_label_element
  1137. if (
  1138. order_by_elem is not None
  1139. and order_by_elem.name in resolve_dict
  1140. and order_by_elem.shares_lineage(
  1141. resolve_dict[order_by_elem.name]
  1142. )
  1143. ):
  1144. kwargs[
  1145. "render_label_as_label"
  1146. ] = element.element._order_by_label_element
  1147. return self.process(
  1148. element.element,
  1149. within_columns_clause=within_columns_clause,
  1150. **kwargs
  1151. )
  1152. def visit_textual_label_reference(
  1153. self, element, within_columns_clause=False, **kwargs
  1154. ):
  1155. if not self.stack:
  1156. # compiling the element outside of the context of a SELECT
  1157. return self.process(element._text_clause)
  1158. compile_state = self.stack[-1]["compile_state"]
  1159. with_cols, only_froms, only_cols = compile_state._label_resolve_dict
  1160. try:
  1161. if within_columns_clause:
  1162. col = only_froms[element.element]
  1163. else:
  1164. col = with_cols[element.element]
  1165. except KeyError as err:
  1166. coercions._no_text_coercion(
  1167. element.element,
  1168. extra=(
  1169. "Can't resolve label reference for ORDER BY / "
  1170. "GROUP BY / DISTINCT etc."
  1171. ),
  1172. exc_cls=exc.CompileError,
  1173. err=err,
  1174. )
  1175. else:
  1176. kwargs["render_label_as_label"] = col
  1177. return self.process(
  1178. col, within_columns_clause=within_columns_clause, **kwargs
  1179. )
  1180. def visit_label(
  1181. self,
  1182. label,
  1183. add_to_result_map=None,
  1184. within_label_clause=False,
  1185. within_columns_clause=False,
  1186. render_label_as_label=None,
  1187. result_map_targets=(),
  1188. **kw
  1189. ):
  1190. # only render labels within the columns clause
  1191. # or ORDER BY clause of a select. dialect-specific compilers
  1192. # can modify this behavior.
  1193. render_label_with_as = (
  1194. within_columns_clause and not within_label_clause
  1195. )
  1196. render_label_only = render_label_as_label is label
  1197. if render_label_only or render_label_with_as:
  1198. if isinstance(label.name, elements._truncated_label):
  1199. labelname = self._truncated_identifier("colident", label.name)
  1200. else:
  1201. labelname = label.name
  1202. if render_label_with_as:
  1203. if add_to_result_map is not None:
  1204. add_to_result_map(
  1205. labelname,
  1206. label.name,
  1207. (label, labelname) + label._alt_names + result_map_targets,
  1208. label.type,
  1209. )
  1210. return (
  1211. label.element._compiler_dispatch(
  1212. self,
  1213. within_columns_clause=True,
  1214. within_label_clause=True,
  1215. **kw
  1216. )
  1217. + OPERATORS[operators.as_]
  1218. + self.preparer.format_label(label, labelname)
  1219. )
  1220. elif render_label_only:
  1221. return self.preparer.format_label(label, labelname)
  1222. else:
  1223. return label.element._compiler_dispatch(
  1224. self, within_columns_clause=False, **kw
  1225. )
  1226. def _fallback_column_name(self, column):
  1227. raise exc.CompileError(
  1228. "Cannot compile Column object until " "its 'name' is assigned."
  1229. )
  1230. def visit_lambda_element(self, element, **kw):
  1231. sql_element = element._resolved
  1232. return self.process(sql_element, **kw)
  1233. def visit_column(
  1234. self,
  1235. column,
  1236. add_to_result_map=None,
  1237. include_table=True,
  1238. result_map_targets=(),
  1239. **kwargs
  1240. ):
  1241. name = orig_name = column.name
  1242. if name is None:
  1243. name = self._fallback_column_name(column)
  1244. is_literal = column.is_literal
  1245. if not is_literal and isinstance(name, elements._truncated_label):
  1246. name = self._truncated_identifier("colident", name)
  1247. if add_to_result_map is not None:
  1248. targets = (column, name, column.key) + result_map_targets
  1249. if column._tq_label:
  1250. targets += (column._tq_label,)
  1251. add_to_result_map(name, orig_name, targets, column.type)
  1252. if is_literal:
  1253. # note we are not currently accommodating for
  1254. # literal_column(quoted_name('ident', True)) here
  1255. name = self.escape_literal_column(name)
  1256. else:
  1257. name = self.preparer.quote(name)
  1258. table = column.table
  1259. if table is None or not include_table or not table.named_with_column:
  1260. return name
  1261. else:
  1262. effective_schema = self.preparer.schema_for_object(table)
  1263. if effective_schema:
  1264. schema_prefix = (
  1265. self.preparer.quote_schema(effective_schema) + "."
  1266. )
  1267. else:
  1268. schema_prefix = ""
  1269. tablename = table.name
  1270. if isinstance(tablename, elements._truncated_label):
  1271. tablename = self._truncated_identifier("alias", tablename)
  1272. return schema_prefix + self.preparer.quote(tablename) + "." + name
  1273. def visit_collation(self, element, **kw):
  1274. return self.preparer.format_collation(element.collation)
  1275. def visit_fromclause(self, fromclause, **kwargs):
  1276. return fromclause.name
  1277. def visit_index(self, index, **kwargs):
  1278. return index.name
  1279. def visit_typeclause(self, typeclause, **kw):
  1280. kw["type_expression"] = typeclause
  1281. kw["identifier_preparer"] = self.preparer
  1282. return self.dialect.type_compiler.process(typeclause.type, **kw)
  1283. def post_process_text(self, text):
  1284. if self.preparer._double_percents:
  1285. text = text.replace("%", "%%")
  1286. return text
  1287. def escape_literal_column(self, text):
  1288. if self.preparer._double_percents:
  1289. text = text.replace("%", "%%")
  1290. return text
  1291. def visit_textclause(self, textclause, add_to_result_map=None, **kw):
  1292. def do_bindparam(m):
  1293. name = m.group(1)
  1294. if name in textclause._bindparams:
  1295. return self.process(textclause._bindparams[name], **kw)
  1296. else:
  1297. return self.bindparam_string(name, **kw)
  1298. if not self.stack:
  1299. self.isplaintext = True
  1300. if add_to_result_map:
  1301. # text() object is present in the columns clause of a
  1302. # select(). Add a no-name entry to the result map so that
  1303. # row[text()] produces a result
  1304. add_to_result_map(None, None, (textclause,), sqltypes.NULLTYPE)
  1305. # un-escape any \:params
  1306. return BIND_PARAMS_ESC.sub(
  1307. lambda m: m.group(1),
  1308. BIND_PARAMS.sub(
  1309. do_bindparam, self.post_process_text(textclause.text)
  1310. ),
  1311. )
  1312. def visit_textual_select(
  1313. self, taf, compound_index=None, asfrom=False, **kw
  1314. ):
  1315. toplevel = not self.stack
  1316. entry = self._default_stack_entry if toplevel else self.stack[-1]
  1317. populate_result_map = (
  1318. toplevel
  1319. or (
  1320. compound_index == 0
  1321. and entry.get("need_result_map_for_compound", False)
  1322. )
  1323. or entry.get("need_result_map_for_nested", False)
  1324. )
  1325. if populate_result_map:
  1326. self._ordered_columns = (
  1327. self._textual_ordered_columns
  1328. ) = taf.positional
  1329. # enable looser result column matching when the SQL text links to
  1330. # Column objects by name only
  1331. self._loose_column_name_matching = not taf.positional and bool(
  1332. taf.column_args
  1333. )
  1334. for c in taf.column_args:
  1335. self.process(
  1336. c,
  1337. within_columns_clause=True,
  1338. add_to_result_map=self._add_to_result_map,
  1339. )
  1340. return self.process(taf.element, **kw)
  1341. def visit_null(self, expr, **kw):
  1342. return "NULL"
  1343. def visit_true(self, expr, **kw):
  1344. if self.dialect.supports_native_boolean:
  1345. return "true"
  1346. else:
  1347. return "1"
  1348. def visit_false(self, expr, **kw):
  1349. if self.dialect.supports_native_boolean:
  1350. return "false"
  1351. else:
  1352. return "0"
  1353. def _generate_delimited_list(self, elements, separator, **kw):
  1354. return separator.join(
  1355. s
  1356. for s in (c._compiler_dispatch(self, **kw) for c in elements)
  1357. if s
  1358. )
  1359. def _generate_delimited_and_list(self, clauses, **kw):
  1360. lcc, clauses = elements.BooleanClauseList._process_clauses_for_boolean(
  1361. operators.and_,
  1362. elements.True_._singleton,
  1363. elements.False_._singleton,
  1364. clauses,
  1365. )
  1366. if lcc == 1:
  1367. return clauses[0]._compiler_dispatch(self, **kw)
  1368. else:
  1369. separator = OPERATORS[operators.and_]
  1370. return separator.join(
  1371. s
  1372. for s in (c._compiler_dispatch(self, **kw) for c in clauses)
  1373. if s
  1374. )
  1375. def visit_tuple(self, clauselist, **kw):
  1376. return "(%s)" % self.visit_clauselist(clauselist, **kw)
  1377. def visit_clauselist(self, clauselist, **kw):
  1378. sep = clauselist.operator
  1379. if sep is None:
  1380. sep = " "
  1381. else:
  1382. sep = OPERATORS[clauselist.operator]
  1383. return self._generate_delimited_list(clauselist.clauses, sep, **kw)
  1384. def visit_case(self, clause, **kwargs):
  1385. x = "CASE "
  1386. if clause.value is not None:
  1387. x += clause.value._compiler_dispatch(self, **kwargs) + " "
  1388. for cond, result in clause.whens:
  1389. x += (
  1390. "WHEN "
  1391. + cond._compiler_dispatch(self, **kwargs)
  1392. + " THEN "
  1393. + result._compiler_dispatch(self, **kwargs)
  1394. + " "
  1395. )
  1396. if clause.else_ is not None:
  1397. x += (
  1398. "ELSE " + clause.else_._compiler_dispatch(self, **kwargs) + " "
  1399. )
  1400. x += "END"
  1401. return x
  1402. def visit_type_coerce(self, type_coerce, **kw):
  1403. return type_coerce.typed_expression._compiler_dispatch(self, **kw)
  1404. def visit_cast(self, cast, **kwargs):
  1405. return "CAST(%s AS %s)" % (
  1406. cast.clause._compiler_dispatch(self, **kwargs),
  1407. cast.typeclause._compiler_dispatch(self, **kwargs),
  1408. )
  1409. def _format_frame_clause(self, range_, **kw):
  1410. return "%s AND %s" % (
  1411. "UNBOUNDED PRECEDING"
  1412. if range_[0] is elements.RANGE_UNBOUNDED
  1413. else "CURRENT ROW"
  1414. if range_[0] is elements.RANGE_CURRENT
  1415. else "%s PRECEDING"
  1416. % (self.process(elements.literal(abs(range_[0])), **kw),)
  1417. if range_[0] < 0
  1418. else "%s FOLLOWING"
  1419. % (self.process(elements.literal(range_[0]), **kw),),
  1420. "UNBOUNDED FOLLOWING"
  1421. if range_[1] is elements.RANGE_UNBOUNDED
  1422. else "CURRENT ROW"
  1423. if range_[1] is elements.RANGE_CURRENT
  1424. else "%s PRECEDING"
  1425. % (self.process(elements.literal(abs(range_[1])), **kw),)
  1426. if range_[1] < 0
  1427. else "%s FOLLOWING"
  1428. % (self.process(elements.literal(range_[1]), **kw),),
  1429. )
  1430. def visit_over(self, over, **kwargs):
  1431. if over.range_:
  1432. range_ = "RANGE BETWEEN %s" % self._format_frame_clause(
  1433. over.range_, **kwargs
  1434. )
  1435. elif over.rows:
  1436. range_ = "ROWS BETWEEN %s" % self._format_frame_clause(
  1437. over.rows, **kwargs
  1438. )
  1439. else:
  1440. range_ = None
  1441. return "%s OVER (%s)" % (
  1442. over.element._compiler_dispatch(self, **kwargs),
  1443. " ".join(
  1444. [
  1445. "%s BY %s"
  1446. % (word, clause._compiler_dispatch(self, **kwargs))
  1447. for word, clause in (
  1448. ("PARTITION", over.partition_by),
  1449. ("ORDER", over.order_by),
  1450. )
  1451. if clause is not None and len(clause)
  1452. ]
  1453. + ([range_] if range_ else [])
  1454. ),
  1455. )
  1456. def visit_withingroup(self, withingroup, **kwargs):
  1457. return "%s WITHIN GROUP (ORDER BY %s)" % (
  1458. withingroup.element._compiler_dispatch(self, **kwargs),
  1459. withingroup.order_by._compiler_dispatch(self, **kwargs),
  1460. )
  1461. def visit_funcfilter(self, funcfilter, **kwargs):
  1462. return "%s FILTER (WHERE %s)" % (
  1463. funcfilter.func._compiler_dispatch(self, **kwargs),
  1464. funcfilter.criterion._compiler_dispatch(self, **kwargs),
  1465. )
  1466. def visit_extract(self, extract, **kwargs):
  1467. field = self.extract_map.get(extract.field, extract.field)
  1468. return "EXTRACT(%s FROM %s)" % (
  1469. field,
  1470. extract.expr._compiler_dispatch(self, **kwargs),
  1471. )
  1472. def visit_scalar_function_column(self, element, **kw):
  1473. compiled_fn = self.visit_function(element.fn, **kw)
  1474. compiled_col = self.visit_column(element, **kw)
  1475. return "(%s).%s" % (compiled_fn, compiled_col)
  1476. def visit_function(self, func, add_to_result_map=None, **kwargs):
  1477. if add_to_result_map is not None:
  1478. add_to_result_map(func.name, func.name, (), func.type)
  1479. disp = getattr(self, "visit_%s_func" % func.name.lower(), None)
  1480. if disp:
  1481. text = disp(func, **kwargs)
  1482. else:
  1483. name = FUNCTIONS.get(func._deannotate().__class__, None)
  1484. if name:
  1485. if func._has_args:
  1486. name += "%(expr)s"
  1487. else:
  1488. name = func.name
  1489. name = (
  1490. self.preparer.quote(name)
  1491. if self.preparer._requires_quotes_illegal_chars(name)
  1492. or isinstance(name, elements.quoted_name)
  1493. else name
  1494. )
  1495. name = name + "%(expr)s"
  1496. text = ".".join(
  1497. [
  1498. (
  1499. self.preparer.quote(tok)
  1500. if self.preparer._requires_quotes_illegal_chars(tok)
  1501. or isinstance(name, elements.quoted_name)
  1502. else tok
  1503. )
  1504. for tok in func.packagenames
  1505. ]
  1506. + [name]
  1507. ) % {"expr": self.function_argspec(func, **kwargs)}
  1508. if func._with_ordinality:
  1509. text += " WITH ORDINALITY"
  1510. return text
  1511. def visit_next_value_func(self, next_value, **kw):
  1512. return self.visit_sequence(next_value.sequence)
  1513. def visit_sequence(self, sequence, **kw):
  1514. raise NotImplementedError(
  1515. "Dialect '%s' does not support sequence increments."
  1516. % self.dialect.name
  1517. )
  1518. def function_argspec(self, func, **kwargs):
  1519. return func.clause_expr._compiler_dispatch(self, **kwargs)
  1520. def visit_compound_select(
  1521. self, cs, asfrom=False, compound_index=None, **kwargs
  1522. ):
  1523. toplevel = not self.stack
  1524. compile_state = cs._compile_state_factory(cs, self, **kwargs)
  1525. if toplevel and not self.compile_state:
  1526. self.compile_state = compile_state
  1527. compound_stmt = compile_state.statement
  1528. entry = self._default_stack_entry if toplevel else self.stack[-1]
  1529. need_result_map = toplevel or (
  1530. not compound_index
  1531. and entry.get("need_result_map_for_compound", False)
  1532. )
  1533. # indicates there is already a CompoundSelect in play
  1534. if compound_index == 0:
  1535. entry["select_0"] = cs
  1536. self.stack.append(
  1537. {
  1538. "correlate_froms": entry["correlate_froms"],
  1539. "asfrom_froms": entry["asfrom_froms"],
  1540. "selectable": cs,
  1541. "compile_state": compile_state,
  1542. "need_result_map_for_compound": need_result_map,
  1543. }
  1544. )
  1545. if compound_stmt._independent_ctes:
  1546. for cte in compound_stmt._independent_ctes:
  1547. cte._compiler_dispatch(self, **kwargs)
  1548. keyword = self.compound_keywords.get(cs.keyword)
  1549. text = (" " + keyword + " ").join(
  1550. (
  1551. c._compiler_dispatch(
  1552. self, asfrom=asfrom, compound_index=i, **kwargs
  1553. )
  1554. for i, c in enumerate(cs.selects)
  1555. )
  1556. )
  1557. kwargs["include_table"] = False
  1558. text += self.group_by_clause(cs, **dict(asfrom=asfrom, **kwargs))
  1559. text += self.order_by_clause(cs, **kwargs)
  1560. if cs._has_row_limiting_clause:
  1561. text += self._row_limit_clause(cs, **kwargs)
  1562. if self.ctes:
  1563. nesting_level = len(self.stack) if not toplevel else None
  1564. text = (
  1565. self._render_cte_clause(
  1566. nesting_level=nesting_level, include_following_stack=True
  1567. )
  1568. + text
  1569. )
  1570. self.stack.pop(-1)
  1571. return text
  1572. def _row_limit_clause(self, cs, **kwargs):
  1573. if cs._fetch_clause is not None:
  1574. return self.fetch_clause(cs, **kwargs)
  1575. else:
  1576. return self.limit_clause(cs, **kwargs)
  1577. def _get_operator_dispatch(self, operator_, qualifier1, qualifier2):
  1578. attrname = "visit_%s_%s%s" % (
  1579. operator_.__name__,
  1580. qualifier1,
  1581. "_" + qualifier2 if qualifier2 else "",
  1582. )
  1583. return getattr(self, attrname, None)
  1584. def visit_unary(
  1585. self, unary, add_to_result_map=None, result_map_targets=(), **kw
  1586. ):
  1587. if add_to_result_map is not None:
  1588. result_map_targets += (unary,)
  1589. kw["add_to_result_map"] = add_to_result_map
  1590. kw["result_map_targets"] = result_map_targets
  1591. if unary.operator:
  1592. if unary.modifier:
  1593. raise exc.CompileError(
  1594. "Unary expression does not support operator "
  1595. "and modifier simultaneously"
  1596. )
  1597. disp = self._get_operator_dispatch(
  1598. unary.operator, "unary", "operator"
  1599. )
  1600. if disp:
  1601. return disp(unary, unary.operator, **kw)
  1602. else:
  1603. return self._generate_generic_unary_operator(
  1604. unary, OPERATORS[unary.operator], **kw
  1605. )
  1606. elif unary.modifier:
  1607. disp = self._get_operator_dispatch(
  1608. unary.modifier, "unary", "modifier"
  1609. )
  1610. if disp:
  1611. return disp(unary, unary.modifier, **kw)
  1612. else:
  1613. return self._generate_generic_unary_modifier(
  1614. unary, OPERATORS[unary.modifier], **kw
  1615. )
  1616. else:
  1617. raise exc.CompileError(
  1618. "Unary expression has no operator or modifier"
  1619. )
  1620. def visit_is_true_unary_operator(self, element, operator, **kw):
  1621. if (
  1622. element._is_implicitly_boolean
  1623. or self.dialect.supports_native_boolean
  1624. ):
  1625. return self.process(element.element, **kw)
  1626. else:
  1627. return "%s = 1" % self.process(element.element, **kw)
  1628. def visit_is_false_unary_operator(self, element, operator, **kw):
  1629. if (
  1630. element._is_implicitly_boolean
  1631. or self.dialect.supports_native_boolean
  1632. ):
  1633. return "NOT %s" % self.process(element.element, **kw)
  1634. else:
  1635. return "%s = 0" % self.process(element.element, **kw)
  1636. def visit_not_match_op_binary(self, binary, operator, **kw):
  1637. return "NOT %s" % self.visit_binary(
  1638. binary, override_operator=operators.match_op
  1639. )
  1640. def visit_not_in_op_binary(self, binary, operator, **kw):
  1641. # The brackets are required in the NOT IN operation because the empty
  1642. # case is handled using the form "(col NOT IN (null) OR 1 = 1)".
  1643. # The presence of the OR makes the brackets required.
  1644. return "(%s)" % self._generate_generic_binary(
  1645. binary, OPERATORS[operator], **kw
  1646. )
  1647. def visit_empty_set_op_expr(self, type_, expand_op):
  1648. if expand_op is operators.not_in_op:
  1649. if len(type_) > 1:
  1650. return "(%s)) OR (1 = 1" % (
  1651. ", ".join("NULL" for element in type_)
  1652. )
  1653. else:
  1654. return "NULL) OR (1 = 1"
  1655. elif expand_op is operators.in_op:
  1656. if len(type_) > 1:
  1657. return "(%s)) AND (1 != 1" % (
  1658. ", ".join("NULL" for element in type_)
  1659. )
  1660. else:
  1661. return "NULL) AND (1 != 1"
  1662. else:
  1663. return self.visit_empty_set_expr(type_)
  1664. def visit_empty_set_expr(self, element_types):
  1665. raise NotImplementedError(
  1666. "Dialect '%s' does not support empty set expression."
  1667. % self.dialect.name
  1668. )
  1669. def _literal_execute_expanding_parameter_literal_binds(
  1670. self, parameter, values
  1671. ):
  1672. typ_dialect_impl = parameter.type._unwrapped_dialect_impl(self.dialect)
  1673. if not values:
  1674. if typ_dialect_impl._is_tuple_type:
  1675. replacement_expression = (
  1676. "VALUES " if self.dialect.tuple_in_values else ""
  1677. ) + self.visit_empty_set_op_expr(
  1678. parameter.type.types, parameter.expand_op
  1679. )
  1680. else:
  1681. replacement_expression = self.visit_empty_set_op_expr(
  1682. [parameter.type], parameter.expand_op
  1683. )
  1684. elif typ_dialect_impl._is_tuple_type or (
  1685. typ_dialect_impl._isnull
  1686. and isinstance(values[0], util.collections_abc.Sequence)
  1687. and not isinstance(
  1688. values[0], util.string_types + util.binary_types
  1689. )
  1690. ):
  1691. replacement_expression = (
  1692. "VALUES " if self.dialect.tuple_in_values else ""
  1693. ) + ", ".join(
  1694. "(%s)"
  1695. % (
  1696. ", ".join(
  1697. self.render_literal_value(value, param_type)
  1698. for value, param_type in zip(
  1699. tuple_element, parameter.type.types
  1700. )
  1701. )
  1702. )
  1703. for i, tuple_element in enumerate(values)
  1704. )
  1705. else:
  1706. replacement_expression = ", ".join(
  1707. self.render_literal_value(value, parameter.type)
  1708. for value in values
  1709. )
  1710. return (), replacement_expression
  1711. def _literal_execute_expanding_parameter(self, name, parameter, values):
  1712. if parameter.literal_execute:
  1713. return self._literal_execute_expanding_parameter_literal_binds(
  1714. parameter, values
  1715. )
  1716. typ_dialect_impl = parameter.type._unwrapped_dialect_impl(self.dialect)
  1717. if not values:
  1718. to_update = []
  1719. if typ_dialect_impl._is_tuple_type:
  1720. replacement_expression = self.visit_empty_set_op_expr(
  1721. parameter.type.types, parameter.expand_op
  1722. )
  1723. else:
  1724. replacement_expression = self.visit_empty_set_op_expr(
  1725. [parameter.type], parameter.expand_op
  1726. )
  1727. elif typ_dialect_impl._is_tuple_type or (
  1728. typ_dialect_impl._isnull
  1729. and isinstance(values[0], util.collections_abc.Sequence)
  1730. and not isinstance(
  1731. values[0], util.string_types + util.binary_types
  1732. )
  1733. ):
  1734. assert not typ_dialect_impl._is_array
  1735. to_update = [
  1736. ("%s_%s_%s" % (name, i, j), value)
  1737. for i, tuple_element in enumerate(values, 1)
  1738. for j, value in enumerate(tuple_element, 1)
  1739. ]
  1740. replacement_expression = (
  1741. "VALUES " if self.dialect.tuple_in_values else ""
  1742. ) + ", ".join(
  1743. "(%s)"
  1744. % (
  1745. ", ".join(
  1746. self.bindtemplate
  1747. % {"name": to_update[i * len(tuple_element) + j][0]}
  1748. for j, value in enumerate(tuple_element)
  1749. )
  1750. )
  1751. for i, tuple_element in enumerate(values)
  1752. )
  1753. else:
  1754. to_update = [
  1755. ("%s_%s" % (name, i), value)
  1756. for i, value in enumerate(values, 1)
  1757. ]
  1758. replacement_expression = ", ".join(
  1759. self.bindtemplate % {"name": key} for key, value in to_update
  1760. )
  1761. return to_update, replacement_expression
  1762. def visit_binary(
  1763. self,
  1764. binary,
  1765. override_operator=None,
  1766. eager_grouping=False,
  1767. from_linter=None,
  1768. lateral_from_linter=None,
  1769. **kw
  1770. ):
  1771. if from_linter and operators.is_comparison(binary.operator):
  1772. if lateral_from_linter is not None:
  1773. enclosing_lateral = kw["enclosing_lateral"]
  1774. lateral_from_linter.edges.update(
  1775. itertools.product(
  1776. binary.left._from_objects + [enclosing_lateral],
  1777. binary.right._from_objects + [enclosing_lateral],
  1778. )
  1779. )
  1780. else:
  1781. from_linter.edges.update(
  1782. itertools.product(
  1783. binary.left._from_objects, binary.right._from_objects
  1784. )
  1785. )
  1786. # don't allow "? = ?" to render
  1787. if (
  1788. self.ansi_bind_rules
  1789. and isinstance(binary.left, elements.BindParameter)
  1790. and isinstance(binary.right, elements.BindParameter)
  1791. ):
  1792. kw["literal_execute"] = True
  1793. operator_ = override_operator or binary.operator
  1794. disp = self._get_operator_dispatch(operator_, "binary", None)
  1795. if disp:
  1796. return disp(binary, operator_, **kw)
  1797. else:
  1798. try:
  1799. opstring = OPERATORS[operator_]
  1800. except KeyError as err:
  1801. util.raise_(
  1802. exc.UnsupportedCompilationError(self, operator_),
  1803. replace_context=err,
  1804. )
  1805. else:
  1806. return self._generate_generic_binary(
  1807. binary,
  1808. opstring,
  1809. from_linter=from_linter,
  1810. lateral_from_linter=lateral_from_linter,
  1811. **kw
  1812. )
  1813. def visit_function_as_comparison_op_binary(self, element, operator, **kw):
  1814. return self.process(element.sql_function, **kw)
  1815. def visit_mod_binary(self, binary, operator, **kw):
  1816. if self.preparer._double_percents:
  1817. return (
  1818. self.process(binary.left, **kw)
  1819. + " %% "
  1820. + self.process(binary.right, **kw)
  1821. )
  1822. else:
  1823. return (
  1824. self.process(binary.left, **kw)
  1825. + " % "
  1826. + self.process(binary.right, **kw)
  1827. )
  1828. def visit_custom_op_binary(self, element, operator, **kw):
  1829. kw["eager_grouping"] = operator.eager_grouping
  1830. return self._generate_generic_binary(
  1831. element,
  1832. " " + self.escape_literal_column(operator.opstring) + " ",
  1833. **kw
  1834. )
  1835. def visit_custom_op_unary_operator(self, element, operator, **kw):
  1836. return self._generate_generic_unary_operator(
  1837. element, self.escape_literal_column(operator.opstring) + " ", **kw
  1838. )
  1839. def visit_custom_op_unary_modifier(self, element, operator, **kw):
  1840. return self._generate_generic_unary_modifier(
  1841. element, " " + self.escape_literal_column(operator.opstring), **kw
  1842. )
  1843. def _generate_generic_binary(
  1844. self, binary, opstring, eager_grouping=False, **kw
  1845. ):
  1846. _in_binary = kw.get("_in_binary", False)
  1847. kw["_in_binary"] = True
  1848. kw["_binary_op"] = binary.operator
  1849. text = (
  1850. binary.left._compiler_dispatch(
  1851. self, eager_grouping=eager_grouping, **kw
  1852. )
  1853. + opstring
  1854. + binary.right._compiler_dispatch(
  1855. self, eager_grouping=eager_grouping, **kw
  1856. )
  1857. )
  1858. if _in_binary and eager_grouping:
  1859. text = "(%s)" % text
  1860. return text
  1861. def _generate_generic_unary_operator(self, unary, opstring, **kw):
  1862. return opstring + unary.element._compiler_dispatch(self, **kw)
  1863. def _generate_generic_unary_modifier(self, unary, opstring, **kw):
  1864. return unary.element._compiler_dispatch(self, **kw) + opstring
  1865. @util.memoized_property
  1866. def _like_percent_literal(self):
  1867. return elements.literal_column("'%'", type_=sqltypes.STRINGTYPE)
  1868. def visit_contains_op_binary(self, binary, operator, **kw):
  1869. binary = binary._clone()
  1870. percent = self._like_percent_literal
  1871. binary.right = percent.__add__(binary.right).__add__(percent)
  1872. return self.visit_like_op_binary(binary, operator, **kw)
  1873. def visit_not_contains_op_binary(self, binary, operator, **kw):
  1874. binary = binary._clone()
  1875. percent = self._like_percent_literal
  1876. binary.right = percent.__add__(binary.right).__add__(percent)
  1877. return self.visit_not_like_op_binary(binary, operator, **kw)
  1878. def visit_startswith_op_binary(self, binary, operator, **kw):
  1879. binary = binary._clone()
  1880. percent = self._like_percent_literal
  1881. binary.right = percent.__radd__(binary.right)
  1882. return self.visit_like_op_binary(binary, operator, **kw)
  1883. def visit_not_startswith_op_binary(self, binary, operator, **kw):
  1884. binary = binary._clone()
  1885. percent = self._like_percent_literal
  1886. binary.right = percent.__radd__(binary.right)
  1887. return self.visit_not_like_op_binary(binary, operator, **kw)
  1888. def visit_endswith_op_binary(self, binary, operator, **kw):
  1889. binary = binary._clone()
  1890. percent = self._like_percent_literal
  1891. binary.right = percent.__add__(binary.right)
  1892. return self.visit_like_op_binary(binary, operator, **kw)
  1893. def visit_not_endswith_op_binary(self, binary, operator, **kw):
  1894. binary = binary._clone()
  1895. percent = self._like_percent_literal
  1896. binary.right = percent.__add__(binary.right)
  1897. return self.visit_not_like_op_binary(binary, operator, **kw)
  1898. def visit_like_op_binary(self, binary, operator, **kw):
  1899. escape = binary.modifiers.get("escape", None)
  1900. # TODO: use ternary here, not "and"/ "or"
  1901. return "%s LIKE %s" % (
  1902. binary.left._compiler_dispatch(self, **kw),
  1903. binary.right._compiler_dispatch(self, **kw),
  1904. ) + (
  1905. " ESCAPE " + self.render_literal_value(escape, sqltypes.STRINGTYPE)
  1906. if escape
  1907. else ""
  1908. )
  1909. def visit_not_like_op_binary(self, binary, operator, **kw):
  1910. escape = binary.modifiers.get("escape", None)
  1911. return "%s NOT LIKE %s" % (
  1912. binary.left._compiler_dispatch(self, **kw),
  1913. binary.right._compiler_dispatch(self, **kw),
  1914. ) + (
  1915. " ESCAPE " + self.render_literal_value(escape, sqltypes.STRINGTYPE)
  1916. if escape
  1917. else ""
  1918. )
  1919. def visit_ilike_op_binary(self, binary, operator, **kw):
  1920. escape = binary.modifiers.get("escape", None)
  1921. return "lower(%s) LIKE lower(%s)" % (
  1922. binary.left._compiler_dispatch(self, **kw),
  1923. binary.right._compiler_dispatch(self, **kw),
  1924. ) + (
  1925. " ESCAPE " + self.render_literal_value(escape, sqltypes.STRINGTYPE)
  1926. if escape
  1927. else ""
  1928. )
  1929. def visit_not_ilike_op_binary(self, binary, operator, **kw):
  1930. escape = binary.modifiers.get("escape", None)
  1931. return "lower(%s) NOT LIKE lower(%s)" % (
  1932. binary.left._compiler_dispatch(self, **kw),
  1933. binary.right._compiler_dispatch(self, **kw),
  1934. ) + (
  1935. " ESCAPE " + self.render_literal_value(escape, sqltypes.STRINGTYPE)
  1936. if escape
  1937. else ""
  1938. )
  1939. def visit_between_op_binary(self, binary, operator, **kw):
  1940. symmetric = binary.modifiers.get("symmetric", False)
  1941. return self._generate_generic_binary(
  1942. binary, " BETWEEN SYMMETRIC " if symmetric else " BETWEEN ", **kw
  1943. )
  1944. def visit_not_between_op_binary(self, binary, operator, **kw):
  1945. symmetric = binary.modifiers.get("symmetric", False)
  1946. return self._generate_generic_binary(
  1947. binary,
  1948. " NOT BETWEEN SYMMETRIC " if symmetric else " NOT BETWEEN ",
  1949. **kw
  1950. )
  1951. def visit_regexp_match_op_binary(self, binary, operator, **kw):
  1952. raise exc.CompileError(
  1953. "%s dialect does not support regular expressions"
  1954. % self.dialect.name
  1955. )
  1956. def visit_not_regexp_match_op_binary(self, binary, operator, **kw):
  1957. raise exc.CompileError(
  1958. "%s dialect does not support regular expressions"
  1959. % self.dialect.name
  1960. )
  1961. def visit_regexp_replace_op_binary(self, binary, operator, **kw):
  1962. raise exc.CompileError(
  1963. "%s dialect does not support regular expression replacements"
  1964. % self.dialect.name
  1965. )
  1966. def visit_bindparam(
  1967. self,
  1968. bindparam,
  1969. within_columns_clause=False,
  1970. literal_binds=False,
  1971. skip_bind_expression=False,
  1972. literal_execute=False,
  1973. render_postcompile=False,
  1974. **kwargs
  1975. ):
  1976. if not skip_bind_expression:
  1977. impl = bindparam.type.dialect_impl(self.dialect)
  1978. if impl._has_bind_expression:
  1979. bind_expression = impl.bind_expression(bindparam)
  1980. wrapped = self.process(
  1981. bind_expression,
  1982. skip_bind_expression=True,
  1983. within_columns_clause=within_columns_clause,
  1984. literal_binds=literal_binds,
  1985. literal_execute=literal_execute,
  1986. render_postcompile=render_postcompile,
  1987. **kwargs
  1988. )
  1989. if bindparam.expanding:
  1990. # for postcompile w/ expanding, move the "wrapped" part
  1991. # of this into the inside
  1992. m = re.match(
  1993. r"^(.*)\(__\[POSTCOMPILE_(\S+?)\]\)(.*)$", wrapped
  1994. )
  1995. wrapped = "(__[POSTCOMPILE_%s~~%s~~REPL~~%s~~])" % (
  1996. m.group(2),
  1997. m.group(1),
  1998. m.group(3),
  1999. )
  2000. return wrapped
  2001. if not literal_binds:
  2002. literal_execute = (
  2003. literal_execute
  2004. or bindparam.literal_execute
  2005. or (within_columns_clause and self.ansi_bind_rules)
  2006. )
  2007. post_compile = literal_execute or bindparam.expanding
  2008. else:
  2009. post_compile = False
  2010. if literal_binds:
  2011. ret = self.render_literal_bindparam(
  2012. bindparam, within_columns_clause=True, **kwargs
  2013. )
  2014. if bindparam.expanding:
  2015. ret = "(%s)" % ret
  2016. return ret
  2017. name = self._truncate_bindparam(bindparam)
  2018. if name in self.binds:
  2019. existing = self.binds[name]
  2020. if existing is not bindparam:
  2021. if (
  2022. (existing.unique or bindparam.unique)
  2023. and not existing.proxy_set.intersection(
  2024. bindparam.proxy_set
  2025. )
  2026. and not existing._cloned_set.intersection(
  2027. bindparam._cloned_set
  2028. )
  2029. ):
  2030. raise exc.CompileError(
  2031. "Bind parameter '%s' conflicts with "
  2032. "unique bind parameter of the same name" % name
  2033. )
  2034. elif existing._is_crud or bindparam._is_crud:
  2035. raise exc.CompileError(
  2036. "bindparam() name '%s' is reserved "
  2037. "for automatic usage in the VALUES or SET "
  2038. "clause of this "
  2039. "insert/update statement. Please use a "
  2040. "name other than column name when using bindparam() "
  2041. "with insert() or update() (for example, 'b_%s')."
  2042. % (bindparam.key, bindparam.key)
  2043. )
  2044. self.binds[bindparam.key] = self.binds[name] = bindparam
  2045. # if we are given a cache key that we're going to match against,
  2046. # relate the bindparam here to one that is most likely present
  2047. # in the "extracted params" portion of the cache key. this is used
  2048. # to set up a positional mapping that is used to determine the
  2049. # correct parameters for a subsequent use of this compiled with
  2050. # a different set of parameter values. here, we accommodate for
  2051. # parameters that may have been cloned both before and after the cache
  2052. # key was been generated.
  2053. ckbm = self._cache_key_bind_match
  2054. if ckbm:
  2055. for bp in bindparam._cloned_set:
  2056. if bp.key in ckbm:
  2057. cb = ckbm[bp.key]
  2058. ckbm[cb].append(bindparam)
  2059. if bindparam.isoutparam:
  2060. self.has_out_parameters = True
  2061. if post_compile:
  2062. if render_postcompile:
  2063. self._render_postcompile = True
  2064. if literal_execute:
  2065. self.literal_execute_params |= {bindparam}
  2066. else:
  2067. self.post_compile_params |= {bindparam}
  2068. ret = self.bindparam_string(
  2069. name,
  2070. post_compile=post_compile,
  2071. expanding=bindparam.expanding,
  2072. **kwargs
  2073. )
  2074. if bindparam.expanding:
  2075. ret = "(%s)" % ret
  2076. return ret
  2077. def render_literal_bindparam(
  2078. self, bindparam, render_literal_value=NO_ARG, **kw
  2079. ):
  2080. if render_literal_value is not NO_ARG:
  2081. value = render_literal_value
  2082. else:
  2083. if bindparam.value is None and bindparam.callable is None:
  2084. op = kw.get("_binary_op", None)
  2085. if op and op not in (operators.is_, operators.is_not):
  2086. util.warn_limited(
  2087. "Bound parameter '%s' rendering literal NULL in a SQL "
  2088. "expression; comparisons to NULL should not use "
  2089. "operators outside of 'is' or 'is not'",
  2090. (bindparam.key,),
  2091. )
  2092. return self.process(sqltypes.NULLTYPE, **kw)
  2093. value = bindparam.effective_value
  2094. if bindparam.expanding:
  2095. leep = self._literal_execute_expanding_parameter_literal_binds
  2096. to_update, replacement_expr = leep(bindparam, value)
  2097. return replacement_expr
  2098. else:
  2099. return self.render_literal_value(value, bindparam.type)
  2100. def render_literal_value(self, value, type_):
  2101. """Render the value of a bind parameter as a quoted literal.
  2102. This is used for statement sections that do not accept bind parameters
  2103. on the target driver/database.
  2104. This should be implemented by subclasses using the quoting services
  2105. of the DBAPI.
  2106. """
  2107. processor = type_._cached_literal_processor(self.dialect)
  2108. if processor:
  2109. return processor(value)
  2110. else:
  2111. raise NotImplementedError(
  2112. "Don't know how to literal-quote value %r" % value
  2113. )
  2114. def _truncate_bindparam(self, bindparam):
  2115. if bindparam in self.bind_names:
  2116. return self.bind_names[bindparam]
  2117. bind_name = bindparam.key
  2118. if isinstance(bind_name, elements._truncated_label):
  2119. bind_name = self._truncated_identifier("bindparam", bind_name)
  2120. # add to bind_names for translation
  2121. self.bind_names[bindparam] = bind_name
  2122. return bind_name
  2123. def _truncated_identifier(self, ident_class, name):
  2124. if (ident_class, name) in self.truncated_names:
  2125. return self.truncated_names[(ident_class, name)]
  2126. anonname = name.apply_map(self.anon_map)
  2127. if len(anonname) > self.label_length - 6:
  2128. counter = self.truncated_names.get(ident_class, 1)
  2129. truncname = (
  2130. anonname[0 : max(self.label_length - 6, 0)]
  2131. + "_"
  2132. + hex(counter)[2:]
  2133. )
  2134. self.truncated_names[ident_class] = counter + 1
  2135. else:
  2136. truncname = anonname
  2137. self.truncated_names[(ident_class, name)] = truncname
  2138. return truncname
  2139. def _anonymize(self, name):
  2140. return name % self.anon_map
  2141. def bindparam_string(
  2142. self,
  2143. name,
  2144. positional_names=None,
  2145. post_compile=False,
  2146. expanding=False,
  2147. escaped_from=None,
  2148. **kw
  2149. ):
  2150. if self.positional:
  2151. if positional_names is not None:
  2152. positional_names.append(name)
  2153. else:
  2154. self.positiontup.append(name)
  2155. elif not escaped_from:
  2156. if _BIND_TRANSLATE_RE.search(name):
  2157. # not quite the translate use case as we want to
  2158. # also get a quick boolean if we even found
  2159. # unusual characters in the name
  2160. new_name = _BIND_TRANSLATE_RE.sub(
  2161. lambda m: _BIND_TRANSLATE_CHARS[m.group(0)],
  2162. name,
  2163. )
  2164. escaped_from = name
  2165. name = new_name
  2166. if escaped_from:
  2167. if not self.escaped_bind_names:
  2168. self.escaped_bind_names = {}
  2169. self.escaped_bind_names[escaped_from] = name
  2170. if post_compile:
  2171. return "__[POSTCOMPILE_%s]" % name
  2172. else:
  2173. return self.bindtemplate % {"name": name}
  2174. def visit_cte(
  2175. self,
  2176. cte,
  2177. asfrom=False,
  2178. ashint=False,
  2179. fromhints=None,
  2180. visiting_cte=None,
  2181. from_linter=None,
  2182. **kwargs
  2183. ):
  2184. self._init_cte_state()
  2185. kwargs["visiting_cte"] = cte
  2186. cte_name = cte.name
  2187. if isinstance(cte_name, elements._truncated_label):
  2188. cte_name = self._truncated_identifier("alias", cte_name)
  2189. is_new_cte = True
  2190. embedded_in_current_named_cte = False
  2191. _reference_cte = cte._get_reference_cte()
  2192. if _reference_cte in self.level_name_by_cte:
  2193. cte_level, _ = self.level_name_by_cte[_reference_cte]
  2194. assert _ == cte_name
  2195. else:
  2196. cte_level = len(self.stack) if cte.nesting else 1
  2197. cte_level_name = (cte_level, cte_name)
  2198. if cte_level_name in self.ctes_by_level_name:
  2199. existing_cte = self.ctes_by_level_name[cte_level_name]
  2200. embedded_in_current_named_cte = visiting_cte is existing_cte
  2201. # we've generated a same-named CTE that we are enclosed in,
  2202. # or this is the same CTE. just return the name.
  2203. if cte is existing_cte._restates or cte is existing_cte:
  2204. is_new_cte = False
  2205. elif existing_cte is cte._restates:
  2206. # we've generated a same-named CTE that is
  2207. # enclosed in us - we take precedence, so
  2208. # discard the text for the "inner".
  2209. del self.ctes[existing_cte]
  2210. existing_cte_reference_cte = existing_cte._get_reference_cte()
  2211. # TODO: determine if these assertions are correct. they
  2212. # pass for current test cases
  2213. # assert existing_cte_reference_cte is _reference_cte
  2214. # assert existing_cte_reference_cte is existing_cte
  2215. del self.level_name_by_cte[existing_cte_reference_cte]
  2216. else:
  2217. raise exc.CompileError(
  2218. "Multiple, unrelated CTEs found with "
  2219. "the same name: %r" % cte_name
  2220. )
  2221. if not asfrom and not is_new_cte:
  2222. return None
  2223. if cte._cte_alias is not None:
  2224. pre_alias_cte = cte._cte_alias
  2225. cte_pre_alias_name = cte._cte_alias.name
  2226. if isinstance(cte_pre_alias_name, elements._truncated_label):
  2227. cte_pre_alias_name = self._truncated_identifier(
  2228. "alias", cte_pre_alias_name
  2229. )
  2230. else:
  2231. pre_alias_cte = cte
  2232. cte_pre_alias_name = None
  2233. if is_new_cte:
  2234. self.ctes_by_level_name[cte_level_name] = cte
  2235. self.level_name_by_cte[_reference_cte] = cte_level_name
  2236. if (
  2237. "autocommit" in cte.element._execution_options
  2238. and "autocommit" not in self.execution_options
  2239. ):
  2240. self.execution_options = self.execution_options.union(
  2241. {
  2242. "autocommit": cte.element._execution_options[
  2243. "autocommit"
  2244. ]
  2245. }
  2246. )
  2247. if pre_alias_cte not in self.ctes:
  2248. self.visit_cte(pre_alias_cte, **kwargs)
  2249. if not cte_pre_alias_name and cte not in self.ctes:
  2250. if cte.recursive:
  2251. self.ctes_recursive = True
  2252. text = self.preparer.format_alias(cte, cte_name)
  2253. if cte.recursive:
  2254. if isinstance(cte.element, selectable.Select):
  2255. col_source = cte.element
  2256. elif isinstance(cte.element, selectable.CompoundSelect):
  2257. col_source = cte.element.selects[0]
  2258. else:
  2259. assert False, "cte should only be against SelectBase"
  2260. # TODO: can we get at the .columns_plus_names collection
  2261. # that is already (or will be?) generated for the SELECT
  2262. # rather than calling twice?
  2263. recur_cols = [
  2264. # TODO: proxy_name is not technically safe,
  2265. # see test_cte->
  2266. # test_with_recursive_no_name_currently_buggy. not
  2267. # clear what should be done with such a case
  2268. fallback_label_name or proxy_name
  2269. for (
  2270. _,
  2271. proxy_name,
  2272. fallback_label_name,
  2273. c,
  2274. repeated,
  2275. ) in (col_source._generate_columns_plus_names(True))
  2276. if not repeated
  2277. ]
  2278. text += "(%s)" % (
  2279. ", ".join(
  2280. self.preparer.format_label_name(
  2281. ident, anon_map=self.anon_map
  2282. )
  2283. for ident in recur_cols
  2284. )
  2285. )
  2286. if self.positional:
  2287. kwargs["positional_names"] = self.cte_positional[cte] = []
  2288. assert kwargs.get("subquery", False) is False
  2289. if not self.stack:
  2290. # toplevel, this is a stringify of the
  2291. # cte directly. just compile the inner
  2292. # the way alias() does.
  2293. return cte.element._compiler_dispatch(
  2294. self, asfrom=asfrom, **kwargs
  2295. )
  2296. else:
  2297. prefixes = self._generate_prefixes(
  2298. cte, cte._prefixes, **kwargs
  2299. )
  2300. inner = cte.element._compiler_dispatch(
  2301. self, asfrom=True, **kwargs
  2302. )
  2303. text += " AS %s\n(%s)" % (prefixes, inner)
  2304. if cte._suffixes:
  2305. text += " " + self._generate_prefixes(
  2306. cte, cte._suffixes, **kwargs
  2307. )
  2308. self.ctes[cte] = text
  2309. if asfrom:
  2310. if from_linter:
  2311. from_linter.froms[cte] = cte_name
  2312. if not is_new_cte and embedded_in_current_named_cte:
  2313. return self.preparer.format_alias(cte, cte_name)
  2314. if cte_pre_alias_name:
  2315. text = self.preparer.format_alias(cte, cte_pre_alias_name)
  2316. if self.preparer._requires_quotes(cte_name):
  2317. cte_name = self.preparer.quote(cte_name)
  2318. text += self.get_render_as_alias_suffix(cte_name)
  2319. return text
  2320. else:
  2321. return self.preparer.format_alias(cte, cte_name)
  2322. def visit_table_valued_alias(self, element, **kw):
  2323. if element._is_lateral:
  2324. return self.visit_lateral(element, **kw)
  2325. else:
  2326. return self.visit_alias(element, **kw)
  2327. def visit_table_valued_column(self, element, **kw):
  2328. return self.visit_column(element, **kw)
  2329. def visit_alias(
  2330. self,
  2331. alias,
  2332. asfrom=False,
  2333. ashint=False,
  2334. iscrud=False,
  2335. fromhints=None,
  2336. subquery=False,
  2337. lateral=False,
  2338. enclosing_alias=None,
  2339. from_linter=None,
  2340. **kwargs
  2341. ):
  2342. if lateral:
  2343. if "enclosing_lateral" not in kwargs:
  2344. # if lateral is set and enclosing_lateral is not
  2345. # present, we assume we are being called directly
  2346. # from visit_lateral() and we need to set enclosing_lateral.
  2347. assert alias._is_lateral
  2348. kwargs["enclosing_lateral"] = alias
  2349. # for lateral objects, we track a second from_linter that is...
  2350. # lateral! to the level above us.
  2351. if (
  2352. from_linter
  2353. and "lateral_from_linter" not in kwargs
  2354. and "enclosing_lateral" in kwargs
  2355. ):
  2356. kwargs["lateral_from_linter"] = from_linter
  2357. if enclosing_alias is not None and enclosing_alias.element is alias:
  2358. inner = alias.element._compiler_dispatch(
  2359. self,
  2360. asfrom=asfrom,
  2361. ashint=ashint,
  2362. iscrud=iscrud,
  2363. fromhints=fromhints,
  2364. lateral=lateral,
  2365. enclosing_alias=alias,
  2366. **kwargs
  2367. )
  2368. if subquery and (asfrom or lateral):
  2369. inner = "(%s)" % (inner,)
  2370. return inner
  2371. else:
  2372. enclosing_alias = kwargs["enclosing_alias"] = alias
  2373. if asfrom or ashint:
  2374. if isinstance(alias.name, elements._truncated_label):
  2375. alias_name = self._truncated_identifier("alias", alias.name)
  2376. else:
  2377. alias_name = alias.name
  2378. if ashint:
  2379. return self.preparer.format_alias(alias, alias_name)
  2380. elif asfrom:
  2381. if from_linter:
  2382. from_linter.froms[alias] = alias_name
  2383. inner = alias.element._compiler_dispatch(
  2384. self, asfrom=True, lateral=lateral, **kwargs
  2385. )
  2386. if subquery:
  2387. inner = "(%s)" % (inner,)
  2388. ret = inner + self.get_render_as_alias_suffix(
  2389. self.preparer.format_alias(alias, alias_name)
  2390. )
  2391. if alias._supports_derived_columns and alias._render_derived:
  2392. ret += "(%s)" % (
  2393. ", ".join(
  2394. "%s%s"
  2395. % (
  2396. self.preparer.quote(col.name),
  2397. " %s"
  2398. % self.dialect.type_compiler.process(
  2399. col.type, **kwargs
  2400. )
  2401. if alias._render_derived_w_types
  2402. else "",
  2403. )
  2404. for col in alias.c
  2405. )
  2406. )
  2407. if fromhints and alias in fromhints:
  2408. ret = self.format_from_hint_text(
  2409. ret, alias, fromhints[alias], iscrud
  2410. )
  2411. return ret
  2412. else:
  2413. # note we cancel the "subquery" flag here as well
  2414. return alias.element._compiler_dispatch(
  2415. self, lateral=lateral, **kwargs
  2416. )
  2417. def visit_subquery(self, subquery, **kw):
  2418. kw["subquery"] = True
  2419. return self.visit_alias(subquery, **kw)
  2420. def visit_lateral(self, lateral_, **kw):
  2421. kw["lateral"] = True
  2422. return "LATERAL %s" % self.visit_alias(lateral_, **kw)
  2423. def visit_tablesample(self, tablesample, asfrom=False, **kw):
  2424. text = "%s TABLESAMPLE %s" % (
  2425. self.visit_alias(tablesample, asfrom=True, **kw),
  2426. tablesample._get_method()._compiler_dispatch(self, **kw),
  2427. )
  2428. if tablesample.seed is not None:
  2429. text += " REPEATABLE (%s)" % (
  2430. tablesample.seed._compiler_dispatch(self, **kw)
  2431. )
  2432. return text
  2433. def visit_values(self, element, asfrom=False, from_linter=None, **kw):
  2434. kw.setdefault("literal_binds", element.literal_binds)
  2435. v = "VALUES %s" % ", ".join(
  2436. self.process(
  2437. elements.Tuple(
  2438. types=element._column_types, *elem
  2439. ).self_group(),
  2440. **kw
  2441. )
  2442. for chunk in element._data
  2443. for elem in chunk
  2444. )
  2445. if isinstance(element.name, elements._truncated_label):
  2446. name = self._truncated_identifier("values", element.name)
  2447. else:
  2448. name = element.name
  2449. if element._is_lateral:
  2450. lateral = "LATERAL "
  2451. else:
  2452. lateral = ""
  2453. if asfrom:
  2454. if from_linter:
  2455. from_linter.froms[element] = (
  2456. name if name is not None else "(unnamed VALUES element)"
  2457. )
  2458. if name:
  2459. v = "%s(%s)%s (%s)" % (
  2460. lateral,
  2461. v,
  2462. self.get_render_as_alias_suffix(self.preparer.quote(name)),
  2463. (
  2464. ", ".join(
  2465. c._compiler_dispatch(
  2466. self, include_table=False, **kw
  2467. )
  2468. for c in element.columns
  2469. )
  2470. ),
  2471. )
  2472. else:
  2473. v = "%s(%s)" % (lateral, v)
  2474. return v
  2475. def get_render_as_alias_suffix(self, alias_name_text):
  2476. return " AS " + alias_name_text
  2477. def _add_to_result_map(self, keyname, name, objects, type_):
  2478. if keyname is None or keyname == "*":
  2479. self._ordered_columns = False
  2480. self._textual_ordered_columns = True
  2481. if type_._is_tuple_type:
  2482. raise exc.CompileError(
  2483. "Most backends don't support SELECTing "
  2484. "from a tuple() object. If this is an ORM query, "
  2485. "consider using the Bundle object."
  2486. )
  2487. self._result_columns.append((keyname, name, objects, type_))
  2488. def _label_returning_column(self, stmt, column, column_clause_args=None):
  2489. """Render a column with necessary labels inside of a RETURNING clause.
  2490. This method is provided for individual dialects in place of calling
  2491. the _label_select_column method directly, so that the two use cases
  2492. of RETURNING vs. SELECT can be disambiguated going forward.
  2493. .. versionadded:: 1.4.21
  2494. """
  2495. return self._label_select_column(
  2496. None,
  2497. column,
  2498. True,
  2499. False,
  2500. {} if column_clause_args is None else column_clause_args,
  2501. )
  2502. def _label_select_column(
  2503. self,
  2504. select,
  2505. column,
  2506. populate_result_map,
  2507. asfrom,
  2508. column_clause_args,
  2509. name=None,
  2510. proxy_name=None,
  2511. fallback_label_name=None,
  2512. within_columns_clause=True,
  2513. column_is_repeated=False,
  2514. need_column_expressions=False,
  2515. ):
  2516. """produce labeled columns present in a select()."""
  2517. impl = column.type.dialect_impl(self.dialect)
  2518. if impl._has_column_expression and (
  2519. need_column_expressions or populate_result_map
  2520. ):
  2521. col_expr = impl.column_expression(column)
  2522. else:
  2523. col_expr = column
  2524. if populate_result_map:
  2525. # pass an "add_to_result_map" callable into the compilation
  2526. # of embedded columns. this collects information about the
  2527. # column as it will be fetched in the result and is coordinated
  2528. # with cursor.description when the query is executed.
  2529. add_to_result_map = self._add_to_result_map
  2530. # if the SELECT statement told us this column is a repeat,
  2531. # wrap the callable with one that prevents the addition of the
  2532. # targets
  2533. if column_is_repeated:
  2534. _add_to_result_map = add_to_result_map
  2535. def add_to_result_map(keyname, name, objects, type_):
  2536. _add_to_result_map(keyname, name, (), type_)
  2537. # if we redefined col_expr for type expressions, wrap the
  2538. # callable with one that adds the original column to the targets
  2539. elif col_expr is not column:
  2540. _add_to_result_map = add_to_result_map
  2541. def add_to_result_map(keyname, name, objects, type_):
  2542. _add_to_result_map(
  2543. keyname, name, (column,) + objects, type_
  2544. )
  2545. else:
  2546. add_to_result_map = None
  2547. # this method is used by some of the dialects for RETURNING,
  2548. # which has different inputs. _label_returning_column was added
  2549. # as the better target for this now however for 1.4 we will keep
  2550. # _label_select_column directly compatible with this use case.
  2551. # these assertions right now set up the current expected inputs
  2552. assert within_columns_clause, (
  2553. "_label_select_column is only relevant within "
  2554. "the columns clause of a SELECT or RETURNING"
  2555. )
  2556. if isinstance(column, elements.Label):
  2557. if col_expr is not column:
  2558. result_expr = _CompileLabel(
  2559. col_expr, column.name, alt_names=(column.element,)
  2560. )
  2561. else:
  2562. result_expr = col_expr
  2563. elif name:
  2564. # here, _columns_plus_names has determined there's an explicit
  2565. # label name we need to use. this is the default for
  2566. # tablenames_plus_columnnames as well as when columns are being
  2567. # deduplicated on name
  2568. assert (
  2569. proxy_name is not None
  2570. ), "proxy_name is required if 'name' is passed"
  2571. result_expr = _CompileLabel(
  2572. col_expr,
  2573. name,
  2574. alt_names=(
  2575. proxy_name,
  2576. # this is a hack to allow legacy result column lookups
  2577. # to work as they did before; this goes away in 2.0.
  2578. # TODO: this only seems to be tested indirectly
  2579. # via test/orm/test_deprecations.py. should be a
  2580. # resultset test for this
  2581. column._tq_label,
  2582. ),
  2583. )
  2584. else:
  2585. # determine here whether this column should be rendered in
  2586. # a labelled context or not, as we were given no required label
  2587. # name from the caller. Here we apply heuristics based on the kind
  2588. # of SQL expression involved.
  2589. if col_expr is not column:
  2590. # type-specific expression wrapping the given column,
  2591. # so we render a label
  2592. render_with_label = True
  2593. elif isinstance(column, elements.ColumnClause):
  2594. # table-bound column, we render its name as a label if we are
  2595. # inside of a subquery only
  2596. render_with_label = (
  2597. asfrom
  2598. and not column.is_literal
  2599. and column.table is not None
  2600. )
  2601. elif isinstance(column, elements.TextClause):
  2602. render_with_label = False
  2603. elif isinstance(column, elements.UnaryExpression):
  2604. render_with_label = column.wraps_column_expression or asfrom
  2605. elif (
  2606. # general class of expressions that don't have a SQL-column
  2607. # addressible name. includes scalar selects, bind parameters,
  2608. # SQL functions, others
  2609. not isinstance(column, elements.NamedColumn)
  2610. # deeper check that indicates there's no natural "name" to
  2611. # this element, which accommodates for custom SQL constructs
  2612. # that might have a ".name" attribute (but aren't SQL
  2613. # functions) but are not implementing this more recently added
  2614. # base class. in theory the "NamedColumn" check should be
  2615. # enough, however here we seek to maintain legacy behaviors
  2616. # as well.
  2617. and column._non_anon_label is None
  2618. ):
  2619. render_with_label = True
  2620. else:
  2621. render_with_label = False
  2622. if render_with_label:
  2623. if not fallback_label_name:
  2624. # used by the RETURNING case right now. we generate it
  2625. # here as 3rd party dialects may be referring to
  2626. # _label_select_column method directly instead of the
  2627. # just-added _label_returning_column method
  2628. assert not column_is_repeated
  2629. fallback_label_name = column._anon_name_label
  2630. fallback_label_name = (
  2631. elements._truncated_label(fallback_label_name)
  2632. if not isinstance(
  2633. fallback_label_name, elements._truncated_label
  2634. )
  2635. else fallback_label_name
  2636. )
  2637. result_expr = _CompileLabel(
  2638. col_expr, fallback_label_name, alt_names=(proxy_name,)
  2639. )
  2640. else:
  2641. result_expr = col_expr
  2642. column_clause_args.update(
  2643. within_columns_clause=within_columns_clause,
  2644. add_to_result_map=add_to_result_map,
  2645. )
  2646. return result_expr._compiler_dispatch(self, **column_clause_args)
  2647. def format_from_hint_text(self, sqltext, table, hint, iscrud):
  2648. hinttext = self.get_from_hint_text(table, hint)
  2649. if hinttext:
  2650. sqltext += " " + hinttext
  2651. return sqltext
  2652. def get_select_hint_text(self, byfroms):
  2653. return None
  2654. def get_from_hint_text(self, table, text):
  2655. return None
  2656. def get_crud_hint_text(self, table, text):
  2657. return None
  2658. def get_statement_hint_text(self, hint_texts):
  2659. return " ".join(hint_texts)
  2660. _default_stack_entry = util.immutabledict(
  2661. [("correlate_froms", frozenset()), ("asfrom_froms", frozenset())]
  2662. )
  2663. def _display_froms_for_select(
  2664. self, select_stmt, asfrom, lateral=False, **kw
  2665. ):
  2666. # utility method to help external dialects
  2667. # get the correct from list for a select.
  2668. # specifically the oracle dialect needs this feature
  2669. # right now.
  2670. toplevel = not self.stack
  2671. entry = self._default_stack_entry if toplevel else self.stack[-1]
  2672. compile_state = select_stmt._compile_state_factory(select_stmt, self)
  2673. correlate_froms = entry["correlate_froms"]
  2674. asfrom_froms = entry["asfrom_froms"]
  2675. if asfrom and not lateral:
  2676. froms = compile_state._get_display_froms(
  2677. explicit_correlate_froms=correlate_froms.difference(
  2678. asfrom_froms
  2679. ),
  2680. implicit_correlate_froms=(),
  2681. )
  2682. else:
  2683. froms = compile_state._get_display_froms(
  2684. explicit_correlate_froms=correlate_froms,
  2685. implicit_correlate_froms=asfrom_froms,
  2686. )
  2687. return froms
  2688. translate_select_structure = None
  2689. """if not ``None``, should be a callable which accepts ``(select_stmt,
  2690. **kw)`` and returns a select object. this is used for structural changes
  2691. mostly to accommodate for LIMIT/OFFSET schemes
  2692. """
  2693. def visit_select(
  2694. self,
  2695. select_stmt,
  2696. asfrom=False,
  2697. insert_into=False,
  2698. fromhints=None,
  2699. compound_index=None,
  2700. select_wraps_for=None,
  2701. lateral=False,
  2702. from_linter=None,
  2703. **kwargs
  2704. ):
  2705. assert select_wraps_for is None, (
  2706. "SQLAlchemy 1.4 requires use of "
  2707. "the translate_select_structure hook for structural "
  2708. "translations of SELECT objects"
  2709. )
  2710. # initial setup of SELECT. the compile_state_factory may now
  2711. # be creating a totally different SELECT from the one that was
  2712. # passed in. for ORM use this will convert from an ORM-state
  2713. # SELECT to a regular "Core" SELECT. other composed operations
  2714. # such as computation of joins will be performed.
  2715. kwargs["within_columns_clause"] = False
  2716. compile_state = select_stmt._compile_state_factory(
  2717. select_stmt, self, **kwargs
  2718. )
  2719. select_stmt = compile_state.statement
  2720. toplevel = not self.stack
  2721. if toplevel and not self.compile_state:
  2722. self.compile_state = compile_state
  2723. is_embedded_select = compound_index is not None or insert_into
  2724. # translate step for Oracle, SQL Server which often need to
  2725. # restructure the SELECT to allow for LIMIT/OFFSET and possibly
  2726. # other conditions
  2727. if self.translate_select_structure:
  2728. new_select_stmt = self.translate_select_structure(
  2729. select_stmt, asfrom=asfrom, **kwargs
  2730. )
  2731. # if SELECT was restructured, maintain a link to the originals
  2732. # and assemble a new compile state
  2733. if new_select_stmt is not select_stmt:
  2734. compile_state_wraps_for = compile_state
  2735. select_wraps_for = select_stmt
  2736. select_stmt = new_select_stmt
  2737. compile_state = select_stmt._compile_state_factory(
  2738. select_stmt, self, **kwargs
  2739. )
  2740. select_stmt = compile_state.statement
  2741. entry = self._default_stack_entry if toplevel else self.stack[-1]
  2742. populate_result_map = need_column_expressions = (
  2743. toplevel
  2744. or entry.get("need_result_map_for_compound", False)
  2745. or entry.get("need_result_map_for_nested", False)
  2746. )
  2747. # indicates there is a CompoundSelect in play and we are not the
  2748. # first select
  2749. if compound_index:
  2750. populate_result_map = False
  2751. # this was first proposed as part of #3372; however, it is not
  2752. # reached in current tests and could possibly be an assertion
  2753. # instead.
  2754. if not populate_result_map and "add_to_result_map" in kwargs:
  2755. del kwargs["add_to_result_map"]
  2756. froms = self._setup_select_stack(
  2757. select_stmt, compile_state, entry, asfrom, lateral, compound_index
  2758. )
  2759. column_clause_args = kwargs.copy()
  2760. column_clause_args.update(
  2761. {"within_label_clause": False, "within_columns_clause": False}
  2762. )
  2763. text = "SELECT " # we're off to a good start !
  2764. if select_stmt._hints:
  2765. hint_text, byfrom = self._setup_select_hints(select_stmt)
  2766. if hint_text:
  2767. text += hint_text + " "
  2768. else:
  2769. byfrom = None
  2770. if select_stmt._independent_ctes:
  2771. for cte in select_stmt._independent_ctes:
  2772. cte._compiler_dispatch(self, **kwargs)
  2773. if select_stmt._prefixes:
  2774. text += self._generate_prefixes(
  2775. select_stmt, select_stmt._prefixes, **kwargs
  2776. )
  2777. text += self.get_select_precolumns(select_stmt, **kwargs)
  2778. # the actual list of columns to print in the SELECT column list.
  2779. inner_columns = [
  2780. c
  2781. for c in [
  2782. self._label_select_column(
  2783. select_stmt,
  2784. column,
  2785. populate_result_map,
  2786. asfrom,
  2787. column_clause_args,
  2788. name=name,
  2789. proxy_name=proxy_name,
  2790. fallback_label_name=fallback_label_name,
  2791. column_is_repeated=repeated,
  2792. need_column_expressions=need_column_expressions,
  2793. )
  2794. for (
  2795. name,
  2796. proxy_name,
  2797. fallback_label_name,
  2798. column,
  2799. repeated,
  2800. ) in compile_state.columns_plus_names
  2801. ]
  2802. if c is not None
  2803. ]
  2804. if populate_result_map and select_wraps_for is not None:
  2805. # if this select was generated from translate_select,
  2806. # rewrite the targeted columns in the result map
  2807. translate = dict(
  2808. zip(
  2809. [
  2810. name
  2811. for (
  2812. key,
  2813. proxy_name,
  2814. fallback_label_name,
  2815. name,
  2816. repeated,
  2817. ) in compile_state.columns_plus_names
  2818. ],
  2819. [
  2820. name
  2821. for (
  2822. key,
  2823. proxy_name,
  2824. fallback_label_name,
  2825. name,
  2826. repeated,
  2827. ) in compile_state_wraps_for.columns_plus_names
  2828. ],
  2829. )
  2830. )
  2831. self._result_columns = [
  2832. (key, name, tuple(translate.get(o, o) for o in obj), type_)
  2833. for key, name, obj, type_ in self._result_columns
  2834. ]
  2835. text = self._compose_select_body(
  2836. text,
  2837. select_stmt,
  2838. compile_state,
  2839. inner_columns,
  2840. froms,
  2841. byfrom,
  2842. toplevel,
  2843. kwargs,
  2844. )
  2845. if select_stmt._statement_hints:
  2846. per_dialect = [
  2847. ht
  2848. for (dialect_name, ht) in select_stmt._statement_hints
  2849. if dialect_name in ("*", self.dialect.name)
  2850. ]
  2851. if per_dialect:
  2852. text += " " + self.get_statement_hint_text(per_dialect)
  2853. if self.ctes:
  2854. # In compound query, CTEs are shared at the compound level
  2855. if not is_embedded_select:
  2856. nesting_level = len(self.stack) if not toplevel else None
  2857. text = (
  2858. self._render_cte_clause(nesting_level=nesting_level) + text
  2859. )
  2860. if select_stmt._suffixes:
  2861. text += " " + self._generate_prefixes(
  2862. select_stmt, select_stmt._suffixes, **kwargs
  2863. )
  2864. self.stack.pop(-1)
  2865. return text
  2866. def _setup_select_hints(self, select):
  2867. byfrom = dict(
  2868. [
  2869. (
  2870. from_,
  2871. hinttext
  2872. % {"name": from_._compiler_dispatch(self, ashint=True)},
  2873. )
  2874. for (from_, dialect), hinttext in select._hints.items()
  2875. if dialect in ("*", self.dialect.name)
  2876. ]
  2877. )
  2878. hint_text = self.get_select_hint_text(byfrom)
  2879. return hint_text, byfrom
  2880. def _setup_select_stack(
  2881. self, select, compile_state, entry, asfrom, lateral, compound_index
  2882. ):
  2883. correlate_froms = entry["correlate_froms"]
  2884. asfrom_froms = entry["asfrom_froms"]
  2885. if compound_index == 0:
  2886. entry["select_0"] = select
  2887. elif compound_index:
  2888. select_0 = entry["select_0"]
  2889. numcols = len(select_0._all_selected_columns)
  2890. if len(compile_state.columns_plus_names) != numcols:
  2891. raise exc.CompileError(
  2892. "All selectables passed to "
  2893. "CompoundSelect must have identical numbers of "
  2894. "columns; select #%d has %d columns, select "
  2895. "#%d has %d"
  2896. % (
  2897. 1,
  2898. numcols,
  2899. compound_index + 1,
  2900. len(select._all_selected_columns),
  2901. )
  2902. )
  2903. if asfrom and not lateral:
  2904. froms = compile_state._get_display_froms(
  2905. explicit_correlate_froms=correlate_froms.difference(
  2906. asfrom_froms
  2907. ),
  2908. implicit_correlate_froms=(),
  2909. )
  2910. else:
  2911. froms = compile_state._get_display_froms(
  2912. explicit_correlate_froms=correlate_froms,
  2913. implicit_correlate_froms=asfrom_froms,
  2914. )
  2915. new_correlate_froms = set(selectable._from_objects(*froms))
  2916. all_correlate_froms = new_correlate_froms.union(correlate_froms)
  2917. new_entry = {
  2918. "asfrom_froms": new_correlate_froms,
  2919. "correlate_froms": all_correlate_froms,
  2920. "selectable": select,
  2921. "compile_state": compile_state,
  2922. }
  2923. self.stack.append(new_entry)
  2924. return froms
  2925. def _compose_select_body(
  2926. self,
  2927. text,
  2928. select,
  2929. compile_state,
  2930. inner_columns,
  2931. froms,
  2932. byfrom,
  2933. toplevel,
  2934. kwargs,
  2935. ):
  2936. text += ", ".join(inner_columns)
  2937. if self.linting & COLLECT_CARTESIAN_PRODUCTS:
  2938. from_linter = FromLinter({}, set())
  2939. warn_linting = self.linting & WARN_LINTING
  2940. if toplevel:
  2941. self.from_linter = from_linter
  2942. else:
  2943. from_linter = None
  2944. warn_linting = False
  2945. if froms:
  2946. text += " \nFROM "
  2947. if select._hints:
  2948. text += ", ".join(
  2949. [
  2950. f._compiler_dispatch(
  2951. self,
  2952. asfrom=True,
  2953. fromhints=byfrom,
  2954. from_linter=from_linter,
  2955. **kwargs
  2956. )
  2957. for f in froms
  2958. ]
  2959. )
  2960. else:
  2961. text += ", ".join(
  2962. [
  2963. f._compiler_dispatch(
  2964. self,
  2965. asfrom=True,
  2966. from_linter=from_linter,
  2967. **kwargs
  2968. )
  2969. for f in froms
  2970. ]
  2971. )
  2972. else:
  2973. text += self.default_from()
  2974. if select._where_criteria:
  2975. t = self._generate_delimited_and_list(
  2976. select._where_criteria, from_linter=from_linter, **kwargs
  2977. )
  2978. if t:
  2979. text += " \nWHERE " + t
  2980. if warn_linting:
  2981. from_linter.warn()
  2982. if select._group_by_clauses:
  2983. text += self.group_by_clause(select, **kwargs)
  2984. if select._having_criteria:
  2985. t = self._generate_delimited_and_list(
  2986. select._having_criteria, **kwargs
  2987. )
  2988. if t:
  2989. text += " \nHAVING " + t
  2990. if select._order_by_clauses:
  2991. text += self.order_by_clause(select, **kwargs)
  2992. if select._has_row_limiting_clause:
  2993. text += self._row_limit_clause(select, **kwargs)
  2994. if select._for_update_arg is not None:
  2995. text += self.for_update_clause(select, **kwargs)
  2996. return text
  2997. def _generate_prefixes(self, stmt, prefixes, **kw):
  2998. clause = " ".join(
  2999. prefix._compiler_dispatch(self, **kw)
  3000. for prefix, dialect_name in prefixes
  3001. if dialect_name is None or dialect_name == self.dialect.name
  3002. )
  3003. if clause:
  3004. clause += " "
  3005. return clause
  3006. def _render_cte_clause(
  3007. self,
  3008. nesting_level=None,
  3009. include_following_stack=False,
  3010. ):
  3011. """
  3012. include_following_stack
  3013. Also render the nesting CTEs on the next stack. Useful for
  3014. SQL structures like UNION or INSERT that can wrap SELECT
  3015. statements containing nesting CTEs.
  3016. """
  3017. if not self.ctes:
  3018. return ""
  3019. if nesting_level and nesting_level > 1:
  3020. ctes = util.OrderedDict()
  3021. for cte in list(self.ctes.keys()):
  3022. cte_level, cte_name = self.level_name_by_cte[
  3023. cte._get_reference_cte()
  3024. ]
  3025. is_rendered_level = cte_level == nesting_level or (
  3026. include_following_stack and cte_level == nesting_level + 1
  3027. )
  3028. if not (cte.nesting and is_rendered_level):
  3029. continue
  3030. ctes[cte] = self.ctes[cte]
  3031. else:
  3032. ctes = self.ctes
  3033. if not ctes:
  3034. return ""
  3035. ctes_recursive = any([cte.recursive for cte in ctes])
  3036. if self.positional:
  3037. self.positiontup = (
  3038. sum([self.cte_positional[cte] for cte in ctes], [])
  3039. + self.positiontup
  3040. )
  3041. cte_text = self.get_cte_preamble(ctes_recursive) + " "
  3042. cte_text += ", \n".join([txt for txt in ctes.values()])
  3043. cte_text += "\n "
  3044. if nesting_level and nesting_level > 1:
  3045. for cte in list(ctes.keys()):
  3046. cte_level, cte_name = self.level_name_by_cte[
  3047. cte._get_reference_cte()
  3048. ]
  3049. del self.ctes[cte]
  3050. del self.ctes_by_level_name[(cte_level, cte_name)]
  3051. del self.level_name_by_cte[cte._get_reference_cte()]
  3052. return cte_text
  3053. def get_cte_preamble(self, recursive):
  3054. if recursive:
  3055. return "WITH RECURSIVE"
  3056. else:
  3057. return "WITH"
  3058. def get_select_precolumns(self, select, **kw):
  3059. """Called when building a ``SELECT`` statement, position is just
  3060. before column list.
  3061. """
  3062. if select._distinct_on:
  3063. util.warn_deprecated(
  3064. "DISTINCT ON is currently supported only by the PostgreSQL "
  3065. "dialect. Use of DISTINCT ON for other backends is currently "
  3066. "silently ignored, however this usage is deprecated, and will "
  3067. "raise CompileError in a future release for all backends "
  3068. "that do not support this syntax.",
  3069. version="1.4",
  3070. )
  3071. return "DISTINCT " if select._distinct else ""
  3072. def group_by_clause(self, select, **kw):
  3073. """allow dialects to customize how GROUP BY is rendered."""
  3074. group_by = self._generate_delimited_list(
  3075. select._group_by_clauses, OPERATORS[operators.comma_op], **kw
  3076. )
  3077. if group_by:
  3078. return " GROUP BY " + group_by
  3079. else:
  3080. return ""
  3081. def order_by_clause(self, select, **kw):
  3082. """allow dialects to customize how ORDER BY is rendered."""
  3083. order_by = self._generate_delimited_list(
  3084. select._order_by_clauses, OPERATORS[operators.comma_op], **kw
  3085. )
  3086. if order_by:
  3087. return " ORDER BY " + order_by
  3088. else:
  3089. return ""
  3090. def for_update_clause(self, select, **kw):
  3091. return " FOR UPDATE"
  3092. def returning_clause(self, stmt, returning_cols):
  3093. raise exc.CompileError(
  3094. "RETURNING is not supported by this "
  3095. "dialect's statement compiler."
  3096. )
  3097. def limit_clause(self, select, **kw):
  3098. text = ""
  3099. if select._limit_clause is not None:
  3100. text += "\n LIMIT " + self.process(select._limit_clause, **kw)
  3101. if select._offset_clause is not None:
  3102. if select._limit_clause is None:
  3103. text += "\n LIMIT -1"
  3104. text += " OFFSET " + self.process(select._offset_clause, **kw)
  3105. return text
  3106. def fetch_clause(self, select, **kw):
  3107. text = ""
  3108. if select._offset_clause is not None:
  3109. text += "\n OFFSET %s ROWS" % self.process(
  3110. select._offset_clause, **kw
  3111. )
  3112. if select._fetch_clause is not None:
  3113. text += "\n FETCH FIRST %s%s ROWS %s" % (
  3114. self.process(select._fetch_clause, **kw),
  3115. " PERCENT" if select._fetch_clause_options["percent"] else "",
  3116. "WITH TIES"
  3117. if select._fetch_clause_options["with_ties"]
  3118. else "ONLY",
  3119. )
  3120. return text
  3121. def visit_table(
  3122. self,
  3123. table,
  3124. asfrom=False,
  3125. iscrud=False,
  3126. ashint=False,
  3127. fromhints=None,
  3128. use_schema=True,
  3129. from_linter=None,
  3130. **kwargs
  3131. ):
  3132. if from_linter:
  3133. from_linter.froms[table] = table.fullname
  3134. if asfrom or ashint:
  3135. effective_schema = self.preparer.schema_for_object(table)
  3136. if use_schema and effective_schema:
  3137. ret = (
  3138. self.preparer.quote_schema(effective_schema)
  3139. + "."
  3140. + self.preparer.quote(table.name)
  3141. )
  3142. else:
  3143. ret = self.preparer.quote(table.name)
  3144. if fromhints and table in fromhints:
  3145. ret = self.format_from_hint_text(
  3146. ret, table, fromhints[table], iscrud
  3147. )
  3148. return ret
  3149. else:
  3150. return ""
  3151. def visit_join(self, join, asfrom=False, from_linter=None, **kwargs):
  3152. if from_linter:
  3153. from_linter.edges.update(
  3154. itertools.product(
  3155. join.left._from_objects, join.right._from_objects
  3156. )
  3157. )
  3158. if join.full:
  3159. join_type = " FULL OUTER JOIN "
  3160. elif join.isouter:
  3161. join_type = " LEFT OUTER JOIN "
  3162. else:
  3163. join_type = " JOIN "
  3164. return (
  3165. join.left._compiler_dispatch(
  3166. self, asfrom=True, from_linter=from_linter, **kwargs
  3167. )
  3168. + join_type
  3169. + join.right._compiler_dispatch(
  3170. self, asfrom=True, from_linter=from_linter, **kwargs
  3171. )
  3172. + " ON "
  3173. # TODO: likely need asfrom=True here?
  3174. + join.onclause._compiler_dispatch(
  3175. self, from_linter=from_linter, **kwargs
  3176. )
  3177. )
  3178. def _setup_crud_hints(self, stmt, table_text):
  3179. dialect_hints = dict(
  3180. [
  3181. (table, hint_text)
  3182. for (table, dialect), hint_text in stmt._hints.items()
  3183. if dialect in ("*", self.dialect.name)
  3184. ]
  3185. )
  3186. if stmt.table in dialect_hints:
  3187. table_text = self.format_from_hint_text(
  3188. table_text, stmt.table, dialect_hints[stmt.table], True
  3189. )
  3190. return dialect_hints, table_text
  3191. def visit_insert(self, insert_stmt, **kw):
  3192. compile_state = insert_stmt._compile_state_factory(
  3193. insert_stmt, self, **kw
  3194. )
  3195. insert_stmt = compile_state.statement
  3196. toplevel = not self.stack
  3197. if toplevel:
  3198. self.isinsert = True
  3199. if not self.compile_state:
  3200. self.compile_state = compile_state
  3201. self.stack.append(
  3202. {
  3203. "correlate_froms": set(),
  3204. "asfrom_froms": set(),
  3205. "selectable": insert_stmt,
  3206. }
  3207. )
  3208. crud_params = crud._get_crud_params(
  3209. self, insert_stmt, compile_state, **kw
  3210. )
  3211. if (
  3212. not crud_params
  3213. and not self.dialect.supports_default_values
  3214. and not self.dialect.supports_default_metavalue
  3215. and not self.dialect.supports_empty_insert
  3216. ):
  3217. raise exc.CompileError(
  3218. "The '%s' dialect with current database "
  3219. "version settings does not support empty "
  3220. "inserts." % self.dialect.name
  3221. )
  3222. if compile_state._has_multi_parameters:
  3223. if not self.dialect.supports_multivalues_insert:
  3224. raise exc.CompileError(
  3225. "The '%s' dialect with current database "
  3226. "version settings does not support "
  3227. "in-place multirow inserts." % self.dialect.name
  3228. )
  3229. crud_params_single = crud_params[0]
  3230. else:
  3231. crud_params_single = crud_params
  3232. preparer = self.preparer
  3233. supports_default_values = self.dialect.supports_default_values
  3234. text = "INSERT "
  3235. if insert_stmt._prefixes:
  3236. text += self._generate_prefixes(
  3237. insert_stmt, insert_stmt._prefixes, **kw
  3238. )
  3239. text += "INTO "
  3240. table_text = preparer.format_table(insert_stmt.table)
  3241. if insert_stmt._hints:
  3242. _, table_text = self._setup_crud_hints(insert_stmt, table_text)
  3243. if insert_stmt._independent_ctes:
  3244. for cte in insert_stmt._independent_ctes:
  3245. cte._compiler_dispatch(self, **kw)
  3246. text += table_text
  3247. if crud_params_single or not supports_default_values:
  3248. text += " (%s)" % ", ".join(
  3249. [expr for c, expr, value in crud_params_single]
  3250. )
  3251. if self.returning or insert_stmt._returning:
  3252. returning_clause = self.returning_clause(
  3253. insert_stmt, self.returning or insert_stmt._returning
  3254. )
  3255. if self.returning_precedes_values:
  3256. text += " " + returning_clause
  3257. else:
  3258. returning_clause = None
  3259. if insert_stmt.select is not None:
  3260. # placed here by crud.py
  3261. select_text = self.process(
  3262. self.stack[-1]["insert_from_select"], insert_into=True, **kw
  3263. )
  3264. if self.ctes and self.dialect.cte_follows_insert:
  3265. nesting_level = len(self.stack) if not toplevel else None
  3266. text += " %s%s" % (
  3267. self._render_cte_clause(
  3268. nesting_level=nesting_level,
  3269. include_following_stack=True,
  3270. ),
  3271. select_text,
  3272. )
  3273. else:
  3274. text += " %s" % select_text
  3275. elif not crud_params and supports_default_values:
  3276. text += " DEFAULT VALUES"
  3277. elif compile_state._has_multi_parameters:
  3278. text += " VALUES %s" % (
  3279. ", ".join(
  3280. "(%s)"
  3281. % (", ".join(value for c, expr, value in crud_param_set))
  3282. for crud_param_set in crud_params
  3283. )
  3284. )
  3285. else:
  3286. insert_single_values_expr = ", ".join(
  3287. [value for c, expr, value in crud_params]
  3288. )
  3289. text += " VALUES (%s)" % insert_single_values_expr
  3290. if toplevel and insert_stmt._post_values_clause is None:
  3291. # don't assign insert_single_values_expr if _post_values_clause
  3292. # is present. what this means concretely is that the
  3293. # "fast insert executemany helper" won't be used, in other
  3294. # words we won't convert "executemany()" of many parameter
  3295. # sets into a single INSERT with many elements in VALUES.
  3296. # We can't apply that optimization safely if for example the
  3297. # statement includes a clause like "ON CONFLICT DO UPDATE"
  3298. self.insert_single_values_expr = insert_single_values_expr
  3299. if insert_stmt._post_values_clause is not None:
  3300. post_values_clause = self.process(
  3301. insert_stmt._post_values_clause, **kw
  3302. )
  3303. if post_values_clause:
  3304. text += " " + post_values_clause
  3305. if returning_clause and not self.returning_precedes_values:
  3306. text += " " + returning_clause
  3307. if self.ctes and not self.dialect.cte_follows_insert:
  3308. nesting_level = len(self.stack) if not toplevel else None
  3309. text = (
  3310. self._render_cte_clause(
  3311. nesting_level=nesting_level, include_following_stack=True
  3312. )
  3313. + text
  3314. )
  3315. self.stack.pop(-1)
  3316. return text
  3317. def update_limit_clause(self, update_stmt):
  3318. """Provide a hook for MySQL to add LIMIT to the UPDATE"""
  3319. return None
  3320. def update_tables_clause(self, update_stmt, from_table, extra_froms, **kw):
  3321. """Provide a hook to override the initial table clause
  3322. in an UPDATE statement.
  3323. MySQL overrides this.
  3324. """
  3325. kw["asfrom"] = True
  3326. return from_table._compiler_dispatch(self, iscrud=True, **kw)
  3327. def update_from_clause(
  3328. self, update_stmt, from_table, extra_froms, from_hints, **kw
  3329. ):
  3330. """Provide a hook to override the generation of an
  3331. UPDATE..FROM clause.
  3332. MySQL and MSSQL override this.
  3333. """
  3334. raise NotImplementedError(
  3335. "This backend does not support multiple-table "
  3336. "criteria within UPDATE"
  3337. )
  3338. def visit_update(self, update_stmt, **kw):
  3339. compile_state = update_stmt._compile_state_factory(
  3340. update_stmt, self, **kw
  3341. )
  3342. update_stmt = compile_state.statement
  3343. toplevel = not self.stack
  3344. if toplevel:
  3345. self.isupdate = True
  3346. if not self.compile_state:
  3347. self.compile_state = compile_state
  3348. extra_froms = compile_state._extra_froms
  3349. is_multitable = bool(extra_froms)
  3350. if is_multitable:
  3351. # main table might be a JOIN
  3352. main_froms = set(selectable._from_objects(update_stmt.table))
  3353. render_extra_froms = [
  3354. f for f in extra_froms if f not in main_froms
  3355. ]
  3356. correlate_froms = main_froms.union(extra_froms)
  3357. else:
  3358. render_extra_froms = []
  3359. correlate_froms = {update_stmt.table}
  3360. self.stack.append(
  3361. {
  3362. "correlate_froms": correlate_froms,
  3363. "asfrom_froms": correlate_froms,
  3364. "selectable": update_stmt,
  3365. }
  3366. )
  3367. text = "UPDATE "
  3368. if update_stmt._prefixes:
  3369. text += self._generate_prefixes(
  3370. update_stmt, update_stmt._prefixes, **kw
  3371. )
  3372. table_text = self.update_tables_clause(
  3373. update_stmt, update_stmt.table, render_extra_froms, **kw
  3374. )
  3375. crud_params = crud._get_crud_params(
  3376. self, update_stmt, compile_state, **kw
  3377. )
  3378. if update_stmt._hints:
  3379. dialect_hints, table_text = self._setup_crud_hints(
  3380. update_stmt, table_text
  3381. )
  3382. else:
  3383. dialect_hints = None
  3384. if update_stmt._independent_ctes:
  3385. for cte in update_stmt._independent_ctes:
  3386. cte._compiler_dispatch(self, **kw)
  3387. text += table_text
  3388. text += " SET "
  3389. text += ", ".join(expr + "=" + value for c, expr, value in crud_params)
  3390. if self.returning or update_stmt._returning:
  3391. if self.returning_precedes_values:
  3392. text += " " + self.returning_clause(
  3393. update_stmt, self.returning or update_stmt._returning
  3394. )
  3395. if extra_froms:
  3396. extra_from_text = self.update_from_clause(
  3397. update_stmt,
  3398. update_stmt.table,
  3399. render_extra_froms,
  3400. dialect_hints,
  3401. **kw
  3402. )
  3403. if extra_from_text:
  3404. text += " " + extra_from_text
  3405. if update_stmt._where_criteria:
  3406. t = self._generate_delimited_and_list(
  3407. update_stmt._where_criteria, **kw
  3408. )
  3409. if t:
  3410. text += " WHERE " + t
  3411. limit_clause = self.update_limit_clause(update_stmt)
  3412. if limit_clause:
  3413. text += " " + limit_clause
  3414. if (
  3415. self.returning or update_stmt._returning
  3416. ) and not self.returning_precedes_values:
  3417. text += " " + self.returning_clause(
  3418. update_stmt, self.returning or update_stmt._returning
  3419. )
  3420. if self.ctes:
  3421. nesting_level = len(self.stack) if not toplevel else None
  3422. text = self._render_cte_clause(nesting_level=nesting_level) + text
  3423. self.stack.pop(-1)
  3424. return text
  3425. def delete_extra_from_clause(
  3426. self, update_stmt, from_table, extra_froms, from_hints, **kw
  3427. ):
  3428. """Provide a hook to override the generation of an
  3429. DELETE..FROM clause.
  3430. This can be used to implement DELETE..USING for example.
  3431. MySQL and MSSQL override this.
  3432. """
  3433. raise NotImplementedError(
  3434. "This backend does not support multiple-table "
  3435. "criteria within DELETE"
  3436. )
  3437. def delete_table_clause(self, delete_stmt, from_table, extra_froms):
  3438. return from_table._compiler_dispatch(self, asfrom=True, iscrud=True)
  3439. def visit_delete(self, delete_stmt, **kw):
  3440. compile_state = delete_stmt._compile_state_factory(
  3441. delete_stmt, self, **kw
  3442. )
  3443. delete_stmt = compile_state.statement
  3444. toplevel = not self.stack
  3445. if toplevel:
  3446. self.isdelete = True
  3447. if not self.compile_state:
  3448. self.compile_state = compile_state
  3449. extra_froms = compile_state._extra_froms
  3450. correlate_froms = {delete_stmt.table}.union(extra_froms)
  3451. self.stack.append(
  3452. {
  3453. "correlate_froms": correlate_froms,
  3454. "asfrom_froms": correlate_froms,
  3455. "selectable": delete_stmt,
  3456. }
  3457. )
  3458. text = "DELETE "
  3459. if delete_stmt._prefixes:
  3460. text += self._generate_prefixes(
  3461. delete_stmt, delete_stmt._prefixes, **kw
  3462. )
  3463. text += "FROM "
  3464. table_text = self.delete_table_clause(
  3465. delete_stmt, delete_stmt.table, extra_froms
  3466. )
  3467. if delete_stmt._hints:
  3468. dialect_hints, table_text = self._setup_crud_hints(
  3469. delete_stmt, table_text
  3470. )
  3471. else:
  3472. dialect_hints = None
  3473. if delete_stmt._independent_ctes:
  3474. for cte in delete_stmt._independent_ctes:
  3475. cte._compiler_dispatch(self, **kw)
  3476. text += table_text
  3477. if delete_stmt._returning:
  3478. if self.returning_precedes_values:
  3479. text += " " + self.returning_clause(
  3480. delete_stmt, delete_stmt._returning
  3481. )
  3482. if extra_froms:
  3483. extra_from_text = self.delete_extra_from_clause(
  3484. delete_stmt,
  3485. delete_stmt.table,
  3486. extra_froms,
  3487. dialect_hints,
  3488. **kw
  3489. )
  3490. if extra_from_text:
  3491. text += " " + extra_from_text
  3492. if delete_stmt._where_criteria:
  3493. t = self._generate_delimited_and_list(
  3494. delete_stmt._where_criteria, **kw
  3495. )
  3496. if t:
  3497. text += " WHERE " + t
  3498. if delete_stmt._returning and not self.returning_precedes_values:
  3499. text += " " + self.returning_clause(
  3500. delete_stmt, delete_stmt._returning
  3501. )
  3502. if self.ctes:
  3503. nesting_level = len(self.stack) if not toplevel else None
  3504. text = self._render_cte_clause(nesting_level=nesting_level) + text
  3505. self.stack.pop(-1)
  3506. return text
  3507. def visit_savepoint(self, savepoint_stmt):
  3508. return "SAVEPOINT %s" % self.preparer.format_savepoint(savepoint_stmt)
  3509. def visit_rollback_to_savepoint(self, savepoint_stmt):
  3510. return "ROLLBACK TO SAVEPOINT %s" % self.preparer.format_savepoint(
  3511. savepoint_stmt
  3512. )
  3513. def visit_release_savepoint(self, savepoint_stmt):
  3514. return "RELEASE SAVEPOINT %s" % self.preparer.format_savepoint(
  3515. savepoint_stmt
  3516. )
  3517. class StrSQLCompiler(SQLCompiler):
  3518. """A :class:`.SQLCompiler` subclass which allows a small selection
  3519. of non-standard SQL features to render into a string value.
  3520. The :class:`.StrSQLCompiler` is invoked whenever a Core expression
  3521. element is directly stringified without calling upon the
  3522. :meth:`_expression.ClauseElement.compile` method.
  3523. It can render a limited set
  3524. of non-standard SQL constructs to assist in basic stringification,
  3525. however for more substantial custom or dialect-specific SQL constructs,
  3526. it will be necessary to make use of
  3527. :meth:`_expression.ClauseElement.compile`
  3528. directly.
  3529. .. seealso::
  3530. :ref:`faq_sql_expression_string`
  3531. """
  3532. def _fallback_column_name(self, column):
  3533. return "<name unknown>"
  3534. @util.preload_module("sqlalchemy.engine.url")
  3535. def visit_unsupported_compilation(self, element, err, **kw):
  3536. if element.stringify_dialect != "default":
  3537. url = util.preloaded.engine_url
  3538. dialect = url.URL.create(element.stringify_dialect).get_dialect()()
  3539. compiler = dialect.statement_compiler(dialect, None)
  3540. if not isinstance(compiler, StrSQLCompiler):
  3541. return compiler.process(element)
  3542. return super(StrSQLCompiler, self).visit_unsupported_compilation(
  3543. element, err
  3544. )
  3545. def visit_getitem_binary(self, binary, operator, **kw):
  3546. return "%s[%s]" % (
  3547. self.process(binary.left, **kw),
  3548. self.process(binary.right, **kw),
  3549. )
  3550. def visit_json_getitem_op_binary(self, binary, operator, **kw):
  3551. return self.visit_getitem_binary(binary, operator, **kw)
  3552. def visit_json_path_getitem_op_binary(self, binary, operator, **kw):
  3553. return self.visit_getitem_binary(binary, operator, **kw)
  3554. def visit_sequence(self, seq, **kw):
  3555. return "<next sequence value: %s>" % self.preparer.format_sequence(seq)
  3556. def returning_clause(self, stmt, returning_cols):
  3557. columns = [
  3558. self._label_select_column(None, c, True, False, {})
  3559. for c in base._select_iterables(returning_cols)
  3560. ]
  3561. return "RETURNING " + ", ".join(columns)
  3562. def update_from_clause(
  3563. self, update_stmt, from_table, extra_froms, from_hints, **kw
  3564. ):
  3565. kw["asfrom"] = True
  3566. return "FROM " + ", ".join(
  3567. t._compiler_dispatch(self, fromhints=from_hints, **kw)
  3568. for t in extra_froms
  3569. )
  3570. def delete_extra_from_clause(
  3571. self, update_stmt, from_table, extra_froms, from_hints, **kw
  3572. ):
  3573. kw["asfrom"] = True
  3574. return ", " + ", ".join(
  3575. t._compiler_dispatch(self, fromhints=from_hints, **kw)
  3576. for t in extra_froms
  3577. )
  3578. def visit_empty_set_expr(self, type_):
  3579. return "SELECT 1 WHERE 1!=1"
  3580. def get_from_hint_text(self, table, text):
  3581. return "[%s]" % text
  3582. def visit_regexp_match_op_binary(self, binary, operator, **kw):
  3583. return self._generate_generic_binary(binary, " <regexp> ", **kw)
  3584. def visit_not_regexp_match_op_binary(self, binary, operator, **kw):
  3585. return self._generate_generic_binary(binary, " <not regexp> ", **kw)
  3586. def visit_regexp_replace_op_binary(self, binary, operator, **kw):
  3587. replacement = binary.modifiers["replacement"]
  3588. return "<regexp replace>(%s, %s, %s)" % (
  3589. binary.left._compiler_dispatch(self, **kw),
  3590. binary.right._compiler_dispatch(self, **kw),
  3591. replacement._compiler_dispatch(self, **kw),
  3592. )
  3593. class DDLCompiler(Compiled):
  3594. @util.memoized_property
  3595. def sql_compiler(self):
  3596. return self.dialect.statement_compiler(
  3597. self.dialect, None, schema_translate_map=self.schema_translate_map
  3598. )
  3599. @util.memoized_property
  3600. def type_compiler(self):
  3601. return self.dialect.type_compiler
  3602. def construct_params(self, params=None, extracted_parameters=None):
  3603. return None
  3604. def visit_ddl(self, ddl, **kwargs):
  3605. # table events can substitute table and schema name
  3606. context = ddl.context
  3607. if isinstance(ddl.target, schema.Table):
  3608. context = context.copy()
  3609. preparer = self.preparer
  3610. path = preparer.format_table_seq(ddl.target)
  3611. if len(path) == 1:
  3612. table, sch = path[0], ""
  3613. else:
  3614. table, sch = path[-1], path[0]
  3615. context.setdefault("table", table)
  3616. context.setdefault("schema", sch)
  3617. context.setdefault("fullname", preparer.format_table(ddl.target))
  3618. return self.sql_compiler.post_process_text(ddl.statement % context)
  3619. def visit_create_schema(self, create, **kw):
  3620. schema = self.preparer.format_schema(create.element)
  3621. return "CREATE SCHEMA " + schema
  3622. def visit_drop_schema(self, drop, **kw):
  3623. schema = self.preparer.format_schema(drop.element)
  3624. text = "DROP SCHEMA " + schema
  3625. if drop.cascade:
  3626. text += " CASCADE"
  3627. return text
  3628. def visit_create_table(self, create, **kw):
  3629. table = create.element
  3630. preparer = self.preparer
  3631. text = "\nCREATE "
  3632. if table._prefixes:
  3633. text += " ".join(table._prefixes) + " "
  3634. text += "TABLE "
  3635. if create.if_not_exists:
  3636. text += "IF NOT EXISTS "
  3637. text += preparer.format_table(table) + " "
  3638. create_table_suffix = self.create_table_suffix(table)
  3639. if create_table_suffix:
  3640. text += create_table_suffix + " "
  3641. text += "("
  3642. separator = "\n"
  3643. # if only one primary key, specify it along with the column
  3644. first_pk = False
  3645. for create_column in create.columns:
  3646. column = create_column.element
  3647. try:
  3648. processed = self.process(
  3649. create_column, first_pk=column.primary_key and not first_pk
  3650. )
  3651. if processed is not None:
  3652. text += separator
  3653. separator = ", \n"
  3654. text += "\t" + processed
  3655. if column.primary_key:
  3656. first_pk = True
  3657. except exc.CompileError as ce:
  3658. util.raise_(
  3659. exc.CompileError(
  3660. util.u("(in table '%s', column '%s'): %s")
  3661. % (table.description, column.name, ce.args[0])
  3662. ),
  3663. from_=ce,
  3664. )
  3665. const = self.create_table_constraints(
  3666. table,
  3667. _include_foreign_key_constraints=create.include_foreign_key_constraints, # noqa
  3668. )
  3669. if const:
  3670. text += separator + "\t" + const
  3671. text += "\n)%s\n\n" % self.post_create_table(table)
  3672. return text
  3673. def visit_create_column(self, create, first_pk=False, **kw):
  3674. column = create.element
  3675. if column.system:
  3676. return None
  3677. text = self.get_column_specification(column, first_pk=first_pk)
  3678. const = " ".join(
  3679. self.process(constraint) for constraint in column.constraints
  3680. )
  3681. if const:
  3682. text += " " + const
  3683. return text
  3684. def create_table_constraints(
  3685. self, table, _include_foreign_key_constraints=None, **kw
  3686. ):
  3687. # On some DB order is significant: visit PK first, then the
  3688. # other constraints (engine.ReflectionTest.testbasic failed on FB2)
  3689. constraints = []
  3690. if table.primary_key:
  3691. constraints.append(table.primary_key)
  3692. all_fkcs = table.foreign_key_constraints
  3693. if _include_foreign_key_constraints is not None:
  3694. omit_fkcs = all_fkcs.difference(_include_foreign_key_constraints)
  3695. else:
  3696. omit_fkcs = set()
  3697. constraints.extend(
  3698. [
  3699. c
  3700. for c in table._sorted_constraints
  3701. if c is not table.primary_key and c not in omit_fkcs
  3702. ]
  3703. )
  3704. return ", \n\t".join(
  3705. p
  3706. for p in (
  3707. self.process(constraint)
  3708. for constraint in constraints
  3709. if (
  3710. constraint._create_rule is None
  3711. or constraint._create_rule(self)
  3712. )
  3713. and (
  3714. not self.dialect.supports_alter
  3715. or not getattr(constraint, "use_alter", False)
  3716. )
  3717. )
  3718. if p is not None
  3719. )
  3720. def visit_drop_table(self, drop, **kw):
  3721. text = "\nDROP TABLE "
  3722. if drop.if_exists:
  3723. text += "IF EXISTS "
  3724. return text + self.preparer.format_table(drop.element)
  3725. def visit_drop_view(self, drop, **kw):
  3726. return "\nDROP VIEW " + self.preparer.format_table(drop.element)
  3727. def _verify_index_table(self, index):
  3728. if index.table is None:
  3729. raise exc.CompileError(
  3730. "Index '%s' is not associated " "with any table." % index.name
  3731. )
  3732. def visit_create_index(
  3733. self, create, include_schema=False, include_table_schema=True, **kw
  3734. ):
  3735. index = create.element
  3736. self._verify_index_table(index)
  3737. preparer = self.preparer
  3738. text = "CREATE "
  3739. if index.unique:
  3740. text += "UNIQUE "
  3741. if index.name is None:
  3742. raise exc.CompileError(
  3743. "CREATE INDEX requires that the index have a name"
  3744. )
  3745. text += "INDEX "
  3746. if create.if_not_exists:
  3747. text += "IF NOT EXISTS "
  3748. text += "%s ON %s (%s)" % (
  3749. self._prepared_index_name(index, include_schema=include_schema),
  3750. preparer.format_table(
  3751. index.table, use_schema=include_table_schema
  3752. ),
  3753. ", ".join(
  3754. self.sql_compiler.process(
  3755. expr, include_table=False, literal_binds=True
  3756. )
  3757. for expr in index.expressions
  3758. ),
  3759. )
  3760. return text
  3761. def visit_drop_index(self, drop, **kw):
  3762. index = drop.element
  3763. if index.name is None:
  3764. raise exc.CompileError(
  3765. "DROP INDEX requires that the index have a name"
  3766. )
  3767. text = "\nDROP INDEX "
  3768. if drop.if_exists:
  3769. text += "IF EXISTS "
  3770. return text + self._prepared_index_name(index, include_schema=True)
  3771. def _prepared_index_name(self, index, include_schema=False):
  3772. if index.table is not None:
  3773. effective_schema = self.preparer.schema_for_object(index.table)
  3774. else:
  3775. effective_schema = None
  3776. if include_schema and effective_schema:
  3777. schema_name = self.preparer.quote_schema(effective_schema)
  3778. else:
  3779. schema_name = None
  3780. index_name = self.preparer.format_index(index)
  3781. if schema_name:
  3782. index_name = schema_name + "." + index_name
  3783. return index_name
  3784. def visit_add_constraint(self, create, **kw):
  3785. return "ALTER TABLE %s ADD %s" % (
  3786. self.preparer.format_table(create.element.table),
  3787. self.process(create.element),
  3788. )
  3789. def visit_set_table_comment(self, create, **kw):
  3790. return "COMMENT ON TABLE %s IS %s" % (
  3791. self.preparer.format_table(create.element),
  3792. self.sql_compiler.render_literal_value(
  3793. create.element.comment, sqltypes.String()
  3794. ),
  3795. )
  3796. def visit_drop_table_comment(self, drop, **kw):
  3797. return "COMMENT ON TABLE %s IS NULL" % self.preparer.format_table(
  3798. drop.element
  3799. )
  3800. def visit_set_column_comment(self, create, **kw):
  3801. return "COMMENT ON COLUMN %s IS %s" % (
  3802. self.preparer.format_column(
  3803. create.element, use_table=True, use_schema=True
  3804. ),
  3805. self.sql_compiler.render_literal_value(
  3806. create.element.comment, sqltypes.String()
  3807. ),
  3808. )
  3809. def visit_drop_column_comment(self, drop, **kw):
  3810. return "COMMENT ON COLUMN %s IS NULL" % self.preparer.format_column(
  3811. drop.element, use_table=True
  3812. )
  3813. def get_identity_options(self, identity_options):
  3814. text = []
  3815. if identity_options.increment is not None:
  3816. text.append("INCREMENT BY %d" % identity_options.increment)
  3817. if identity_options.start is not None:
  3818. text.append("START WITH %d" % identity_options.start)
  3819. if identity_options.minvalue is not None:
  3820. text.append("MINVALUE %d" % identity_options.minvalue)
  3821. if identity_options.maxvalue is not None:
  3822. text.append("MAXVALUE %d" % identity_options.maxvalue)
  3823. if identity_options.nominvalue is not None:
  3824. text.append("NO MINVALUE")
  3825. if identity_options.nomaxvalue is not None:
  3826. text.append("NO MAXVALUE")
  3827. if identity_options.cache is not None:
  3828. text.append("CACHE %d" % identity_options.cache)
  3829. if identity_options.order is not None:
  3830. text.append("ORDER" if identity_options.order else "NO ORDER")
  3831. if identity_options.cycle is not None:
  3832. text.append("CYCLE" if identity_options.cycle else "NO CYCLE")
  3833. return " ".join(text)
  3834. def visit_create_sequence(self, create, prefix=None, **kw):
  3835. text = "CREATE SEQUENCE %s" % self.preparer.format_sequence(
  3836. create.element
  3837. )
  3838. if prefix:
  3839. text += prefix
  3840. if create.element.start is None:
  3841. create.element.start = self.dialect.default_sequence_base
  3842. options = self.get_identity_options(create.element)
  3843. if options:
  3844. text += " " + options
  3845. return text
  3846. def visit_drop_sequence(self, drop, **kw):
  3847. return "DROP SEQUENCE %s" % self.preparer.format_sequence(drop.element)
  3848. def visit_drop_constraint(self, drop, **kw):
  3849. constraint = drop.element
  3850. if constraint.name is not None:
  3851. formatted_name = self.preparer.format_constraint(constraint)
  3852. else:
  3853. formatted_name = None
  3854. if formatted_name is None:
  3855. raise exc.CompileError(
  3856. "Can't emit DROP CONSTRAINT for constraint %r; "
  3857. "it has no name" % drop.element
  3858. )
  3859. return "ALTER TABLE %s DROP CONSTRAINT %s%s" % (
  3860. self.preparer.format_table(drop.element.table),
  3861. formatted_name,
  3862. drop.cascade and " CASCADE" or "",
  3863. )
  3864. def get_column_specification(self, column, **kwargs):
  3865. colspec = (
  3866. self.preparer.format_column(column)
  3867. + " "
  3868. + self.dialect.type_compiler.process(
  3869. column.type, type_expression=column
  3870. )
  3871. )
  3872. default = self.get_column_default_string(column)
  3873. if default is not None:
  3874. colspec += " DEFAULT " + default
  3875. if column.computed is not None:
  3876. colspec += " " + self.process(column.computed)
  3877. if (
  3878. column.identity is not None
  3879. and self.dialect.supports_identity_columns
  3880. ):
  3881. colspec += " " + self.process(column.identity)
  3882. if not column.nullable and (
  3883. not column.identity or not self.dialect.supports_identity_columns
  3884. ):
  3885. colspec += " NOT NULL"
  3886. return colspec
  3887. def create_table_suffix(self, table):
  3888. return ""
  3889. def post_create_table(self, table):
  3890. return ""
  3891. def get_column_default_string(self, column):
  3892. if isinstance(column.server_default, schema.DefaultClause):
  3893. if isinstance(column.server_default.arg, util.string_types):
  3894. return self.sql_compiler.render_literal_value(
  3895. column.server_default.arg, sqltypes.STRINGTYPE
  3896. )
  3897. else:
  3898. return self.sql_compiler.process(
  3899. column.server_default.arg, literal_binds=True
  3900. )
  3901. else:
  3902. return None
  3903. def visit_table_or_column_check_constraint(self, constraint, **kw):
  3904. if constraint.is_column_level:
  3905. return self.visit_column_check_constraint(constraint)
  3906. else:
  3907. return self.visit_check_constraint(constraint)
  3908. def visit_check_constraint(self, constraint, **kw):
  3909. text = ""
  3910. if constraint.name is not None:
  3911. formatted_name = self.preparer.format_constraint(constraint)
  3912. if formatted_name is not None:
  3913. text += "CONSTRAINT %s " % formatted_name
  3914. text += "CHECK (%s)" % self.sql_compiler.process(
  3915. constraint.sqltext, include_table=False, literal_binds=True
  3916. )
  3917. text += self.define_constraint_deferrability(constraint)
  3918. return text
  3919. def visit_column_check_constraint(self, constraint, **kw):
  3920. text = ""
  3921. if constraint.name is not None:
  3922. formatted_name = self.preparer.format_constraint(constraint)
  3923. if formatted_name is not None:
  3924. text += "CONSTRAINT %s " % formatted_name
  3925. text += "CHECK (%s)" % self.sql_compiler.process(
  3926. constraint.sqltext, include_table=False, literal_binds=True
  3927. )
  3928. text += self.define_constraint_deferrability(constraint)
  3929. return text
  3930. def visit_primary_key_constraint(self, constraint, **kw):
  3931. if len(constraint) == 0:
  3932. return ""
  3933. text = ""
  3934. if constraint.name is not None:
  3935. formatted_name = self.preparer.format_constraint(constraint)
  3936. if formatted_name is not None:
  3937. text += "CONSTRAINT %s " % formatted_name
  3938. text += "PRIMARY KEY "
  3939. text += "(%s)" % ", ".join(
  3940. self.preparer.quote(c.name)
  3941. for c in (
  3942. constraint.columns_autoinc_first
  3943. if constraint._implicit_generated
  3944. else constraint.columns
  3945. )
  3946. )
  3947. text += self.define_constraint_deferrability(constraint)
  3948. return text
  3949. def visit_foreign_key_constraint(self, constraint, **kw):
  3950. preparer = self.preparer
  3951. text = ""
  3952. if constraint.name is not None:
  3953. formatted_name = self.preparer.format_constraint(constraint)
  3954. if formatted_name is not None:
  3955. text += "CONSTRAINT %s " % formatted_name
  3956. remote_table = list(constraint.elements)[0].column.table
  3957. text += "FOREIGN KEY(%s) REFERENCES %s (%s)" % (
  3958. ", ".join(
  3959. preparer.quote(f.parent.name) for f in constraint.elements
  3960. ),
  3961. self.define_constraint_remote_table(
  3962. constraint, remote_table, preparer
  3963. ),
  3964. ", ".join(
  3965. preparer.quote(f.column.name) for f in constraint.elements
  3966. ),
  3967. )
  3968. text += self.define_constraint_match(constraint)
  3969. text += self.define_constraint_cascades(constraint)
  3970. text += self.define_constraint_deferrability(constraint)
  3971. return text
  3972. def define_constraint_remote_table(self, constraint, table, preparer):
  3973. """Format the remote table clause of a CREATE CONSTRAINT clause."""
  3974. return preparer.format_table(table)
  3975. def visit_unique_constraint(self, constraint, **kw):
  3976. if len(constraint) == 0:
  3977. return ""
  3978. text = ""
  3979. if constraint.name is not None:
  3980. formatted_name = self.preparer.format_constraint(constraint)
  3981. if formatted_name is not None:
  3982. text += "CONSTRAINT %s " % formatted_name
  3983. text += "UNIQUE (%s)" % (
  3984. ", ".join(self.preparer.quote(c.name) for c in constraint)
  3985. )
  3986. text += self.define_constraint_deferrability(constraint)
  3987. return text
  3988. def define_constraint_cascades(self, constraint):
  3989. text = ""
  3990. if constraint.ondelete is not None:
  3991. text += " ON DELETE %s" % self.preparer.validate_sql_phrase(
  3992. constraint.ondelete, FK_ON_DELETE
  3993. )
  3994. if constraint.onupdate is not None:
  3995. text += " ON UPDATE %s" % self.preparer.validate_sql_phrase(
  3996. constraint.onupdate, FK_ON_UPDATE
  3997. )
  3998. return text
  3999. def define_constraint_deferrability(self, constraint):
  4000. text = ""
  4001. if constraint.deferrable is not None:
  4002. if constraint.deferrable:
  4003. text += " DEFERRABLE"
  4004. else:
  4005. text += " NOT DEFERRABLE"
  4006. if constraint.initially is not None:
  4007. text += " INITIALLY %s" % self.preparer.validate_sql_phrase(
  4008. constraint.initially, FK_INITIALLY
  4009. )
  4010. return text
  4011. def define_constraint_match(self, constraint):
  4012. text = ""
  4013. if constraint.match is not None:
  4014. text += " MATCH %s" % constraint.match
  4015. return text
  4016. def visit_computed_column(self, generated, **kw):
  4017. text = "GENERATED ALWAYS AS (%s)" % self.sql_compiler.process(
  4018. generated.sqltext, include_table=False, literal_binds=True
  4019. )
  4020. if generated.persisted is True:
  4021. text += " STORED"
  4022. elif generated.persisted is False:
  4023. text += " VIRTUAL"
  4024. return text
  4025. def visit_identity_column(self, identity, **kw):
  4026. text = "GENERATED %s AS IDENTITY" % (
  4027. "ALWAYS" if identity.always else "BY DEFAULT",
  4028. )
  4029. options = self.get_identity_options(identity)
  4030. if options:
  4031. text += " (%s)" % options
  4032. return text
  4033. class GenericTypeCompiler(TypeCompiler):
  4034. def visit_FLOAT(self, type_, **kw):
  4035. return "FLOAT"
  4036. def visit_REAL(self, type_, **kw):
  4037. return "REAL"
  4038. def visit_NUMERIC(self, type_, **kw):
  4039. if type_.precision is None:
  4040. return "NUMERIC"
  4041. elif type_.scale is None:
  4042. return "NUMERIC(%(precision)s)" % {"precision": type_.precision}
  4043. else:
  4044. return "NUMERIC(%(precision)s, %(scale)s)" % {
  4045. "precision": type_.precision,
  4046. "scale": type_.scale,
  4047. }
  4048. def visit_DECIMAL(self, type_, **kw):
  4049. if type_.precision is None:
  4050. return "DECIMAL"
  4051. elif type_.scale is None:
  4052. return "DECIMAL(%(precision)s)" % {"precision": type_.precision}
  4053. else:
  4054. return "DECIMAL(%(precision)s, %(scale)s)" % {
  4055. "precision": type_.precision,
  4056. "scale": type_.scale,
  4057. }
  4058. def visit_INTEGER(self, type_, **kw):
  4059. return "INTEGER"
  4060. def visit_SMALLINT(self, type_, **kw):
  4061. return "SMALLINT"
  4062. def visit_BIGINT(self, type_, **kw):
  4063. return "BIGINT"
  4064. def visit_TIMESTAMP(self, type_, **kw):
  4065. return "TIMESTAMP"
  4066. def visit_DATETIME(self, type_, **kw):
  4067. return "DATETIME"
  4068. def visit_DATE(self, type_, **kw):
  4069. return "DATE"
  4070. def visit_TIME(self, type_, **kw):
  4071. return "TIME"
  4072. def visit_CLOB(self, type_, **kw):
  4073. return "CLOB"
  4074. def visit_NCLOB(self, type_, **kw):
  4075. return "NCLOB"
  4076. def _render_string_type(self, type_, name):
  4077. text = name
  4078. if type_.length:
  4079. text += "(%d)" % type_.length
  4080. if type_.collation:
  4081. text += ' COLLATE "%s"' % type_.collation
  4082. return text
  4083. def visit_CHAR(self, type_, **kw):
  4084. return self._render_string_type(type_, "CHAR")
  4085. def visit_NCHAR(self, type_, **kw):
  4086. return self._render_string_type(type_, "NCHAR")
  4087. def visit_VARCHAR(self, type_, **kw):
  4088. return self._render_string_type(type_, "VARCHAR")
  4089. def visit_NVARCHAR(self, type_, **kw):
  4090. return self._render_string_type(type_, "NVARCHAR")
  4091. def visit_TEXT(self, type_, **kw):
  4092. return self._render_string_type(type_, "TEXT")
  4093. def visit_BLOB(self, type_, **kw):
  4094. return "BLOB"
  4095. def visit_BINARY(self, type_, **kw):
  4096. return "BINARY" + (type_.length and "(%d)" % type_.length or "")
  4097. def visit_VARBINARY(self, type_, **kw):
  4098. return "VARBINARY" + (type_.length and "(%d)" % type_.length or "")
  4099. def visit_BOOLEAN(self, type_, **kw):
  4100. return "BOOLEAN"
  4101. def visit_large_binary(self, type_, **kw):
  4102. return self.visit_BLOB(type_, **kw)
  4103. def visit_boolean(self, type_, **kw):
  4104. return self.visit_BOOLEAN(type_, **kw)
  4105. def visit_time(self, type_, **kw):
  4106. return self.visit_TIME(type_, **kw)
  4107. def visit_datetime(self, type_, **kw):
  4108. return self.visit_DATETIME(type_, **kw)
  4109. def visit_date(self, type_, **kw):
  4110. return self.visit_DATE(type_, **kw)
  4111. def visit_big_integer(self, type_, **kw):
  4112. return self.visit_BIGINT(type_, **kw)
  4113. def visit_small_integer(self, type_, **kw):
  4114. return self.visit_SMALLINT(type_, **kw)
  4115. def visit_integer(self, type_, **kw):
  4116. return self.visit_INTEGER(type_, **kw)
  4117. def visit_real(self, type_, **kw):
  4118. return self.visit_REAL(type_, **kw)
  4119. def visit_float(self, type_, **kw):
  4120. return self.visit_FLOAT(type_, **kw)
  4121. def visit_numeric(self, type_, **kw):
  4122. return self.visit_NUMERIC(type_, **kw)
  4123. def visit_string(self, type_, **kw):
  4124. return self.visit_VARCHAR(type_, **kw)
  4125. def visit_unicode(self, type_, **kw):
  4126. return self.visit_VARCHAR(type_, **kw)
  4127. def visit_text(self, type_, **kw):
  4128. return self.visit_TEXT(type_, **kw)
  4129. def visit_unicode_text(self, type_, **kw):
  4130. return self.visit_TEXT(type_, **kw)
  4131. def visit_enum(self, type_, **kw):
  4132. return self.visit_VARCHAR(type_, **kw)
  4133. def visit_null(self, type_, **kw):
  4134. raise exc.CompileError(
  4135. "Can't generate DDL for %r; "
  4136. "did you forget to specify a "
  4137. "type on this Column?" % type_
  4138. )
  4139. def visit_type_decorator(self, type_, **kw):
  4140. return self.process(type_.type_engine(self.dialect), **kw)
  4141. def visit_user_defined(self, type_, **kw):
  4142. return type_.get_col_spec(**kw)
  4143. class StrSQLTypeCompiler(GenericTypeCompiler):
  4144. def process(self, type_, **kw):
  4145. try:
  4146. _compiler_dispatch = type_._compiler_dispatch
  4147. except AttributeError:
  4148. return self._visit_unknown(type_, **kw)
  4149. else:
  4150. return _compiler_dispatch(self, **kw)
  4151. def __getattr__(self, key):
  4152. if key.startswith("visit_"):
  4153. return self._visit_unknown
  4154. else:
  4155. raise AttributeError(key)
  4156. def _visit_unknown(self, type_, **kw):
  4157. if type_.__class__.__name__ == type_.__class__.__name__.upper():
  4158. return type_.__class__.__name__
  4159. else:
  4160. return repr(type_)
  4161. def visit_null(self, type_, **kw):
  4162. return "NULL"
  4163. def visit_user_defined(self, type_, **kw):
  4164. try:
  4165. get_col_spec = type_.get_col_spec
  4166. except AttributeError:
  4167. return repr(type_)
  4168. else:
  4169. return get_col_spec(**kw)
  4170. class IdentifierPreparer(object):
  4171. """Handle quoting and case-folding of identifiers based on options."""
  4172. reserved_words = RESERVED_WORDS
  4173. legal_characters = LEGAL_CHARACTERS
  4174. illegal_initial_characters = ILLEGAL_INITIAL_CHARACTERS
  4175. schema_for_object = operator.attrgetter("schema")
  4176. """Return the .schema attribute for an object.
  4177. For the default IdentifierPreparer, the schema for an object is always
  4178. the value of the ".schema" attribute. if the preparer is replaced
  4179. with one that has a non-empty schema_translate_map, the value of the
  4180. ".schema" attribute is rendered a symbol that will be converted to a
  4181. real schema name from the mapping post-compile.
  4182. """
  4183. def __init__(
  4184. self,
  4185. dialect,
  4186. initial_quote='"',
  4187. final_quote=None,
  4188. escape_quote='"',
  4189. quote_case_sensitive_collations=True,
  4190. omit_schema=False,
  4191. ):
  4192. """Construct a new ``IdentifierPreparer`` object.
  4193. initial_quote
  4194. Character that begins a delimited identifier.
  4195. final_quote
  4196. Character that ends a delimited identifier. Defaults to
  4197. `initial_quote`.
  4198. omit_schema
  4199. Prevent prepending schema name. Useful for databases that do
  4200. not support schemae.
  4201. """
  4202. self.dialect = dialect
  4203. self.initial_quote = initial_quote
  4204. self.final_quote = final_quote or self.initial_quote
  4205. self.escape_quote = escape_quote
  4206. self.escape_to_quote = self.escape_quote * 2
  4207. self.omit_schema = omit_schema
  4208. self.quote_case_sensitive_collations = quote_case_sensitive_collations
  4209. self._strings = {}
  4210. self._double_percents = self.dialect.paramstyle in (
  4211. "format",
  4212. "pyformat",
  4213. )
  4214. def _with_schema_translate(self, schema_translate_map):
  4215. prep = self.__class__.__new__(self.__class__)
  4216. prep.__dict__.update(self.__dict__)
  4217. def symbol_getter(obj):
  4218. name = obj.schema
  4219. if name in schema_translate_map and obj._use_schema_map:
  4220. if name is not None and ("[" in name or "]" in name):
  4221. raise exc.CompileError(
  4222. "Square bracket characters ([]) not supported "
  4223. "in schema translate name '%s'" % name
  4224. )
  4225. return quoted_name(
  4226. "__[SCHEMA_%s]" % (name or "_none"), quote=False
  4227. )
  4228. else:
  4229. return obj.schema
  4230. prep.schema_for_object = symbol_getter
  4231. return prep
  4232. def _render_schema_translates(self, statement, schema_translate_map):
  4233. d = schema_translate_map
  4234. if None in d:
  4235. d["_none"] = d[None]
  4236. def replace(m):
  4237. name = m.group(2)
  4238. effective_schema = d[name]
  4239. if not effective_schema:
  4240. effective_schema = self.dialect.default_schema_name
  4241. if not effective_schema:
  4242. # TODO: no coverage here
  4243. raise exc.CompileError(
  4244. "Dialect has no default schema name; can't "
  4245. "use None as dynamic schema target."
  4246. )
  4247. return self.quote_schema(effective_schema)
  4248. return re.sub(r"(__\[SCHEMA_([^\]]+)\])", replace, statement)
  4249. def _escape_identifier(self, value):
  4250. """Escape an identifier.
  4251. Subclasses should override this to provide database-dependent
  4252. escaping behavior.
  4253. """
  4254. value = value.replace(self.escape_quote, self.escape_to_quote)
  4255. if self._double_percents:
  4256. value = value.replace("%", "%%")
  4257. return value
  4258. def _unescape_identifier(self, value):
  4259. """Canonicalize an escaped identifier.
  4260. Subclasses should override this to provide database-dependent
  4261. unescaping behavior that reverses _escape_identifier.
  4262. """
  4263. return value.replace(self.escape_to_quote, self.escape_quote)
  4264. def validate_sql_phrase(self, element, reg):
  4265. """keyword sequence filter.
  4266. a filter for elements that are intended to represent keyword sequences,
  4267. such as "INITIALLY", "INITIALLY DEFERRED", etc. no special characters
  4268. should be present.
  4269. .. versionadded:: 1.3
  4270. """
  4271. if element is not None and not reg.match(element):
  4272. raise exc.CompileError(
  4273. "Unexpected SQL phrase: %r (matching against %r)"
  4274. % (element, reg.pattern)
  4275. )
  4276. return element
  4277. def quote_identifier(self, value):
  4278. """Quote an identifier.
  4279. Subclasses should override this to provide database-dependent
  4280. quoting behavior.
  4281. """
  4282. return (
  4283. self.initial_quote
  4284. + self._escape_identifier(value)
  4285. + self.final_quote
  4286. )
  4287. def _requires_quotes(self, value):
  4288. """Return True if the given identifier requires quoting."""
  4289. lc_value = value.lower()
  4290. return (
  4291. lc_value in self.reserved_words
  4292. or value[0] in self.illegal_initial_characters
  4293. or not self.legal_characters.match(util.text_type(value))
  4294. or (lc_value != value)
  4295. )
  4296. def _requires_quotes_illegal_chars(self, value):
  4297. """Return True if the given identifier requires quoting, but
  4298. not taking case convention into account."""
  4299. return not self.legal_characters.match(util.text_type(value))
  4300. def quote_schema(self, schema, force=None):
  4301. """Conditionally quote a schema name.
  4302. The name is quoted if it is a reserved word, contains quote-necessary
  4303. characters, or is an instance of :class:`.quoted_name` which includes
  4304. ``quote`` set to ``True``.
  4305. Subclasses can override this to provide database-dependent
  4306. quoting behavior for schema names.
  4307. :param schema: string schema name
  4308. :param force: unused
  4309. .. deprecated:: 0.9
  4310. The :paramref:`.IdentifierPreparer.quote_schema.force`
  4311. parameter is deprecated and will be removed in a future
  4312. release. This flag has no effect on the behavior of the
  4313. :meth:`.IdentifierPreparer.quote` method; please refer to
  4314. :class:`.quoted_name`.
  4315. """
  4316. if force is not None:
  4317. # not using the util.deprecated_params() decorator in this
  4318. # case because of the additional function call overhead on this
  4319. # very performance-critical spot.
  4320. util.warn_deprecated(
  4321. "The IdentifierPreparer.quote_schema.force parameter is "
  4322. "deprecated and will be removed in a future release. This "
  4323. "flag has no effect on the behavior of the "
  4324. "IdentifierPreparer.quote method; please refer to "
  4325. "quoted_name().",
  4326. # deprecated 0.9. warning from 1.3
  4327. version="0.9",
  4328. )
  4329. return self.quote(schema)
  4330. def quote(self, ident, force=None):
  4331. """Conditionally quote an identifier.
  4332. The identifier is quoted if it is a reserved word, contains
  4333. quote-necessary characters, or is an instance of
  4334. :class:`.quoted_name` which includes ``quote`` set to ``True``.
  4335. Subclasses can override this to provide database-dependent
  4336. quoting behavior for identifier names.
  4337. :param ident: string identifier
  4338. :param force: unused
  4339. .. deprecated:: 0.9
  4340. The :paramref:`.IdentifierPreparer.quote.force`
  4341. parameter is deprecated and will be removed in a future
  4342. release. This flag has no effect on the behavior of the
  4343. :meth:`.IdentifierPreparer.quote` method; please refer to
  4344. :class:`.quoted_name`.
  4345. """
  4346. if force is not None:
  4347. # not using the util.deprecated_params() decorator in this
  4348. # case because of the additional function call overhead on this
  4349. # very performance-critical spot.
  4350. util.warn_deprecated(
  4351. "The IdentifierPreparer.quote.force parameter is "
  4352. "deprecated and will be removed in a future release. This "
  4353. "flag has no effect on the behavior of the "
  4354. "IdentifierPreparer.quote method; please refer to "
  4355. "quoted_name().",
  4356. # deprecated 0.9. warning from 1.3
  4357. version="0.9",
  4358. )
  4359. force = getattr(ident, "quote", None)
  4360. if force is None:
  4361. if ident in self._strings:
  4362. return self._strings[ident]
  4363. else:
  4364. if self._requires_quotes(ident):
  4365. self._strings[ident] = self.quote_identifier(ident)
  4366. else:
  4367. self._strings[ident] = ident
  4368. return self._strings[ident]
  4369. elif force:
  4370. return self.quote_identifier(ident)
  4371. else:
  4372. return ident
  4373. def format_collation(self, collation_name):
  4374. if self.quote_case_sensitive_collations:
  4375. return self.quote(collation_name)
  4376. else:
  4377. return collation_name
  4378. def format_sequence(self, sequence, use_schema=True):
  4379. name = self.quote(sequence.name)
  4380. effective_schema = self.schema_for_object(sequence)
  4381. if (
  4382. not self.omit_schema
  4383. and use_schema
  4384. and effective_schema is not None
  4385. ):
  4386. name = self.quote_schema(effective_schema) + "." + name
  4387. return name
  4388. def format_label(self, label, name=None):
  4389. return self.quote(name or label.name)
  4390. def format_alias(self, alias, name=None):
  4391. return self.quote(name or alias.name)
  4392. def format_savepoint(self, savepoint, name=None):
  4393. # Running the savepoint name through quoting is unnecessary
  4394. # for all known dialects. This is here to support potential
  4395. # third party use cases
  4396. ident = name or savepoint.ident
  4397. if self._requires_quotes(ident):
  4398. ident = self.quote_identifier(ident)
  4399. return ident
  4400. @util.preload_module("sqlalchemy.sql.naming")
  4401. def format_constraint(self, constraint, _alembic_quote=True):
  4402. naming = util.preloaded.sql_naming
  4403. if constraint.name is elements._NONE_NAME:
  4404. name = naming._constraint_name_for_table(
  4405. constraint, constraint.table
  4406. )
  4407. if name is None:
  4408. return None
  4409. else:
  4410. name = constraint.name
  4411. if constraint.__visit_name__ == "index":
  4412. return self.truncate_and_render_index_name(
  4413. name, _alembic_quote=_alembic_quote
  4414. )
  4415. else:
  4416. return self.truncate_and_render_constraint_name(
  4417. name, _alembic_quote=_alembic_quote
  4418. )
  4419. def truncate_and_render_index_name(self, name, _alembic_quote=True):
  4420. # calculate these at format time so that ad-hoc changes
  4421. # to dialect.max_identifier_length etc. can be reflected
  4422. # as IdentifierPreparer is long lived
  4423. max_ = (
  4424. self.dialect.max_index_name_length
  4425. or self.dialect.max_identifier_length
  4426. )
  4427. return self._truncate_and_render_maxlen_name(
  4428. name, max_, _alembic_quote
  4429. )
  4430. def truncate_and_render_constraint_name(self, name, _alembic_quote=True):
  4431. # calculate these at format time so that ad-hoc changes
  4432. # to dialect.max_identifier_length etc. can be reflected
  4433. # as IdentifierPreparer is long lived
  4434. max_ = (
  4435. self.dialect.max_constraint_name_length
  4436. or self.dialect.max_identifier_length
  4437. )
  4438. return self._truncate_and_render_maxlen_name(
  4439. name, max_, _alembic_quote
  4440. )
  4441. def _truncate_and_render_maxlen_name(self, name, max_, _alembic_quote):
  4442. if isinstance(name, elements._truncated_label):
  4443. if len(name) > max_:
  4444. name = name[0 : max_ - 8] + "_" + util.md5_hex(name)[-4:]
  4445. else:
  4446. self.dialect.validate_identifier(name)
  4447. if not _alembic_quote:
  4448. return name
  4449. else:
  4450. return self.quote(name)
  4451. def format_index(self, index):
  4452. return self.format_constraint(index)
  4453. def format_table(self, table, use_schema=True, name=None):
  4454. """Prepare a quoted table and schema name."""
  4455. if name is None:
  4456. name = table.name
  4457. result = self.quote(name)
  4458. effective_schema = self.schema_for_object(table)
  4459. if not self.omit_schema and use_schema and effective_schema:
  4460. result = self.quote_schema(effective_schema) + "." + result
  4461. return result
  4462. def format_schema(self, name):
  4463. """Prepare a quoted schema name."""
  4464. return self.quote(name)
  4465. def format_label_name(
  4466. self,
  4467. name,
  4468. anon_map=None,
  4469. ):
  4470. """Prepare a quoted column name."""
  4471. if anon_map is not None and isinstance(
  4472. name, elements._truncated_label
  4473. ):
  4474. name = name.apply_map(anon_map)
  4475. return self.quote(name)
  4476. def format_column(
  4477. self,
  4478. column,
  4479. use_table=False,
  4480. name=None,
  4481. table_name=None,
  4482. use_schema=False,
  4483. anon_map=None,
  4484. ):
  4485. """Prepare a quoted column name."""
  4486. if name is None:
  4487. name = column.name
  4488. if anon_map is not None and isinstance(
  4489. name, elements._truncated_label
  4490. ):
  4491. name = name.apply_map(anon_map)
  4492. if not getattr(column, "is_literal", False):
  4493. if use_table:
  4494. return (
  4495. self.format_table(
  4496. column.table, use_schema=use_schema, name=table_name
  4497. )
  4498. + "."
  4499. + self.quote(name)
  4500. )
  4501. else:
  4502. return self.quote(name)
  4503. else:
  4504. # literal textual elements get stuck into ColumnClause a lot,
  4505. # which shouldn't get quoted
  4506. if use_table:
  4507. return (
  4508. self.format_table(
  4509. column.table, use_schema=use_schema, name=table_name
  4510. )
  4511. + "."
  4512. + name
  4513. )
  4514. else:
  4515. return name
  4516. def format_table_seq(self, table, use_schema=True):
  4517. """Format table name and schema as a tuple."""
  4518. # Dialects with more levels in their fully qualified references
  4519. # ('database', 'owner', etc.) could override this and return
  4520. # a longer sequence.
  4521. effective_schema = self.schema_for_object(table)
  4522. if not self.omit_schema and use_schema and effective_schema:
  4523. return (
  4524. self.quote_schema(effective_schema),
  4525. self.format_table(table, use_schema=False),
  4526. )
  4527. else:
  4528. return (self.format_table(table, use_schema=False),)
  4529. @util.memoized_property
  4530. def _r_identifiers(self):
  4531. initial, final, escaped_final = [
  4532. re.escape(s)
  4533. for s in (
  4534. self.initial_quote,
  4535. self.final_quote,
  4536. self._escape_identifier(self.final_quote),
  4537. )
  4538. ]
  4539. r = re.compile(
  4540. r"(?:"
  4541. r"(?:%(initial)s((?:%(escaped)s|[^%(final)s])+)%(final)s"
  4542. r"|([^\.]+))(?=\.|$))+"
  4543. % {"initial": initial, "final": final, "escaped": escaped_final}
  4544. )
  4545. return r
  4546. def unformat_identifiers(self, identifiers):
  4547. """Unpack 'schema.table.column'-like strings into components."""
  4548. r = self._r_identifiers
  4549. return [
  4550. self._unescape_identifier(i)
  4551. for i in [a or b for a, b in r.findall(identifiers)]
  4552. ]