PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i WWWWWW
Current Directory: /usr/include/mysql/server/private
Viewing File: /usr/include/mysql/server/private/sp_pcontext.h
/* -*- C++ -*- */ /* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2009, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ #ifndef _SP_PCONTEXT_H_ #define _SP_PCONTEXT_H_ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #include "sql_string.h" // LEX_STRING #include "field.h" // Create_field #include "sql_array.h" // Dynamic_array /// This class represents a stored program variable or a parameter /// (also referenced as 'SP-variable'). class sp_variable : public Sql_alloc { public: enum enum_mode { MODE_IN, MODE_OUT, MODE_INOUT }; /// Name of the SP-variable. LEX_CSTRING name; /// Mode of the SP-variable. enum_mode mode; /// The index to the variable's value in the runtime frame. /// /// It is calculated during parsing and used when creating sp_instr_set /// instructions and Item_splocal items. I.e. values are set/referred by /// array indexing in runtime. uint offset; /// Default value of the SP-variable (if any). Item *default_value; /// Full type information (field meta-data) of the SP-variable. Spvar_definition field_def; /// Field-type of the SP-variable. const Type_handler *type_handler() const { return field_def.type_handler(); } public: sp_variable(const LEX_CSTRING *name_arg, uint offset_arg) :Sql_alloc(), name(*name_arg), mode(MODE_IN), offset(offset_arg), default_value(NULL) { } /* Find a ROW field by its qualified name. @param var_name - the name of the variable @param field_name - the name of the variable field @param[OUT] row_field_offset - the index of the field @retval NULL if the variable with the given name was not found, or it is not a row variable, or it does not have a field with the given name, or a non-null pointer otherwise. row_field_offset[0] is set only when the method returns !NULL. */ const Spvar_definition *find_row_field(const LEX_CSTRING *var_name, const LEX_CSTRING *field_name, uint *row_field_offset); }; /////////////////////////////////////////////////////////////////////////// /// This class represents an SQL/PSM label. Can refer to the identifier /// used with the "label_name:" construct which may precede some SQL/PSM /// statements, or to an implicit implementation-dependent identifier which /// the parser inserts before a high-level flow control statement such as /// IF/WHILE/REPEAT/LOOP, when such statement is rewritten into a /// combination of low-level jump/jump_if instructions and labels. class sp_label : public Sql_alloc { public: enum enum_type { /// Implicit label generated by parser. IMPLICIT, /// Label at BEGIN. BEGIN, /// Label at iteration control ITERATION, /// Label for jump GOTO }; /// Name of the label. LEX_CSTRING name; /// Instruction pointer of the label. uint ip; /// Type of the label. enum_type type; /// Scope of the label. class sp_pcontext *ctx; public: sp_label(const LEX_CSTRING *_name, uint _ip, enum_type _type, sp_pcontext *_ctx) :Sql_alloc(), name(*_name), ip(_ip), type(_type), ctx(_ctx) { } }; /////////////////////////////////////////////////////////////////////////// /// This class represents condition-value term in DECLARE CONDITION or /// DECLARE HANDLER statements. sp_condition_value has little to do with /// SQL-conditions. /// /// In some sense, this class is a union -- a set of filled attributes /// depends on the sp_condition_value::type value. class sp_condition_value : public Sql_alloc, public Sql_state_errno { bool m_is_user_defined; public: enum enum_type { ERROR_CODE, SQLSTATE, WARNING, NOT_FOUND, EXCEPTION }; /// Type of the condition value. enum_type type; public: sp_condition_value(uint _mysqlerr) :Sql_alloc(), Sql_state_errno(_mysqlerr), m_is_user_defined(false), type(ERROR_CODE) { } sp_condition_value(uint _mysqlerr, const char *_sql_state) :Sql_alloc(), Sql_state_errno(_mysqlerr, _sql_state), m_is_user_defined(false), type(ERROR_CODE) { } sp_condition_value(const char *_sql_state, bool is_user_defined= false) :Sql_alloc(), Sql_state_errno(0, _sql_state), m_is_user_defined(is_user_defined), type(SQLSTATE) { } sp_condition_value(enum_type _type) :Sql_alloc(), m_is_user_defined(false), type(_type) { DBUG_ASSERT(type != ERROR_CODE && type != SQLSTATE); } /// Check if two instances of sp_condition_value are equal or not. /// /// @param cv another instance of sp_condition_value to check. /// /// @return true if the instances are equal, false otherwise. bool equals(const sp_condition_value *cv) const; /** Checks if this condition is OK for search. See also sp_context::find_handler(). @param identity - The condition identity @param found_cv - A previously found matching condition or NULL. @return true - If the current value matches identity and makes a stronger match than the previously found condition found_cv. @return false - If the current value does not match identity, of the current value makes a weaker match than found_cv. */ bool matches(const Sql_condition_identity &identity, const sp_condition_value *found_cv) const; Sql_user_condition_identity get_user_condition_identity() const { return Sql_user_condition_identity(m_is_user_defined ? this : NULL); } }; class sp_condition_value_user_defined: public sp_condition_value { public: sp_condition_value_user_defined() :sp_condition_value("45000", true) { } }; /////////////////////////////////////////////////////////////////////////// /// This class represents 'DECLARE CONDITION' statement. /// sp_condition has little to do with SQL-conditions. class sp_condition : public Sql_alloc { public: /// Name of the condition. LEX_CSTRING name; /// Value of the condition. sp_condition_value *value; public: sp_condition(const LEX_CSTRING *name_arg, sp_condition_value *value_arg) :Sql_alloc(), name(*name_arg), value(value_arg) { } sp_condition(const char *name_arg, size_t name_length_arg, sp_condition_value *value_arg) :value(value_arg) { name.str= name_arg; name.length= name_length_arg; } bool eq_name(const LEX_CSTRING *str) const { return system_charset_info->strnncoll(name.str, name.length, str->str, str->length) == 0; } }; /////////////////////////////////////////////////////////////////////////// /** class sp_pcursor. Stores information about a cursor: - Cursor's name in LEX_STRING. - Cursor's formal parameter descriptions. Formal parameter descriptions reside in a separate context block, pointed by the "m_param_context" member. m_param_context can be NULL. This means a cursor with no parameters. Otherwise, the number of variables in m_param_context means the number of cursor's formal parameters. Note, m_param_context can be not NULL, but have no variables. This is also means a cursor with no parameters (similar to NULL). */ class sp_pcursor: public LEX_CSTRING { class sp_pcontext *m_param_context; // Formal parameters class sp_lex_cursor *m_lex; // The cursor statement LEX public: sp_pcursor(const LEX_CSTRING *name, class sp_pcontext *param_ctx, class sp_lex_cursor *lex) :LEX_CSTRING(*name), m_param_context(param_ctx), m_lex(lex) { } class sp_pcontext *param_context() const { return m_param_context; } class sp_lex_cursor *lex() const { return m_lex; } bool check_param_count_with_error(uint param_count) const; }; /////////////////////////////////////////////////////////////////////////// /// This class represents 'DECLARE HANDLER' statement. class sp_handler : public Sql_alloc { public: /// Enumeration of possible handler types. /// Note: UNDO handlers are not (and have never been) supported. enum enum_type { EXIT, CONTINUE }; /// Handler type. enum_type type; /// Conditions caught by this handler. List<sp_condition_value> condition_values; public: /// The constructor. /// /// @param _type SQL-handler type. sp_handler(enum_type _type) :Sql_alloc(), type(_type) { } }; /////////////////////////////////////////////////////////////////////////// /// The class represents parse-time context, which keeps track of declared /// variables/parameters, conditions, handlers, cursors and labels. /// /// sp_pcontext objects are organized in a tree according to the following /// rules: /// - one sp_pcontext object corresponds for for each BEGIN..END block; /// - one sp_pcontext object corresponds for each exception handler; /// - one additional sp_pcontext object is created to contain /// Stored Program parameters. /// /// sp_pcontext objects are used both at parse-time and at runtime. /// /// During the parsing stage sp_pcontext objects are used: /// - to look up defined names (e.g. declared variables and visible /// labels); /// - to check for duplicates; /// - for error checking; /// - to calculate offsets to be used at runtime. /// /// During the runtime phase, a tree of sp_pcontext objects is used: /// - for error checking (e.g. to check correct number of parameters); /// - to resolve SQL-handlers. class sp_pcontext : public Sql_alloc { public: enum enum_scope { /// REGULAR_SCOPE designates regular BEGIN ... END blocks. REGULAR_SCOPE, /// HANDLER_SCOPE designates SQL-handler blocks. HANDLER_SCOPE }; class Lex_for_loop: public Lex_for_loop_st { public: /* The label poiting to the body start, either explicit or automatically generated. Used during generation of "ITERATE loop_label" to check if "loop_label" is a FOR loop label. - In case of a FOR loop, some additional code (cursor fetch or iteger increment) is generated before the backward jump to the beginning of the loop body. - In case of other loop types (WHILE, REPEAT) only the jump is generated. */ const sp_label *m_start_label; Lex_for_loop() :m_start_label(NULL) { Lex_for_loop_st::init(); } Lex_for_loop(const Lex_for_loop_st &for_loop, const sp_label *start) :m_start_label(start) { Lex_for_loop_st::operator=(for_loop); } }; public: sp_pcontext(); ~sp_pcontext(); /// Create and push a new context in the tree. /// @param thd thread context. /// @param scope scope of the new parsing context. /// @return the node created. sp_pcontext *push_context(THD *thd, enum_scope scope); /// Pop a node from the parsing context tree. /// @return the parent node. sp_pcontext *pop_context(); sp_pcontext *parent_context() const { return m_parent; } sp_pcontext *child_context(uint i) const { return i < m_children.elements() ? m_children.at(i) : NULL; } /// Calculate and return the number of handlers to pop between the given /// context and this one. /// /// @param ctx the other parsing context. /// @param exclusive specifies if the last scope should be excluded. /// /// @return the number of handlers to pop between the given context and /// this one. If 'exclusive' is true, don't count the last scope we are /// leaving; this is used for LEAVE where we will jump to the hpop /// instructions. uint diff_handlers(const sp_pcontext *ctx, bool exclusive) const; /// Calculate and return the number of cursors to pop between the given /// context and this one. /// /// @param ctx the other parsing context. /// @param exclusive specifies if the last scope should be excluded. /// /// @return the number of cursors to pop between the given context and /// this one. If 'exclusive' is true, don't count the last scope we are /// leaving; this is used for LEAVE where we will jump to the cpop /// instructions. uint diff_cursors(const sp_pcontext *ctx, bool exclusive) const; ///////////////////////////////////////////////////////////////////////// // SP-variables (parameters and variables). ///////////////////////////////////////////////////////////////////////// /// @return the maximum number of variables used in this and all child /// contexts. For the root parsing context, this gives us the number of /// slots needed for variables during the runtime phase. uint max_var_index() const { return m_max_var_index; } /// @return the current number of variables used in the parent contexts /// (from the root), including this context. uint current_var_count() const { return m_var_offset + (uint)m_vars.elements(); } /// @return the number of variables in this context alone. uint context_var_count() const { return (uint)m_vars.elements(); } /// return the i-th variable on the current context sp_variable *get_context_variable(uint i) const { DBUG_ASSERT(i < m_vars.elements()); return m_vars.at(i); } /* Return the i-th last context variable. If i is 0, then return the very last variable in m_vars. */ sp_variable *get_last_context_variable(uint i= 0) const { DBUG_ASSERT(i < m_vars.elements()); return m_vars.at(m_vars.elements() - i - 1); } /// Add SP-variable to the parsing context. /// /// @param thd Thread context. /// @param name Name of the SP-variable. /// /// @return instance of newly added SP-variable. sp_variable *add_variable(THD *thd, const LEX_CSTRING *name); /// Retrieve full type information about SP-variables in this parsing /// context and its children. /// /// @param field_def_lst[out] Container to store type information. void retrieve_field_definitions(List<Spvar_definition> *field_def_lst) const; /// Find SP-variable by name. /// /// The function does a linear search (from newer to older variables, /// in case we have shadowed names). /// /// The function is called only at parsing time. /// /// @param name Variable name. /// @param current_scope_only A flag if we search only in current scope. /// /// @return instance of found SP-variable, or NULL if not found. sp_variable *find_variable(const LEX_CSTRING *name, bool current_scope_only) const; /// Find SP-variable by the offset in the root parsing context. /// /// The function is used for two things: /// - When evaluating parameters at the beginning, and setting out parameters /// at the end, of invocation. (Top frame only, so no recursion then.) /// - For printing of sp_instr_set. (Debug mode only.) /// /// @param offset Variable offset in the root parsing context. /// /// @return instance of found SP-variable, or NULL if not found. sp_variable *find_variable(uint offset) const; /// Set the current scope boundary (for default values). /// /// @param n The number of variables to skip. void declare_var_boundary(uint n) { m_pboundary= n; } ///////////////////////////////////////////////////////////////////////// // CASE expressions. ///////////////////////////////////////////////////////////////////////// int register_case_expr() { return m_num_case_exprs++; } int get_num_case_exprs() const { return m_num_case_exprs; } bool push_case_expr_id(int case_expr_id) { return m_case_expr_ids.append(case_expr_id); } void pop_case_expr_id() { m_case_expr_ids.pop(); } int get_current_case_expr_id() const { return *m_case_expr_ids.back(); } ///////////////////////////////////////////////////////////////////////// // Labels. ///////////////////////////////////////////////////////////////////////// sp_label *push_label(THD *thd, const LEX_CSTRING *name, uint ip, sp_label::enum_type type, List<sp_label> * list); sp_label *push_label(THD *thd, const LEX_CSTRING *name, uint ip, sp_label::enum_type type) { return push_label(thd, name, ip, type, &m_labels); } sp_label *push_goto_label(THD *thd, const LEX_CSTRING *name, uint ip, sp_label::enum_type type) { return push_label(thd, name, ip, type, &m_goto_labels); } sp_label *push_label(THD *thd, const LEX_CSTRING *name, uint ip) { return push_label(thd, name, ip, sp_label::IMPLICIT); } sp_label *push_goto_label(THD *thd, const LEX_CSTRING *name, uint ip) { return push_goto_label(thd, name, ip, sp_label::GOTO); } sp_label *find_label(const LEX_CSTRING *name); sp_label *find_goto_label(const LEX_CSTRING *name, bool recusive); sp_label *find_goto_label(const LEX_CSTRING *name) { return find_goto_label(name, true); } sp_label *find_label_current_loop_start(); sp_label *last_label() { sp_label *label= m_labels.head(); if (!label && m_parent) label= m_parent->last_label(); return label; } sp_label *last_goto_label() { return m_goto_labels.head(); } sp_label *pop_label() { return m_labels.pop(); } bool block_label_declare(LEX_CSTRING *label) { sp_label *lab= find_label(label); if (lab) { my_error(ER_SP_LABEL_REDEFINE, MYF(0), label->str); return true; } return false; } ///////////////////////////////////////////////////////////////////////// // Conditions. ///////////////////////////////////////////////////////////////////////// bool add_condition(THD *thd, const LEX_CSTRING *name, sp_condition_value *value); /// See comment for find_variable() above. sp_condition_value *find_condition(const LEX_CSTRING *name, bool current_scope_only) const; sp_condition_value * find_declared_or_predefined_condition(THD *thd, const LEX_CSTRING *name) const; bool declare_condition(THD *thd, const LEX_CSTRING *name, sp_condition_value *val) { if (find_condition(name, true)) { my_error(ER_SP_DUP_COND, MYF(0), name->str); return true; } return add_condition(thd, name, val); } ///////////////////////////////////////////////////////////////////////// // Handlers. ///////////////////////////////////////////////////////////////////////// sp_handler *add_handler(THD* thd, sp_handler::enum_type type); /// This is an auxilary parsing-time function to check if an SQL-handler /// exists in the current parsing context (current scope) for the given /// SQL-condition. This function is used to check for duplicates during /// the parsing phase. /// /// This function can not be used during the runtime phase to check /// SQL-handler existence because it searches for the SQL-handler in the /// current scope only (during runtime, current and parent scopes /// should be checked according to the SQL-handler resolution rules). /// /// @param condition_value the handler condition value /// (not SQL-condition!). /// /// @retval true if such SQL-handler exists. /// @retval false otherwise. bool check_duplicate_handler(const sp_condition_value *cond_value) const; /// Find an SQL handler for the given SQL condition according to the /// SQL-handler resolution rules. This function is used at runtime. /// /// @param value The error code and the SQL state /// @param level The SQL condition level /// /// @return a pointer to the found SQL-handler or NULL. sp_handler *find_handler(const Sql_condition_identity &identity) const; ///////////////////////////////////////////////////////////////////////// // Cursors. ///////////////////////////////////////////////////////////////////////// bool add_cursor(const LEX_CSTRING *name, sp_pcontext *param_ctx, class sp_lex_cursor *lex); /// See comment for find_variable() above. const sp_pcursor *find_cursor(const LEX_CSTRING *name, uint *poff, bool current_scope_only) const; const sp_pcursor *find_cursor_with_error(const LEX_CSTRING *name, uint *poff, bool current_scope_only) const { const sp_pcursor *pcursor= find_cursor(name, poff, current_scope_only); if (!pcursor) { my_error(ER_SP_CURSOR_MISMATCH, MYF(0), name->str); return NULL; } return pcursor; } /// Find cursor by offset (for SHOW {PROCEDURE|FUNCTION} CODE only). const sp_pcursor *find_cursor(uint offset) const; const sp_pcursor *get_cursor_by_local_frame_offset(uint offset) const { return &m_cursors.at(offset); } uint cursor_offset() const { return m_cursor_offset; } uint frame_cursor_count() const { return (uint)m_cursors.elements(); } uint max_cursor_index() const { return m_max_cursor_index + (uint)m_cursors.elements(); } uint current_cursor_count() const { return m_cursor_offset + (uint)m_cursors.elements(); } void set_for_loop(const Lex_for_loop_st &for_loop) { m_for_loop= Lex_for_loop(for_loop, last_label()); } const Lex_for_loop &for_loop() { return m_for_loop; } private: /// Constructor for a tree node. /// @param prev the parent parsing context /// @param scope scope of this parsing context sp_pcontext(sp_pcontext *prev, enum_scope scope); void init(uint var_offset, uint cursor_offset, int num_case_expressions); /* Prevent use of these */ sp_pcontext(const sp_pcontext &); void operator=(sp_pcontext &); sp_condition_value *find_predefined_condition(const LEX_CSTRING *name) const; private: /// m_max_var_index -- number of variables (including all types of arguments) /// in this context including all children contexts. /// /// m_max_var_index >= m_vars.elements(). /// /// m_max_var_index of the root parsing context contains number of all /// variables (including arguments) in all enclosed contexts. uint m_max_var_index; /// The maximum sub context's framesizes. uint m_max_cursor_index; /// Parent context. sp_pcontext *m_parent; /// An index of the first SP-variable in this parsing context. The index /// belongs to a runtime table of SP-variables. /// /// Note: /// - m_var_offset is 0 for root parsing context; /// - m_var_offset is different for all nested parsing contexts. uint m_var_offset; /// Cursor offset for this context. uint m_cursor_offset; /// Boundary for finding variables in this context. This is the number of /// variables currently "invisible" to default clauses. This is normally 0, /// but will be larger during parsing of DECLARE ... DEFAULT, to get the /// scope right for DEFAULT values. uint m_pboundary; int m_num_case_exprs; /// SP parameters/variables. Dynamic_array<sp_variable *> m_vars; /// Stack of CASE expression ids. Dynamic_array<int> m_case_expr_ids; /// Stack of SQL-conditions. Dynamic_array<sp_condition *> m_conditions; /// Stack of cursors. Dynamic_array<sp_pcursor> m_cursors; /// Stack of SQL-handlers. Dynamic_array<sp_handler *> m_handlers; /* In the below example the label <<lab>> has two meanings: - GOTO lab : must go before the beginning of the loop - CONTINUE lab : must go to the beginning of the loop We solve this by storing block labels and goto labels into separate lists. BEGIN <<lab>> FOR i IN a..10 LOOP ... GOTO lab; ... CONTINUE lab; ... END LOOP; END; */ /// List of block labels List<sp_label> m_labels; /// List of goto labels List<sp_label> m_goto_labels; /// Children contexts, used for destruction. Dynamic_array<sp_pcontext *> m_children; /// Scope of this parsing context. enum_scope m_scope; /// FOR LOOP characteristics Lex_for_loop m_for_loop; }; // class sp_pcontext : public Sql_alloc #endif /* _SP_PCONTEXT_H_ */