Mercurial > hg > dotemacs
changeset 198:542bdd6b7739
sql-indent: replace with newer ELPA version
line wrap: on
line diff
--- a/dotemacs.el +++ b/dotemacs.el @@ -426,7 +426,7 @@ ("gnu" . "http://elpa.gnu.org/packages/")))) '(package-selected-packages (quote - (sqlup-mode rjsx-mode mastodon rust-mode systemd fountain-mode markdown-mode magit js2-mode yaml-mode web-mode undo-tree puppet-mode nginx-mode json-mode jade-mode idomenu haml-mode goto-last-change flymake-haml elpy dockerfile-mode))) + (sql-indent sqlup-mode rjsx-mode mastodon rust-mode systemd fountain-mode markdown-mode magit js2-mode yaml-mode web-mode undo-tree puppet-mode nginx-mode json-mode jade-mode idomenu haml-mode goto-last-change flymake-haml elpy dockerfile-mode))) '(safe-local-variable-values (quote ((encoding . utf-8)
index e76e68522f36382fa5897866680fdb5afc73abdb..4d573d0ee2c5ffa9b1270385cafd71fb05b41a52 GIT binary patch literal 2349 zc$|%uc{CJy8^>p}3uDbbmSKz~S+b3?Oh_gn%S^+y&nQNgq1))CNf=~AhAfHfQeqTk zxr$=qig-gJvLq>*E=`tsx%c*-d+s^6bANyR&hMP(JkRHx&-eLV1M5Lfs17<n`2oq4 z71kH34*j4%;Y09X`O6$K{5a<7Fn3-`30LM@OJ7Qi<Fs@^9`l(=&3~@6`h|MZT<q@C zZ4=e*+IQ><NUQV)7D<h3H&o1SEa~Xc9YA;9ZYV8~N9<VvzV8|>hMin*s0hP5d2#X_ zu*N?3`14yhg=PBP*ogH<bzwQ1%Xe(#Vk-QqJq%<g^@m#u+d;E2Y+Ap#-)Ktg>FV0S zk3?XR{eSYr@o!x65Epp2%po^lu_Niuw2Q~km+X{Wo-mTH)DC(#WCiCI6C^Q;@rP`q z(y7xq!xpiW{hVtCBM+-SM$}X8ts_cD<RsHXTNc&AyEiP5xd}MFr%PM@o<P9#^RVVS zm=SCS52`Tdi1wN<IF^cxpu5;^5ZDxPP7og#(?|8PTi!}VvPV5TL;5op0S?>hB9%Gh z&f7kg)-X!_)>>w20bPg=?_kVJm-D(;6|vqeE#71^-Z?O{2pI~=+Z*US)WqRTvVMS= z+0sXqtX^3SSfh9uSEn?3P+=>9*f!as*!N`5%*@_Vg-32Gy%SAtX*YtP4GrMs7oBCG zy=ZHTwR!9<R>Mho<B9Ds1mn?kU%IZO<lUnmDMqh6bYGxrdKN=jG9yo$1kVr8IcQjA za>vKEs;S5gj+VUUJ%=qyC~5Mf@(I6n0rO4vzRE0I$cLo)Dvy_*m~7$2sd0xPC2bA; zQZgr9RsMnzj+k`obiW&0RClt(#hQ<cMHW-z-Xwb{8Q2tcGDVk;9L{yrv0Ge;c_e1e zU(54Wu<hD)%~fn}97~b+^-K>FkyHp&0_W?7eAQ1<CF8U*MF;APwKeFM)&dihrr^pA z-AD99E9=kU1GZxZc-4|0HEL_Zvr&nkD6h)QTL*-6$n?#h4JWi(RH3-HB)OhhL5dsQ z)lyV)I123Vu$Jz9sNdW2RYRS)vA@l9i0x{Pzpd~TvICxW>esaMjusDYM@@BXDJE97 z_I4<pXRg%TxjD3I((2kZ4K1n=oSrZtl>1b)k(-;`x%RxovrW&*GMH!NZ%OCS2IzqX zgu;Q2pb)hYqrTgD&S@#QwjpM{FaSU}LjVGPKTJLQWA3oSPRFfbZXpCx2#El*CIpe9 zVW^<cGk#G!Pgc7ZJpzfW7amDC_-8ffkLr{Jh{R6t5ImsW2!iCnJOTp2zyw|)0e(I( zh*ydqBp@gRkp_W*ASED3CIKKQAZG8(b1}Z{Q$g%q0M{0&oDF)Kmb~$$TT-EK>M&5T zBsTror$9>^zOzNup=&?@qYN<DTU)g7)%ehjYZAW}t7k+O<Chmis8`wXW)RP)dR_o{ zXC464_#ZeB2KxJrwEiUy<9D2c(kc)ZS_i<9iC&Gzj@5skm<NRKAcy>)l4qB47jlOY z^be5fivX@`0IG%jYF_BB?&mir93O{`J=D_*3^tq`$$sMO$o(J>;JQVm5Olk!YxmP7 zToZ0al_rpe7UK>24vHrX4=R}W(7r=n173#UJBWfnVE`+wLX*NadOrcKbnY)8#?d5Q zqY8S265DSy*PgOJ1Cy241E>_kLLI`lgYq8Q_lXf#eVS9N6cG58a)Z6a`uE0<re@|B z-rV#Lh$KhnuPK}pNfs5n7~Q7PGjC&Um3QK2>{-$Z9PbNfVDnjDBhD*sC*cO0p3S8S zz`CfNY&0F^ur#anmcsHE)t@i0%1%bSSsp(VYWC&A13`(Z*FVjnh}#L}cxyHTcjK&8 zp0?aq>3g%j3%(*@C8)>nQQPTnV6})UxyEYUMg&WUzs0!82QEP{s>-ksom7ofzcf1~ zWDK2fZ;B^5OSR3Vy@-pM`OO>pUVrR(MJJt(Qh_p$<0eq1N|*=9C1YtEEk^A9O)34z z%0gt#K(O7wg8Oeqv8#<_9upE<W2o3Lsn_Fcki_$db}#5{znc43uD+|~l#8s4^+}t4 z@nhgH&?^2f*OigESC<w2oo5)0TTZ5pbl>4w6Eu-a?6;nbe`(RHtldz^_Kuwy9r1e! zfC2%)zeVXs3Yz^(1!=%xhy?Ht2fGa2?So&ueqy82QNtT{=h=l>9jjdjqfh_ops>-8 z9Q<BVBqp?N5-6XW^*Fm)m7(P8J?HC)OX@t(P{@Z@gPYDqQ!7WbA!z}*Zob0HVjT0& zhpEURr%YxvR1RK|Wj@h)%BT#@#T-*N<+nuXNZS`(UKDoIyy|in0zD?EW9j9tITY4c zWE3z+3(o1Y@40B;ETr9hdTqMfnA6-Oo}~AS@)J{SoQk4ZxU|=p+BE1>7(~BopI!h( z)`W1z!&+DRWumQoS#GWLX9GXOprDFVcvCeECXJbTZoh|AqWD5hsm*^UBCvt<Oj%b? zkr@~8N<A$<U#BeteSWi-Mw7cW$*1Di4k^0ibYLGwyMtIKF-?&3DJ4ZK?fmX8z$w`v z7pM9|L+@ygKskXR))krcPD<413Ir6ne(C_t8{u)e5#t+`7t3vFYj+Q3s;MWHVhA5J zhW5ew&03Yo4vne6vbtpFTY<w7CHAfv>iKrVm%mAbqRy=})zHO{2#kGFc-#E;XbgXX zq-djL?Bewod&r)F-?-F;y78XC&r;V5A0GXl;1n`MY-htL{$RsIr~Gw+T!;W{LA{=# z^a@~1{Mxz}c$=g(Zc(Ee9-%(FB4c{?ryAK?0B+Q4Y%sl*gSUHVR<Qg&axAjX^>l8P U>p)7ce@%8c8obkf*D=8V0AUsY3jhEB
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a9dbcf591a194cecc43181c62d68f9aaa1c23bcc GIT binary patch literal 2353 zc$|%uc{J4f8^^!1*oCoX8)F}9vSb@&nUG9EmYIfYABvG>=r;P%Bn&blLzYB#DKUz& zTt%UAMf^e{vLq>*E=`vCaqsPS?z!jO&i(xLIiGW$^E|I}Uhn5~4WbJ@p)_a@;{}q* zD}7%m+O&gygbzW3<u7wcs>d-`hdJ{Sa9o*BEo~_=j@{A)eavGjG5@*J@)ycUGm*Pb zw~dv$Yu~XdpskV{SWQY?yMcUmV@XGk&H%dec0*}_EOO5Z=zZ5{G2-NULq!<g(UYBL zk2UhX$D7~6E-cgQ#zw3^ste26T)ty16I0<^?XE99sW;qG*bbhJVNv@<eMeJbPgmCt zehdZ`+5IO^6#vFK4|#!m%M5z+6)TeFM7?+neaRN?{Dhu-rFPJ(AuA}im>`akk3VD+ zl}?$?88(k4?`L1rA9+~yF`}M)Zyi}WA|swA+_I<~-o0V2nVW#)dAhXa=K%typNBQy z!Hi%txKM>TN3_;_Ah8t92%59a27yHuWe4(bFieW4?ebQtCTrBAGo(Lr5wPD@5vt4~ zb>8;2utJdQx7IRK3upo~)eic+WI4B6RZ-u&rNx^p`a63@79m3}d3yt$hnhH?Nz(Hd zF<ttonAIz-hG-Nm<7k&g56W#N1h-AL$TOepnVH!;D)-1$v3H`$HSI<qtf2w2{GziA zycca{zBZ4&)z@%R)@Wio3`u`9%}m!37r%S-BiZnkyUq)AP0wOzpVY|HCjRrobM|VM znVj*lt!j$q23tc`{hs|6Ig~hgQsIQ}I-l7lYhPs+F62Yfe3ko44@|b;;?%hP5L`=5 zuav}2SCYM8hzm}-b-Le`C9E@9;%vpk!D<#$;@%{?!}YC;IvK)CM-JyYXxlEX#5@u) z<E`a-%inhGy80?MH?B{f`}Ir@1DR9^f<y9kLcZ!HDUom*nZg5gMp|mLOKSlM@F`V= zhVCP}!j<*s@c!E|1Ki5Vj~cbqRkKlvpUAJu%vuKov`MthpA9B7T9jb8w?vtqS$?uB z&Ba1kd^if?XTO&2b*SIV;#EVPsF9!bbcoGrjh~I+lxBx&+NodD&O4YtxE(dsu_d2a z+1lFyKhIdHxpQ-9)wtEAYZ_Km!9P7=OepuRXd^W@xpC~cgU>cSCrM$Rk-jCJL+hgl z8jx}aIs!wKM+}*_^PJLBaBV}3dO-jnoFRaK-w#9A?wA|mu;Xznglh<a7(yf<tO$X` zXap)S^o(!R&XeWtMVCM%>4rxV4*ppU{-Zi20V=i=JR}!*H-cbU2p1n;5Ga9LfRC34 z0_K+B1@rL>KqbKt5Eu>uOC<pOd?I#ETo>cpJ{82?1voaE3fbVNX~`R3y2a&~Q-?wF zC9&zxJ_T4<^PDZJ4qXEQ^fF+sx3*~EtI?qw*TjA;R>_Dg#xE}jQLeJ$O`#r9_1pkt zXC8oI^bZ_JeZBpL8vhc9{yWY=NkwQMS{q<XMX$zV$LhaN%mv1GkV5`X$+b(l3%SDx z{s+kPMS$btk7^;knisgM^ZCsQhsR-K4|O#Hf(#}{vY$9Pa6ZTa9M^~xf=(A@?S8tL zOTx{l(gfnrV!S@{plHJIpq#Nc^*dxe7=T;@U54U2g84y$KwnygI+<noegabI)L#%B zM-_L8D(DeNY`@W5d&=$%LRwZAP%K7-+J|ok<~_7yiUhBEH>Xy~A@M8a`g@D@?u{Q! z&CD;nx#{O0Ns7*2lRGDrEX;o~x=pQT-rCAC@5Im8v&0ouypJj!o8R{};=KHJ5^k{R z*<30gqKneWLeo(8OS2kp$$fspdh-RA*~!Q^%j0K4O}|`tz%N$y`lmTm@ODBu-ik%X z-8gHRrzP`M^4_e^f{##G3F@)xsLk{@h;l@gOk=f9BeG9`x5cQ*TUCr;Se0QeJgF3^ za%px-zz8<s))Y^4l4zStdl45i^P3m!z24aIicT60r3hmj$4#J2;Ft%=C1Yu94SMYT zO$oio%0kVWfgsy~1-IV}V^<qVT*gF}+EB4UQm^~hK(Xf$?VhmPzBTu+Tzyx|E*DxE zV@jHQ@ulN1uqxg!*A+B#uP)2`InB@;w;W9xX+FcV#^_*9aKF`L{7ds*1+9icmRIb| z=!ox200sg;e~Z(PG&KE}8d5>SP%+RS9(EbH*#*6L{lr?aqlP=|&a(@%+LpT>MxXxE zLqWqIdHB7gNJL=UI6yWx>v49q5*_a2HRt1iOX@t(P{@N<RyCQ8rc{n-LDT$mU3~<X zMc8Ja4^uRU95WfwFd5Z~EVGHuQ-)<|4(6DO39ki8ThgxR@}i)t`c>z<P}nhkZ3|B~ z^`S6kk)i(}H7JK^*K<+dNkFUl^xAZ{5xcobG)eatg(oIjI7NBWa7oWG<!SJzFsNSF zK3#vZv@zj~yOoaQ%S0R5vfNt9&-%Uwfq@mL@FvP?3@Rh_+<te7MA3zsQtSUtL|_AG znbIyELNm^gm3nG^zIIy%`ut`ul`3;<l1I_E9a?nB@xVTeR!4B1*fc@LyObCW-}&L4 zK~vI!&W`nmhTc&fKr(!ReOIK`JIPU_D^PIc`l$m{FQohBMvPBXUM#1jt=%n%p{$Zr ziXnVZ8`_8HH*HlQ**B(w%IcDxZUqcSl-RjssN~xYU;ZW*iaNK_R6`Rz!Z-Fw?rrni zqcOY*;=+yMv5VJV>>+sseB)3S>c)ElK1*CLe0cPGic?5Xk)16g|AQ?Po$}Wuav=iP zf_Xke=@uXu__cKn$Tm@9+`L99JVIr5MatytPc_oF08Z3vY!I!LjkkShTCn^+ax9YR XayqxlWgw;3uO>Sj4cTeG>lpAq8BhSg
new file mode 100644 index 0000000000000000000000000000000000000000..817c045f61f5c2b43d9e36b9bd10b266a7df1bd7 GIT binary patch literal 49152 zc%1Fp(Qng69KdnAK+>iSVNZTQ5m)sk7S`4-+sk+up?F<H2qCx<eX>GwsVow^*bX93 zs0jWC-uWLU?PY)29(GRcCWds|%fw`TKWdV@^Z9r7-7k@>>$9gFFP35)gwsJRn%XT* z*R}gXXqu+0*N(QdrC!%p>bmyNbnV;ypQ<-MXxo*ZR{NvUt9`iHto~jd?*!F@oz3k} zwfet^0ssJj|E+hujj~a%>+hp@@M0ogc>c)qPowPf+F{>rIks?G4?4EUS}URvcq7s7 zI`)y>7rlP_ajSnK9@!_Nb?iK8chy;s?XF{0gcz$6WOx>Oek>gOxnl`A9e9(pJd0%L zs!$iT*qh2MYI5#bF!6@-%W)2WwGSVOM%wE6qH$n}?=8`^#1EGE(KM5DhJim;$7Au# z>9@N_YPj)O4rA}NbUzFC(Eg=$+;PNy7Wj*v$q@UNSToAZ_g>AUXsp~_dSj+JtdxxA zp8i%%mV6`qVK_gFy}*y$boy4Bw$tftcOTl%#hSh%@K>8fBW*Y3R@vCw)6c(IEZa(# zm0~5gc<aJk&PDf$Bf7_(jwN!7V4nY6E*rbM`n&dGoX9)%2k|VF(XzCe8)exp{%#c2 z%^i8CGRl%d1fh4T=KG?S9L^;}J~dQkgx+)z&c#bPzZ_;Ys+Gnw&E{swINH^<#cD*a zChF<Q9n9ijQFoV@>mDr2TTe?R!>sEs7oD=KcNgoM)ylc0%lAoEEo)I}wMdIMH_Aq< zuAkq@$6QIEeEib-_+Rv|<Of@mkiF|A<L+Jk<YEOcW+0L(ef{C*)f@S>%pYv{gQ>Js z&8+>Vef-)#T<eUtOUAu>x?J4pY@%{z5X;Hjjl)?K%aN<HCAy+{CwJ#pbP^5q?v2dv zu9b|#`c*k~xmE{RDR~OtOfK-gUNUaqPM6}f3?ubzOg}bq7mzlJMpnqakX02$ul=d1 zKL7v#002-x8~Vmp^8Bye`r20l000000RBsr<c;Tl0000001A!$e*gdg004@Q{eJ)e z0001rkLP~?00000ijV*Q2LJ#70HFBT{|5j7005x)*#8Fr0001>_}Kpk00000p!nGT M2LJ#70HFB(0_jh|8vp<R
index 1f010e05dbfab36a59d0267c55eb2fcfedfdaccb..33f8b6457db49eef40cd7050a040f1a392032c0c GIT binary patch literal 1200 qc${NQFGy!*W@Ke#Vql1UE4-NjJ7DC(A%PA?)s3nfRX3`RR_Xv-(FB43
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4.signed @@ -0,0 +1,1 @@ +Good signature from 066DAFCB81E42C40 GNU ELPA Signing Agent (2019) <elpasign@elpa.gnu.org> (trust undefined) created at 2019-09-21T13:58:51-0400 using RSA \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/.elpaignore @@ -0,0 +1,7 @@ +.elpaignore +.gitignore +.travis.yml +test-data +sql-indent-test.el +*~ +*.elc
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/.gitignore @@ -0,0 +1,7 @@ +# -*- mode: conf -*- +sql-indent-autoloads.el +sql-indent-pkg.el +*.elc +*~ +\#*\# +.\#*
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/.travis.yml @@ -0,0 +1,36 @@ +language: emacs-lisp + +# Require sudo because Emacs needs to disable ASLR to dump, only possible on +# sudo-enabled environment. See also +# https://github.com/travis-ci/travis-ci/issues/9061 +# https://github.com/flycheck/emacs-travis/issues/13 + +sudo: required +dist: trusty + +cache: + - directories: + # Cache stable Emacs binaries (saves 1min per job) + - "$HOME/emacs/" + +# Allow Emacs snapshot builds to fail and don’t wait for these as they can +# take a looooong time + +matrix: + fast_finish: true + allow_failures: + - env: EMACS_VERSION=snapshot +env: + - EMACS_VERSION=26.2 +before_install: + # Configure $PATH: Executables are installed to $HOME/bin + - export PATH="$HOME/bin:$PATH" + # Download the makefile to emacs-travis.mk + - wget 'https://raw.githubusercontent.com/alex-hhh/emacs-travis/master/emacs-travis.mk' + # Install Emacs (according to $EMACS_VERSION) + - make -f emacs-travis.mk install_emacs +install: + # Install your dependencies +script: + - emacs -batch -Q --no-site-file -L . -f batch-byte-compile *.el + - emacs -batch -Q --no-site-file -L . -l sql-indent-test.el -f ert-run-tests-batch-and-exit
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/CONTRIBUTING.md @@ -0,0 +1,52 @@ +# If you have a question or found a bug + +To ask a question about the package, please please [create an +issue][gh-issue-link] containing a description of what you are trying to do +and consider providing sample SQL code if appropriate. There is also a +[manual](./sql-indent.org) which provides information about customizing the +indentation rules. + +If you found a bug in the SQL indentation code, or don't know how to configure +the indentation rules to suit your preferences, please [create an +issue][gh-issue-link]. Please provide a sample SQL code snippet that +demonstrates the problem. + +# Submitting code changes + +The preferred way to accept contributions is to submit a pull request using +GitHub. Before doing so, you need to be aware of the copyright assignment +requirements and the automated test-suite. These are detailed in the sections +below. + +## Copyright Assignment + +This package is part of [GNU ELPA][elpa-link] and it is subject to the GNU +[Copyright Assignment][copy-papers-link] policy. Any [legally +significant][legally-link] contributions can only be accepted after the author +has completed their paperwork. Please see [the request form][request-link] if +you want to proceed with the assignment. + +## Automated test suite + +There's an automated test suite which is used to ensure we don't re-introduce +bugs that that were already fixed. If you fix the problem with the +indentation, please provide an automated test for your fixes and add it to the +test suite. The "Commentary" section in the +[sql-indent-test.el](./sql-indent-test.el) file contains a description on how +to add and run tests. + +## Other considerations for the pull request + +In your pull request, please provide a clear description of what the changes +do and add a sample SQL snippet that illustrates the problem being solved. + +Once you submit the pull request, an automated build will start and will run +the unit tests, please verify that the build succeeds and fix any issues if +the build failed. + +[elpa-link]: http://elpa.gnu.org/packages/ +[copy-papers-link]: http://www.gnu.org/prep/maintain/html_node/Copyright-Papers.html +[legally-link]: http://www.gnu.org/prep/maintain/html_node/Legally-Significant.html#Legally-Significant +[request-link]: http://git.savannah.gnu.org/cgit/gnulib.git/tree/doc/Copyright/request-assign.future +[gh-issue-link]: https://github.com/alex-hhh/emacs-sql-indent/issues +
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/ChangeLog @@ -0,0 +1,998 @@ +2019-06-20 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Update version to 1.4 + +2019-06-08 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Recognize left and right outer join statements #85 + + * sql-indent.el (sqlind-find-join-start): new defun to look for join + statements, can find "left outer join" statements as well, see #85 + (sqlind-syntax-in-select, sqlind-refine-syntax): use + `sqlind-find-join-start` + (sqlind-lineup-joins-to-anchor): only look for the first join keyword, + to detect the case where they un on multiple lines + +2019-04-18 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Recognize more types of begin transaction statements (fixes #84) + + "begin" follwed by a semicolon, "begin work" and "begin transaction" are + considered statements and not block start delimters. + +2019-03-31 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Don't recognize select keywords in comments, fixes #83 + + when searching for select keywords for anchors, don't stop inside + comments -- this just uses `sqlind-search-backward`, which makes sure + that the position that is found is at the same level as the starting + position. + + Also fixed a bug in `sqlind-same-level-statement` which missed that the + anchor was inside a comment. + +2019-03-15 Alex Harsanyi <AlexHarsanyi@gmail.com> + + recognize elseif in addition to elif #81 + +2019-03-15 Alex Harsanyi <AlexHarsanyi@gmail.com> + + don't be confused by drop function or procedure statements #80 + +2019-03-10 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Apply advices of `checkdoc' (#77) + + * sql-indent.el: spelling and other documentation fixes. + +2019-03-10 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Fix `sqlind-comment-end' regexp. (#79) + + * sql-indent.el: Fix the regexp detected by + trawl (https://github.com/mattiase/trawl). + +2019-03-01 Alex Harsanyi <AlexHarsanyi@gmail.com> + + also fix sqlind-end-statement-regexp + +2019-03-01 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Fix regexp bug in `sqlind-good-if-candidate` (fixes #76) + +2019-02-20 Alex Harsányi <alex-hhh@users.noreply.github.com> + + Recognize more create keywords (#75) + + + +2018-12-13 Alex Harsányi <alex-hhh@users.noreply.github.com> + + Recognize FULL JOIN, UNION ALL and EXCEPT keywords #73 (#74) + + * sql-indent.el (sqlind-select-clauses-regexp): match "UNION ALL" and + "EXCEPT" as select clauses. + (sqlind-select-join-regexp): match FULL JOIN keywords + (sqlind-lineup-joins-to-anchor): use `sqlind-select-join-regexp` to + match all join keywords. + +2018-12-13 Alex Harsányi <alex-hhh@users.noreply.github.com> + + Recognize `select-join-condition` syntax inside nested statements #70 + (#71) + + Updated syntax parser to recognize some JOIN condition keywords as + `select-join-condition` syntax, even inside nested statements. + Updated some non-related tests (m, pr17 and pr68), as this syntax was + not recognized when these tests were written. While this change will + modify the indentation in such cases, it allows more refined control + over the indention. + + * sql-indent.el (sqlind-join-condition-regexp): keywords that + constitute JOIN conditions + (sqlind-syntax-in-select): match `sqlind-join-condition-regexp` when + looking for join condition keywords + (sqlind-refine-syntax): try to refine a + `nested-statement-continuation into a `select-join-condition` if there + is a JOIN in the nested statement. + +2018-12-11 Alex Harsányi <alex-hhh@users.noreply.github.com> + + `sqlind-search-backward` finds things at the same nesting level (#68) + (#69) + + * sql-indent.el (sqlind-search-backward): use + `sqlind-same-level-statement` to check if the position is at the same + nesting level as the starting point + + * (sqlind-same-level-statement): fix to check that the point has the + same nesting, in-comment and in-string status as start. + +2018-10-25 Alex Harsanyi <AlexHarsanyi@gmail.com> + + update version to 1.3 + +2018-10-23 Alex Harsányi <alex-hhh@users.noreply.github.com> + + Fix up bad detection of $$ delimiters in PostgreSQL dialect (#67) + + this resulted in severe performance degradation for the indent function + and bad anchor for the $$ blocks. + + * sql-indent.el (sqlind-maybe-create-statement): strip off any parens + off the function name. + (sqlind-maybe-$$-statement): re-wrote the function to avoid calling + `sqlind-beginning-of-block` recursively. + (sqlind-start-block-regexp): fixup $$ matching + +2018-10-09 Alex Harsanyi <AlexHarsanyi@gmail.com> + + don't recognize "begin transaction" as a block + + "begin transaction;" is a statement, and the code used to confuse the + "begin" with a block begin, breaking some indentation. + +2018-07-12 Alex Harsányi <alex-hhh@users.noreply.github.com> + + recognize implicit JOIN clauses (fixes #64) (#65) + + ... these are JOIN clauses without an explicit INNER, LEFT, RIGHT, etc. + +2018-05-07 Stefan Monnier <monnier@iro.umontreal.ca> + + * sql-indent.el: Add `package-requires` for cl-lib + +2018-05-06 Alex Harsanyi <AlexHarsanyi@gmail.com> + + update to version 1.2 + +2018-02-26 Alex Harsányi <alex-hhh@users.noreply.github.com> + + Recognize MySQL optional clauses, #60 (#61) + + (sqlind-maybe-skip-mysql-create-options): skip over optional clauses + between CREATE and the thing being created -- this allows correct + identification of the create statement + + (sqlind-maybe-create-statement): skip over any "if not exist" keywords + between the thing being created and its name -- this allows correct + identification of the view or table name. + + (sqlind-refine-syntax): refine SELECT statements inside table + declarations, as in "CREATE TABLE AS SELECT..." + also recognize tabs as whitespace syntax in various regexps. + add tests, also update the `if-exists.sql` test as the view name is + correctly determined now. + +2018-02-13 Stefan Monnier <monnier@iro.umontreal.ca> + + * sql-indent.el: Don't require cc-defs. + + (sqlind-indent-comment-start): Use line-end-position. + (sqlind-indent-select-column, sqlind-indent-select-table) + (sqlind-lineup-to-clause-end): Use eolp. + +2018-02-11 Stefan Monnier <monnier@iro.umontreal.ca> + + sql-indent.el: Fix Author: email format + +2018-01-30 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Add .elpaignore file + + Files and patterns listed here will be ignored when the ELPA package is + assembled. + +2018-01-28 Alex Harsányi <alex-hhh@users.noreply.github.com> + + Fix travis build. (#58) + + See also + + * https://github.com/travis-ci/travis-ci/issues/9061 + * https://github.com/flycheck/emacs-travis/issues/13 + +2018-01-28 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Update sql-indent.el to version 1.1 + + Updated / clarified some of the documentation as well + +2018-01-06 Alex Harsanyi <AlexHarsanyi@gmail.com> + + add explanation on how `sqlind-beginning-of-block` works + +2018-01-06 Alex Harsányi <alex-hhh@users.noreply.github.com> + + Recognize PostgreSQL $$ quote syntax, #54 (#55) + + Function bodies in PostgreSQL are defined between '$$' markers. The + code now recognizes these as begin/end statements. There's a test + file, + `test-data/pr54.sql`, specifying the cases that are correctly detected. + PostgreSQL support likely needs more work. + +2018-01-04 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Fix various typos here and there. (#57) + + + +2018-01-04 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Fix typo in sql-indent.org. (#56) + + + +2018-01-03 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Updated documentation + + * Simplified CONTRIBUTING.md -- removed information that is + available + elsewhere + + * Fixed a type in the user manual, `sql-indent.org` specifying the + wrong hook + name for the customization + + * Clarified test naming conventions in `sql-indent-test.el` + +2018-01-03 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Correct indentation of column continuation with operators. (#53) + + * Correct indentation of column continuation with operators. + Correct from + ```sql select my_col || chr(10) + || '-*-' data_type, + x from dual; + ``` + to + ```sql select my_col || chr(10) + || '-*-' data_type, + x from dual; + ``` + + * sql-indent.el + (sqlind-column-definition-start): find the first column of the + statement. + (sqlind-use-anchor-indentation): use the indentation of the anchor + instead of the indentation of the line containing the anchor. + (sqlind-adjust-operator): search the column start in + select-column-continuation. + + * Add test for PR#53. + + * Simplify code. + + (sqlind-column-definition-start): avoid unnecessary (unless (while + ...)). + (sqlind-adjust-operator): avoid complex goto-char. + +2017-12-16 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Correct the adjustment of indentation for operators in select (#52) + + * Correct the adjustment of indentation for operators in select + With this fix the following statement is propely indented + + ``` sql select mt.myVar + || '-*-' myVarLabel, + myVar2 from myTable mt; + ``` + instead of + + ``` sql select mt.myVar + || '-*-' myVarLabel, + myVar2 from myTable mt; + ``` + + * sql-indent.el: Use sqlind syntax table in adjustments functions. + (sqlind-adjust-operator): Use sqlind syntax table. + + * Add test to pr52 + +2017-12-16 Alex Harsányi <alex-hhh@users.noreply.github.com> + + Add CONTRIBUTING.md file (#51) + + + +2017-12-12 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Add new indentation function for select columns. (#50) + + * Add new indentation function for select columns. + + * sql-indent-left.el: Improve indentation of select columns + (sqlind-indent-select-keywords): tweak indentation after DISTINCT, + UNIQUE or TOP keywords. + + * Add tests for pr50, correct sqlind-indentation-left-offsets-alist. + + * sql-indent-left.el: correct sqlind-indent-select-keywords + (sqlind-indent-select-keywords): avoid error when no keyword found. + + * sql-indent-test.el: add test for pr50. + + * Add `sqlind-indent-select-column-alt'. + Clone `sqlind-indent-select-column' into + `sqlind-indent-select-column-alt' to allow alignment of select colums + with KEYWORDS. + + * sql-indent-left.el: Change setup to use + `sqlind-indent-select-column-alt' + (sqlind-indent-select-column-alt): extends + `sqlind-indent-select-column'. + + * Checkdoc style corrections. + sql-indent-left.el: apply chechdoc advices. + +2017-12-02 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Update README with instructions on how to install from GNU ELPA + + * README.md: add instructions for installing from GNU ELPA + + * sql-indent.el: reference `sql-indent.org` in the commentary section + +2017-11-30 Stefan Monnier <monnier@iro.umontreal.ca> + + Fix up copyrights for GNU ELPA, plus minor tweaks + + * .gitignore: Add -autoloads and -pkg files. + + * sql-indent-test.el, sql-indent-left.el: Fix copyright header. + + * sql-indent.el: Fix copyright header. Don't require `align`. + (sqlind-minor-mode-map): New keymap. + (sqlind-minor-mode): Don't modify sql-mode's keymap. Use + kill-local-variable. + +2017-10-13 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Correct detection of labels in `sqlind-maybe-loop-statement'. (#49) + + Correct detection of labels in `sqlind-maybe-loop-statement' + +2017-10-09 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Correct detection of labels in `for` or `while` loops. (#48) + + Correct detection of labels in `for` or `while` loops. + +2017-09-21 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Introduce a nested-statement-close syntax + + This is recognized inside a nested statement when the line to be + indented starts with a closing bracket. This is intended to replace + `sqlind-lineup-close-paren-to-open` and + `sqlind-lineup-close-paren-to-open-indentation` indentation helpers + which had to be added to too many syntactic symbols. + + With the new syntax symbol, using `sqlind-use-anchor-indentation` will + lineup hanging close brackets with the start of the statement and + `sqlind-use-anchor-indentation` will line them up with the actual + opening bracket itself. + +2017-09-19 Alex Harsanyi <AlexHarsanyi@gmail.com> + + new alignment rule for issue #47 + +2017-09-19 Alex Harsanyi <AlexHarsanyi@gmail.com> + + fixup refining a nested-statement-continuation (#46) + + when the nested statement continuation had a comment at the start, any + select statements inside it were missed. + +2017-09-18 Brendan Rocks <brendan-r@users.noreply.github.com> + + Minor documentation tweaks (#44) + + Fix installation command in documentation and other typos + + `install-package-from-buffer` makes more linguistic sense, but + `package-install-from-buffer`, seems to be the appropriate command + (Emacs 25.2) + + +2017-09-18 Alex Harsanyi <AlexHarsanyi@gmail.com> + + new indentation helper function and clarified documentation + + added `sqlind-lineup-close-paren-to-open-indentation` function to assist + with issue #43 + +2017-08-19 Alex Harsányi <alex-hhh@users.noreply.github.com> + + Don't be confused by names that contain keywords (#42) + + Don't be confused by names that contain keywords + for example, the "FOR" in "V_SPORT_ZONE_FOR_SESSION" is not a keyword. + + * Add test cases for PR42 + +2017-08-19 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Fix example in documentation + +2017-08-09 Alex Harsányi <alex-hhh@users.noreply.github.com> + + Travis build and test support (#41) + + Add Travis CI support to the repository + +2017-08-09 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Recognize MsSQL directives and declarations (#40) + +2017-08-02 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Fix detection of select column start and LIMIT keyword #39 + + * sql-indent.el (sqlind-column-definition-start): use LIMIT as the + bounds for `sqlind-same-level-statement`, so we search between the start + of the SELECT and the current point. + (sqlind-select-clauses-regexp): recognize LIMIT as a select clause + keyword. + +2017-07-30 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Correct display of lighter when minor-mode is enabled. (#38) + + Add an space before text to avoid it to stick on previous word in + modeline. + +2017-07-24 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Allow detection of user name in package, procedure or function. (#37) + + * Allow detection of user name in package, procedure or function. + Avoid `mismatched end label for package (1 104)` message whith and sql + of this form: + + ```sql create or replace package my_user.my_wonderfull_package as + function my_amazing_func return number; end my_wonderfull_package; + / + ``` + + * Add tests to PR #37. + +2017-07-21 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Try to correct 'bad closing for begin block' message. (#36) + + Detection of for .. loop inside another statement + see "test-data/pr36.sql" for an example. + +2017-07-15 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Add %type, %rowtype and table prefix in function's return type. (#33) + + * Add %type, %rowtype and table prefix in function's return type. + Allow correct indenting after and function declaration like bellow: + declare + function dummy return my_user.my_table%rowtype; + function dummy2 return my_user.my_table.my_col%type; + var dummy3 number; begin + null; end; + + * Add tests cases for PR #33. + +2017-07-15 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Improve left indentation of case statement. (#34) + + + +2017-06-29 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Don't be fooled by "if exists" statements + + "IF" keywords in things like "drop index if exists" statements are no + longer considered statement starts. + +2017-06-29 Alex Harsányi <alex-hhh@users.noreply.github.com> + + Performance improvements (#31) + + * Establish a limit for syntactic information search + See also issue #26 + + `sqlind-syntax-of-line' will use `sqlind-begining-of-directive' to + establish a search limit for the current syntax. This avoids calling + `sqlind-begining-of-directive' repeatedly. + This changes the indentation anchor for toplevel statements when + directives are present in the file. Unit test data updated + accordingly. + + * sql-indent.el (sqlind-search-limit): new variable + (sqlind-beginning-of-statement-1): avoid searching before + `sqlind-search-limit' + (sqlind-beginning-of-statement): use `sqlind-search-limit' + (sqlind-maybe-loop-statement): fix mispelling of throw symbol + (sqlind-beginning-of-block): limit search to `sqlind-search-limit' + (sqlind-syntax-of-line): bind `sqlind-search-limit' to + `sqlind-begining-of-directive' + + * Fix spelling of `sqlind-beginning-of-directive` + +2017-06-20 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Performance improvements (#26) + + * sql-indent.el (sqlind-backward-syntactic-ws) + (sqlind-forward-syntactic-ws, sqlind-search-backward): rewrite code to + avoid catch/throw forms + (sqlind-match-string): make it a `defsubst' + (sqlind-beginning-of-statement): avoid calling + `sqlind-begining-of-directive' when not needed + (sqlind-syntax-of-line): avoid unnecessary goto-char calls, and replace + `parse-partial-sexp' with `syntax-ppss' + +2017-06-15 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Moved most of the README.md contents into sql-indent.org + + ... this is the beginning of a sql-ident manual. The ORG format should + make it easier to browse in Emacs, and Github also renders it quite + nicely. + +2017-06-15 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Avoid infinite loop in `sqlind-syntax-in-case` + + Updated the test case with code that triggered the bug + +2017-06-15 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Detect end of exception block correctly (#30) + + + +2017-06-13 Alex Harsanyi <AlexHarsanyi@gmail.com> + + fix anchor point for case statement syntax (#29) + + code that was looking for the "when" keyword was moving the point, + resulting in the incorrect anchor point being used for '(in-block case + ...) syntax. Updated tests to reflect fixed code. + + Also added `sqlind-syntax-keyword` helper function, to be used by + indentation functions. + +2017-06-13 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Fix exception being a type as well as a keyword (#28) + + "exception" is both a keyword and a datatype. Add code to differentiate + between the two. Only the keyword is a block start. Updated test files + to reflect that. + +2017-06-12 Alex Harsanyi <AlexHarsanyi@gmail.com> + + fix syntax detection in exception blocks and case statements (#28 and + #29) + + Exception statements with multiple when clauses are correctly recognized + and classified. Case statements with multi-lone when clauses are also + correctly identified. Added unit tests for both cases. + + Some refactoring was necessary to allow recursive syntax refinement + (`sqlind-refine-syntax`) + +2017-06-12 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Fix incorrect match for end keyword in sqlind-end-statement-regexp + +2017-06-08 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Fix bug with wrong regexp and throw clause + + a wrong "end" keyword regexp would match non-keywords that ended with + the string "end", causing problems + + also fixes a misspelling for a throw clause + +2017-06-08 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Various minor improvements on left align SQL statments. (#22) + + * Various minor improvements on left align SQL statments. + + * Update pr17-io-left after updating sql-indent-left setup. + +2017-06-03 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Remove execution bits on sql-indent-left.el (#25) + + + +2017-06-03 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Recognize assignments as statement starts (#24) + +2017-06-01 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Update test for issue #19 to be more comprehensive + +2017-06-01 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Merge branch 'master' of github.com:alex-hhh/emacs-sql-indent + +2017-06-01 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Update unit test suite to run independent of user settings + + Previously, the test suite depended on whether the tabs are expanded + into spaces or not and other user settings. + +2017-05-31 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Exclude equals inside strings from alignments. (#20) + + Update align rules to ignore equal signs inside strings (#20) + +2017-05-31 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Add a rule to align pipes (||). (#21) + + Align rules for string concatenation operators (#21) + +2017-05-30 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Correctly recognize the begin block of a package (#19) + +2017-05-29 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Correctly detect syntax for cursor statements (fix #19) + + Cursors are correctly detected as beginning of a statement. Also an + optional type for the cursor is recognized correctly. + + Also fixed block navigation for package names (so package end statements + are correctly recognized) + + Added tests for the above cases. + +2017-05-26 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Identify syntax for CASE expressions in assignment (fixes #18) + + Also added unit tests that shows/tests the types of CASE expressions + that can show up in PL/SQL. + +2017-05-25 Alex Harsanyi <AlexHarsanyi@gmail.com> + + use cl-lib instead of cl and provide some helpers + + the cl library is deprecated in Emacs, to be replaced with cl-lib (which + has the same functions, but with the "cl-" prefix) + + Also provided some helper functions to access syntactic context, + hopefully this will simplify the code somewhat. + +2017-05-24 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Fix checkdoc errors in sql-indent.el + +2017-05-24 Alex Harsanyi <AlexHarsanyi@gmail.com> + + moved contents of customize-indentation.md into README.md + +2017-05-24 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Recognize syntax of CASE statements which are not nested + + Based on an example in https://github.com/bsvingen/sql-indent/issues/1 + + Also added test case for this syntax type. + +2017-05-24 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Add test cases for sample indentation mode + + Based on a sample SQL indentation example provided by the SQL mode + maintainer. + +2017-05-24 Alex Harsanyi <AlexHarsanyi@gmail.com> + + updated .gitignore + +2017-05-23 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Add a test suite for sql-indent + +2017-05-23 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Updated installation and customization documentation + +2017-05-23 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Fix indentation. + + Previous version didn't work. + +2017-05-23 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Compilation error ... + +2017-05-23 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Correct indentation of function's declaration in package specs. + + Detect end of function declaration in package spec. + +2017-05-22 Alex Harsanyi <AlexHarsanyi@gmail.com> + + sqlind-begining-of-directive -- another approach to disambiguate SET + +2017-05-22 Alex Harsanyi <AlexHarsanyi@gmail.com> + + sqlind-begining-of-directive -- another approach to disambiguate SET + +2017-05-22 Alex Harsanyi <AlexHarsanyi@gmail.com> + + sqlind-adjust-operator -- fix up string concatenation cases + + The operator correctly determines the position of the left hand operand + for the binary operator. For example the code below is indented + correctly now: + + ```sql select col1, 'abc def'--comment + || 'abc' + || 'def' + + ``` + +2017-05-22 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Renamed some indentation functions for consistency + + * `sqlind-adjust-and-or-left` renamed to + `sqlind-left-justify-logical-operator` + + * `sqlind-adjust-and-or-right` renamed to + `sqlind-right-justify-logical-operator` + +2017-05-22 Alex Harsanyi <AlexHarsanyi@gmail.com> + + silence byte compiler warnings + +2017-05-22 Alex Harsanyi <AlexHarsanyi@gmail.com> + + sqlind-begining-of-directive -- disambiguate Oracle SET keyword + + The SET keyword in Oracle SQLPlus is a directive as well as part of the + SQL UPDATE statement. `sqlind-begining-of-directive' will correctly + identify uses of SET which are directives. + +2017-05-20 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Start workgin on aligning keywords left or right. (#14) + + Provide sample customization for the SQL indentation engine + Some extra indentation helper functions are also provided and + documented. + +2017-05-14 Alex Harsanyi <AlexHarsanyi@gmail.com> + + sqlind-beginning-of-statement-1 -- don't look inside comments, fixes #15 + +2017-05-14 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Separate indentation of AND, OR into a separate rule. + +2017-05-11 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Use default value of indent-line-function when deactivating minor mode. + + As the user could change the value of indent-line-function, we could not + reset it to 'indent-relative. + +2017-05-11 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Create a `sqlind-minor-mode` to toggle syntactic indentation + + Also updated commentary section with customization starting points. + +2017-05-10 Alex Harsanyi <AlexHarsanyi@gmail.com> + + update alignment rules to handle variable declarations with assignments + + This is further work on pull request #13 + +2017-05-10 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Merge branch 'master' of github.com:alex-hhh/emacs-sql-indent + +2017-05-10 Alex Harsányi <alex-hhh@users.noreply.github.com> + + Merge pull request #13 from PierreTechoueyres/pte/sqlind-align-rules + + Add support for assignment and arrow (=>) in align. + +2017-05-10 Alex Harsanyi <AlexHarsanyi@gmail.com> + + fixup sqlind-lineup-joins-to-anchor + +2017-05-10 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Add a handful if indentation helpers + + They are not used directly, but they can be used to construct custom + indentation tables. + +2017-05-10 Alex Harsanyi <AlexHarsanyi@gmail.com> + + classify select columns start start with a comma as select-column + + This helps with indenting SQL statements that use a comma at the start + of the column, like this: + + SELECT col1 + ,col2 + FROM ... + + This is also consistent with how we classify select-table syntaxes + +2017-05-09 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Add support for assignment and arrow (=>) in align. + + Allow to align some keywords in sql statements. Ex: + + declare + function dummy(p_param_1 in varchar2, + p_param_2 in out varchar2, + p_param_2 out varchar2) + return boolean; + end dummy; + + function dummy_2(p_param_1 out varchar2, + p_param_2 out varchar2, + p_param_2 out varchar2) + return boolean; + + function dummy_3(p_param_1 varchar2, + p_param_2 in varchar2, + p_param_2 out varchar2) + return boolean; + + var1 boolean := true; + var2 number := 1; + var42 varchar2(1) := 'Y'; begin + if dummy(p_param_1 => val1, + p_param_10 => val10) then + null; + end if; end; + / + +2017-05-07 Alex Harsanyi <AlexHarsanyi@gmail.com> + + install a separate syntax table for syntax parsing + + keep the sql-mode syntax table unchanged, but use a special one during + syntactic parsing. This is done so that navigation over syntactic + elements is simpler for parsing, but stays reasonable while the user + edits the file. + + For example, the string "table.column" will be considered one symbol for + indentation purposes, but two symbols for editing (so an M-b will move + to the dot) + +2017-05-07 Alex Harsanyi <AlexHarsanyi@gmail.com> + + put our own syntax table into sql-mode + +2017-05-07 Alex Harsanyi <AlexHarsanyi@gmail.com> + + move default indentation offsets in separate constant + + `sqlind-indentation-offsets-alist' is now buffer local and it is simpler + to override + +2017-05-06 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Merge branch 'master' of github.com:alex-hhh/emacs-sql-indent + +2017-05-06 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Add initial align rules for SQL statements + +2017-05-05 Alex Harsányi <alex-hhh@users.noreply.github.com> + + Merge pull request #6 from PierreTechoueyres/pte/add-keywors + + Add new keywords in `sqlind-sqlplus-directive'. + +2017-05-05 Alex Harsanyi <AlexHarsanyi@gmail.com> + + don't move cursor when indenting the line + + previous simplified too much + +2017-05-04 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Add new keywords in `sqlind-sqlplus-directive'. + + Add Oracle's keywords to start scripts inside a script. + +2017-05-04 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Updated README file + +2017-05-04 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Use `indent-line-to` in `sqlind-indent-line` + +2017-03-23 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Indent nested if statements correctly, fixes #4 + + `sqlind-begining-of-block` and `sqlind-begining-of-statement` recognize + IF statements and stop at the right point so that syntactic info is + created correctly. + +2017-03-22 Alex Harsanyi <AlexHarsanyi@gmail.com> + + fix parsing the "end if" block when an "elsif" is present + +2017-01-02 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Add new keywords in `sqlind-sqlplus-directive'. + +2016-12-30 Alex Harsanyi <AlexHarsanyi@gmail.com> + + update markdown formatting + +2016-12-30 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Added documentation on how to customize indentation + +2016-12-28 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Enable lexical-binding. + + Enable lexical-binding and suppress compiler warning about unused + variables. + +2016-10-07 alex-hhh <alex-hhh@users.noreply.github.com> + + Merge pull request #1 from PierreTechoueyres/pte/start-with-connect-by + + Add support for connect by/start with. + +2016-10-06 Pierre Téchoueyres <pierre.techoueyres@free.fr> + + Add support for connect by/start with. + + Add support for Oracle SQL start with / connect by. Align them like + group by. + +2016-05-21 Alex Harsanyi <AlexHarsanyi@gmail.com> + + fixup parsing of case clauses + +2015-12-23 Alex Harsanyi <AlexHarsanyi@gmail.com> + + Add comments and headers to make it a proper pakage + + This file can now be installed using package-install and friends. + +2015-12-21 Alex Harsanyi <AlexHarsanyi@gmail.com> + + updated README file + +2015-12-21 Alex Harsanyi <AlexHarsanyi@gmail.com> + + initial revision + +2015-12-21 alex-hhh <alex-hhh@users.noreply.github.com> + + Initial commit +
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/LICENSE @@ -0,0 +1,675 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + 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, either version 3 of the License, or + (at your option) any later version. + + 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, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. +
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/README.md @@ -0,0 +1,47 @@ +# Syntax based indentation for SQL files for GNU Emacs + +[](https://travis-ci.org/alex-hhh/emacs-sql-indent) + +sql-indent.el is a GNU Emacs minor mode which adds support for syntax-based +indentation when editing SQL code: TAB indents the current line based on the +syntax of the SQL code on previous lines. This works like the indentation for +C and C++ code. + +The package also defines align rules so that the `align` function works for +SQL statements, see `sqlind-align-rules` for which rules are defined. This +can be used to align multiple lines around equal signs or "as" statements, +like this. + +`sqlind-minor-mode` together with the align rules can assist in writing tidy +SQL code or formatting existing SQL code. The indentation rules are +customizable and they can be adapted to match your coding style. + +See the [manual](./sql-indent.org) for more details. + +# Installation + +You can install a released version of this package +from [GNU ELPA](http://elpa.gnu.org/packages/sql-indent.html), by running the +following commands in Emacs: + + M-x package-install RET sql-indent RET + +To install sql-indent from this repository, open the file `sql-indent.el` in +Emacs and type: + + M-x package-install-from-buffer RET + +The syntax-based indentation of SQL code can be turned ON/OFF at any time by +enabling or disabling `sqlind-minor-mode`: + + M-x sqlind-minor-mode RET + +To enable syntax-based indentation for every SQL buffer, you can add +`sqlind-minor-mode` to `sql-mode-hook`. First, bring up the customization +buffer using the command: + + M-x customize-variable RET sql-mode-hook RET + +Than, click on the "INS" button to add a new entry and put "sqlind-minor-mode" +in the text field. +
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/sql-indent-autoloads.el @@ -0,0 +1,77 @@ +;;; sql-indent-autoloads.el --- automatically extracted autoloads +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "sql-indent" "sql-indent.el" (0 0 0 0)) +;;; Generated autoloads from sql-indent.el + +(autoload 'sqlind-minor-mode "sql-indent" "\ +Toggle SQL syntactic indentation on or off. +With syntactic indentation, hitting TAB on a line in a SQL buffer +will indent the line according to the syntactic context of the +SQL statement being edited. + +A set of alignment rules are also enabled with this minor mode. +Selecting a region of text and typing `M-x align RET` will align +the statements. This can be used, for example, to align the 'as' +column aliases in select statements. + +\(fn &optional ARG)" t nil) + +(autoload 'sqlind-setup "sql-indent" "\ +Enable SQL syntactic indentation unconditionally. +This function is deprecated, consider using the function +`sqlind-minor-mode' instead. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sql-indent" '("sqlind-"))) + +;;;*** + +;;;### (autoloads nil "sql-indent-left" "sql-indent-left.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from sql-indent-left.el + +(autoload 'sqlind-setup-style-left "sql-indent-left" "\ +Define an sql-indentation style where keywords are left aligned. + +\(fn)" t nil) + +(autoload 'sqlind-setup-style-right "sql-indent-left" "\ +Define an sql-indentation style where keywords are right aligned. + +\(fn)" t nil) + +(autoload 'sqlind-setup-style-default "sql-indent-left" "\ +Define an sql-indentation style where keywords are right aligned. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sql-indent-left" '("sqlind-indent" "indent-case-statement-items"))) + +;;;*** + +;;;### (autoloads nil "sql-indent-test" "sql-indent-test.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from sql-indent-test.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sql-indent-test" '("m-indentation-offsets-alist" "sqlind-"))) + +;;;*** + +;;;### (autoloads nil nil ("sql-indent-pkg.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; sql-indent-autoloads.el ends here
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/sql-indent-left.el @@ -0,0 +1,351 @@ +;;; sql-indent-left.el --- configuration options to indent sql -*- lexical-binding: t -*- + +;; Copyright (C) 2017 Free Software Foundation, Inc + +;; Filename: sql-indent-left.el +;; Description: +;; Author: pierre.techoueyres@free.fr +;; Maintainer: pierre.techoueyres@free.fr +;; Created: +;; Version: pierre.techoueyres@free.fr +;; Last-Updated: +;; By: +;; Update #: 0 +;; URL: +;; Keywords: language sql indentation +;; Compatibility: +;; +;; Features that might be required by this library: +;; +;; None + +;; 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; either version 3 of the License, or +;; (at your option) any later version. +;; +;; 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 GNU Emacs. If not, see <https://www.gnu.org/licenses/>. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;; Commentary: +;; +;; Set configuration options to indent sql my way. +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;; Change log: +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; 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; either version 3, or +;; (at your option) any later version. +;; +;; 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; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth +;; Floor, Boston, MA 02110-1301, USA. +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;; Code: + +(require 'sql-indent) + +(defun indent-case-statement-items (syntax base-indentation) + "Look for a SYNTAX of ((block-start when) (in-block case \"\") ...) +or ((block-start else) (in-block case \"\") ...)." + (let ((outer (sqlind-outer-context syntax))) + (if (and (eq 'in-block (sqlind-syntax-symbol outer)) + (eq 'case (sqlind-syntax-keyword outer)) + (eq 'block-start (sqlind-syntax-symbol syntax)) + (memq (sqlind-syntax-keyword syntax) '(when else))) + (+ base-indentation sqlind-basic-offset) + base-indentation))) + +(defvar sqlind-indentation-right-offsets-alist + `((select-column-continuation sqlind-indent-select-column + sqlind-adjust-operator + sqlind-lone-semicolon) + (in-select-clause sqlind-lineup-to-clause-end + sqlind-adjust-operator + sqlind-right-justify-logical-operator + sqlind-lone-semicolon) + (in-delete-clause sqlind-lineup-to-clause-end + sqlind-adjust-operator + sqlind-right-justify-logical-operator + sqlind-lone-semicolon) + (in-insert-clause sqlind-lineup-to-clause-end + sqlind-adjust-operator + sqlind-right-justify-logical-operator + sqlind-lone-semicolon) + (in-update-clause sqlind-lineup-to-clause-end + sqlind-adjust-operator + sqlind-right-justify-logical-operator + sqlind-lone-semicolon) + ;; mandatory + (select-table-continuation sqlind-indent-select-table + + sqlind-lone-semicolon) + ;; rest picked up from the original indentation offsets + ,@sqlind-default-indentation-offsets-alist) + "Align sql code like this : + +clear columns +set linesize 2500 +set trimout on trimspool on + +select atc.column_name, + atc.data_type, + data_length, + data_precision, + nullable, + data_scale, + nvl(substr(comments, 1, 100), atc.column_name) comments + from all_tab_columns atc, + all_col_comments acc + where atc.owner = acc.owner + and atc.table_name = acc.table_name + and atc.column_name = acc.column_name + and atc.owner = user + and atc.table_name = 'MY_TABLE' + and atc.column_name = p_column_name + and not exists (select 1 + from all_tab_columns atc1, + all_col_comments acc1 + where atc1.owner = acc1.owner + and atc1.table_name = acc1.table_name + and atc1.column_name = acc1.column_name + and atc1.owner = atc.owner + and atc1.table_name = atc.table_name + and acc1.column_name = acc.column_name) + ; + +delete from my_table mt + where col_1 = v_col1 + and ( col_2 = v_col2 + or col_3 = v_col3) + and col_42 = '42' + ; + +update my_table + set col1_has_a_long_name = value1, + col2_is_short = value2 + where cond1 is not null + and ( col_2 = v_col2 + or col_3 = v_col3) + and col_42 = '42' + ; + +insert into xyzxx + ( aaa, xxx, bbb, ccc, + ddd, eee, fff, ggg, + hhh ) +select aaa, + xxx, + max (m.b1) as bbb, + min (m.b1) as ccc, + coalesce (max (n.c2), 0)  as ddd, + coalesce (min (n.c2), 0)  as eee, + max (m.b1) over ( partition by c2 + order by aaa desc ) as fff, + min (m.b1) over ( partition by c2 + order by aaa desc ) as ggg, + avg (n.c2) as hhh + from (select * from (select aaa, + jjj + kkk  as b1, + row_number () over ( partition by qqq + order by rrr, + sss ) as rn + from mno) + where rn = 1) m + inner join (select aaa, + nnn + ooo as c2 + from pqr) n + using (aaa), + group by aaa, + xxx + order by xxx desc, + aaa asc + ;") + +(defvar sqlind-indentation-left-offsets-alist + `((select-clause 0) + (insert-clause 0) + (delete-clause 0) + (update-clause 0) + (case-clause-item-cont 0) + (block-start indent-case-statement-items) + (begin-block 0) + (case-clause +) + (package +) + (package-body +) + (statement-continuation + sqlind-adjust-operator) + (nested-statement-open 1) + (nested-statement-continuation 1) + (nested-statement-close sqlind-use-anchor-indentation) + (string-continuation 0) ;; or should it be a beginning of line or aligned with the previous block ? + ;; Anyway. It's really *BAD* to continue a string across lines. + (select-column sqlind-indent-select-column-alt + sqlind-adjust-operator + sqlind-lone-semicolon) + (select-column-continuation sqlind-indent-select-column-alt + sqlind-adjust-operator + sqlind-lone-semicolon) + (in-select-clause sqlind-lineup-to-clause-end + sqlind-adjust-operator + sqlind-left-justify-logical-operator + sqlind-lone-semicolon) + (in-delete-clause sqlind-lineup-to-clause-end + sqlind-adjust-operator + sqlind-left-justify-logical-operator + sqlind-lone-semicolon) + (in-insert-clause + + sqlind-adjust-operator + sqlind-left-justify-logical-operator + sqlind-lone-semicolon) + (in-update-clause sqlind-lineup-to-clause-end + sqlind-adjust-operator + sqlind-left-justify-logical-operator + sqlind-lone-semicolon) + (select-table-continuation + sqlind-lone-semicolon) + ;; rest picked up from the original indentation offsets + ,@sqlind-default-indentation-offsets-alist) + "Align sql code like this : + +clear columns +set linesize 2500 +set trimout on trimspool on + +select DISTINCT + atc.column_name, + atc.data_type, + data_length, + data_precision, + nullable, + data_scale, + nvl(substr(comments, 1, 100), atc.column_name) comments +from all_tab_columns atc, + all_col_comments acc +where atc.owner = acc.owner +and atc.table_name = acc.table_name +and atc.column_name = acc.column_name +and atc.owner = user +and atc.table_name = 'MY_TABLE' +and atc.column_name = p_column_name +and not exists (select 1 + from all_tab_columns atc1, + all_col_comments acc1 + where atc1.owner = acc1.owner + and atc1.table_name = acc1.table_name + and atc1.column_name = acc1.column_name + and atc1.owner = atc.owner + and atc1.table_name = atc.table_name + and acc1.column_name = acc.column_name) +; + +delete from my_table mt +where col_1 = v_col1 +and ( col_2 = v_col2 + or col_3 = v_col3) +and col_42 = '42' +; + +update my_table +set col1_has_a_long_name = value1, + col2_is_short = value2 +where cond1 is not null +and ( col_2 = v_col2 + or col_3 = v_col3) +and col_42 = '42' +; + +insert into xyzxx + ( aaa, xxx, bbb, ccc, + ddd, eee, fff, ggg, + hhh ) +select aaa, + xxx, + max (m.b1) as bbb, + min (m.b1) as ccc, + coalesce (max (n.c2), 0)  as ddd, + coalesce (min (n.c2), 0)  as eee, + max (m.b1) over ( partition by c2 + order by aaa desc ) as fff, + min (m.b1) over ( partition by c2 + order by aaa desc ) as ggg, + avg (n.c2) as hhh +from (select * from (select aaa, + jjj + kkk  as b1, + row_number () over ( partition by qqq + order by rrr, + sss ) as rn + from mno) + where rn = 1) m + inner join (select aaa, + nnn + ooo as c2 + from pqr) n + using (aaa), +group by aaa, + xxx +order by xxx desc, + aaa asc +;") + +(defun sqlind-indent-select-column-alt (syntax base-indentation) + "Return the indentation for a column after a SELECT DISTINCT clause. + +SYNTAX is the syntax of the current line, BASE-INDENTATION is the +current indentation, which we need to update. + +Like `sqlind-indent-select-column' but we try to align to the KEYWORD, +but if we are the first column after the SELECT clause we simply +add `sqlind-basic-offset'." + (save-excursion + (goto-char (sqlind-anchor-point syntax)) + (when (looking-at "select\\s *\\(top\\s +[0-9]+\\|distinct\\|unique\\)?") + (if (match-beginning 1) + (goto-char (match-beginning 1)) + (goto-char (match-end 0)))) + (skip-syntax-forward " ") + (if (or (looking-at sqlind-comment-start-skip) + (looking-at "$")) + (+ base-indentation sqlind-basic-offset) + (current-column)))) + +;;;###autoload +(defun sqlind-setup-style-left () + "Define an sql-indentation style where keywords are left aligned." + (interactive) + (setq sqlind-indentation-offsets-alist sqlind-indentation-left-offsets-alist)) + +;;;###autoload +(defun sqlind-setup-style-right () + "Define an sql-indentation style where keywords are right aligned." + (interactive) + (setq sqlind-indentation-offsets-alist sqlind-indentation-right-offsets-alist)) + + +;;;###autoload +(defun sqlind-setup-style-default () + "Define an sql-indentation style where keywords are right aligned." + (interactive) + (setq sqlind-indentation-offsets-alist sqlind-default-indentation-offsets-alist)) + + +(provide 'sql-indent-left) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; sql-indent-left.el ends here
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/sql-indent-pkg.el @@ -0,0 +1,2 @@ +;; Generated package description from sql-indent.el +(define-package "sql-indent" "1.4" "Support for indenting code in SQL files." '((cl-lib "0.5")) :url "http://elpa.gnu.org/packages/sql-indent.html" :keywords '("languages" "sql"))
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/sql-indent-test.el @@ -0,0 +1,425 @@ +;;; sql-indent-test.el --- Automated tests for sql-indent.el. -*- lexical-binding: t -*- + +;; Copyright (C) 2017 Free Software Foundation, Inc + +;; Author: Alex Harsanyi (AlexHarsanyi@gmail.com) +;; Created: 23 May 2017 +;; Keywords: languages sql +;; Homepage: https://github.com/alex-hhh/emacs-sql-indent + +;; 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; either version 3 of the License, or +;; (at your option) any later version. +;; +;; 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 GNU Emacs. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; This file defines tests for the sql-indent.el package. To run the tests, +;; eval this file, than type: +;; +;; M-x ert RET "^sqlind-" RET +;; +;; Tests can also be run in batch mode using the following command: +;; +;; emacs -batch -Q --no-site-file -L . -l sql-indent-test.el -f ert-run-tests-batch-and-exit +;; +;; The above command used '-Q' and '--no-site-file options', making sure that +;; the tests are run in a "standard" environment, regardless of what packages +;; and settings are present in your personal init and site-init files. +;; +;;;; There are two types of tests, +;; +;; * SYNTAX CHECKS check if the syntax in an SQL file is correctly +;; identified. These tests are independent of indentation preferences (see +;; `sqlind-ert-check-file-syntax') +;; +;; * INDENTATION CHECKS check if a file is indented correctly for a set of +;; rules. (see `sqlind-ert-check-file-indentation') +;; +;; Both types of tests work by having a sample SQL file with syntax and +;; indentation data saved in an .eld files. These data files need to be +;; prepared separately using `sqlind-collect-syntax-from-buffer' and +;; `sqlind-collect-indentation-offsets-from-buffer'. +;; +;; +;;;; PREPARING NEW TESTS +;; +;; To create a syntax check file, open an *ielm* buffer (M-x ielm RET) and +;; run: +;; +;; (sqlind-collect-syntax-from-buffer (find-file-noselect "./test-data/pr7.sql")) +;; +;; The function will output a set of syntax definitions. Put these into an +;; .eld file. +;; +;; To create an indentation offsets file, run: +;; +;; (sqlind-collect-indentation-offsets-from-buffer +;; (find-file-noselect "./test-data/pr7.sql") +;; sqlind-indentation-left-offsets-alist +;; 2) +;; +;; The function will output a list of indentation offsets. Put these into an +;; .eld file. +;; +;; See the end of file for examples on how to put together the actual tests. +;; +;; +;;;; NAMING CONVENTION +;; +;; If there's a problem report on GitHub, use the issue number as the "tag" +;; for the test. For example, a test that addresses issue number 30 will have +;; a tag "pr30". If there is no issue on GitHub, use the pull request number. +;; In this case you will have to create the pull request first, so you know +;; the number, before you can add the tests -- sorry about that. +;; +;; With the issue or pull request tag the following files are created: +;; +;; * "test-data/pr30.sql" -- contains the sample SQL code that is verified +;; +;; * "test-data/pr30-syn.eld" -- contains the syntactic information for the ;; +;; test (as generated by `sqlind-collect-syntax-from-buffer') +;; +;; * "test-data/pr30-io-XXX.eld" -- contains the indentation offsets for the +;; indentation rules being tested (where XXX is a short name for those +;; rules) +;; +;; * `sqlind-ert-pr30' -- is the name of the test function in this file. If +;; there are multiple tests, append another tag (e.g. `sqlind-ert-pr30-syn', +;; for the syntactic check test, `sqlind-ert-pr30-io-XXX' for the indentation +;; offset test). +;; + +;;; Code +(require 'ert) +(require 'sql-indent) +(require 'sql-indent-left) + + +;;................................................ test data preparation .... + +(defun sqlind-collect-syntax-from-buffer (buffer) + (let ((result '())) + (with-current-buffer buffer + ;; NOTE: we indent the buffer according to the default rules first, as + ;; this affects anchor points. We could get rid of this if we write a + ;; smarter `sqlind-ert-check-line-syntax' + (sqlind-ert-indent-buffer + (default-value 'sqlind-indentation-offsets-alist) + (default-value 'sqlind-basic-offset)) + (goto-char (point-min)) + (let ((syn (sqlind-syntax-of-line))) + (setq result (cons syn result))) + (while (= (forward-line 1) 0) + (let ((syn (sqlind-syntax-of-line))) + (setq result (cons syn result))))) + (reverse result))) + +(defun sqlind-collect-indentation-offsets-from-buffer (buffer rules basic-offset) + (let ((result '())) + (with-current-buffer buffer + (sqlind-ert-indent-buffer + (or rules (default-value 'sqlind-indentation-offsets-alist)) + (or basic-offset (default-value 'sqlind-basic-offset))) + (goto-char (point-min)) + (setq result (cons (current-indentation) result)) + (while (= (forward-line 1) 0) + (setq result (cons (current-indentation) result)))) + (reverse result))) + + +;;......................................................... test helpers .... + +(defun sqlind-ert-indent-buffer (rules basic-offset) + "Indent the buffer according to RULES and BASIC-OFFSET. +The RULES and BASIC-OFFSET are installed as +`sqlind-indentation-offsets-alist' and `sqlind-basic-offset' than +indent the whole buffer." + (when rules + (setq sqlind-indentation-offsets-alist rules)) + (when basic-offset + (setq sqlind-basic-offset basic-offset)) + ;; To ensure we are consistent in our offsets regardless of he users + ;; personal tab choices, setup spaces only indentation for this buffer. + (setq indent-tabs-mode nil) + (untabify (point-min) (point-max)) + (indent-region (point-min) (point-max)) + ;; (save-buffer) ; if you want to see the result of this command + (set-buffer-modified-p nil)) + +(defun sqlind-ert-check-line-syntax (expected) + "Check that the current line has EXPECTED syntax. +Get the syntax of the current line in the current buffer using +`sqlind-syntax-of-line' and compare it against EXPECTED. + + The comparison is done using the `should' ERT macro, so this +function should be run a part of an ERT test." + (let ((actual (sqlind-syntax-of-line)) + (info (format "%s:%s" + (buffer-file-name) + (line-number-at-pos)))) + ;; NOTE: should does not appear to have a message argument, so the "cons" + ;; trick is used to add some information in case of failure. + (should + (equal (cons info actual) (cons info expected))))) + +(defun sqlind-ert-read-data (file) + "Read saved ELISP data from FILE." + (with-current-buffer (or (get-buffer file) + (find-file-noselect file)) + (goto-char (point-min)) + (read (current-buffer)))) + +(defun sqlind-ert-check-file-syntax (sql-file data-file) + "Check the syntax of each line in SQL-FILE. +The syntax of each line in SQL-FILE is checked against the +previously saved syntax data in DATA-FILE. An error is signalled +if there is a mismatch." + (let ((syntax-data (sqlind-ert-read-data data-file))) + (with-current-buffer (find-file sql-file) + (sqlind-minor-mode 1) ; ensure this is enabled + ;; NOTE: indent the buffer according to default rules first -- this + ;; affects anchor points. + ;; (message "sql-product: %s" sql-product) + (sqlind-ert-indent-buffer + (default-value 'sqlind-indentation-offsets-alist) + (default-value 'sqlind-basic-offset)) + (goto-char (point-min)) + (should (consp syntax-data)) ; "premature end of syntax-data" + (sqlind-ert-check-line-syntax (car syntax-data)) + (setq syntax-data (cdr syntax-data)) + (while (= (forward-line 1) 0) + (should (consp syntax-data)) ; "premature end of syntax-data" + (sqlind-ert-check-line-syntax (car syntax-data)) + (setq syntax-data (cdr syntax-data)))))) + +(defun sqlind-ert-check-line-indentation (expected) + "Check that the current line has EXPECTED indentation. +The comparison is done using the `should' ERT macro, so this +function should be run a part of an ERT test." + (let ((actual (current-indentation)) + (info (format "%s:%s" + (buffer-file-name) + (line-number-at-pos)))) + ;; NOTE: should does not appear to have a message argument, so the "cons" + ;; trick is used to add some information in case of failure. + (should + (equal (cons info actual) (cons info expected))))) + +(defun sqlind-ert-check-file-indentation (sql-file data-file rules basic-offset) + "Check that SQL-FILE is indented correctly according to RULES +and BASIC-OFFSET The file is indented first according to RULES +and BASIC-OFFSET, than each line is compared with the indentation +information read from DATA-FILE (as generated by +`sqlind-collect-indentation-offsets-from-buffer')" + (let ((indentation-data (sqlind-ert-read-data data-file))) + (with-current-buffer (find-file sql-file) + (sqlind-minor-mode 1) + ;; (message "sql-product: %s" sql-product) + (sqlind-ert-indent-buffer rules basic-offset) + (goto-char (point-min)) + (should (consp indentation-data)) ; "premature end of indentation-data + (sqlind-ert-check-line-indentation (car indentation-data)) + (setq indentation-data (cdr indentation-data)) + (while (= (forward-line 1) 0) + (should (consp indentation-data)) ; "premature end of syntax-data" + (sqlind-ert-check-line-indentation (car indentation-data)) + (setq indentation-data (cdr indentation-data)))))) + + +;;..................................................... the actual tests .... + +;; See https://gist.github.com/alex-hhh/834a91621680e826a27b2b08463eb12f + +(defvar m-indentation-offsets-alist + `((select-clause 0) + (insert-clause 0) + (delete-clause 0) + (update-clause 0) + (in-insert-clause +) + (in-select-clause sqlind-lineup-to-clause-end) + (nested-statement-continuation sqlind-lineup-into-nested-statement + sqlind-align-comma) + (nested-statement-close sqlind-lineup-to-anchor) + (select-column sqlind-indent-select-column + sqlind-align-comma) + (select-column-continuation sqlind-indent-select-column) + (select-table-continuation sqlind-indent-select-table + sqlind-lineup-joins-to-anchor + sqlind-lineup-open-paren-to-anchor + sqlind-align-comma) + ,@sqlind-default-indentation-offsets-alist)) + +(ert-deftest sqlind-ert-pr17 () + (sqlind-ert-check-file-syntax "test-data/pr17.sql" "test-data/pr17-syn.eld")) + +(ert-deftest sqlind-ert-pr17-indentation-default () + (sqlind-ert-check-file-indentation + "test-data/pr17.sql" "test-data/pr17-io-default.eld" + (default-value 'sqlind-indentation-offsets-alist) + (default-value 'sqlind-basic-offset))) + +(ert-deftest sqlind-ert-pr17-indentation-left () + (sqlind-ert-check-file-indentation + "test-data/pr17.sql" "test-data/pr17-io-left.eld" + sqlind-indentation-left-offsets-alist + (default-value 'sqlind-basic-offset))) + +(ert-deftest sqlind-ert-pr17-indentation-right () + (sqlind-ert-check-file-indentation + "test-data/pr17.sql" "test-data/pr17-io-right.eld" + sqlind-indentation-right-offsets-alist + (default-value 'sqlind-basic-offset))) + +(ert-deftest sqlind-ert-pr7 () + (sqlind-ert-check-file-syntax "test-data/pr7.sql" "test-data/pr7-syn.eld")) + +(ert-deftest sqlind-ert-case-stmt () + (sqlind-ert-check-file-syntax "test-data/case-stmt.sql" "test-data/case-stmt-syn.eld")) + +(ert-deftest sqlind-ert-m-syn () + (sqlind-ert-check-file-syntax "test-data/m.sql" "test-data/m-syn.eld")) + +(ert-deftest sqlind-ert-m-io () + (sqlind-ert-check-file-indentation + "test-data/m.sql" "test-data/m-io.eld" + m-indentation-offsets-alist 4)) + +(ert-deftest sqlind-ert-pr18 () + (sqlind-ert-check-file-syntax "test-data/pr18.sql" "test-data/pr18-syn.eld")) + +(ert-deftest sqlind-ert-pr19 () + (sqlind-ert-check-file-syntax "test-data/pr19.sql" "test-data/pr19-syn.eld")) + +(ert-deftest sqlind-ert-pr24 () + (sqlind-ert-check-file-syntax "test-data/pr24.sql" "test-data/pr24-syn.eld")) + +(ert-deftest sqlind-ert-pr28 () + (sqlind-ert-check-file-syntax "test-data/pr28.sql" "test-data/pr28-syn.eld")) + +(ert-deftest sqlind-ert-pr29 () + (sqlind-ert-check-file-syntax "test-data/pr29.sql" "test-data/pr29-syn.eld")) + +(ert-deftest sqlind-ert-if-exists () + (sqlind-ert-check-file-syntax "test-data/if-exists.sql" "test-data/if-exists-syn.eld")) + +(ert-deftest sqlind-ert-pr33 () + (sqlind-ert-check-file-syntax "test-data/pr33.sql" "test-data/pr33-syn.eld")) + +(ert-deftest sqlind-ert-pr33-io-left () + (sqlind-ert-check-file-indentation + "test-data/pr33.sql" "test-data/pr33-io-left.eld" + sqlind-indentation-left-offsets-alist 2)) + +(ert-deftest sqlind-ert-pr36 () + (sqlind-ert-check-file-syntax "test-data/pr36.sql" "test-data/pr36-syn.eld")) + +(ert-deftest sqlind-ert-pr36-io-left () + (sqlind-ert-check-file-indentation "test-data/pr36.sql" "test-data/pr36-io-left.eld" + sqlind-indentation-left-offsets-alist 2)) + +(ert-deftest sqlind-ert-pr37 () + (sqlind-ert-check-file-syntax "test-data/pr37.sql" "test-data/pr37-syn.eld")) + +(ert-deftest sqlind-ert-pr37-io-left () + (sqlind-ert-check-file-indentation "test-data/pr37.sql" "test-data/pr37-io-left.eld" + sqlind-indentation-left-offsets-alist 2)) + +(ert-deftest sqlind-ert-pr39 () + (sqlind-ert-check-file-syntax "test-data/pr39.sql" "test-data/pr39-syn.eld")) + +(ert-deftest sqlind-ert-pr40 () + (sqlind-ert-check-file-syntax "test-data/pr40.sql" "test-data/pr40-syn.eld")) + +(ert-deftest sqlind-ert-pr42 () + (sqlind-ert-check-file-syntax "test-data/pr42.sql" "test-data/pr42-syn.eld")) + +(ert-deftest sqlind-ert-pr46 () + (sqlind-ert-check-file-syntax "test-data/pr46.sql" "test-data/pr46-syn.eld")) + +(ert-deftest sqlind-ert-pr48 () + (sqlind-ert-check-file-syntax "test-data/pr48.sql" "test-data/pr48-syn.eld")) + +(ert-deftest sqlind-ert-pr49 () + (sqlind-ert-check-file-syntax "test-data/pr49.sql" "test-data/pr49-syn.eld")) + +(ert-deftest sqlind-ert-pr50-io-left () + (sqlind-ert-check-file-indentation "test-data/pr50.sql" "test-data/pr50-io-left.eld" + sqlind-indentation-left-offsets-alist 2)) + +(ert-deftest sqlind-ert-pr52-io-left () + (sqlind-ert-check-file-indentation "test-data/pr52.sql" "test-data/pr52-io-left.eld" + sqlind-indentation-left-offsets-alist 2)) + +(ert-deftest sqlind-ert-pr53-io-left () + (sqlind-ert-check-file-indentation "test-data/pr53.sql" "test-data/pr53-io-left.eld" + sqlind-indentation-left-offsets-alist 2)) + +(ert-deftest sqlind-ert-pr54 () + (sqlind-ert-check-file-syntax "test-data/pr54.sql" "test-data/pr54-syn.eld")) + +(ert-deftest sqlind-ert-pr60 () + (sqlind-ert-check-file-syntax "test-data/pr60.sql" "test-data/pr60-syn.eld")) + +(ert-deftest sqlind-ert-pr64 () + (sqlind-ert-check-file-syntax "test-data/pr64.sql" "test-data/pr64-syn.eld")) + +(ert-deftest sqlind-ert-pr66 () + (sqlind-ert-check-file-syntax "test-data/pr66.sql" "test-data/pr66-syn.eld")) + +(ert-deftest sqlind-ert-pr67 () + (sqlind-ert-check-file-syntax "test-data/pr67.sql" "test-data/pr67-syn.eld")) + +(ert-deftest sqlind-ert-pr68 () + (sqlind-ert-check-file-syntax "test-data/pr68.sql" "test-data/pr68-syn.eld")) + +(ert-deftest sqlind-ert-pr70 () + (sqlind-ert-check-file-syntax "test-data/pr70.sql" "test-data/pr70-syn.eld")) + +(ert-deftest sqlind-ert-pr73 () + (sqlind-ert-check-file-syntax "test-data/pr73.sql" "test-data/pr73-syn.eld")) + +(ert-deftest sqlind-ert-pr75-postgres () + (sqlind-ert-check-file-syntax + "test-data/pr75-postgres.sql" + "test-data/pr75-postgres-syn.eld")) + +(ert-deftest sqlind-ert-pr75-oracle () + (sqlind-ert-check-file-syntax + "test-data/pr75-oracle.sql" + "test-data/pr75-oracle-syn.eld")) + +(ert-deftest sqlind-ert-pr80 () + (sqlind-ert-check-file-syntax + "test-data/pr80.sql" + "test-data/pr80-syn.eld")) + +(ert-deftest sqlind-ert-pr81 () + (sqlind-ert-check-file-syntax + "test-data/pr81.sql" + "test-data/pr81-syn.eld")) + +(ert-deftest sqlind-ert-pr83 () + (sqlind-ert-check-file-syntax + "test-data/pr83.sql" + "test-data/pr83-syn.eld")) + +(ert-deftest sqlind-ert-pr84 () + (sqlind-ert-check-file-syntax + "test-data/pr84.sql" + "test-data/pr84-syn.eld")) + +(ert-deftest sqlind-ert-pr85 () + (sqlind-ert-check-file-syntax + "test-data/pr85.sql" + "test-data/pr85-syn.eld")) + +;;; sql-indent-test.el ends here
rename from packages/sql-indent.el rename to elpa/sql-indent-1.4/sql-indent.el --- a/packages/sql-indent.el +++ b/elpa/sql-indent-1.4/sql-indent.el @@ -1,195 +1,2445 @@ -;;; sql-indent.el --- indentation of SQL statements - -;; Copyright (C) 2000 Alex Schroeder +;;; sql-indent.el --- Support for indenting code in SQL files. -*- lexical-binding: t -*- -;; Authors: Alex Schroeder <alex@gnu.org> -;; Matt Henry <mcthenry+gnu@gmail.com> -;; Maintainer: Boerge Svingen <bsvingen@borkdal.com> -;; Version: $Id: sql-indent.el,v 1.10 2009/03/25 22:52:25 mhenry Exp $ +;; Copyright (C) 2015, 2017-2018 Free Software Foundation, Inc -;; Keywords: languages -;; URL: https://github.com/bsvingen/sql-indent - -;; This file is not part of GNU Emacs. - -;; This is free software; you can redistribute it and/or modify +;; Author: Alex Harsanyi <AlexHarsanyi@gmail.com> +;; Created: 27 Sep 2006 +;; Version: 1.4 +;; Keywords: languages sql +;; Homepage: https://github.com/alex-hhh/emacs-sql-indent +;; Package-Requires: ((cl-lib "0.5")) +;; +;; 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; either version 2, or (at your option) -;; any later version. - -;; This is distributed in the hope that it will be useful, +;; the Free Software Foundation; either version 3 of the License, or +;; (at your option) any later version. +;; +;; 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 GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. +;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. ;;; Commentary: - -;; Indent SQL statements. - -;; As the indentation of SQL statements depends not only on the previous -;; line but also on the current line, empty lines cannot always be -;; indented correctly. - -;; Usage note: Loading this file will make all SQL mode buffers created -;; from then on use `sql-indent-line' for indentation. A possible way -;; to install sql-indent.el would be to add the following to your -;; .emacs: - -;; (eval-after-load "sql" -;; '(load-library "sql-indent")) - -;; Thanks: -;; Arcady Genkin <antipode@thpoon.com> - - -;;; History: -;; 2009-03-22* -;; * mhenry -;; Added `sql-indent-buffer' for efficient full buffer processing. -;; Modified `sql-indent' to be savvy to comments and strings. -;; Removed "and", "or" and "exists" from `sql-indent-first-column-regexp' -;; Added "create", "drop" and "truncate" to `sql-indent-first-column-regexp' +;; +;; `sqlind-minor-mode' is a minor mode that enables syntax-based indentation +;; for `sql-mode' buffers: the TAB key indents the current line based on the +;; SQL code on previous lines. To setup syntax-based indentation for every +;; SQL buffer, add `sqlind-minor-mode' to `sql-mode-hook'. Indentation rules +;; are flexible and can be customized to match your personal coding style. +;; For more information, see the "sql-indent.org" file. +;; +;; The package also defines align rules so that the `align' function works for +;; SQL statements, see `sqlind-align-rules'. ;;; Code: (require 'sql) +(require 'cl-lib) -;; Need the following to allow GNU Emacs 19 to compile the file. -(require 'regexp-opt) +;;;; General setup + +(defvar sqlind-syntax-table + (let ((table (make-syntax-table))) + ;; C-style comments /**/ (see elisp manual "Syntax Flags")) + (modify-syntax-entry ?/ ". 14" table) + (modify-syntax-entry ?* ". 23" table) + ;; double-dash starts comment + (modify-syntax-entry ?- ". 12b" table) + ;; newline and formfeed end coments + (modify-syntax-entry ?\n "> b" table) + (modify-syntax-entry ?\f "> b" table) + ;; single quotes (') quotes delimit strings + (modify-syntax-entry ?' "\"" table) + ;; backslash is no escape character + (modify-syntax-entry ?\\ "." table) + + ;; the following are symbol constituents. Note that the dot '.' is more + ;; usefull as a symbol constituent than as a punctuation char. + + (modify-syntax-entry ?_ "_" table) + (modify-syntax-entry ?. "_" table) + (modify-syntax-entry ?$ "_" table) + (modify-syntax-entry ?# "_" table) + (modify-syntax-entry ?% "_" table) + + table) + "Syntax table used in `sql-mode' for indenting SQL code. +This is slightly different than the syntax table used for +navigation: some punctuation characters are made symbol +constituents so that syntactic navigation works over them.") + +;;;; Utilities + +;; The following routines perform rudimentary syntactical analysis of SQL +;; code. The indentation engine decides how to indent based on what this code +;; returns. The main function is `sqlind-syntax-of-line'. +;; +;; To examine the syntax of the current line, you can use the +;; `sqlind-show-syntax-of-line'. This is only useful if you want to debug this +;; package or are just curious. + +(defconst sqlind-comment-start-skip "\\(--+\\|/\\*+\\)\\s *" + "Regexp to match the start of a SQL comment.") + +(defconst sqlind-comment-end "\\*+/" + "Regexp to match the end of a multiline SQL comment.") + +(defvar sqlind-comment-prefix "\\*+\\s " + "Regexp to match the line prefix inside comments. +This is used to indent multi-line comments.") + +(defsubst sqlind-in-comment-or-string (pos) + "Return non nil if POS is inside a comment or a string. +We actually return 'string if POS is inside a string, 'comment if +POS is inside a comment, nil otherwise." + (syntax-ppss-context (syntax-ppss pos))) + +(defun sqlind-backward-syntactic-ws () + "Move point backwards over whitespace and comments. +Leave point on the first character which is not syntactic +whitespace, or at the beginning of the buffer." + (let ((done nil)) + (while (not done) + (skip-chars-backward " \t\n\r\f\v") + (unless (eq (point) (point-min)) + (forward-char -1)) + (let ((pps (syntax-ppss (point)))) + (if (nth 4 pps) ; inside a comment? + (goto-char (nth 8 pps)) ; move to comment start than repeat + (setq done t))))) + (point)) + +(defun sqlind-forward-syntactic-ws () + "Move point forward over whitespace and comments. +Leave point at the first character which is not syntactic +whitespace, or at the end of the buffer." + ;; if we are inside a comment, move to the comment start and scan + ;; from there. + (let ((pps (syntax-ppss (point)))) + (when (nth 4 pps) + (goto-char (nth 8 pps)))) + (let ((done nil)) + (while (not done) + (skip-chars-forward " \t\n\r\f\v") + (cond ((looking-at sqlind-comment-start-skip) (forward-comment 1)) + ;; a slash ("/") by itself is a SQL*plus directive and + ;; counts as whitespace + ((looking-at "/\\s *$") (goto-char (match-end 0))) + (t (setq done t))))) + (point)) + +(defun sqlind-search-backward (start regexp limit) + "Search for REGEXP from START backward until LIMIT. +Finds a match that is not inside a comment or string, moves point +to the match and returns it. If no match is found, point is moved +to LIMIT and nil is returned." + (goto-char start) + (let ((done nil)) + (while (and (not done) + (re-search-backward regexp limit 'noerror)) + (when (sqlind-same-level-statement (point) start) + (setq done (point)))) + done)) + +(defsubst sqlind-match-string (pos) + "Return the match data at POS in the current buffer. +This is similar to `match-data', but the text is fetched without +text properties and it is conveted to lower case." + (let ((start (match-beginning pos)) + (end (match-end pos))) + (when (and start end) + (downcase (buffer-substring-no-properties start end))))) + +(defsubst sqlind-labels-match (lb1 lb2) + "Return t when LB1 equals LB2 or LB1 is an empty string. +This is used to compare start/end block labels where the end +block label might be empty." + (or (string= lb1 lb2) + (string= lb1 ""))) + +(defun sqlind-same-level-statement (point start) + "Return t if POINT is at the same syntactic level as START. +This means that POINT is at the same nesting level and not inside +a string or comment." + (save-excursion + (let ((ppss-point (syntax-ppss point)) + (ppss-start (syntax-ppss start))) + (and (equal (nth 3 ppss-point) (nth 3 ppss-start)) ; string + (equal (nth 4 ppss-point) (nth 4 ppss-start)) ; comment + (= (nth 0 ppss-point) (nth 0 ppss-start)))))) ; same nesting + +(defun sqlind-column-definition-start (pos limit) + "Find the beginning of a column definition in a select statement. +POS is the current position of the line to be indented, assumed +to be in a 'select-column-continuation syntax. + +LIMIT is the limit of the search, the beginning of the select +statement." + (save-excursion + (goto-char pos) + (catch 'found + (while (re-search-backward "," limit 'noerror) + (when (sqlind-same-level-statement (point) limit) + (forward-char 1) + (sqlind-forward-syntactic-ws) + (throw 'found (point)))) + ;; nothing was found in (while ...) so try to find the first column definition. + (goto-char limit) + (forward-sexp) + (sqlind-forward-syntactic-ws) + (point)))) + +(defun sqlind-syntax (context) + "Return the most specific syntax of CONTEXT. +See `sqlind-syntax-of-line' for the definition of CONTEXT." + (when context + (caar context))) + +(defun sqlind-syntax-symbol (context) + "Return the syntax symbol for the most specific syntax of CONTEXT. +See `sqlind-syntax-of-line' for the definition of CONTEXT." + (when context + (let ((syntax-part (caar context))) + (if (symbolp syntax-part) + syntax-part + (car syntax-part))))) + +(defun sqlind-syntax-keyword (context) + "Return the syntax keyword for the most specific syntax of CONTEXT. +This is used for complex syntax symbols like '(in-block case +\"\"), in that case, it will return the 'case symbol. See +`sqlind-syntax-of-line' for the definition of CONTEXT." + (when context + (let ((syntax-part (caar context))) + (if (symbolp syntax-part) + nil ; no KEYWORD + (nth 1 syntax-part))))) + +(defun sqlind-anchor-point (context) + "Return the anchor point for the most specifc syntax of CONTEXT. +See `sqlind-syntax-of-line' for the definition of CONTEXT." + (when context + (cdar context))) + +(defun sqlind-outer-context (context) + "Return the outer context from CONTEXT. +See `sqlind-syntax-of-line' for the definition of CONTEXT." + (when context + (cdr context))) + +(defun sqlind-find-context (syntax-symbol context) + "Find SYNTAX-SYMBOL in the CONTEXT chain. +CONTEXT chain is a list of (SYNTAX-SYMBOL . ANCHOR), as returned +by `sqlind-syntax-of-line'. The function finds the fist element +which matches the specified syntax symbol and returns the list +from that point. + +See `sqlind-indentation-syntax-symbols' for the possible syntax +symbols and their meaning." + (cond ((null context) + nil) + ((eq syntax-symbol (sqlind-syntax-symbol context)) + context) + (t + (sqlind-find-context syntax-symbol (sqlind-outer-context context))))) + +(defun sqlind-looking-at-begin-transaction () + "Return t if the point is on a \"begin transaction\" statement." + (and (looking-at "begin") + (save-excursion + (forward-word 1) + (sqlind-forward-syntactic-ws) + (looking-at "transaction\\>\\|work\\>\\|;")))) + +;;;; Syntactic analysis of SQL code + +;;;;; Find the beginning of the current statement + +(defconst sqlind-sqlplus-directive + (concat ;; SET is handled in a special way, to avoid conflicts with the SET + ;; keyworkd in updated clauses + "\\(^set\\s-+\\w+\\(\\s-+[^=].*\\)?$\\)\\|\\(^" + (regexp-opt '("column" "rem" "define" "spool" "prompt" + "clear" "compute" "whenever" "@" "@@" "start") + t) + "\\)\\b") + "Match an SQL*Plus directive at the beginning of a line. +A directive always stands on a line by itself -- we use that to +determine the statement start in SQL*Plus scripts.") + +(defconst sqlind-sqlite-directive + "^[.].*?\\>" + "Match an SQLite directive at the beginning of a line. +A directive always stands on a line by itself -- we use that to +determine the statement start in SQLite scripts.") + +(defconst sqlind-ms-directive + (concat + "\\(^set\\s-+\\(\\w\\|\\s_\\)+\\s-+\\(on\\|off\\)\\)\\|\\(^" + (regexp-opt '("use" "go" "declare") t) + "\\)\\b") + "Match an MS SQL Sever directive at the beginning of a line.") + +(defun sqlind-beginning-of-directive () + "Return the position of an SQL directive, or nil. +We will never move past one of these in our scan. We also assume +they are one-line only directives." + (let ((rx (cl-case (and (boundp 'sql-product) sql-product) + (ms sqlind-ms-directive) + (sqlite sqlind-sqlite-directive) + (oracle sqlind-sqlplus-directive) + (t nil)))) + (when rx + (save-excursion + (when (re-search-backward rx nil 'noerror) + (forward-line 1) + (point)))))) + +(defvar sqlind-search-limit nil + "Limit of search when looking for syntactic elements. +This variable is dynamically bound.") + +(defun sqlind-beginning-of-statement-1 (limit) + "Return the position of a block start, or nil. +But don't go before LIMIT." + (save-excursion + (catch 'done + (while (> (point) (or limit (point-min))) + (when (re-search-backward + ";\\|:=\\|\\_<\\(declare\\|begin\\|cursor\\|for\\|while\\|loop\\|if\\|then\\|else\\|elsif\\|elseif\\)\\_>\\|)" + limit 'noerror) + (unless (sqlind-in-comment-or-string (point)) + (let ((candidate-pos (match-end 0))) + (cond ((looking-at ")") + ;; Skip parenthesis expressions, we don't want to find one + ;; of the keywords inside one of them and think this is a + ;; statement start. + (progn (forward-char 1) (forward-sexp -1))) + ((looking-at "cursor\\|for\\|while") + ;; statement begins at the start of the keyword + (throw 'done (point))) + ((looking-at "else?if") + ;; statement begins at the start of the keyword + (throw 'done (point))) + ((looking-at "then\\|else") + ;; then and else start statements when they are inside + ;; blocks, not expressions. + (sqlind-backward-syntactic-ws) + (when (looking-at ";") + ;; Statement begins after the keyword + (throw 'done candidate-pos))) + ((looking-at "if") + (when (sqlind-good-if-candidate) + ;; statement begins at the start of the keyword + (throw 'done (point)))) + ((looking-at ":=") + ;; assignment statements start at the assigned variable + (sqlind-backward-syntactic-ws) + (forward-sexp -1) + (throw 'done (point))) + ((sqlind-looking-at-begin-transaction) + ;; This is a "begin transaction" call, statement begins + ;; at "begin", see #66 + (throw 'done (point))) + ((not (sqlind-in-comment-or-string (point))) + (throw 'done candidate-pos)))))))))) + +(defun sqlind-beginning-of-statement () + "Move point to the beginning of the current statement." + (interactive) + + (goto-char + (or + ;; If we are inside a paranthesis expression, the start is the start of + ;; that expression. + (let ((ppss (syntax-ppss (point)))) + (when (> (nth 0 ppss) 0) + (nth 1 ppss))) + ;; Look for an ordinary statement start + (or (sqlind-beginning-of-statement-1 sqlind-search-limit) + ;; Fall back on the search limit + sqlind-search-limit) + ;; ... or point-min + (point-min))) + + ;; a loop keyword might be part of an "end loop" statement, in that case, + ;; the statement starts with the "end" keyword. we use skip-syntax-backward + ;; so we won't skip over a semicolon (;) + (let ((pos (point))) + (skip-syntax-backward "w") + (if (looking-at "loop") + (progn + (forward-word -1) + (if (looking-at "\\bend\\b") + (goto-char (match-beginning 0)) + (goto-char pos))) + (goto-char pos))) + + ;; now skip over any whitespace and comments until we find the first + ;; character that is program code. + (sqlind-forward-syntactic-ws)) + +;;;;; Find the syntax and beginning of the current block + +(defconst sqlind-end-statement-regexp + "\\_<end\\_>\\(?:[ \t\n\r\f]*\\)\\(if\\_>\\|loop\\_>\\|case\\_>\\)?\\(?:[ \t\n\r\f]*\\)\\([a-z0-9_]+\\)?" + "Match an end of statement. +Matches a string like \"end if|loop|case MAYBE-LABEL\".") + +(defvar sqlind-end-stmt-stack nil + "Stack of end-of-statement positions. +This is used by the sqlind-maybe-* functions to skip over SQL +programming blocks. This variable is dynamically bound.") + +(defun sqlind-maybe-end-statement () + "Look for SQL end statements return t if found one. +If (point) is at an end statement, add it to the +`sqlind-end-stmt-stack' and return t, otherwise return nil. + +See also `sqlind-beginning-of-block'" + (when (looking-at sqlind-end-statement-regexp) + (prog1 t ; make sure we return t + (let ((kind (or (sqlind-match-string 1) "")) + (label (or (sqlind-match-string 2) ""))) + (push (list (point) (if (equal kind "") nil (intern kind)) label) + sqlind-end-stmt-stack))))) + +(defun sqlind-maybe-then-statement () + "Find the corresponding start block for a \"then\" statement. +When (point) is on a \"then\" statement, find the corresponding +start of the block and report its syntax. This code will skip +over nested statements to determine the actual start. + +Only keywords in program code are matched, not the ones inside +expressions. + +See also `sqlind-beginning-of-block'" + (when (looking-at "then") + (prog1 t ; make sure we return t + (let ((start-pos (point))) + + ;; a then keyword at the begining of a line is a block start + (when (null sqlind-end-stmt-stack) + (save-excursion + (back-to-indentation) + (when (eq (point) start-pos) + (throw 'finished (list 'in-block 'then ""))))) + + ;; if it is not at the beginning of a line, the beginning of + ;; the statement is the block start + (ignore-errors (forward-char -1)) + (sqlind-beginning-of-statement) + ;; a then keyword only starts a block when it is part of an + ;; if, case/when or exception statement + (cond + ((looking-at "\\(<<[a-z0-9_]+>>\\)?\\(?:[ \t\n\r\f]*\\)\\(\\(?:els\\)?if\\)\\_>") + (let ((if-label (sqlind-match-string 1)) + (if-kind (intern (sqlind-match-string 2)))) ; can be if or elsif + (setq if-label (if if-label (substring if-label 2 -2) "")) + (if (null sqlind-end-stmt-stack) + (throw 'finished (list 'in-block if-kind if-label)) + ;; "if" blocks (but not "elsif" blocks) need to be + ;; ended with "end if" + (when (eq if-kind 'if) + (cl-destructuring-bind (pos kind label) + (pop sqlind-end-stmt-stack) + (unless (and (eq kind 'if) + (sqlind-labels-match label if-label)) + (throw 'finished + (list 'syntax-error + "bad closing for if block" (point) pos)))))))) + ((looking-at "\\(<<[a-z0-9_]+>>\\)?\\(?:[ \t\n\r\f]*\\)case\\_>") + ;; find the nearest when block, but only if there are no + ;; end statements in the stack + (let ((case-label (sqlind-match-string 1))) + (setq case-label + (if case-label (substring case-label 2 -2) "")) + (if (null sqlind-end-stmt-stack) + (save-excursion + (when (sqlind-search-backward start-pos "\\_<when\\_>" (point)) + (throw 'finished (list 'in-block 'case case-label)))) + ;; else + (cl-destructuring-bind (pos kind label) + (pop sqlind-end-stmt-stack) + (unless (and (eq kind 'case) + (sqlind-labels-match label case-label)) + (throw 'finished + (list 'syntax-error + "bad closing for case block" (point) pos))))))) + ((looking-at "exception\\_>") + ;; an exception statement is a block start only if we have + ;; no end statements in the stack + (when (null sqlind-end-stmt-stack) + (throw 'finished (list 'in-block 'exception "")))) + (t ; restore position if we didn't do anything + (goto-char start-pos) + nil)))))) + +(defun sqlind-good-if-candidate () + "Return non-nil if point is on an actual if statement. +We try to avoid false positives, like \"end if\" or the various +\"drop STUFF if exists\" variants." + (and (looking-at "if") + (save-excursion + (sqlind-backward-syntactic-ws) + (forward-word -1) + ;; we don't want to match an "end if", and things like "drop index if + ;; exists..." and "create index if not exist..." + (not (looking-at "end\\|table\\|view\\|index\\|trigger\\|procedure\\|function\\|package\\|body"))))) + +(defun sqlind-maybe-if-statement () + "If (point) is on an IF statement, report its syntax." + (when (sqlind-good-if-candidate) + (cond ((null sqlind-end-stmt-stack) + (throw 'finished (list 'in-block 'if ""))) + (t + (cl-destructuring-bind (pos kind _label) + (pop sqlind-end-stmt-stack) + (unless (eq kind 'if) + (throw 'finshed + (list 'syntax-error + "bad closing for if block" (point) pos)))))))) + +(defun sqlind-maybe-case-statement () + "If (point) is on a case statement." + (when (looking-at "case") + (save-excursion + (sqlind-backward-syntactic-ws) + (forward-word -1) + (unless (looking-at "end") ; we don't want to match an "end case" here + (if (null sqlind-end-stmt-stack) + (throw 'finished (list 'in-block 'case "")) + (cl-destructuring-bind (pos kind _label) + (pop sqlind-end-stmt-stack) + (unless (or (not kind) (eq kind 'case)) + (throw 'finished + (list 'syntax-error + "bad closing for case block" (point) pos))))))))) + +(defun sqlind-maybe-else-statement () + "If (point) is on an ELSE statement, report its syntax. +Only keywords in program code are matched, not the ones inside +expressions. + +See also `sqlind-beginning-of-block'" + ;; an else statement is only a block start if the `sqlind-end-stmt-stack' is + ;; empty, otherwise, we don't do anything. + (when (and (looking-at "els\\(e\\|if\\)") + (null sqlind-end-stmt-stack)) + (throw 'finished (list 'in-block (intern (sqlind-match-string 0)) "")))) + +(defun sqlind-maybe-loop-statement () + "If (point) is on a LOOP statement, report its syntax. +Only keywords in program code are matched, not the ones inside +expressions. + +See also `sqlind-beginning-of-block'" + (when (looking-at "loop") + (prog1 t ; make sure we return t + (sqlind-beginning-of-statement) + ;; note that we might have found a loop in an "end loop;" statement. + (or (sqlind-maybe-end-statement) + (progn + (let ((posn (point))) + (unless (looking-at "<<") ;; whe're inside an label. + (forward-word -1) + (back-to-indentation)) + (let ((loop-label (if (looking-at "<<\\([a-z0-9_]+\\)>>") + (sqlind-match-string 1) ""))) + (goto-char posn) + ;; start of loop. this always starts a block, we only check if + ;; the labels match + (if (null sqlind-end-stmt-stack) + (throw 'finished (list 'in-block 'loop loop-label)) + (cl-destructuring-bind (pos kind label) + (pop sqlind-end-stmt-stack) + (unless (and (eq kind 'loop) + (sqlind-labels-match label loop-label)) + (throw 'finished + (list 'syntax-error + "bad closing for loop block" (point) pos)))))))))))) + +(defun sqlind-maybe-begin-statement () + "Return the syntax of a \"begin\" statement. +If (point) is on a \"begin\" statement, report its syntax. Only +keywords in program code are matched, not the ones inside +expressions. -(defcustom sql-indent-first-column-regexp - (concat "\\(^\\s-*" (regexp-opt '( - "select" "update" "insert" "delete" - "union" "intersect" - "from" "where" "into" "group" "having" "order" - "set" - "create" "drop" "truncate" - "--") t) "\\(\\b\\|\\s-\\)\\)\\|\\(^```$\\)") - "Regexp matching keywords relevant for indentation. -The regexp matches lines which start SQL statements and it matches lines -that should be indented at the same column as the start of the SQL -statement. The regexp is created at compile-time. Take a look at the -source before changing it. All lines not matching this regexp will be -indented by `sql-indent-offset'." - :type 'regexp - :group 'SQL) +See also `sqlind-beginning-of-block'" + (when (and (looking-at "begin") (not (sqlind-looking-at-begin-transaction))) + ;; a begin statement starts a block unless it is the first begin in a + ;; procedure over which we need to skip it. + (prog1 t ; make sure we return t + (let* ((saved-pos (point)) + (begin-label (save-excursion + (sqlind-beginning-of-statement) + (if (looking-at "<<\\([a-z0-9_]+\\)>>\\_>") + (sqlind-match-string 1) ""))) + (previous-block (save-excursion + (ignore-errors (forward-char -1)) + (cons (sqlind-beginning-of-block) (point)))) + (previous-block-kind (nth 0 previous-block))) + + (goto-char saved-pos) + (when (null sqlind-end-stmt-stack) + (throw 'finished + (cond ((memq previous-block-kind '(toplevel declare-statement)) + (list 'in-begin-block 'toplevel-block begin-label)) + ((and (listp previous-block-kind) + (eq (nth 0 previous-block-kind) 'defun-start)) + (list 'in-begin-block 'defun (nth 1 previous-block-kind))) + ((and (listp previous-block-kind) + (memq (nth 0 previous-block-kind) '(package package-body))) + (list 'in-begin-block 'package (nth 1 previous-block-kind))) + (t + (list 'in-begin-block nil begin-label))))) + + (cl-destructuring-bind (pos kind label) (pop sqlind-end-stmt-stack) + (cond + (kind + (throw 'finished + (list 'syntax-error "bad closing for begin block" (point) pos))) + + ((not (equal begin-label "")) + ;; we have a begin label. In this case it must match the end + ;; label + (unless (equal begin-label label) + (throw 'finished + (list 'syntax-error "mismatched block labels" (point) pos)))) + + (t + ;; we don't have a begin label. In this case, the begin + ;; statement might not start a block if it is the begining of a + ;; procedure or declare block over which we need to skip. + + (cond ((memq previous-block-kind '(toplevel declare-statement)) + (goto-char (cdr previous-block))) + ((and (listp previous-block-kind) + (memq (nth 0 previous-block-kind) + '(defun-start package package-body))) + (unless (sqlind-labels-match + label (nth 1 previous-block-kind)) + (throw 'finished + (list 'syntax-error + "bad end label for defun" (point) pos))) + (goto-char (cdr previous-block))))))))))) + +(defun sqlind-maybe-declare-statement () + "If (point) is on a DECLARE statement, report its syntax. +Only keywords in program code are matched, not the ones inside +expressions, also we don't match DECLARE directives here. + +See also `sqlind-beginning-of-block'" + (when (looking-at "declare") + ;; a declare block is always toplevel, if it is not, its an error + (throw 'finished + (if (null sqlind-end-stmt-stack) + 'declare-statement + (list 'syntax-error "nested declare block" (point) (point)))))) + +(defun sqlind-maybe-skip-create-options () + "Move point past any MySQL option declarations. + +Statements like \"CREATE VIEW\" or \"CREATE TABLE\" can have +various options betwen the CREATE keyword and the thing being +created. If such options exist at (point) the cursor is moved +past them. + +Currently we move over the following options, for different +products: + +MySQL: + + TEMPORARY + ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE} + DEFINER = { user | CURENT_USER } + SQL SECURITY { DEFINER | INVOKER } + +PostgresSQL + + TEMP + TEMPORARY + GLOBAL + LOCAL + UNLOGGED + MATERIALIZED + +Oracle + + PRIVATE + TEMP + TEMPORARY + MATERIALIZED + +We don't consider if the options are valid or not for the thing +being created. We just skip any and all of them that are +present." + (cond + ((eq sql-product 'mysql) + (catch 'finished + (while t + (cond + ((looking-at "temporary\\_>") + (goto-char (match-end 0)) + (sqlind-forward-syntactic-ws)) + ((looking-at "\\(definer\\|algorithm\\)\\(\\s-\\|[\n]\\)*=\\(\\s-\\|[\n]\\)*\\S-+") + (goto-char (match-end 0)) + (sqlind-forward-syntactic-ws)) + ((looking-at "sql\\(\\s-\\|[\n]\\)+security\\(\\s-\\|[\n]\\)+\\S-+") + (goto-char (match-end 0)) + (sqlind-forward-syntactic-ws)) + (t (throw 'finished nil)))))) + ((eq sql-product 'postgres) + (catch 'finished + (while t + (cond + ((looking-at "temp\\(orary\\)?\\_>") + (goto-char (match-end 0)) + (sqlind-forward-syntactic-ws)) + ((looking-at "\\(global\\|local\\|unlogged\\)\\_>") + (goto-char (match-end 0)) + (sqlind-forward-syntactic-ws)) + ((looking-at "materialized\\_>") + (goto-char (match-end 0)) + (sqlind-forward-syntactic-ws)) + (t (throw 'finished nil)))))) + ((eq sql-product 'oracle) + (catch 'finished + (while t + (cond + ((looking-at "temp\\(orary\\)\\_>") + (goto-char (match-end 0)) + (sqlind-forward-syntactic-ws)) + ((looking-at "materialized\\_>") + (goto-char (match-end 0)) + (sqlind-forward-syntactic-ws)) + ((looking-at "private\\_>") + (goto-char (match-end 0)) + (sqlind-forward-syntactic-ws)) + (t (throw 'finished nil)))))))) + +(defun sqlind-maybe-create-statement () + "If (point) is on a CREATE statement, report its syntax. +See also `sqlind-beginning-of-block'" + (when (or (looking-at "create\\_>\\(?:[ \t\n\r\f]+\\)\\(or\\(?:[ \t\n\r\f]+\\)replace\\_>\\)?") + (looking-at "alter\\_>")) + (prog1 t ; make sure we return t + (save-excursion + ;; let's see what are we creating + (goto-char (match-end 0)) + (sqlind-forward-syntactic-ws) + (sqlind-maybe-skip-create-options) + (let ((what (intern (downcase (buffer-substring-no-properties + (point) + (progn (forward-word) (point)))))) + (name (downcase (buffer-substring-no-properties + (progn (sqlind-forward-syntactic-ws) + ;; Skip over a possible "if (not) + ;; exists", to get the actual name + (when (looking-at "if\\(\\s-\\|[\n]\\)+\\(not\\)?\\(\\s-\\|[\n]\\)exists") + (goto-char (match-end 0)) + (sqlind-forward-syntactic-ws)) + (point)) + (progn (skip-syntax-forward "w_()") (point)))))) + (when (and (eq what 'package) (equal name "body")) + (setq what 'package-body) + (setq name (downcase + (buffer-substring-no-properties + (progn (sqlind-forward-syntactic-ws) (point)) + (progn (skip-syntax-forward "w_()") (point)))))) + + ;; Keep just the name, not the argument list + (when (string-match "\\(.*?\\)(" name) + (setq name (match-string 1 name))) + + (if (memq what '(procedure function package package-body)) + ;; check is name is in the form user.name, if so then suppress user part. + (progn + (when (string-match "\\(?:.*\\.\\)?\\(.*\\)" name) + (setq name (match-string 1 name))) + (if (null sqlind-end-stmt-stack) + (throw 'finished + (list (if (memq what '(procedure function)) 'defun-start what) + name)) + (cl-destructuring-bind (pos kind label) (pop sqlind-end-stmt-stack) + (when (not (eq kind nil)) + (throw 'finished + (list 'syntax-error + "bad closing for create block" (point) pos))) + (unless (sqlind-labels-match label name) + (throw 'finished + (list 'syntax-error + "label mismatch in create block" (point) pos)))))) + ;; we are creating a non-code block thing: table, view, + ;; index, etc. These things only exist at toplevel. + (unless (null sqlind-end-stmt-stack) + (throw 'finished + (list 'syntax-error "nested create statement" (point) (point)))) + (throw 'finished (list 'create-statement what name)))))))) + +(defun sqlind-maybe-defun-statement () + "If (point) is on a procedure definition statement, report its syntax. +See also `sqlind-beginning-of-block'" + (catch 'exit + (when (looking-at "\\(procedure\\|function\\)\\(?:[ \t\n\r\f]+\\)\\([a-z0-9_]+\\)") + (prog1 t ; make sure we return t + (let ((proc-name (sqlind-match-string 2))) + ;; need to find out if this is a procedure/function + ;; declaration or a definition + (save-excursion + (goto-char (match-end 0)) + (sqlind-forward-syntactic-ws) + ;; skip param list, if any. + (when (looking-at "(") + (ignore-errors (forward-sexp 1)) + (sqlind-forward-syntactic-ws)) + (when (looking-at "return\\(?:[ \t\n\r\f]+\\)\\([a-z0-9_.]+\\(?:%\\(?:row\\)?type\\)?\\)") + (goto-char (match-end 0)) + (sqlind-forward-syntactic-ws)) + (when (looking-at ";") + ;; not a procedure after all. + (throw 'exit nil))) + + ;; Find out if it is a drop procedure or function statement + (save-excursion + (sqlind-backward-syntactic-ws) + (forward-word -1) + (when (looking-at "drop") + ;; not a procedure after all + (throw 'exit nil))) + + ;; so it is a definition + + ;; if the procedure starts with "create or replace", move + ;; point to the real start + (let ((real-start (point))) + (save-excursion + (forward-word -1) + (when (looking-at "replace") + (forward-word -2)) + (when (and (or (looking-at "create\\([ \t\r\n\f]+or[ \t\r\n\f]+replace\\)?") + (looking-at "alter")) + (not (sqlind-in-comment-or-string (point)))) + (setq real-start (point)))) + (goto-char real-start)) + + (when (null sqlind-end-stmt-stack) + (throw 'finished (list 'defun-start proc-name))) + + (cl-destructuring-bind (pos kind label) (pop sqlind-end-stmt-stack) + (unless (and (eq kind nil) + (sqlind-labels-match label proc-name)) + (throw 'finished + (list 'syntax-error "bad end label for defun" (point) pos))))))))) -(defcustom sql-indent-offset 4 - "*Offset for SQL indentation." - :type 'number - :group 'SQL) +(defun sqlind-maybe-exception-statement () + "If (point) is on an exception keyword, report its syntax. +See also `sqlind-beginning-of-block'" + (when (and (looking-at "exception") + (null sqlind-end-stmt-stack)) + ;; Exception is both a keyword and a type. We need to only stop on the + ;; keyword. We detect that if the previous token is either ";" or + ;; "BEGIN". + (save-excursion + (forward-char -1) + (sqlind-backward-syntactic-ws) + (when (or (looking-at ";") + (progn (forward-word -1) (looking-at "\\<_begin\\_>"))) + (throw 'finished (list 'in-block 'exception)))))) + +(defun sqlind-maybe-$$-statement () + "If (point) is on a PostgreSQL $$ quote, report its syntax. + +PostgreSQL uses $$ to delimit SQL blocks in create statements, +this function tries to determine if the $$ block is a begin or an +end block and creates the appropiate syntactic context. + +See also `sqlind-beginning-of-block'" + (when (looking-at "\\$\\$") + (prog1 t + (let* ((saved-pos (point))) + (ignore-errors (forward-char -1)) + (sqlind-backward-syntactic-ws) + (cond ((looking-at ";") + ;; Assume the $$ is ending a statement (previous line is a ';' + ;; which ends another statement) + (push (list saved-pos '$$ "") sqlind-end-stmt-stack) + (goto-char saved-pos)) + ((null sqlind-end-stmt-stack) + (sqlind-beginning-of-statement) + (let ((syntax (catch 'finished + (sqlind-maybe-create-statement) + (sqlind-maybe-defun-statement) + 'toplevel))) + (if (and (listp syntax) (eq (nth 0 syntax) 'defun-start)) + (throw 'finished (list 'in-begin-block 'defun (nth 1 syntax))) + (throw 'finished (list 'in-begin-block syntax nil))))) + (t + (sqlind-beginning-of-statement) + (cl-destructuring-bind (pos kind _label) (pop sqlind-end-stmt-stack) + (unless (eq kind '$$) + (throw 'finished + (list 'syntax-error "bad closing for $$ begin block" (point) pos)))))))))) + +(defconst sqlind-start-block-regexp + (concat "\\(\\_<" + (regexp-opt '("if" "then" "else" "elsif" "elseif" "loop" + "begin" "declare" "create" "alter" "exception" + "procedure" "function" "end" "case") t) + "\\_>\\)\\|)\\|\\$\\$") + "Regexp to match the start of a block.") + +(defun sqlind-beginning-of-block (&optional end-statement-stack) + "Find the start of the current block and return its syntax. + +END-STATEMENT-STACK contains a list of \"end\" syntaxes in +reverse order (a stack) and is used to skip over nested blocks." + (interactive) + ;; This function works as follows: `sqlind-start-block-regexp` defines the + ;; keywords where it stops to inspect the code. Each time it stops at one + ;; of these keywords, it checks to see if the keyword is inside a comment or + ;; string. If the keyworkd is not inside a comment or string, the + ;; `sqlind-maybe-*` functions are called to check if the keyword is valid. + ;; Each of these functions will do one of the following: + ;; + ;; * throw a syntax object with a 'finished tag, if they decide that the + ;; keyword is valid + ;; + ;; * return t to indicate that they decided that the keyword is not valid + ;; and `sqlind-beginning-of-block` should search for the next keyword + ;; + ;; * return nil to indicate that they don't recognize the keyword and + ;; another `sqlind-maybe-*` function should be called + ;; + ;; Some of these `sqlind-maybe-*` functions are specific to the + ;; `sql-product` and are only invoked for the speficied SQL dialect. + + (catch 'finished + (let ((sqlind-end-stmt-stack end-statement-stack)) + (while (re-search-backward sqlind-start-block-regexp sqlind-search-limit 'noerror) + (or (sqlind-in-comment-or-string (point)) + (when (looking-at ")") (forward-char 1) (forward-sexp -1) t) + (sqlind-maybe-end-statement) + (sqlind-maybe-if-statement) + (sqlind-maybe-case-statement) + (sqlind-maybe-then-statement) + (sqlind-maybe-exception-statement) + (sqlind-maybe-else-statement) + (sqlind-maybe-loop-statement) + (sqlind-maybe-begin-statement) + (when (eq sql-product 'oracle) ; declare statements only start blocks in PL/SQL + (sqlind-maybe-declare-statement)) + (when (eq sql-product 'postgres) + (sqlind-maybe-$$-statement)) + (sqlind-maybe-create-statement) + (sqlind-maybe-defun-statement)))) + 'toplevel)) + +;;;;; Determine the syntax inside a case expression + +(defconst sqlind-case-clauses-regexp + "\\_<\\(when\\|then\\|else\\|end\\)\\_>") + +(defun sqlind-syntax-in-case (pos start) + "Return the syntax at POS which is part a \"case\" expression at START." + (save-excursion + (goto-char pos) + (cond ((looking-at "when\\|else") + ;; A WHEN, or ELSE clause is indented relative to the start of the + ;; case expression + (cons 'case-clause start)) + ((looking-at "end") + (cons (list 'block-end 'case "") start)) + ((looking-at "then") + ;; THEN and ELSE clauses are indented relative to the start of the + ;; when clause, which we must find + (while (not (and (re-search-backward "\\_<when\\_>") + (sqlind-same-level-statement (point) start))) + nil) + (cons 'case-clause-item (point))) + (t + ;; It is a statement continuation from the closest CASE element + (while (and (not (= (point) start)) + (not (and (re-search-backward sqlind-case-clauses-regexp start 'noerror) + (sqlind-same-level-statement (point) start)))) + nil) + (cons 'case-clause-item-cont (point)))))) + +;;;;; Determine the syntax inside a with statement + +(defconst sqlind-with-clauses-regexp + "\\_<\\(with\\|recursive\\)\\_>") + +(defun sqlind-syntax-in-with (pos start) + "Return the syntax at POS which is part of a \"with\" statement at START." + (save-excursion + (catch 'finished + (goto-char pos) + (cond + ((looking-at sqlind-with-clauses-regexp) + (throw 'finished (cons 'with-clause start))) + ((and (looking-at "\\_<select\\_>") + (sqlind-same-level-statement (point) start)) + (throw 'finished (cons 'with-clause start)))) + (while (re-search-backward "\\_<select\\_>" start 'noerror) + (when (sqlind-same-level-statement (point) start) + (throw 'finished (sqlind-syntax-in-select pos (point))))) + (goto-char pos) + (when (looking-at "\\_<as\\_>") + (throw 'finished (cons 'with-clause-cte-cont start))) + (sqlind-backward-syntactic-ws) + (when (looking-at ",") + (throw 'finished (cons 'with-clause-cte start))) + (forward-word -1) + (when (looking-at sqlind-with-clauses-regexp) + ;; We're right after the with (recursive keyword) + (throw 'finished (cons 'with-clause-cte start))) + (throw 'finished (cons 'with-clause-cte-cont start))))) + +;;;;; Determine the syntax inside a select statement + +(defconst sqlind-select-clauses-regexp + (concat + "\\_<\\(" + "\\(\\(union\\(\\s-+all\\)?\\)\\|intersect\\|minus\\|except\\)?[ \t\r\n\f]*select\\|" + "\\(bulk[ \t\r\n\f]+collect[ \t\r\n\f]+\\)?into\\|" + "from\\|" + "where\\|" + "order[ \t\r\n\f]+by\\|" + "having\\|" + "group[ \t\r\n\f]+by\\|" + "connect[ \t\r\n\f]+by\\|" + "start[ \t\r\n\f]+with\\|" + "limit" + "\\)\\_>")) + +(defconst sqlind-select-join-regexp + (regexp-opt '("inner" "left" "right" "natural" "cross" "full") 'symbols)) + +(defconst sqlind-join-condition-regexp + (regexp-opt '("on" "using" "and" "or") 'symbols)) + +(defun sqlind-find-join-start (start limit) + "Look backwards for the start of a JOIN statement, +begin looking for it at the START position in the buffer, and +look backwards until LIMIT is reached. Returns the buffer +position where the JOIN condition starts, or nil if no JOIN +statement is found." + (save-excursion + (when (sqlind-search-backward start "\\bjoin\\b" limit) + (let ((candidate (point))) + (forward-char -1) + (sqlind-backward-syntactic-ws) + (backward-word) + (if (looking-at sqlind-select-join-regexp) + (point) + ;; The "outer" keyword is composed with a "left" or "right" keyword + ;; so we need to move backwards one more word. + (if (looking-at "\\bouter\\b") + (progn + (forward-char -1) + (sqlind-backward-syntactic-ws) + (backward-word) + (if (looking-at "\\b\\(left\\|right\\)\\b") + (point) + candidate)) + candidate)))))) + +(defun sqlind-syntax-in-select (pos start) + "Return the syntax ar POS which is inside a \"select\" statement at START." + (save-excursion + (catch 'finished + (goto-char pos) + + ;; all select query components are indented relative to the + ;; start of the select statement) + (when (looking-at sqlind-select-clauses-regexp) + (throw 'finished (cons 'select-clause start))) + + ;; when we are not looking at a select component, find the + ;; nearest one from us. + + (while (sqlind-search-backward (point) sqlind-select-clauses-regexp start) + (let* ((match-pos (match-beginning 0)) + (clause (sqlind-match-string 0))) + (setq clause (replace-regexp-in-string "[ \t\r\n\f]" " " clause)) + (when (sqlind-same-level-statement (point) start) + (cond + ((looking-at "select\\(\\s *\\_<\\(top\\s +[0-9]+\\|distinct\\|unique\\)\\_>\\)?") + ;; we are in the column selection section. + (goto-char pos) + (if (looking-at ",") + (throw 'finished (cons 'select-column match-pos)) + (progn + (sqlind-backward-syntactic-ws) + (throw 'finished + (cons (if (or (eq (match-end 0) (1+ (point))) + (looking-at ",")) + 'select-column + 'select-column-continuation) + match-pos))))) + + ((looking-at "from") + ;; FROM is only keyword if the previous char is NOT a + ;; comma ',' + (forward-char -1) + (sqlind-backward-syntactic-ws) + (unless (looking-at ",") + ;; We are in the from section. If this line starts with 'on' + ;; or the previous line ends with 'on' we have a join + ;; condition + (goto-char pos) + (when (or (looking-at sqlind-join-condition-regexp) + (progn (forward-word -1) (looking-at sqlind-select-join-regexp))) + ;; look for the join start, that will be the anchor + (let ((jstart (sqlind-find-join-start (point) start))) + (when jstart + (throw 'finished (cons 'select-join-condition jstart)))))) + + ;; if this line starts with a ',' or the previous line starts + ;; with a ',', we have a new table + (goto-char pos) + (when (or (looking-at ",") + (progn + (sqlind-backward-syntactic-ws) + (looking-at ","))) + (throw 'finished (cons 'select-table match-pos))) + + ;; otherwise, we continue the table definition from the + ;; previous line. + (throw 'finished (cons 'select-table-continuation match-pos))) + + (t + (throw 'finished + (cons (list 'in-select-clause clause) match-pos)))))))))) -(defvar sql-indent-debug nil - "If non-nil, `sql-indent-line' will output debugging messages.") +;;;;; Determine the syntax inside an insert statement -(defun sql-indent-is-string-or-comment () - "Return nil if point is not in a comment or string; non-nil otherwise." - (let ((parse-state (syntax-ppss))) - (or (nth 3 parse-state) ; String - (nth 4 parse-state))) ; Comment - ) +(defconst sqlind-insert-clauses-regexp + "\\_<\\(insert\\([ \t\r\n\f]+into\\)?\\|values\\|select\\)\\_>") -(defun sql-indent-get-last-line-start () - "Find the last non-blank line. Return the beginning position of that line and its indentation." - - (save-excursion - (forward-line -1) +(defun sqlind-syntax-in-insert (pos start) + "Return the syntax at POS which is inside an \"insert\" statement at START." - (while (and (not (bobp)) - (or - (looking-at "^\\s-*$") - (sql-indent-is-string-or-comment)) ; Skip comments or strings - ) - - (forward-line -1)) - (list (point) (current-indentation)) - ) - ) - -(defun sql-indent-level-delta (&optional prev-start prev-indent) - "Calculate the change in level from the previous non-blank line. -Given the optional parameter `PREV-START' and `PREV-INDENT', assume that to be -the previous non-blank line. -Return a list containing the level change and the previous indentation." + ;; The insert clause is really easy since it has the form insert into TABLE + ;; (COLUMN_LIST) values (VALUE_LIST) or insert into TABLE select + ;; SELECT_CLAUSE + ;; + ;; note that we will never be called when point is in COLUMN_LIST or + ;; VALUE_LIST, as that is a nested-statement-continuation which starts with + ;; the open paranthesis. + ;; + ;; if we are inside the SELECT_CLAUSE, we delegate the syntax to + ;; `sqlind-syntax-in-select' (save-excursion - ;; Go back to the previous non-blank line - (let* ((p-line (cond ((and prev-start prev-indent) - (list prev-start prev-indent)) - ((sql-indent-get-last-line-start)))) - (curr-start (point-at-bol)) - (paren (nth 0 (parse-partial-sexp (nth 0 p-line) curr-start)))) + (catch 'finished + (goto-char pos) + + ;; all select query components are indented relative to the + ;; start of the select statement) + (when (looking-at sqlind-insert-clauses-regexp) + (throw 'finished (cons 'insert-clause start))) + + (while (re-search-backward sqlind-insert-clauses-regexp start t) + (let* ((match-pos (match-beginning 0)) + (clause (sqlind-match-string 0))) + (setq clause (replace-regexp-in-string "[ \t\r\n\f]" " " clause)) + (when (sqlind-same-level-statement (point) start) + (throw 'finished + (if (looking-at "select") + (sqlind-syntax-in-select pos match-pos) + (cons (list 'in-insert-clause clause) match-pos))))))))) + + +;;;;; Determine the syntax inside a delete statement + +(defconst sqlind-delete-clauses-regexp + "\\_<\\(delete\\([ \t\r\n\f]+from\\)?\\|where\\|returning\\|\\(bulk[ \t\r\n\f]collect[ \t\r\n\f]\\)?into\\)\\_>") + +(defun sqlind-syntax-in-delete (pos start) + "Return the syntax at POS which is inside a \"delete\" statement at START." + (save-excursion + (catch 'finished + (goto-char pos) + + ;; all select query components are indented relative to the + ;; start of the select statement) + (when (looking-at sqlind-delete-clauses-regexp) + (throw 'finished (cons 'delete-clause start))) + + (while (re-search-backward sqlind-delete-clauses-regexp start t) + (let* ((match-pos (match-beginning 0)) + (clause (sqlind-match-string 0))) + (setq clause (replace-regexp-in-string "[ \t\r\n\f]" " " clause)) + (when (sqlind-same-level-statement (point) start) + (throw 'finished + (cons (list 'in-delete-clause clause) match-pos)))))))) + + +;;;;; Determine the syntax inside an update statement + +(defconst sqlind-update-clauses-regexp + "\\_<\\(update\\|set\\|where\\)\\_>") + +(defun sqlind-syntax-in-update (pos start) + "Return the syntax at POS which is inside an \"update\" statement at START." + (save-excursion + (catch 'finished + (goto-char pos) + + ;; all select query components are indented relative to the start of the + ;; select statement) + (when (looking-at sqlind-update-clauses-regexp) + (throw 'finished (cons 'update-clause start))) + + (while (re-search-backward sqlind-update-clauses-regexp start t) + (let* ((match-pos (match-beginning 0)) + (clause (sqlind-match-string 0))) + (setq clause (replace-regexp-in-string "[ \t\r\n\f]" " " clause)) + (when (sqlind-same-level-statement (point) start) + (throw 'finished + (cons (list 'in-update-clause clause) match-pos)))))))) + + +;;;;; Refine the syntax of an end statement. + +(defun sqlind-refine-end-syntax (end-kind end-label end-pos context) + "Return a 'block-end syntax for a line containing an \"end\" keyword. + +END-KIND contains the symbol after the end statement ('if if the +statement is an \"end if\", 'loop if the statement is an \"end +loop\", etc). This can be nil if there is a plain \"end\" +keyword. + +END-LABEL contains the label of the end statement, if there is +one. + +END-POS is the position where the \"end\" keyword is. + +CONTEXT represents the syntactic context up to the current line. + +The function will perform some validations, for example, an \"end +if\" must close an if statement, an \"end loop\" must close a +loop, etc. It will return a 'syntax-error syntax if the +validation fails. + +If all checks pass, it will return a (block-end KIND LABEL) where +KIND is the symbol determining the type of the block ('if, 'loop, +'procedure, etc) and LABEL is the block label, if there is any." + (catch 'done + + (when (null context) ; can happen + (throw 'done + (cons (list 'syntax-error "end statement closes nothing" + end-pos end-pos) + end-pos))) + + (let ((syntax (sqlind-syntax context)) + (anchor (sqlind-anchor-point context)) + (syntax-symbol (sqlind-syntax-symbol context))) + (cond + ((memq syntax-symbol '(package package-body)) + ;; we are closing a package declaration or body, `end-kind' must be + ;; empty, `end-label' can be empty or it must match the package name + (throw 'done + (cons + (cond (end-kind ; no end-kind is allowed for a package + (list 'syntax-error + "bad closing for package" anchor end-pos)) + ((sqlind-labels-match end-label (nth 1 syntax)) + (list 'block-end syntax-symbol (nth 1 syntax))) + (t + (list 'syntax-error "mismatched end label for package" + anchor end-pos))) + anchor))) + + ((eq syntax-symbol 'in-begin-block) + ;; we are closing a begin block (either toplevel, procedure/function + ;; or a simple begin block. `end-kind' must be empty, `end-label' + ;; can be empty or it must match the pakage-name + (let ((block-label (nth 2 syntax))) + (throw 'done + (cons + (cond (end-kind ; no end-kind is allowed for a begin block + (list 'syntax-error + "bad closing for begin block" anchor end-pos)) + ((sqlind-labels-match end-label block-label) + (list 'block-end (nth 1 syntax) block-label)) + (t + (list 'syntax-error "mismatched end label for block" + anchor end-pos))) + anchor)))) + + ((eq syntax-symbol 'in-block) + (let ((block-kind (nth 1 syntax)) + (block-label (nth 2 syntax))) + (cond + ((eq block-kind 'exception) + (goto-char anchor) + (throw 'done + (sqlind-refine-end-syntax + end-kind end-label end-pos (sqlind-syntax-of-line)))) + + ((eq block-kind 'loop) + (throw 'done + (cons + (cond ((not (eq end-kind 'loop)) + (list 'syntax-error "bad closing for loop block" + anchor end-pos)) + ((not (sqlind-labels-match end-label block-label)) + (list 'syntax-error "mismatched end label for loop" + anchor end-pos)) + (t + (list 'block-end block-kind block-label))) + anchor))) + + ((eq block-kind 'then) + (goto-char anchor) + + (catch 'found + (while t + (let ((then-context (sqlind-syntax-of-line))) + (goto-char (cdar then-context)) + (cond + ((looking-at "when\\_>\\|then\\_>") t) + ((looking-at "\\(?:<<\\([a-z0-9_]+\\)>>[ \t\r\n\f]*\\)?\\_<\\(if\\|case\\)\\_>") + (throw 'found t)) + (t + (throw 'done + (cons + (list 'syntax-error "bad syntax start for then keyword" + (point) (point)) + anchor))))))) + + (let ((start-label (or (sqlind-match-string 1) "")) + (start-kind (intern (sqlind-match-string 2)))) + (throw 'done + (cons + (cond ((not (or (null end-kind) (eq end-kind start-kind))) + (list 'syntax-error "bad closing for if/case block" + (point) end-pos)) + ((not (sqlind-labels-match end-label start-label)) + (list 'syntax-error "mismatched labels for if/case block" + (point) end-pos)) + (t + (list 'block-end start-kind start-label))) + anchor)))) + + ((memq block-kind '(else elsif elseif)) + ;; search the enclosing then context and refine form there. The + ;; `cdr' in sqlind-syntax-of-line is used to remove the + ;; block-start context for the else clause + (goto-char anchor) + (throw 'done + (sqlind-refine-end-syntax + end-kind end-label end-pos (cdr (sqlind-syntax-of-line))))) + + ((memq block-kind '(if case)) + (throw 'done + (cons + (cond ((not (eq end-kind block-kind)) + (list 'syntax-error "bad closing for if/case block" + anchor end-pos)) + ((not (sqlind-labels-match end-label block-label)) + (list 'syntax-error + "bad closing for if/case block (label mismatch)" + anchor end-pos)) + (t (list 'block-end block-kind block-label))) + anchor))) + ))) + + ((memq syntax-symbol '(block-start comment-start)) + ;; there is a more generic context following one of these + (throw 'done + (sqlind-refine-end-syntax + end-kind end-label end-pos (cdr context)))) + + ((eq syntax-symbol 'defun-start) + (throw 'done + (cons + (if (and (null end-kind) + (sqlind-labels-match end-label (nth 1 syntax))) + (list 'block-end 'defun end-label) + (list 'syntax-error "mismatched end label for defun" + anchor end-pos)) + anchor))) + + ((eq syntax-symbol 'block-end) + (goto-char anchor) + (forward-line -1) + (throw 'done + (sqlind-refine-end-syntax + end-kind end-label end-pos (sqlind-syntax-of-line))))) + + ;; if the above cond fell through, we have a syntax error + (cons (list 'syntax-error "end statement closes nothing" + end-pos end-pos) + anchor)))) + + +;;;;; sqlind-syntax-of-line + +(defun sqlind-refine-syntax (context pos have-block-context) + "Refine a basic syntax CONTEXT at POS. +CONTEXT is a syntactic context obtained by looking at the +statement start and block start, see `sqlind-syntax-of-line'. We +refine it by looking at the contents of the current line and the +contents of the anchor. + +HAVE-BLOCK-CONTEXT indicates that we are indenting a statement, +not a statement-continuation POS is the same as the +`sqlind-beginning-of-statement'." + (let ((syntax (sqlind-syntax context)) + (anchor (sqlind-anchor-point context)) + (syntax-symbol (sqlind-syntax-symbol context))) + + (goto-char pos) + + (cond + ;; do we start a comment? + ((and (not (eq syntax-symbol 'comment-continuation)) + (looking-at sqlind-comment-start-skip)) + (push (cons 'comment-start anchor) context)) + + ;; Refine a statement continuation + ((memq syntax-symbol '(statement-continuation nested-statement-continuation)) + + ;; a (nested) statement continuation which starts with loop + ;; or then is a block start + (if (and have-block-context (looking-at "\\(loop\\|then\\|when\\)\\_>")) + (push (cons (list 'block-start (intern (sqlind-match-string 0))) anchor) + context) + ;; else + (goto-char anchor) + (when (eq syntax 'nested-statement-continuation) + (forward-char 1) + (sqlind-forward-syntactic-ws) + (setq anchor (point))) - ;; Add opening or closing parens. - ;; If the current line starts with a keyword statement (e.g. SELECT, FROM, ...) back up one level - ;; If the previous line starts with a keyword statement then add one level + ;; when all we have before `pos' is a label, we have a + ;; labeled-statement-start + (when (looking-at "<<\\([a-z0-9_]+\\)>>") + (goto-char (match-end 0)) + (forward-char 1) + (sqlind-forward-syntactic-ws) + (when (eq (point) pos) + (push (cons 'labeled-statement-start anchor) context))) + + (when (looking-at "when\\_>") + (let* ((acontext (sqlind-syntax-of-line)) + (asyntax (sqlind-syntax acontext))) + (cond ((equal asyntax '(in-block exception "")) + (push (cons '(in-block exception-handler "") (point)) context)) + ((equal asyntax '(block-start when)) + ;; Refine again in the context of the when line + (setq context (sqlind-refine-syntax (cdr acontext) pos have-block-context)))))) + + ;; maybe we have a DML statement (select, insert, update and + ;; delete) + + ;; skip a cursor definition if it is before our point, in the + ;; following format: + ;; + ;; CURSOR name IS + ;; CURSOR name type IS + (when (looking-at "cursor\\b") + (let ((origin (point))) + (forward-sexp 3) + (sqlind-forward-syntactic-ws) + (when (looking-at "is\\b") + (goto-char (match-end 0)) + (sqlind-forward-syntactic-ws)) + (unless (<= (point) pos) + (goto-char origin)))) + + ;; skip a forall statement if it is before our point + (when (looking-at "forall\\b") + (when (re-search-forward "\\b\\(select\\|update\\|delete\\|insert\\)\\b" pos 'noerror) + (goto-char (match-beginning 0)))) + + ;; only check for syntax inside DML clauses if we are not + ;; at the start of one. + (when (< (point) pos) + (cond + ;; NOTE: We only catch here "CASE" expressions, not CASE + ;; statements. We also catch assignments with case (var + ;; := CASE ...) + ((looking-at "\\(\\w+[ \t\r\n\f]+:=[ \t\r\n\f]+\\)?\\(case\\)") + (when (< (match-beginning 2) pos) + (push (sqlind-syntax-in-case pos (match-beginning 2)) context))) + ((looking-at "with") + (push (sqlind-syntax-in-with pos (point)) context)) + ((looking-at "select") + (push (sqlind-syntax-in-select pos (point)) context)) + ((looking-at "insert") + (push (sqlind-syntax-in-insert pos (point)) context)) + ((looking-at "delete") + (push (sqlind-syntax-in-delete pos (point)) context)) + ((looking-at "update") + (push (sqlind-syntax-in-update pos (point)) context)))) + + (when (eq (sqlind-syntax-symbol context) 'select-column-continuation) + (let ((cdef (sqlind-column-definition-start pos (sqlind-anchor-point context)))) + (when cdef + (save-excursion + (goto-char cdef) + (when (looking-at "case") + (push (sqlind-syntax-in-case pos (point)) context)))))) + + (when (eq (sqlind-syntax-symbol context) 'nested-statement-continuation) + (save-excursion + ;; Look for a join expression inside a nested statement, see #70 + (goto-char pos) + (when (or (looking-at sqlind-join-condition-regexp) + (progn (forward-word -1) (looking-at sqlind-join-condition-regexp))) + ;; look for the join start, that will be the anchor + (let ((jstart (sqlind-find-join-start (point) anchor))) + (when jstart + (push (cons 'select-join-condition jstart) context)))))) + + )) + + ;; create block start syntax if needed + + ((and (eq syntax-symbol 'in-block) + (memq (nth 1 syntax) '(if elsif elseif then case)) + (looking-at "\\(then\\|\\(els\\(e\\|e?if\\)\\)\\)\\_>")) + (let ((what (intern (sqlind-match-string 0)))) + ;; the only invalid combination is a then statement in + ;; an (in-block "then") context + (unless (and (eq what 'then) (equal (nth 1 syntax) 'then)) + (push (cons (list 'block-start what) anchor) context)))) + + ((and (eq syntax-symbol 'in-block) + (eq (nth 1 syntax) 'exception) + (not (looking-at "\\(when\\|end\\)\\_>"))) + (save-excursion + (when (sqlind-search-backward pos "when\\_>" anchor) + (push (cons (list 'in-block 'exception-handler) (point)) context)))) + + ;; note that begin is not a block-start in a 'in-begin-block + ;; context + ((and (memq syntax-symbol '(defun-start declare-statement toplevel + package package-body)) + (or (looking-at "begin\\_>") + (and (eq sql-product 'postgres) (looking-at "\\$\\$")))) + (push (cons (list 'block-start 'begin) anchor) context)) + + ((and (memq syntax-symbol '(defun-start package package-body)) + (looking-at "\\(is\\|as\\)\\_>")) + (push (cons (list 'block-start 'is-or-as) anchor) context)) + + ((and (memq syntax-symbol '(in-begin-block in-block)) + (looking-at "exception\\_>")) + (push (cons (list 'block-start 'exception) anchor) context)) + + ((and (eq syntax-symbol 'in-block) + (memq (nth 1 syntax) '(then case))) + (if (looking-at "when\\_>") + (push (cons (list 'block-start 'when) anchor) context) + ;; NOTE: the "when" case is handed above + (when (sqlind-search-backward pos "when\\_>" anchor) + (push (cons '(in-block when) (point)) context)))) + + ;; indenting the select clause inside a view or a "create table as" + ;; statement. + ((and (eq syntax-symbol 'create-statement) + (memq (nth 1 syntax) '(view table))) + (goto-char anchor) + (catch 'done + (while (re-search-forward "\\bselect\\b" pos 'noerror) + (goto-char (match-beginning 0)) + (when (sqlind-same-level-statement (point) anchor) + (push (sqlind-syntax-in-select pos (point)) context) + (throw 'done nil)) + (goto-char (match-end 0))))) + + ;; create a block-end syntax if needed + + ((and (not (eq syntax-symbol 'comment-continuation)) + (looking-at "end[ \t\r\n\f]*\\(\\_<\\(?:if\\|loop\\|case\\)\\_>\\)?[ \t\r\n\f]*\\(\\_<\\(?:[a-z0-9_]+\\)\\_>\\)?")) + ;; so we see the syntax which closes the current block. We still + ;; need to check if the current end is a valid closing block + (let ((kind (or (sqlind-match-string 1) "")) + (label (or (sqlind-match-string 2) ""))) + (push (sqlind-refine-end-syntax + (if (equal kind "") nil (intern kind)) + label (point) context) + context))) + + ((and (eq sql-product 'postgres) + (not (eq syntax-symbol 'comment-continuation)) + (looking-at "\\$\\$")) + (push (sqlind-refine-end-syntax + nil "" (point) context) + context)) + ) + context)) + +(defun sqlind-syntax-of-line () + "Return the syntax at the start of the current line. +The function returns a list of (SYNTAX . ANCHOR) cons cells. +SYNTAX is either a symbol or a list starting with a symbol, +ANCHOR is a buffer position which is the reference for the +SYNTAX. `sqlind-indentation-syntax-symbols' lists the syntax +symbols and their meaning. + +The first element in the list is the most specific syntax for the +line, the remaining elemens are more generic ones. For example, +a line can be inside an SELECT clause which itself is inside a +procedure block." + (save-excursion + (with-syntax-table sqlind-syntax-table + (let* ((pos (progn (back-to-indentation) (point))) + (sqlind-search-limit (sqlind-beginning-of-directive)) + (context-start (progn (sqlind-beginning-of-statement) (point))) + (context (list (cons 'statement-continuation context-start))) + (have-block-context nil)) + + (goto-char context-start) + (when (or (>= context-start pos) + (and (looking-at sqlind-start-block-regexp) + (not (sqlind-looking-at-begin-transaction)))) + (goto-char pos) + ;; if we are at the start of a statement, or the nearest statement + ;; starts after us, make the enclosing block the starting context + (setq have-block-context t) + (let ((block-info (sqlind-beginning-of-block))) + + ;; certain kind of blocks end within a statement + ;; (e.g. create view). If we found one of those blocks and + ;; it is not within our statement, we ignore the block info. + + (if (and (listp block-info) + (eq (nth 0 block-info) 'create-statement) + (not (memq (nth 1 block-info) '(function procedure))) + (not (eql context-start (point)))) + (progn + (setq context-start (point-min)) + (setq context (list (cons 'toplevel context-start)))) + ;; else + (setq context-start (point)) + (setq context (list (cons block-info context-start)))))) + + (let ((parse-info (syntax-ppss pos))) + (cond ((nth 4 parse-info) ; inside a comment + (push (cons 'comment-continuation (nth 8 parse-info)) context)) + ((nth 3 parse-info) ; inside a string + (push (cons 'string-continuation (nth 8 parse-info)) context)) + ((> (nth 0 parse-info) 0) ; nesting + (let ((start (nth 1 parse-info))) + (goto-char (1+ start)) + (skip-chars-forward " \t\r\n\f\v" pos) + (if (eq (point) pos) + (push (cons 'nested-statement-open start) context) + (goto-char pos) + (if (looking-at ")") + (push (cons 'nested-statement-close start) context) + (push (cons 'nested-statement-continuation start) context))))))) + + ;; now let's refine the syntax by adding info about the current line + ;; into the mix. + (sqlind-refine-syntax context pos have-block-context))))) + + +(defun sqlind-show-syntax-of-line () + "Print the syntax of the current line." + (interactive) + (prin1 (sqlind-syntax-of-line))) + + +;;;; Indentation of SQL code +;;;;; Indentation calculation routines +(defvar sqlind-basic-offset 2 + "The basic indentaion amount for SQL code. +Indentation is usually done in multiples of this amount, but +special indentation functions can do other types of indentation +such as aligning. See also `sqlind-indentation-offsets-alist'.") + +(make-variable-buffer-local 'sqlind-basic-offset) + +(defvar sqlind-indentation-syntax-symbols '() + "This variable exists just for its documentation. + +The the SQL parsing code returns a syntax definition (either a +symbol or a list) and an anchor point, which is a buffer +position. The syntax symbols can be used to define how to indent +each line, see `sqlind-indentation-offsets-alist' + +The following syntax symbols are defined for SQL code: + +- (syntax-error MESSAGE START END) -- this is returned when the + parse failed. MESSAGE is an informative message, START and END + are buffer locations denoting the problematic region. ANCHOR + is undefined for this syntax info + +- `in-comment' -- line is inside a multi line comment, ANCHOR is + the start of the comment. + +- `comment-start' -- line starts with a comment. ANCHOR is the + start of the enclosing block. + +- `in-string' -- line is inside a string, ANCHOR denotes the start + of the string. + +- `toplevel' -- line is at toplevel (not inside any programming + construct). ANCHOR is usually (point-min). + +- (in-block BLOCK-KIND LABEL) -- line is inside a block + construct. BLOCK-KIND (a symbol) is the actual block type and + can be one of \"if\", \"case\", \"exception\", \"loop\" etc. + If the block is labeled, LABEL contains the label. ANCHOR is + the start of the block. + +- (in-begin-block KIND LABEL) -- line is inside a block started + by a begin statement. KIND (a symbol) is \"toplevel-block\" + for a begin at toplevel, \"defun\" for a begin that starts the + body of a procedure or function, \"package\" for a begin that + starts the body of a package, or nil for a begin that is none + of the previous. For a \"defun\" or \"package\", LABEL is the + name of the procedure, function or package, for the other block + types LABEL contains the block label, or the empty string if + the block has no label. ANCHOR is the start of the block. + +- (block-start KIND) -- line begins with a statement that starts + a block. KIND (a symbol) can be one of \"then\", \"else\" or + \"loop\". ANCHOR is the reference point for the block + start (the coresponding if, case, etc). - (list - (+ paren - (if (progn (goto-char (nth 0 p-line)) - (looking-at sql-indent-first-column-regexp)) - 1 - 0) - (if (progn (goto-char curr-start) - (looking-at sql-indent-first-column-regexp)) - -1 - 0) - ) - (nth 1 p-line)) - ) - ) +- (block-end KIND LABEL) -- the line contains an end statement. + KIND (a symbol) is the type of block we are closing, LABEL (a + string) is the block label (or procedure name for an end + defun). + +- declare-statement -- line is after a declare keyword, but + before the begin. ANCHOR is the start of the declare + statement. + +- (package NAME) -- line is inside a package definition. NAME is + the name of the package, ANCHOR is the start of the package. + +- (package-body NAME) -- line is inside a package body. NAME is + the name of the package, ANCHOR is the start of the package + body. + +- (create-statement WHAT NAME) -- line is inside a CREATE + statement (other than create procedure or function). WHAT is + the thing being created, NAME is its name. ANCHOR is the start + of the create statement. + +- (defun-start NAME) -- line is inside a procedure of function + definition but before the begin block that starts the body. + NAME is the name of the procedure/function, ANCHOR is the start + of the procedure/function definition. + +The following SYNTAX-es are for SQL statements. For all of +them ANCHOR points to the start of a statement itself. + +- labeled-statement-start -- line is just after a label. + +- statement-continuation -- line is inside a statement which + starts on a previous line. + +- nested-statement-open -- line is just inside an opening + bracket, but the actual bracket is on a previous line. + +- nested-statement-continuation -- line is inside an opening + bracket, but not the first element after the bracket. + +- nested-statement-close -- line is inside an opening bracket and + the line contains the closing bracket as the first character. + +The following SYNTAX-es are for statements which are SQL +code (DML statements). They are pecialisations on the previous +statement syntaxes and for all of them a previous generic +statement syntax is present earlier in the SYNTAX list. Unless +otherwise specified, ANCHOR points to the start of the +clause (select, from, where, etc) in which the current point is. + +- with-clause -- line is inside a WITH clause, but before the + main SELECT clause. + +- with-clause-cte -- line is inside a with clause before a + CTE (common table expression) declaration + +- with-clause-cte-cont -- line is inside a with clause before a + CTE definition + +- case-clause -- line is on a CASE expression (WHEN or END + clauses). ANCHOR is the start of the CASE expression. + +- case-clause-item -- line is on a CASE expression (THEN and ELSE + clauses). ANCHOR is the position of the case clause. + +- case-clause-item-cont -- line is on a CASE expression but not + on one of the CASE sub-keywords. ANCHOR points to the case + keyword that this line is a continuation of. + +- select-clause -- line is inside a select statement, right + before one of its clauses (from, where, order by, etc). + +- select-column -- line is inside the select column section, + after a full column was defined (and a new column definition is + about to start). + +- select-column-continuation -- line is inside the select column + section, but in the middle of a column definition. The defined + column starts on a previous like. Note that ANCHOR still + points to the start of the select statement itself. + +- select-join-condition -- line is right before or just after the ON clause + for an INNER, LEFT or RIGHT join. ANCHOR points to the join statement + for which the ON is defined. + +- select-table -- line is inside the from clause, just after a + table was defined and a new one is about to start. + +- select-table-continuation -- line is inside the from clause, + inside a table definition which starts on a previous line. Note + that ANCHOR still points to the start of the select statement + itself. + +- (in-select-clause CLAUSE) -- line is inside the select CLAUSE, + which can be \"where\", \"order by\", \"group by\" or + \"having\". Note that CLAUSE can never be \"select\" and + \"from\", because we have special syntaxes inside those + clauses. + +- insert-clause -- line is inside an insert statement, right + before one of its clauses (values, select). + +- (in-insert-clause CLAUSE) -- line is inside the insert CLAUSE, + which can be \"insert into\" or \"values\". + +- delete-clause -- line is inside a delete statement right before + one of its clauses. + +- (in-delete-clause CLAUSE) -- line is inside a delete CLAUSE, + which can be \"delete from\" or \"where\". + +- update-clause -- line is inside an update statement right + before one of its clauses. + +- (in-update-clause CLAUSE) -- line is inside an update CLAUSE, + which can be \"update\", \"set\" or \"where\".") + +(defconst sqlind-default-indentation-offsets-alist + '((syntax-error sqlind-report-sytax-error) + (in-string sqlind-report-runaway-string) + + (comment-continuation sqlind-indent-comment-continuation) + (comment-start sqlind-indent-comment-start) + + (toplevel 0) + (in-block +) + (in-begin-block +) + (block-start 0) + (block-end 0) + (declare-statement +) + (package ++) + (package-body 0) + (create-statement +) + (defun-start +) + (labeled-statement-start 0) + (statement-continuation +) + (nested-statement-open sqlind-use-anchor-indentation +) + (nested-statement-continuation sqlind-use-previous-line-indentation) + (nested-statement-close sqlind-use-anchor-indentation) + + (with-clause sqlind-use-anchor-indentation) + (with-clause-cte +) + (with-clause-cte-cont ++) + (case-clause 0) + (case-clause-item sqlind-use-anchor-indentation +) + (case-clause-item-cont sqlind-right-justify-clause) + (select-clause sqlind-right-justify-clause) + (select-column sqlind-indent-select-column) + (select-column-continuation sqlind-indent-select-column +) + (select-join-condition ++) + (select-table sqlind-indent-select-table) + (select-table-continuation sqlind-indent-select-table +) + (in-select-clause sqlind-lineup-to-clause-end + sqlind-right-justify-logical-operator) + (insert-clause sqlind-right-justify-clause) + (in-insert-clause sqlind-lineup-to-clause-end) + (delete-clause sqlind-right-justify-clause) + (in-delete-clause sqlind-lineup-to-clause-end) + (update-clause sqlind-right-justify-clause) + (in-update-clause sqlind-lineup-to-clause-end)) + "Define the indentation amount for each syntactic symbol. + +The value of this variable is an ALIST with the format: + + ((SYNTACTIC-SYMBOL . INDENTATION-OFFSETS) ... ) + +`sqlind-indentation-syntax-symbols' documents the list of possible +SYNTACTIC-SYMBOL values. + +INDENTATION-OFFSETS defines the adjustments made to the +indentation for each syntactic-symbol. It is a list of: + + a NUMBER -- the NUMBER will be added to the indentation offset. + + '+ -- the current indentation offset is incremented by + `sqlind-basic-offset' + + '++ -- the current indentation offset is indentation by 2 * + `sqlind-basic-offset' + + '- -- the current indentation offset is decremented by + `sqlind-basic-offset' + + '-- -- the current indentation offset is decremented by 2 * + `sqlind-basic-offset' + + a FUNCTION -- the syntax and current indentation offset is + passed to the function and its result is used as the new + indentation offset. + +See `sqlind-calculate-indentation' for how the indentation offset +is calculated.") + +(defvar sqlind-indentation-offsets-alist + sqlind-default-indentation-offsets-alist + "Define the indentation amount for each syntactic symbol. +See also `sqlind-default-indentation-offsets-alist', +`sqlind-indentation-syntax-symbols' and +`sqlind-calculate-indentation'") + +(make-variable-buffer-local 'sqlind-indentation-offsets-alist) + +(defun sqlind-calculate-indentation (syntax &optional base-indentation) + "Return the indentation that should be applied to the current line. +SYNTAX is the syntaxtic information as returned by +`sqlind-syntax-of-line', BASE-INDENTATION is an indentation offset +to start with. When BASE-INDENTATION is nil, it is initialised +to the column of the anchor. + +The indentation is done as follows: first, the indentation +offsets for the current syntactic symbol is looked up in +`sqlind-indentation-offsets-alist'. Than, for each indentation +offset, BASE-INDENTATION is adjusted according to that +indentation offset. The final value of BASE-INDENTATION is than +returned." + (if (null syntax) + base-indentation + ;; else + + ;; when the user did not specify a base-indentation, we use the + ;; column of the anchor as a starting point + (when (null base-indentation) + (setq base-indentation (save-excursion + (goto-char (cdar syntax)) + (current-column)))) + + (let* ((syntax-symbol (sqlind-syntax-symbol syntax)) + (indent-info (cdr (assoc syntax-symbol + sqlind-indentation-offsets-alist))) + (new-indentation base-indentation)) + + ;; the funcall below can create a nil indentation symbol to + ;; abort the indentation process + (while (and new-indentation indent-info) + (let ((i (car indent-info))) + (setq new-indentation + (cond + ((eq i '+) (+ new-indentation sqlind-basic-offset)) + ((eq i '++) (+ new-indentation (* 2 sqlind-basic-offset))) + ((eq i '-) (- new-indentation sqlind-basic-offset)) + ((eq i '--) (- new-indentation (* 2 sqlind-basic-offset))) + ((integerp i) (+ new-indentation i)) + ((functionp i) (funcall i syntax new-indentation)) + ;; ignore unknown symbols by default + (t new-indentation)))) + (setq indent-info (cdr indent-info))) + new-indentation))) + +;;;;; Indentation helper functions + +(defun sqlind-report-sytax-error (syntax _base-indentation) + "Report a syntax error for a 'syntax-error SYNTAX." + (cl-destructuring-bind (_sym msg start end) (sqlind-syntax syntax) + (message "%s (%d %d)" msg start end)) + nil) + +(defun sqlind-report-runaway-string (_syntax _base-indentation) + "Report an error for a runaway string. +This is a string that extends over multiple lines. This is not +supported in SQL." + (message "runaway string constant") + nil) + +(defun sqlind-use-anchor-indentation (syntax _base-indentation) + "Return the indentation of the line containing anchor of SYNTAX. +By default, the column of the anchor position is uses as a base +indentation. You can use this function to switch to using the +indentation of the anchor as the base indentation." + (save-excursion + (goto-char (sqlind-anchor-point syntax)) + (current-indentation))) + +(defun sqlind-lineup-to-anchor (syntax _base-indentation) + "Return the column of the anchor point of SYNTAX. +This need not be the indentation of the actual line that contains +anchor." + (save-excursion + (goto-char (sqlind-anchor-point syntax)) + (current-column))) + +(defun sqlind-use-previous-line-indentation (syntax _base-indentation) + "Return the indentation of the previous line. +If the start of the previous line is before the anchor of SYNTAX, +use the column of the anchor + 1." + (let ((anchor (sqlind-anchor-point syntax))) + (save-excursion + (forward-line -1) + (back-to-indentation) + (if (< (point) anchor) + (progn + (goto-char anchor) + (1+ (current-column))) + (current-column))))) + +(defun sqlind-indent-comment-continuation (syntax _base-indentation) + "Return the indentation for a line inside a comment SYNTAX. +If the current line matches `sqlind-comment-prefix' or +`sqlind-comment-end', we indent to one plus the column of the +comment start, which will make comments line up nicely, like +this: + + /* Some comment line + * another comment line + */ + +When the current line does not match `sqlind-comment-prefix', we +indent it so it lines up with the text of the start of the +comment, like this: + + /* Some comment line + Some other comment line + */" + (save-excursion + (back-to-indentation) + (if (or (looking-at sqlind-comment-prefix) + (looking-at sqlind-comment-end)) + (progn + (goto-char (sqlind-anchor-point syntax)) + (1+ (current-column))) + ;; else + (goto-char (sqlind-anchor-point syntax)) + (when (looking-at sqlind-comment-start-skip) + (goto-char (match-end 0))) + (current-column)))) + +(defun sqlind-indent-comment-start (syntax base-indentation) + "Return the indentation for a comment start SYNTAX. +If we start a line comment (--) and the previous line also has a +line comment, we line up the two comments. Otherwise we indent +in the previous context (cdr SYNTAX) starting at +BASE-INDENTATION." + (save-excursion + (back-to-indentation) + (if (and (looking-at "\\s *--") + (progn + (forward-line -1) + (re-search-forward "--" (line-end-position) t))) + (progn + (goto-char (match-beginning 0)) + (current-column)) + (sqlind-calculate-indentation + (sqlind-outer-context syntax) base-indentation)))) + +(defun sqlind-indent-select-column (syntax base-indentation) + "Return the indentation for a column of a SELECT clause. + +SYNTAX is the syntax of the current line, BASE-INDENTATION is the +current indentation, which we need to update. + +We try to align to the previous column start, but if we are the +first column after the SELECT clause we simply add +`sqlind-basic-offset'." + (save-excursion + (goto-char (sqlind-anchor-point syntax)) + (when (looking-at "select\\s *\\(top\\s +[0-9]+\\|distinct\\|unique\\)?") + (goto-char (match-end 0))) + (skip-syntax-forward " ") + (if (or (looking-at sqlind-comment-start-skip) + (eolp)) + (+ base-indentation sqlind-basic-offset) + (current-column)))) + +(defun sqlind-indent-select-table (syntax base-indentation) + "Return the indentation for a table in the FROM section. + +SYNTAX is the syntax of the current line, BASE-INDENTATION is the +current indentation, which we need to update. + +We try to align to the first table, but if we are the first +table, we simply add `sqlind-basic-offset'." + (save-excursion + (goto-char (sqlind-anchor-point syntax)) + (when (looking-at "from") + (goto-char (match-end 0))) + (skip-syntax-forward " ") + (if (or (looking-at sqlind-comment-start-skip) + (eolp)) + (+ base-indentation sqlind-basic-offset) + (current-column)))) + +(defun sqlind-lineup-to-clause-end (syntax base-indentation) + "Line up the current line with the end of a query clause. + +This assumes SYNTAX is one of in-select-clause, in-update-clause, +in-insert-clause or in-delete-clause. It will return an +indentation so that: + +If the clause is on a line by itself, the current line is +indented by `sqlind-basic-offset', otherwise the current line is +indented so that it starts in next column from where the clause +keyword ends. +Argument BASE-INDENTATION is updated." + (cl-destructuring-bind ((_sym clause) . anchor) (car syntax) + (save-excursion + (goto-char anchor) + (forward-char (1+ (length clause))) + (skip-syntax-forward " ") + (if (or (looking-at sqlind-comment-start-skip) + (eolp)) + ;; if the clause is on a line by itself, indent this line with a + ;; sqlind-basic-offset + (+ base-indentation sqlind-basic-offset) + ;; otherwise, align to the end of the clause, with a few exceptions + (current-column))))) + +(defun sqlind-right-justify-logical-operator (syntax base-indentation) + "Align an AND, OR or NOT operator with the end of the WHERE clause. + +SYNTAX is the syntax of the current line, BASE-INDENTATION is the +current indentation, which we need to update. + +If this rule is added to the 'in-select-clause syntax after the +`sqlind-lineup-to-clause-end' rule, it will adjust lines starting +with AND, OR or NOT to be aligned so they sit under the WHERE clause." + (save-excursion + (back-to-indentation) + (cl-destructuring-bind ((_sym clause) . anchor) (car syntax) + (if (and (equal clause "where") + (looking-at "and\\|or\\|not")) + (- base-indentation (1+ (- (match-end 0) (match-beginning 0)))) + base-indentation)))) + +(defun sqlind-left-justify-logical-operator (syntax base-indentation) + "Align an AND, OR or NOT operator with the start of the WHERE clause. + +SYNTAX is the syntax of the current line, BASE-INDENTATION is the +current indentation, which we need to update. + +If this rule is added to the 'in-select-clause syntax after the +`sqlind-lineup-to-clause-end' rule, it will adjust lines starting +with AND, OR or NOT to be aligned so they sit left under the WHERE clause." + (save-excursion + (back-to-indentation) + (cl-destructuring-bind ((_sym clause) . anchor) (car syntax) + (if (and (equal clause "where") + (looking-at "and\\|or\\|not")) + (progn (goto-char anchor) (current-column)) + base-indentation)))) + +(defconst sqlind-operator-regexp + (concat (regexp-opt '("||" "*" "/" "%" "+" "-" "<<" ">>" "&" "|" + "<" "<=" ">" ">=" "=" "==" "!=" "<>") + t) + "\\s-*") + "Regexp to match a SQL expression operator.") + +(defun sqlind-adjust-operator (syntax base-indentation) + "Adjust the indentation for operators in select clauses. + +If the line to be indented starts with an operator, the +right-hand operand is lined up with the left hand operand on the +previous line. Otherwise, BASE-INDENTATION is returned. For +example: + + select col1, col2 + || col3 as composed_column, + col4 + || col5 as composed_column2 + from my_table + where cond1 = 1 + and cond2 = 2; + +This is an indentation adjuster and needs to be added to the +`sqlind-indentation-offsets-alist`" + (save-excursion + (with-syntax-table sqlind-syntax-table + (back-to-indentation) + ;; If there are non-word constituents at the beginning if the line, + ;; consider them an operator and line up the line to the first word of the + ;; line, not the operator + (cond ((looking-at sqlind-operator-regexp) + (let ((ofs (length (match-string 0)))) + (if (eq (sqlind-syntax-symbol syntax) + 'select-column-continuation) + (goto-char (sqlind-column-definition-start + (point) (sqlind-anchor-point syntax))) + (forward-line -1) + (end-of-line) + (sqlind-backward-syntactic-ws) + ;; Previous function leaves us on the first non-white-space + ;; character. This might be a string terminator (') char, move + ;; the cursor one to the left, so 'forward-sexp' works correctly. + (ignore-errors (forward-char 1)) + (forward-sexp -1)) + (max 0 (- (current-column) ofs)))) + ('t base-indentation))))) + +(defun sqlind-lone-semicolon (syntax base-indentation) + "Indent a lone semicolon with the statement start. For example: + +If the current line contains a single semicolon ';', it will be +indented at the same level as the anhcor of SYNTAX. Otherwise, +BASE-INDENTATION is returned unchanged. For example: + + select col + from my_table + ; + +This is an indentation adjuster and needs to be added to the +`sqlind-indentation-offsets-alist`" + (save-excursion + (back-to-indentation) + (if (looking-at ";") + (sqlind-use-anchor-indentation syntax base-indentation) + base-indentation))) + +(defun sqlind-right-justify-clause (syntax base-indentation) + "Return an indentation which right-aligns the first word at +anchor of SYNTAX with the first word in the curent line. + +This is intended to be used as an indentation function for +select-clause, update-clause, insert-clause and update-clause +syntaxes" + (save-excursion + (let ((clause-length 0) + (statement-keyword-length 0) + offset) + (back-to-indentation) + (when (looking-at "\\sw+\\b") + (setq clause-length (- (match-end 0) (match-beginning 0)))) + (goto-char (cdar syntax)) ; move to ANCHOR + (when (looking-at "\\sw+\\b") + (setq statement-keyword-length (- (match-end 0) (match-beginning 0)))) + (setq offset (- statement-keyword-length clause-length)) + (if (> offset 0) + (+ base-indentation offset) + base-indentation)))) + +(defun sqlind-lineup-joins-to-anchor (syntax base-indentation) + "Align JOIN keywords with the anchor point of SYNTAX. +If the line starts with an INNER,OUTER or CROSS JOIN keyword, +return the column of the anchor point, otherwise return +BASE-INDENTATION. + +If this rule is added to `select-table-continuation' indentation, +it will indent lines starting with JOIN keywords to line up with +the FROM keyword." + (save-excursion + (back-to-indentation) + ;; NOTE: we are a bit loose here as we only look for the first keyword + ;; which might indicate a join regexp, e.g. we are happy to see "left" + ;; even though, the correct statement is "left outer? join" + (if (or (looking-at sqlind-select-join-regexp) + (looking-at "\\bjoin\\b")) + (sqlind-lineup-to-anchor syntax base-indentation) + base-indentation))) + +(defun sqlind-lineup-open-paren-to-anchor (syntax base-indentation) + "Align an open paranthesis with the anchor point of SYNTAX. +If the line starts with an open paren '(', return the column of +the anchor point. If line does not start with an open paren, the +function returns BASE-INDENTATION, acting as a no-op." + (save-excursion + (back-to-indentation) + (if (looking-at "(") + (sqlind-lineup-to-anchor syntax base-indentation) + base-indentation))) + +(defun sqlind-adjust-comma (_syntax base-indentation) + "Lineup lines starting with a comma ',' to the word start. +Adjust BASE-INDENTATION so that the actual word is lined up. For +example: + + SELECT col1 + , col2 -- ignore the comma and align the actual word." + (save-excursion + (back-to-indentation) + (let ((ofs (if (looking-at ",\\s-*") (length (match-string 0)) 0))) + (max 0 (- base-indentation ofs))))) + +(defun sqlind-lineup-into-nested-statement (syntax _base-indentation) + "Align the line to the first word inside a nested statement. +Return the column of the first non-witespace char in a nested +statement. For example: + + ( a, + b, -- b is always aligned with 'a' ) -(defun sql-indent-buffer () - "Indent the buffer's SQL statements." - (interactive) +This function only makes sense in a +'nested-statement-continuation SYTNAX indentation rule." (save-excursion - (goto-char (point-min)) - (while (/= (point) (point-max)) - (forward-line) - (sql-indent-line) - (end-of-line)))) + (goto-char (sqlind-anchor-point syntax)) + (forward-char 1) + (sqlind-forward-syntactic-ws) + (current-column))) + +;;;;; sqlind-indent-line + +(defun sqlind-indent-line () + "Indent the current line according to SQL conventions. +`sqlind-basic-offset' defined the number of spaces in the basic +indentation unit and `sqlind-indentation-offsets-alist' is used to +determine how to indent each type of syntactic element." + (let* ((syntax (sqlind-syntax-of-line)) + (base-column (current-column)) + (indent-column (sqlind-calculate-indentation syntax))) + (when indent-column + (back-to-indentation) + (let ((offset (- base-column (current-column)))) + ;; avoid modifying the buffer when the indentation does not + ;; have to change + (unless (eq (current-column) indent-column) + (indent-line-to indent-column)) + (when (> offset 0) + (forward-char offset)))))) + +;;;; Alignment rules -(defun sql-indent-line () - "Indent current line in an SQL statement." - (interactive) - (let* ((pos (point)) - (indent-info (sql-indent-level-delta)) - (level-delta (nth 0 indent-info)) - (prev-indent (nth 1 indent-info)) - (this-indent (max 0 ; Make sure the indentation is at least 0 - (+ prev-indent - (* sql-indent-offset - (nth 0 indent-info))))) - ) - - (if sql-indent-debug - (message "SQL Indent: line: %3d, level delta: %3d; prev: %3d; this: %3d" - (line-number-at-pos) level-delta prev-indent this-indent)) +(defvar sqlind-align-rules + `(;; Line up the two side of arrow => + (sql-arrow-lineup + (regexp . "\\(\\s-*\\)=>\\(\\s-*\\)") + (modes quote (sql-mode)) + (group 1 2) + (case-fold . t) + (repeat . t)) + ;; Line up the two sides of an assigment + (sql-assign-lineup + (regexp . "^\\s-*\\S-+\\(\\s-*\\):=\\(\\s-*\\)") + (modes quote (sql-mode)) + (group 1 2) + (case-fold . t) + (repeat . t)) + ;; lineup a variable declaration with an assignment + (sql-assign-lineup-2 + (regexp . "^\\s-*\\S-+\\(\\s-+\\)\\S-+\\(\\s-*\\):=\\(\\s-*\\)") + (modes quote (sql-mode)) + (group 1 2 3) + (case-fold . t) + (repeat . t)) + ;; Line up the two sides of in / out / in out parameter + (sql-param-lineup-in-out + (regexp . "\\(\\s-+\\)\\(in out\\|in\\|out\\)\\(\\s-+\\)") + (modes quote (sql-mode)) + (group 1 3) + (case-fold . t) + (repeat . t)) + ;; Line up the two sides of an equal sign in an update expression + (sql-equals + (regexp . "[^:<>!]\\(\\s-*\\)=\\(\\s-*\\)[^>]") + (modes quote (sql-mode)) + (group 1 2) + (case-fold . t) + (valid . ,(function (lambda () + (save-excursion + (goto-char (match-end 1)) + (not (nth 3 (syntax-ppss (point)))))))) + (repeat . t)) + (sql-comparison-operators ; see issue #47 + (regexp . "[^:]\\(\\s-*\\)[<>=!]+\\(\\s-*\\)[^>]") + (modes quote (sql-mode)) + (group 1 2) + (case-fold . t) + (valid . ,(function (lambda () + (save-excursion + (goto-char (match-end 1)) + (not (nth 3 (syntax-ppss (point)))))))) + (repeat . t)) + ;; Line up the two sides of piped string + (sql-pipes + (regexp . "[^:]\\(\\s-*\\)||\\(\\s-*\\)[^>]") + (modes quote (sql-mode)) + (group 1 2) + (case-fold . t) + (repeat . t)) + ;; lineup the column aliases (the "as name" part) in a select statement + (sql-select-lineup-column-names + (regexp . ".*?\\(\\s +\\)as\\(\\s +\\).*") + (modes quote (sql-mode)) + (group 1 2) + (case-fold . t) + (repeat . t))) + "Align rules for SQL codes. - (save-excursion +These rules help aligning some SQL statements, such as the column +names in select queries, or equal signs in update statements or +where clauses. + +To use it, select the region to be aligned and run \\[align]. + +See also `align' and `align-rules-list'") + +;;;; sqlind-minor-mode, sqlind-setup - (beginning-of-line) +(defvar sqlind-minor-mode-map + (let ((map (make-sparse-keymap))) + (define-key map [remap beginning-of-defun] 'sqlind-beginning-of-block) + map)) + +(defvar align-mode-rules-list) + +;;;###autoload +(define-minor-mode sqlind-minor-mode + "Toggle SQL syntactic indentation on or off. +With syntactic indentation, hitting TAB on a line in a SQL buffer +will indent the line according to the syntactic context of the +SQL statement being edited. - (if (and (not (looking-at "^\\s-*$")) ; Leave blank lines alone - (not (sql-indent-is-string-or-comment)) ; Don't mess with comments or strings - (/= this-indent (current-indentation))) ; Don't change the line if already ok. - (indent-line-to this-indent)) - ) - ) - ) +A set of alignment rules are also enabled with this minor mode. +Selecting a region of text and typing `M-x align RET` will align +the statements. This can be used, for example, to align the 'as' +column aliases in select statements." + :lighter " sqlind" + ;; :group 'sqlind ;;FIXME: There's no such group! + :global nil + :init-value nil + (if sqlind-minor-mode + (progn + (set (make-local-variable 'indent-line-function) #'sqlind-indent-line) + (set (make-local-variable 'align-mode-rules-list) sqlind-align-rules)) + (progn + (kill-local-variable 'indent-line-function) + (kill-local-variable 'align-mode-rules-list)))) -(add-hook 'sql-mode-hook - (function (lambda () - (make-local-variable 'indent-line-function) - (setq indent-line-function 'sql-indent-line)))) +;;;###autoload +(defun sqlind-setup () + "Enable SQL syntactic indentation unconditionally. +This function is deprecated, consider using the function +`sqlind-minor-mode' instead." + (set (make-local-variable 'indent-line-function) 'sqlind-indent-line) + (define-key sql-mode-map [remap beginning-of-defun] 'sqlind-beginning-of-statement) + (setq align-mode-rules-list sqlind-align-rules)) + +;; Local Variables: +;; mode: emacs-lisp +;; mode: outline-minor +;; outline-regexp: ";;;;+" +;; End: (provide 'sql-indent) - ;;; sql-indent.el ends here
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/sql-indent.org @@ -0,0 +1,556 @@ + + sql-indent.el -- syntax based indentation for SQL files for GNU Emacs + +*NOTE* This file is formatted as an Emacs Org file. If you open it in GNU +Emacs, you will be able to open-close sections of the file, which will make +navigation easier. + +* Overview + +sql-indent.el is a GNU Emacs minor mode which adds support for syntax-based +indentation when editing SQL code: TAB indents the current line based on the +syntax of the SQL code on previous lines. This works like the indentation for +C and C++ code. + +The package also defines align rules so that the ~align~ function works for +SQL statements, see ~sqlind-align-rules~ for which rules are defined. This +can be used to align multiple lines around equal signs or "as" statements. +Here is an example of alignment rules: + +#+BEGIN_SRC sql + update my_table + set col1_has_a_long_name = value1, + col2_is_short = value2, + col3_med = v2, + c4 = v5 + where cond1 is not null; + + select long_colum as lcol, + scol as short_column, + mcolu as mcol, + from my_table; +#+END_SRC + +To use this feature, select the region you want to align and type: + +#+BEGIN_SRC text + M-x align RET +#+END_SRC + +~sqlind-minor-mode~ together with the align rules can assist in writing tidy +SQL code or formatting existing SQL code. The indentation rules are +customizable, so you can adapt it to match your own indentation preferences. + +* Installation + +To install this package, open the file ~sql-indent.el~ in Emacs and type + +#+BEGIN_SRC text + M-x package-install-from-buffer RET +#+END_SRC + +The syntax-based indentation of SQL code can be turned ON/OFF at any time by +enabling or disabling ~sqlind-minor-mode~: + +#+BEGIN_SRC text + M-x sqlind-minor-mode RET +#+END_SRC + +To enable syntax-based indentation for every SQL buffer, you can add +~sqlind-minor-mode~ to ~sql-mode-hook~. First, bring up the customization +buffer using the command: + +#+BEGIN_SRC text + M-x customize-variable RET sql-mode-hook RET +#+END_SRC + +Than, click on the "INS" button to add a new entry and put "sqlind-minor-mode" +in the text field. + +* Customization + +The sql-indent.el package allows customizing the indentation rules to suit +your personal preferences or site specific coding styles. To create a set of +customized rules, you will need to have basic familiarity with how indentation +works. See also the "A Simple Example" section below and the +~sql-indent-left.el~ file, which demonstrate how to set up custom indentation +rules. The sections below contain the rest of the details. + +The indentation process happens in two separate phases: first syntactic +information is determined about the line, than the line is indented based on +that syntactic information. The syntactic parse is not expected to change +often, since it deals with the structure of the SQL code, however, indentation +is a personal preference, and can be easily customized. + +Two variables control the way code is indented: ~sqlind-basic-offset~ and +~sqlind-indentation-offsets-alist~. To customize these variables, you need to +create a function that sets custom values and add it to ~sql-mode-hook~. + +** A Simple Example + +The default indentation rules will align to the right all the keywords in a +SELECT statement, like this: + +#+BEGIN_SRC sql + select c1, c2 + from t1 + where c3 = 2 +#+END_SRC + +If you prefer to have them aligned to the left, like this: + +#+BEGIN_SRC sql + select c1, c2 + from t1 + where c3 = 2 +#+END_SRC + +You can add the following code to your init file: + +#+BEGIN_SRC emacs-lisp + (require 'sql-indent) + + ;; Update indentation rules, select, insert, delete and update keywords + ;; are aligned with the clause start + + (defvar my-sql-indentation-offsets-alist + `((select-clause 0) + (insert-clause 0) + (delete-clause 0) + (update-clause 0) + ,@sqlind-default-indentation-offsets-alist)) + + (add-hook 'sqlind-minor-mode-hook + (lambda () + (setq sqlind-indentation-offsets-alist + my-sql-indentation-offsets-alist))) +#+END_SRC + +** Customization Basics + +To customize indentation, you will need to provide a new value for the +~sqlind-indentation-offsets-alist~ variable. The variable is made buffer +local each time it is set, so you need to set it inside the ~sql-mode-hook~. +The variable specifies how each syntactic symbol should be indented. Since +only a few symbols need to be updated, the usual way to update it is to +"extend" the value of ~sqlind-default-indentation-offsets-alist~, like so: + +#+BEGIN_SRC emacs-lisp + (defvar my-sql-indentation-offsets-alist + `( ;; put new syntactic symbols here, and add the default ones at the end. + ;; If there is no value specified for a syntactic symbol, the default + ;; will be picked up. + ,@sqlind-default-indentation-offsets-alist)) + + ;; Arrange for the new indentation offset to be set up for each SQL buffer. + (add-hook 'sqlind-minor-mode-hook + (lambda () + (setq sqlind-indentation-offsets-alist + my-sql-indentation-offsets-alist))) +#+END_SRC + +The simplest way to adjust the indentation is to explore the syntactic +information using ~sqlind-show-syntax-of-line~. To use it, move the cursor to +the line you would like to indent and type: + +#+BEGIN_SRC text +M-x sqlind-show-syntax-of-line RET +#+END_SRC + +A message like the one below will be shown in the messages buffer: + +#+BEGIN_SRC text +((select-clause . 743) (statement-continuation . 743)) +#+END_SRC + +The first symbol displayed is the syntactic symbol used for indentation, in +this case ~select-clause~. The syntactic symbols are described in a section +below, however, for now, this is the symbol that will need to be updated in +~sqlind-indentation-offsets-alist~. The number next to it represents the +anchor, or reference position in the buffer where the current statement +starts. The anchor and is useful if you need to write your own indentation +functions. + +To customize indentation for this type of statement, add an entry in the +~sqlind-indentation-offsets-alist~, for the syntactic symbol shown, with +information about how it should be indented. This information is a list +containing *indentation control items* (these are described below). + +For example, to indent keyword in SELECT clauses at the same level as the +keyword itself, we use a number which is added to the indentation level of the +anchor, in this case, 0: + +#+BEGIN_SRC text +(select-clause 0) +#+END_SRC + +To indent it at ~sqlind-basic-offset~ plus one more space, use: + +#+BEGIN_SRC text +(select-clause + 1) +#+END_SRC + +To right-justify the keyword w.r.t the SELECT keyword, use: + +#+BEGIN_SRC text +(select-clause sqlind-right-justify-clause) +#+END_SRC + +The default value for ~sqlind-indentation-offsets-alist~ contains many +examples for indentation setup rules. + +** Indentation control items + +~sqlind-calculate-indentation~ is the function that calculates the indentation +offset to use, based on the contents of ~sqlind-indentation-offsets-alist~. +The indentation offset starts with the indentation column of the ANCHOR point +and it is adjusted based on the following items: + + * a ~NUMBER~ -- the NUMBER will be added to the indentation offset. + + * ~+~ -- the current indentation offset is incremented by + ~sqlind-basic-offset~ + + * ~++~ -- the current indentation offset is indentation by ~2 * + sqlind-basic-offset~ + + * ~-~ -- the current indentation offset is decremented by + ~sqlind-basic-offset~ + + * ~--~ -- the current indentation offset is decremented by 2 * + ~sqlind-basic-offset~ + + * a ~FUNCTION~ -- the syntax and current indentation offset is passed to the + function and its result is used as the new indentation offset. This can be + used to further customize indentation. + +*** Indentation Helper Functions + +The following helper functions are available as part of the package and can be +used as the FUNCTION part in the ~sqlind-indentation-offsets-alist~ + +**** sqlind-use-anchor-indentation + +discard the current offset and returns the indentation column of the ANCHOR + +**** sqlind-lineup-to-anchor + +discard the current offset and returns the column of the anchor point, which +may be different than the indentation column of the anchor point. + +**** sqlind-use-previous-line-indentation + +discard the current offset and returns the indentation column of the previous +line + +**** sqlind-lineup-open-paren-to-anchor + +if the line starts with an open parenthesis, discard the current +offset and return the column of the anchor point. + +**** sqlind-lone-semicolon + +if the line contains a single semicolon ';', use the value of +~sqlind-use-anchor-indentation~ + +**** sqlind-adjust-operator + +if the line starts with an arithmetic operator (like ~+~ , ~-~, or ~||~), line +it up so that the right hand operand lines up with the left hand operand of +the previous line. For example, it will indent the ~||~ operator like this: + +#+BEGIN_SRC sql +select col1, col2 + || col3 as composed_column, -- align col3 with col2 + col4 + || col5 as composed_column2 +from my_table +where cond1 = 1 +and cond2 = 2; +#+END_SRC + +**** sqlind-left-justify-logical-operator + +If the line starts with a logic operator (AND, OR NOT), line the operator with +the start of the WHERE clause. This rule should be added to the +~in-select-clause~ syntax after the ~sqlind-lineup-to-clause-end~ rule. + +**** sqlind-right-justify-logical-operator + +If the line starts with a logic operator (AND, OR NOT), line the operator with +the end of the WHERE clause. This rule should be added to the +~in-select-clause~ syntax. + +#+BEGIN_SRC sql +select * + from table + where a = b + and c = d; -- AND clause sits under the where clause +#+END_SRC + +**** sqlind-adjust-comma + +if the line starts with a comma, adjust the current offset so that the line is +indented to the first word character. For example, if added to a +~select-column~ syntax indentation rule, it will indent as follows: + +#+BEGIN_SRC sql +select col1 + , col2 -- align "col2" with "col1" +from my_table; +#+END_SRC + +**** sqlind-lineup-into-nested-statement + +discard the current offset and return the column of the first word inside a +nested statement. This rule should be added to +~nested-statement-continuation~ syntax indentation rule, and will indent as +follows: + +#+BEGIN_SRC sql +( a, + b -- b is aligned with a +) +#+END_SRC + +*** More Indentation Helper Functions +The following function contain indentation code specific to various SQL +statements. Have a look at their doc strings for what they do: + + * ~sqlind-indent-comment-start~, ~sqlind-indent-comment-continuation~ + + * ~sqlind-indent-select-column~ + + * ~sqlind-indent-select-table~ + + * ~sqlind-lineup-to-clause-end~ + + * ~sqlind-right-justify-clause~ + + * ~sqlind-lineup-joins-to-anchor~ + +** Syntactic Symbols + +The SQL parsing code returns a syntax definition (either a symbol or a +list) and an anchor point, which is a buffer position. The syntax symbols can +be used to define how to indent each line. The following syntax symbols are +defined for SQL code: + + * ~(syntax-error MESSAGE START END)~ -- this is returned when the parse + failed. MESSAGE is an informative message, START and END are buffer + locations denoting the problematic region. ANCHOR is undefined for this + syntax info + + * ~in-comment~ -- line is inside a multi line comment, ANCHOR is the start of + the comment. + + * ~comment-start~ -- line starts with a comment. ANCHOR is the start of the + enclosing block. + + * ~in-string~ -- line is inside a string, ANCHOR denotes the start of the + string. + + * ~toplevel~ -- line is at toplevel (not inside any programming construct). + ANCHOR is usually (point-min). + + * ~(in-block BLOCK-KIND LABEL)~ -- line is inside a block construct. + BLOCK-KIND (a symbol) is the actual block type and can be one of "if", + "case", "exception", "loop" etc. If the block is labeled, LABEL contains + the label. ANCHOR is the start of the block. + + * ~(in-begin-block KIND LABEL)~ -- line is inside a block started by a begin + statement. KIND (a symbol) is "toplevel-block" for a begin at toplevel, + "defun" for a begin that starts the body of a procedure or function, + \"package\" for a begin that starts the body of a package, nil for a begin + that is none of the previous. For a "defun" or "package", LABEL is the + name of the procedure, function or package, for the other block types LABEL + contains the block label, or the empty string if the block has no label. + ANCHOR is the start of the block. + + * ~(block-start KIND)~ -- line begins with a statement that starts a block. + KIND (a symbol) can be one of "then", "else" or "loop". ANCHOR is the + reference point for the block start (the corresponding if, case, etc). + + * ~(block-end KIND LABEL)~ -- the line contains an end statement. KIND (a + symbol) is the type of block we are closing, LABEL (a string) is the block + label (or procedure name for an end defun). + + * ~declare-statement~ -- line is after a declare keyword, but before the + begin. ANCHOR is the start of the declare statement. + + * ~(package NAME)~ -- line is inside a package definition. NAME is the name + of the package, ANCHOR is the start of the package. + + * ~(package-body NAME)~ -- line is inside a package body. NAME is the name + of the package, ANCHOR is the start of the package body. + + * ~(create-statement WHAT NAME)~ -- line is inside a CREATE statement (other + than create procedure or function). WHAT is the thing being created, NAME + is its name. ANCHOR is the start of the create statement. + + * ~(defun-start NAME)~ -- line is inside a procedure of function definition + but before the begin block that starts the body. NAME is the name of the + procedure/function, ANCHOR is the start of the procedure/function + definition. + +The following SYNTAX-es are for SQL statements. For all of them ANCHOR points +to the start of a statement itself. + + * ~labeled-statement-start~ -- line is just after a label. + + * ~statement-continuation~ -- line is inside a statement which starts on a + previous line. + + * ~nested-statement-open~ -- line is just inside an opening bracket, but the + actual bracket is on a previous line. + + * ~nested-statement-continuation~ -- line is inside an opening bracket, but + not the first element after the bracket. + + * ~nested-statement-close~ line is inside an opening bracket and the line + contains the closing bracket as the first character. + +The following SYNTAX-es are for statements which are SQL code (DML +statements). They are specializations on the previous statement syntaxes and +for all of them a previous generic statement syntax is present earlier in the +SYNTAX list. Unless otherwise specified, ANCHOR points to the start of the +clause (select, from, where, etc) in which the current point is. + + * ~with-clause~ -- line is inside a WITH clause, but before the main SELECT + clause. + + * ~with-clause-cte~ -- line is inside a with clause before a CTE (common + table expression) declaration + + * ~with-clause-cte-cont~ -- line is inside a with clause before a CTE + definition + + * ~case-clause~ -- line is on a CASE expression (WHEN or END clauses). + ANCHOR is the start of the CASE expression. + + * ~case-clause-item~ -- line is on a CASE expression (THEN and ELSE clauses). + ANCHOR is the position of the case clause. + + * ~case-clause-item-cont~ -- line is on a CASE expression but not on one of + the CASE sub-keywords. ANCHOR points to the case keyword that this line is + a continuation of. + + * ~select-clause~ -- line is inside a select statement, right before one of + its clauses (from, where, order by, etc). + + * ~select-column~ -- line is inside the select column section, after a full + column was defined (and a new column definition is about to start). + + * ~select-column-continuation~ -- line is inside the select column section, + but in the middle of a column definition. The defined column starts on a + previous like. Note that ANCHOR still points to the start of the select + statement itself. + + * ~select-join-condition~ -- line is right before or just after the ON clause + for an INNER, LEFT or RIGHT join. ANCHOR points to the join statement for + which the ON is defined. + + * ~select-table~ -- line is inside the from clause, just after a table was + defined and a new one is about to start. + + * ~select-table-continuation~ -- line is inside the from clause, inside a + table definition which starts on a previous line. Note that ANCHOR still + points to the start of the select statement itself. + + * ~(in-select-clause CLAUSE)~ -- line is inside the select CLAUSE, which can + be "where", "order by", "group by" or "having". Note that CLAUSE can never + be "select" and "from", because we have special syntaxes inside those + clauses. + + * ~insert-clause~ -- line is inside an insert statement, right before one of + its clauses (values, select). + + * ~(in-insert-clause CLAUSE)~ -- line is inside the insert CLAUSE, which can + be "insert into" or "values". + + * ~delete-clause~ -- line is inside a delete statement right before one of + its clauses. + + * ~(in-delete-clause CLAUSE)~ -- line is inside a delete CLAUSE, which can be + "delete from" or "where". + + * ~update-clause~ -- line is inside an update statement right before one of + its clauses. + + * ~(in-update-clause CLAUSE)~ -- line is inside an update CLAUSE, which can + be "update", "set" or "where" +* Limitations +** Parsing expressions + +There is no support for parsing SQL expressions, so if an expression is broken +over several lines, sql-indent.el will consider all lines to be +~statement-continuation~ lines. The exception is that bracketed expressions +are identified correctly so they can be used for indentation. + +The examples below summarize what is supported and what is not, as well as the +workarounds: + +#+BEGIN_SRC sql + -- SUPPORTED: case expression immediately after assignment + var := case ind + when 1 then 'Guy' + when 2 then 'Abc' + when 3 then 'Def' + else 'World' + end case; + + -- NOT SUPPORTED: any complex expression involving a case expression. entire + -- expression is a 'statement-continuation + var := 'abc' + || case ind + when 1 then 'Guy' + when 2 then 'Abc' + when 3 then 'Def' + else 'World' + end case; + + -- WORKAROUND: use brackets instead + var := 'abc' + || (case ind + when 1 then 'Guy' + when 2 then 'Abc' + when 3 then 'Def' + else 'World' + end case); + + -- SUPPORTED: case expression as select column + select col1, + case ind + when 1 then 'Guy' + when 2 then 'Abc' + when 3 then 'Def' + else 'World' + end case, + col2, + from some_table; + + -- NOT SUPPORTED: any complex expression involving a case expression in a + -- select column. Entire column is a 'select-column-continuation + select col1, + 'abc' || case ind + when 1 then 'Guy' + when 2 then 'Abc' + when 3 then 'Def' + else 'World' + end case, + col2, + from some_table; + + -- WORKAROUND: use brackets instead + select col1, + 'abc' || (case ind + when 1 then 'Guy' + when 2 then 'Abc' + when 3 then 'Def' + else 'World' + end case), + col2, + from some_table; +#+END_SRC + +.
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/case-stmt-syn.eld @@ -0,0 +1,35 @@ +(((comment-start . 1) + (toplevel . 1)) + ((toplevel . 1)) + ((select-column . 52) + (statement-continuation . 52)) + ((case-clause . 70) + (select-column-continuation . 52) + (statement-continuation . 52)) + ((case-clause . 70) + (select-column-continuation . 52) + (statement-continuation . 52)) + ((case-clause . 70) + (select-column-continuation . 52) + (statement-continuation . 52)) + (((block-end case "") + . 70) + (select-column-continuation . 52) + (statement-continuation . 52)) + ((select-clause . 52) + (statement-continuation . 52)) + ((toplevel . 1)) + ((toplevel . 1)) + ((case-clause-item-cont . 197) + (statement-continuation . 190)) + ((case-clause . 197) + (statement-continuation . 190)) + ((case-clause . 197) + (statement-continuation . 190)) + ((case-clause . 197) + (statement-continuation . 190)) + (((block-end case "") + . 197) + (statement-continuation . 190)) + ((toplevel . 1))) +
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/case-stmt.sql @@ -0,0 +1,15 @@ +-- https://github.com/bsvingen/sql-indent/issues/1 +SELECT y , + CASE + WHEN foo>5 THEN "great" + WHEN foo=5 THEN "normal" + ELSE "poor" + END AS level + FROM bar; + +var := CASE + var -- tricky case + WHEN foo>5 THEN "great" + WHEN foo=5 THEN "normal" + ELSE "poor" + END;
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/if-exists-syn.eld @@ -0,0 +1,14 @@ +(((toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + (((create-statement index "ix1_some_table") + . 39)) + ((toplevel . 1)) + ((toplevel . 1)) + (((create-statement index "ix2_some_table") + . 98)) + ((toplevel . 1)) + ((toplevel . 1)) + (((create-statement index "ix3_some_table") + . 177)) + ((toplevel . 1)))
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/if-exists.sql @@ -0,0 +1,10 @@ +drop index if exists IX1_SOME_TABLE; + +create index IX1_SOME_TABLE + on SOME_TABLE(some_column); + +create index if not exists IX2_SOME_TABLE + on SOME_TABLE(some_other_column); + +create index IX3_SOME_TABLE + on SOME_TABLE(some_other_column);
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/m-io.eld @@ -0,0 +1,1 @@ +(0 4 4 6 6 4 0 4 4 4 4 4 4 4 10 4 4 4 8 4 4 0 0 10 16 16 16 16 20 20 20 16 12 16 10 1 5 0 0 0 6 6 2 6 0 8 0 4 0)
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/m-syn.eld @@ -0,0 +1,115 @@ +(((toplevel . 1)) + (((in-insert-clause "insert into") + . 1) + (statement-continuation . 1)) + (((in-insert-clause "insert into") + . 1) + (statement-continuation . 1)) + ((nested-statement-continuation . 25) + (statement-continuation . 25)) + ((nested-statement-continuation . 25) + (statement-continuation . 25)) + ((nested-statement-close . 25) + (statement-continuation . 25)) + ((insert-clause . 1) + (statement-continuation . 1)) + ((select-column . 80) + (statement-continuation . 1)) + ((select-column . 80) + (statement-continuation . 1)) + ((select-column . 80) + (statement-continuation . 1)) + ((select-column . 80) + (statement-continuation . 1)) + ((select-column . 80) + (statement-continuation . 1)) + ((select-column . 80) + (statement-continuation . 1)) + ((select-column-continuation . 80) + (statement-continuation . 1)) + ((nested-statement-continuation . 242) + (statement-continuation . 242)) + ((nested-statement-close . 242) + (statement-continuation . 242)) + ((select-column . 80) + (statement-continuation . 1)) + ((select-column-continuation . 80) + (statement-continuation . 1)) + ((nested-statement-continuation . 327) + (statement-continuation . 327)) + ((nested-statement-close . 327) + (statement-continuation . 327)) + ((select-column . 80) + (statement-continuation . 1)) + ((select-clause . 80) + (statement-continuation . 1)) + ((select-table-continuation . 411) + (statement-continuation . 1)) + ((select-table-continuation . 433) + (nested-statement-continuation . 423) + (statement-continuation . 423)) + ((select-column . 461) + (nested-statement-continuation . 459) + (statement-continuation . 459)) + ((select-column . 461) + (nested-statement-continuation . 459) + (statement-continuation . 459)) + ((select-column . 461) + (nested-statement-continuation . 459) + (statement-continuation . 459)) + ((select-column-continuation . 461) + (nested-statement-continuation . 459) + (statement-continuation . 459)) + ((nested-statement-continuation . 614) + (statement-continuation . 614)) + ((nested-statement-continuation . 614) + (statement-continuation . 614)) + ((nested-statement-continuation . 614) + (statement-continuation . 614)) + ((nested-statement-close . 614) + (statement-continuation . 614)) + ((select-clause . 461) + (nested-statement-continuation . 459) + (statement-continuation . 459)) + ((select-table-continuation . 795) + (nested-statement-continuation . 459) + (statement-continuation . 459)) + ((nested-statement-close . 459) + (statement-continuation . 459)) + ((select-clause . 424) + (nested-statement-continuation . 423) + (statement-continuation . 423)) + (((in-select-clause "where") + . 865) + (nested-statement-continuation . 423) + (statement-continuation . 423)) + ((nested-statement-close . 423) + (statement-continuation . 423)) + ((select-table-continuation . 411) + (statement-continuation . 1)) + ((select-table-continuation . 411) + (statement-continuation . 1)) + ((select-column . 928) + (nested-statement-continuation . 926) + (statement-continuation . 926)) + ((select-column . 928) + (nested-statement-continuation . 926) + (statement-continuation . 926)) + ((select-clause . 928) + (nested-statement-continuation . 926) + (statement-continuation . 926)) + ((select-table-continuation . 990) + (nested-statement-continuation . 926) + (statement-continuation . 926)) + ((nested-statement-close . 926) + (statement-continuation . 926)) + ((select-join-condition . 908) + (statement-continuation . 1)) + ((select-clause . 80) + (statement-continuation . 1)) + (((in-select-clause "group by") + . 1051) + (statement-continuation . 1)) + (((in-select-clause "group by") + . 1051) + (statement-continuation . 1)))
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/m.sql @@ -0,0 +1,48 @@ +INSERT INTO + xyzxx + ( aaa, bbb, ccc + , ddd, eee, fff, ggg + , hhh + ) +SELECT + aaa + , MAX (m.b1) AS bbb + , MIN (m.b1) AS ccc + , COALESCE (MAX (n.c2), 0)  AS ddd + , COALESCE (MIN (n.c2), 0)  AS eee + , MAX (m.b1) OVER + ( PARTITION BY c2 + ORDER BY aaa DESC + ) AS fff + , MIN (m.b1) OVER + ( PARTITION BY c2 + ORDER BY aaa DESC + ) AS ggg + , AVG (n.c2)  AS hhh + FROM + (SELECT * FROM + ( SELECT + aaa + , jjj + kkk  AS b1 + , ROW_NUMBER () OVER + ( PARTITION BY qqq + ORDER BY + rrr + , sss + ) AS rn + FROM + mno + ) + WHERE + rn = 1 + )  m + INNER JOIN + ( SELECT + aaa + , nnn + ooo AS c2 + FROM + pqr + ) n + USING (aaa), + GROUP BY + aaa
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr17-io-default.eld @@ -0,0 +1,1 @@ +(0 0 0 0 0 0 0 0 9 9 9 7 9 2 1 8 4 0 0 7 7 7 7 7 7 2 9 1 4 4 4 4 4 4 25 32 24 27 27 27 27 27 8 0 0 1 8 15 8 8 0 0 3 10 1 7 13 7 7 0 0 12 12 12 0 7 7 7 7 7 7 24 7 24 7 2 31 31 51 51 26 10 10 29 24 14 1 10 1 10 10 0 0 0 0)
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr17-io-left.eld @@ -0,0 +1,1 @@ +(0 0 0 0 0 0 0 0 10 10 10 7 4 0 0 12 0 0 0 7 7 7 7 7 7 0 7 0 0 0 0 0 0 0 19 26 19 19 19 19 19 19 0 0 0 0 0 7 0 0 0 0 0 7 0 0 6 0 0 0 0 2 3 3 0 7 7 7 7 7 7 24 7 24 7 0 29 29 49 49 22 7 2 21 14 6 0 9 0 9 0 0 0 0 0)
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr17-io-right.eld @@ -0,0 +1,1 @@ +(0 0 0 0 0 0 0 0 10 10 10 7 4 2 1 13 4 0 0 7 7 7 7 7 7 2 9 1 4 4 4 4 4 4 25 32 24 27 27 27 27 27 1 0 0 1 4 11 4 1 0 0 3 10 1 3 9 3 1 0 0 12 12 12 0 7 7 7 7 7 7 24 7 24 7 2 31 31 51 51 26 10 10 29 24 14 1 10 1 10 1 0 0 0 0) \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr17-syn.eld @@ -0,0 +1,214 @@ +(((toplevel . 1)) + ((toplevel . 15)) + ((comment-start . 33) + (toplevel . 33)) + ((comment-start . 33) + (toplevel . 33)) + ((toplevel . 33)) + ((toplevel . 33)) + ((toplevel . 33)) + ((toplevel . 33)) + ((select-column-continuation . 99) + (statement-continuation . 99)) + ((select-column-continuation . 99) + (statement-continuation . 99)) + ((select-column-continuation . 99) + (statement-continuation . 99)) + ((select-column . 99) + (statement-continuation . 99)) + ((select-column-continuation . 99) + (statement-continuation . 99)) + ((select-clause . 99) + (statement-continuation . 99)) + ((select-clause . 99) + (statement-continuation . 99)) + (((in-select-clause "where") + . 306) + (statement-continuation . 99)) + (((in-select-clause "where") + . 306) + (statement-continuation . 99)) + ((toplevel . 33)) + ((toplevel . 33)) + ((select-column . 375) + (statement-continuation . 375)) + ((select-column . 375) + (statement-continuation . 375)) + ((select-column . 375) + (statement-continuation . 375)) + ((select-column . 375) + (statement-continuation . 375)) + ((select-column . 375) + (statement-continuation . 375)) + ((select-column . 375) + (statement-continuation . 375)) + ((select-clause . 375) + (statement-continuation . 375)) + ((select-table . 565) + (statement-continuation . 375)) + ((select-clause . 375) + (statement-continuation . 375)) + (((in-select-clause "where") + . 624) + (statement-continuation . 375)) + (((in-select-clause "where") + . 624) + (statement-continuation . 375)) + (((in-select-clause "where") + . 624) + (statement-continuation . 375)) + (((in-select-clause "where") + . 624) + (statement-continuation . 375)) + (((in-select-clause "where") + . 624) + (statement-continuation . 375)) + (((in-select-clause "where") + . 624) + (statement-continuation . 375)) + ((select-clause . 888) + (nested-statement-continuation . 887) + (statement-continuation . 887)) + ((select-table . 922) + (nested-statement-continuation . 887) + (statement-continuation . 887)) + ((select-clause . 888) + (nested-statement-continuation . 887) + (statement-continuation . 887)) + (((in-select-clause "where") + . 1029) + (nested-statement-continuation . 887) + (statement-continuation . 887)) + (((in-select-clause "where") + . 1029) + (nested-statement-continuation . 887) + (statement-continuation . 887)) + (((in-select-clause "where") + . 1029) + (nested-statement-continuation . 887) + (statement-continuation . 887)) + (((in-select-clause "where") + . 1029) + (nested-statement-continuation . 887) + (statement-continuation . 887)) + (((in-select-clause "where") + . 1029) + (nested-statement-continuation . 887) + (statement-continuation . 887)) + (((in-select-clause "where") + . 624) + (statement-continuation . 375)) + ((toplevel . 33)) + ((toplevel . 33)) + ((delete-clause . 1417) + (statement-continuation . 1417)) + (((in-delete-clause "where") + . 1442) + (statement-continuation . 1417)) + ((nested-statement-continuation . 1481) + (statement-continuation . 1481)) + (((in-delete-clause "where") + . 1442) + (statement-continuation . 1417)) + (((in-delete-clause "where") + . 1442) + (statement-continuation . 1417)) + ((toplevel . 33)) + ((toplevel . 33)) + ((update-clause . 1576) + (statement-continuation . 1576)) + (((in-update-clause "set") + . 1595) + (statement-continuation . 1576)) + ((update-clause . 1576) + (statement-continuation . 1576)) + (((in-update-clause "where") + . 1674) + (statement-continuation . 1576)) + ((nested-statement-continuation . 1710) + (statement-continuation . 1710)) + (((in-update-clause "where") + . 1674) + (statement-continuation . 1576)) + (((in-update-clause "where") + . 1674) + (statement-continuation . 1576)) + ((toplevel . 33)) + ((toplevel . 33)) + (((in-insert-clause "insert into") + . 1800) + (statement-continuation . 1800)) + ((nested-statement-continuation . 1830) + (statement-continuation . 1830)) + ((nested-statement-continuation . 1830) + (statement-continuation . 1830)) + ((insert-clause . 1800) + (statement-continuation . 1800)) + ((select-column . 1902) + (statement-continuation . 1800)) + ((select-column . 1902) + (statement-continuation . 1800)) + ((select-column . 1902) + (statement-continuation . 1800)) + ((select-column . 1902) + (statement-continuation . 1800)) + ((select-column . 1902) + (statement-continuation . 1800)) + ((select-column . 1902) + (statement-continuation . 1800)) + ((nested-statement-continuation . 2081) + (statement-continuation . 2081)) + ((select-column . 1902) + (statement-continuation . 1800)) + ((nested-statement-continuation . 2174) + (statement-continuation . 2174)) + ((select-column . 1902) + (statement-continuation . 1800)) + ((select-clause . 1902) + (statement-continuation . 1800)) + ((select-column . 2293) + (nested-statement-continuation . 2292) + (statement-continuation . 2292)) + ((select-column . 2293) + (nested-statement-continuation . 2292) + (statement-continuation . 2292)) + ((nested-statement-continuation . 2403) + (statement-continuation . 2403)) + ((nested-statement-continuation . 2403) + (statement-continuation . 2403)) + ((select-clause . 2293) + (nested-statement-continuation . 2292) + (statement-continuation . 2292)) + ((select-clause . 2278) + (nested-statement-continuation . 2277) + (statement-continuation . 2277)) + ((select-table-continuation . 2271) + (statement-continuation . 1800)) + ((select-column . 2650) + (nested-statement-continuation . 2649) + (statement-continuation . 2649)) + ((select-clause . 2650) + (nested-statement-continuation . 2649) + (statement-continuation . 2649)) + ((select-join-condition . 2638) + (statement-continuation . 1800)) + ((select-clause . 1902) + (statement-continuation . 1800)) + (((in-select-clause "group by") + . 2773) + (statement-continuation . 1800)) + ((select-clause . 1902) + (statement-continuation . 1800)) + (((in-select-clause "order by") + . 2802) + (statement-continuation . 1800)) + (((in-select-clause "order by") + . 2802) + (statement-continuation . 1800)) + ((comment-start . 33) + (toplevel . 33)) + ((comment-start . 33) + (toplevel . 33)) + ((comment-start . 33) + (toplevel . 33)) + ((toplevel . 33))) \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr17.sql @@ -0,0 +1,94 @@ +clear columns +set linesize 2500 +-- set trimout on +-- set trimspool on + +select sysdate from dual; + +select col1, 'a long line of text ending with a single word' + || col2 + || col3 + || 'some text' as composed_column, + col4 + || col5 as composed_column2 + from my_table + where cond1 = fct1 + || 'another text' + and cond2 = 2; + +select atc.column_name, + atc.data_type, + data_length, + data_precision, + nullable, + data_scale, + nvl(substr(comments, 1, 100), atc.column_name) comments + from all_tab_columns atc, + all_col_comments acc + where atc.owner = acc.owner + and atc.table_name = acc.table_name + and atc.column_name = acc.column_name + and atc.owner = user + and atc.table_name = 'MY_TABLE' + and atc.column_name = p_column_name + and not exists (select 1 + from all_tab_columns atc1, + all_col_comments acc1 + where atc1.owner = acc1.owner + and atc1.table_name = acc1.table_name + and atc1.column_name = acc1.column_name + and atc1.owner = atc.owner + and atc1.table_name = atc.table_name + and acc1.column_name = acc.column_name) + ; + +delete from my_table mt + where col_1 = v_col1 + and (col_2 = v_col2 + or col_3 = v_col3) + and col_42 = '42' + ; + +update my_table + set col1_has_a_long_name = value1, + col2_is_short = value2 + where cond1 is not null + and ( col_2 = v_col2 + or col_3 = v_col3) + and col_42 = '42' + ; + +insert into xyzxx + ( aaa, xxx, bbb, ccc, + ddd, eee, fff, ggg, + hhh ) +select aaa, + xxx, + max (m.b1) as bbb, + min (m.b1) as ccc, + coalesce (max (n.c2), 0) as ddd, + coalesce (min (n.c2), 0) as eee, + max (m.b1) over ( partition by c2 + order by aaa desc ) as fff, + min (m.b1) over ( partition by c2 + order by aaa desc ) as ggg, + avg (n.c2) as hhh + from (select * from (select aaa, + jjj + kkk as b1, + row_number () over ( partition by qqq + order by rrr, + sss ) as rn + from mno) a_nested_nested + where rn = 1) m + inner join (select aaa, + nnn + ooo as c2 + from pqr) n + using (aaa), + group by aaa, + xxx + order by xxx desc, + aaa asc + ; +-- Local Variables: +-- sql-product: oracle +-- End:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr18-syn.eld @@ -0,0 +1,68 @@ +(((toplevel . 1)) + ((toplevel . 21)) + ((declare-statement . 21)) + ((declare-statement . 21)) + (((block-start begin) + . 21) + (declare-statement . 21)) + (((in-begin-block toplevel-block "") + . 78)) + (((in-begin-block toplevel-block "") + . 78)) + (((in-begin-block toplevel-block "") + . 78)) + ((case-clause . 126) + (statement-continuation . 117)) + ((case-clause . 126) + (statement-continuation . 117)) + ((case-clause . 126) + (statement-continuation . 117)) + (((block-end case "") + . 126) + (statement-continuation . 117)) + (((in-begin-block toplevel-block "") + . 78)) + (((in-begin-block toplevel-block "") + . 78)) + (((in-begin-block toplevel-block "") + . 78)) + (((in-begin-block toplevel-block "") + . 78)) + (((block-start when) + . 290) + ((in-block case "") + . 290)) + (((block-start when) + . 290) + ((in-block case "") + . 290)) + (((block-start when) + . 290) + ((in-block case "") + . 290)) + (((block-start else) + . 290) + ((in-block case "") + . 290)) + (((block-end case "") + . 290) + ((in-block else "") + . 392)) + (((in-begin-block toplevel-block "") + . 78)) + (((in-begin-block toplevel-block "") + . 78)) + (((block-end toplevel-block "") + . 78) + ((in-begin-block toplevel-block "") + . 78)) + ((toplevel . 21)) + ((comment-start . 21) + (toplevel . 21)) + ((comment-start . 21) + (toplevel . 21)) + ((comment-start . 21) + (toplevel . 21)) + ((toplevel . 21))) + + \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr18.sql @@ -0,0 +1,28 @@ +set serveroutput on +declare + dummy varchar2(25); + ind number := 2; +begin + dbms_output.enable(null); + + dummy := case + when ind = 1 then 'Guy' + when ind = 2 then 'Abc' + else 'World' + end; + + dbms_output.put_line('Hello ' || dummy); + + case ind + when 1 then dummy := 'Guy'; + when 2 then dummy := 'Abc'; + when 3 then dummy := 'Def'; + else dummy := 'World'; + end case; + + dbms_output.put_line('Hello ' || dummy); +end; +/ +-- Local Variables: +-- sql-product: oracle +-- End:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr19-syn.eld @@ -0,0 +1,93 @@ +(((toplevel . 1)) + (((package-body "my_pacakge") + . 1)) + (((package-body "my_pacakge") + . 1)) + ((statement-continuation . 67)) + ((select-clause . 84) + (statement-continuation . 67)) + ((select-clause . 84) + (statement-continuation . 67)) + (((in-select-clause "where") + . 122) + (statement-continuation . 67)) + (((package-body "my_pacakge") + . 1)) + (((package-body "my_pacakge") + . 1)) + (((package-body "my_pacakge") + . 1)) + (((package-body "my_pacakge") + . 1)) + (((defun-start "get_my_value") + . 198)) + (((defun-start "get_my_value") + . 198)) + (((defun-start "get_my_value") + . 198)) + ((statement-continuation . 286)) + ((select-clause . 340) + (statement-continuation . 286)) + ((select-clause . 340) + (statement-continuation . 286)) + (((defun-start "get_my_value") + . 198)) + (((defun-start "get_my_value") + . 198)) + (((block-start begin) + . 198) + ((defun-start "get_my_value") + . 198)) + (((in-begin-block defun "get_my_value") + . 437)) + (((in-block loop "") + . 445)) + (((block-end loop "") + . 445) + ((in-block loop "") + . 445)) + (((block-end defun "get_my_value") + . 437) + ((in-begin-block defun "get_my_value") + . 437)) + (((package-body "my_pacakge") + . 1)) + (((block-start begin) + . 1) + ((package-body "my_pacakge") + . 1)) + (((in-begin-block package "my_pacakge") + . 533)) + (((in-block loop "") + . 541)) + (((block-end loop "") + . 541) + ((in-block loop "") + . 541)) + (((in-begin-block package "my_pacakge") + . 533)) + (((in-begin-block package "my_pacakge") + . 533)) + (((in-begin-block nil "") + . 614)) + (((block-end nil "") + . 614) + ((in-begin-block nil "") + . 614)) + (((in-begin-block package "my_pacakge") + . 533)) + (((in-begin-block package "my_pacakge") + . 533)) + (((block-end package "my_pacakge") + . 533) + ((in-begin-block package "my_pacakge") + . 533)) + ((toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((toplevel . 1))) +
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr19.sql @@ -0,0 +1,40 @@ +create or replace package body my_pacakge authid current user is + + cursor cur1 is + select 1 dummy + from my_table + where 1 = 1 + and col1 = p_col1; + + p_col1 my_table.col1%type := 42; + + function get_my_value(p_param1 in my_table.col1%type) + return my_table.col2%type is + + cursor cur2 (p_val_col1 in my_table.col1%type) is + select col2 + from my_table + where col1 = p_val_col1; + + v_result my_table.col2%type; + begin + for rec in cur2(p_param1) loop + v_result := rec.col2; + end loop; + end get_my_value; + +begin + for rec in cur1 loop + dbms_output.put_line(rec.dummy); + end loop; + + begin + null; + end; + + dbms_output.put_line(get_my_value(p_col1)); +end my_pacakge; +/ +-- Local Variables: +-- sql-product: oracle +-- End:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr24-syn.eld @@ -0,0 +1,77 @@ +(((toplevel . 1)) + ((toplevel . 21)) + ((toplevel . 49)) + ((toplevel . 49)) + ((declare-statement . 50)) + ((declare-statement . 50)) + (((block-start begin) + . 50) + (declare-statement . 50)) + (((in-begin-block toplevel-block "") + . 106)) + (((in-begin-block toplevel-block "") + . 106)) + (((in-block if "") + . 142)) + ((statement-continuation . 171)) + ((statement-continuation . 171)) + (((in-block if "") + . 142)) + ((statement-continuation . 253)) + ((statement-continuation . 253)) + (((block-start elsif) + . 142) + ((in-block if "") + . 142)) + (((in-block elsif "") + . 299)) + ((statement-continuation . 331)) + ((statement-continuation . 331)) + (((in-block elsif "") + . 299)) + ((statement-continuation . 413)) + ((statement-continuation . 413)) + (((block-start else) + . 299) + ((in-block elsif "") + . 299)) + (((in-block else "") + . 459)) + (((in-block else "") + . 459)) + (((block-end if "") + . 142) + ((in-block else "") + . 459)) + (((in-begin-block toplevel-block "") + . 106)) + (((in-begin-block toplevel-block "") + . 106)) + ((statement-continuation . 531)) + ((statement-continuation . 531)) + (((in-begin-block toplevel-block "") + . 106)) + ((statement-continuation . 607)) + ((statement-continuation . 607)) + (((in-begin-block toplevel-block "") + . 106)) + (((in-begin-block toplevel-block "") + . 106)) + (((block-end toplevel-block "") + . 106) + ((in-begin-block toplevel-block "") + . 106)) + ((toplevel . 49)) + ((comment-start . 49) + (toplevel . 49)) + ((comment-start . 49) + (toplevel . 49)) + ((comment-start . 49) + (toplevel . 49)) + ((comment-start . 49) + (toplevel . 49)) + ((comment-start . 49) + (toplevel . 49)) + ((comment-start . 49) + (toplevel . 49)) + ((toplevel . 49))) \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr24.sql @@ -0,0 +1,43 @@ +set serveroutput on +set trimout on trimspool on + +declare + var1 varchar2(25000); + var2 varchar2(25000); +begin + dbms_output.enable(null); + if var1 is not null then + var2 := 'var1 is set : -*-' + || var1 + || '-*- some text after ...'; + var1 := '-*-' + || var1 + || '-*-'; + elsif var2 is not null then + var1 := 'var2 is set : -*-' + || var2 + || '-*- some text after ...'; + var2 := '-*-' + || var2 + || '-*-'; + else + var2 := '-*-empty-*-'; + var1 := '-*-empty-*-'; + end if; + + var2 := 'var1 is set : -*-' + || var1 + || '-*- some text after ...'; + var1 := 'var2 is set : -*-' + || var2 + || '-*- some text after ...'; + dbms_output.put_line(var1); + dbms_output.put_line(var2); +end; +/ +-- Local Variables: +-- mode: sql +-- tab-width: 2 +-- indent-tabs-mode: nil +-- sql-product: oracle +-- End:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr28-syn.eld @@ -0,0 +1,102 @@ +(((toplevel . 1)) + ((declare-statement . 1)) + ((declare-statement . 1)) + (((block-start begin) + . 1) + (declare-statement . 1)) + (((in-begin-block toplevel-block "") + . 62)) + (((in-begin-block nil "") + . 70)) + (((in-block if "") + . 80)) + (((in-block if "") + . 80)) + (((block-start elsif) + . 80) + ((in-block if "") + . 80)) + (((in-block elsif "") + . 124)) + (((in-block elsif "") + . 124)) + (((block-start else) + . 124) + ((in-block elsif "") + . 124)) + (((in-block else "") + . 166)) + (((block-end if "") + . 80) + ((in-block else "") + . 166)) + (((in-begin-block nil "") + . 70)) + (((block-start when) + . 215) + ((in-block case "") + . 215)) + (((block-start when) + . 215) + ((in-block case "") + . 215)) + (((block-start when) + . 215) + ((in-block case "") + . 215)) + (((block-start else) + . 215) + ((in-block case "") + . 215)) + (((block-end case "") + . 215) + ((in-block else "") + . 325)) + (((block-start exception) + . 70) + ((in-begin-block nil "") + . 70)) + (((in-block exception) + . 364)) + (((in-block exception-handler) + . 378) + ((in-block exception "") + . 364)) + (((in-block exception-handler) + . 378) + ((in-block exception "") + . 364)) + (((in-block exception "") + . 364)) + (((in-block exception-handler "") + . 432) + (statement-continuation . 432)) + (((in-block exception-handler) + . 432) + ((in-block exception "") + . 364)) + (((in-block exception "") + . 364)) + (((in-block exception-handler "") + . 486) + (statement-continuation . 486)) + (((block-end nil "") + . 70) + ((in-block exception "") + . 364)) + (((block-end toplevel-block "") + . 62) + ((in-begin-block toplevel-block "") + . 62)) + ((toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((toplevel . 1)))
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr28.sql @@ -0,0 +1,37 @@ +declare + dummy number; + e_stop_program exception; +begin + begin + if 1 = 1 then + proc1; + proc2; + elsif 1 = 2 + proc3; + proc4; + else + raise e_stop_program; + end if; + case ind + when 1 then dummy := 'Guy'; + when 2 then dummy := 'Abc'; + when 3 then dummy := 'Def'; + else dummy := 'World'; + end case; + exception + when no_data_found then + proc1; + proc2; + when too_many_rows then + proc3; + proc4; + when others then + proc5; + end; +end; +/ +-- Local Variables: +-- mode: sqlind-minor +-- mode: sql +-- sql-product: oracle +-- End:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr29-syn.eld @@ -0,0 +1,81 @@ +(((toplevel . 1)) + ((select-column . 1) + (statement-continuation . 1)) + ((case-clause . 19) + (select-column-continuation . 1) + (statement-continuation . 1)) + ((case-clause . 19) + (select-column-continuation . 1) + (statement-continuation . 1)) + ((case-clause . 19) + (select-column-continuation . 1) + (statement-continuation . 1)) + (((block-end case "") + . 19) + (select-column-continuation . 1) + (statement-continuation . 1)) + ((select-clause . 1) + (statement-continuation . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((declare-statement . 141)) + (((block-start begin) + . 141) + (declare-statement . 141)) + (((in-begin-block toplevel-block "") + . 165)) + (((block-start when) + . 173) + ((in-block case "") + . 173)) + (((in-block when) + . 184) + ((in-block case "") + . 173)) + (((in-block when) + . 184) + ((in-block case "") + . 173)) + (((block-start when) + . 173) + ((in-block case "") + . 173)) + (((in-block when) + . 239) + ((in-block case "") + . 173)) + (((in-block when) + . 239) + ((in-block case "") + . 173)) + (((block-start when) + . 173) + ((in-block case "") + . 173)) + (((in-block when) + . 294) + ((in-block case "") + . 173)) + (((block-start else) + . 173) + ((in-block case "") + . 173)) + (((in-block else "") + . 329)) + (((block-end case "") + . 173) + ((in-block else "") + . 329)) + (((block-end toplevel-block "") + . 165) + ((in-begin-block toplevel-block "") + . 165)) + ((toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((toplevel . 1))) + \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr29.sql @@ -0,0 +1,28 @@ +select y , + case + when foo>5 then "great" + when foo=5 then "normal" + else "poor" + end as level + from bar; + +declare + dummy number; +begin + case ind + when 1 then + dummy := 'Guy'; + dummy1 := 'Abc'; + when 2 then + dummy := 'Abc'; + dummy1 := 'Abc'; + when 3 then + dummy := 'Def'; + else + dummy := 'World'; + end case; +end; +/ +-- Local Variables: +-- sql-product: oracle +-- End:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr33-io-left.eld @@ -0,0 +1,1 @@ +(0 2 2 2 0 2 0 0 0 0 0 0 0 0 0)
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr33-syn.eld @@ -0,0 +1,27 @@ +(((toplevel . 1)) + ((declare-statement . 1)) + ((declare-statement . 1)) + ((declare-statement . 1)) + (((block-start begin) + . 1) + (declare-statement . 1)) + (((in-begin-block toplevel-block "") + . 135)) + (((block-end toplevel-block "") + . 135) + ((in-begin-block toplevel-block "") + . 135)) + ((toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((toplevel . 1)))
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr33.sql @@ -0,0 +1,14 @@ +declare + function dummy return my_user.my_table%rowtype; + function dummy2 return my_user.my_table.my_col%type; + var dummy3 number; +begin + null; +end; + +-- Local Variables: +-- mode: sql +-- tab-width: 2 +-- indent-tabs-mode: nil +-- sql-product: oracle +-- End:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr36-io-left.eld @@ -0,0 +1,1 @@ +(0 2 4 6 8 6 4 2 0 0 0 0 0 0 0 0 0 0)
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr36-syn.eld @@ -0,0 +1,43 @@ +((((block-start begin) + . 1) + (toplevel . 1)) + (((in-begin-block toplevel-block "") + . 1)) + (((in-block if "") + . 9)) + (((in-block loop "") + . 27)) + (((in-block if "") + . 53)) + (((block-end if "") + . 53) + ((in-block if "") + . 53)) + (((block-end loop "") + . 27) + ((in-block loop "") + . 27)) + (((block-end if "") + . 9) + ((in-block if "") + . 9)) + (((block-end toplevel-block "") + . 1) + ((in-begin-block toplevel-block "") + . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((toplevel . 1))) +
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr36.sql @@ -0,0 +1,17 @@ +begin + if a = b then + for rec in cur loop + if c = d then + inst1; + end if; + end loop; + end if; +end; +/ + +-- Local Variables: +-- mode: sql +-- tab-width: 2 +-- indent-tabs-mode: nil +-- sql-product: oracle +-- End:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr37-io-left.eld @@ -0,0 +1,1 @@ +(0 2 0 0 0 0 0 0 0 0 0 0 0) \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr37-syn.eld @@ -0,0 +1,24 @@ +(((toplevel . 1)) + (((package "my_wonderfull_package") + . 1)) + (((block-end package "my_wonderfull_package") + . 1) + ((package "my_wonderfull_package") + . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((toplevel . 1)))
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr37.sql @@ -0,0 +1,12 @@ +create or replace package my_user.my_wonderfull_package as + function my_amazing_func return number; +end my_wonderfull_package; +/ + +-- Local Variables: +-- mode: sql +-- mode: sqlind-minor +-- tab-width: 2 +-- indent-tabs-mode: nil +-- sql-product: oracle +-- End:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr39-syn.eld @@ -0,0 +1,22 @@ +(((toplevel . 1)) + ((select-column . 1) + (statement-continuation . 1)) + ((case-clause . 23) + (select-column-continuation . 1) + (statement-continuation . 1)) + ((case-clause . 23) + (select-column-continuation . 1) + (statement-continuation . 1)) + ((case-clause . 23) + (select-column-continuation . 1) + (statement-continuation . 1)) + (((block-end case "") + . 23) + (select-column-continuation . 1) + (statement-continuation . 1)) + ((select-clause . 1) + (statement-continuation . 1)) + ((select-clause . 1) + (statement-continuation . 1)) + ((toplevel . 1))) + \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr39.sql @@ -0,0 +1,8 @@ +select pk_id + , case + when t1.c1 is null then '(null)' + when t1.c1 in ('a', 'b','c','d','e') then 'a' + else t1.c1 + end c1_alt + from t1 + limit 10;
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr40-syn.eld @@ -0,0 +1,49 @@ +(((toplevel . 1)) + ((toplevel . 14)) + ((toplevel . 17)) + ((toplevel . 35)) + ((toplevel . 38)) + ((toplevel . 63)) + ((toplevel . 66)) + (((defun-start "[test]") + . 66)) + (((defun-start "[test]") + . 66)) + (((defun-start "[test]") + . 66)) + (((defun-start "[test]") + . 66)) + ((nested-statement-open . 130) + (statement-continuation . 130)) + ((nested-statement-continuation . 130) + (statement-continuation . 130)) + ((nested-statement-close . 130) + (statement-continuation . 130)) + (((block-start is-or-as) + . 66) + ((defun-start "[test]") + . 66)) + (((block-start begin) + . 66) + ((defun-start "[test]") + . 66)) + (((in-begin-block defun "[test]") + . 209)) + (((in-begin-block defun "[test]") + . 209)) + (((in-begin-block defun "[test]") + . 209)) + (((in-begin-block defun "[test]") + . 209)) + (((block-end defun "[test]") + . 209) + ((in-begin-block defun "[test]") + . 209)) + ((comment-start . 66) + (toplevel . 66)) + ((comment-start . 66) + (toplevel . 66)) + ((comment-start . 66) + (toplevel . 66)) + ((toplevel . 66))) + \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr40.sql @@ -0,0 +1,24 @@ +USE [testdb] +GO +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +ALTER FUNCTION [dbo].[Test] +() +RETURNS +@TestBatch TABLE +( + [param] [varchar](20) NOT NULL, + [param2] [datetime] NOT NULL, +) +AS +BEGIN + DECLARE @var int; + DECLARE @var2 int; + set @var = 100; + RETURN; +END +-- Local Variables: +-- sql-product: ms +-- End:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr42-syn.eld @@ -0,0 +1,33 @@ +(((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((toplevel . 1)) + (((create-statement view "v_sport_zone_for_session") + . 109)) + ((select-column . 151) + ((create-statement view "v_sport_zone_for_session") + . 109)) + ((select-column . 151) + ((create-statement view "v_sport_zone_for_session") + . 109)) + ((select-clause . 151) + ((create-statement view "v_sport_zone_for_session") + . 109)) + ((select-clause . 151) + ((create-statement view "v_sport_zone_for_session") + . 109)) + (((in-select-clause "where") + . 299) + ((create-statement view "v_sport_zone_for_session") + . 109)) + ((nested-statement-continuation . 341) + (statement-continuation . 341)) + ((nested-statement-continuation . 340) + (statement-continuation . 340)) + (((in-select-clause "where") + . 299) + ((create-statement view "v_sport_zone_for_session") + . 109)) + ((toplevel . 1))) + \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr42.sql @@ -0,0 +1,12 @@ +-- sql-indent used to think that the statement begins at the "FOR" keyword in +-- "V_SPORT_ZONE_FOR_SESSION" +create view V_SPORT_ZONE_FOR_SESSION as + select S.id as session_id, + VSZ.zone_id as zone_id, + VSZ.zone_metric_id as zone_metric_id + from A_SESSION S, V_SPORT_ZONE VSZ + where S.sport_id = VSZ.sport_id + and (((S.sub_sport_id is null or S.sub_sport_id = 0) + and (VSZ.sub_sport_id is null or VSZ.sub_sport_id = 0)) + or S.sub_sport_id = VSZ.sub_sport_id) + and S.start_time between VSZ.valid_from and VSZ.valid_until;
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr46-syn.eld @@ -0,0 +1,20 @@ +(((toplevel . 1)) + ((comment-start . 20) + (nested-statement-open . 20) + (statement-continuation . 20)) + ((nested-statement-continuation . 20) + (statement-continuation . 20)) + ((select-column . 52) + (nested-statement-continuation . 20) + (statement-continuation . 20)) + ((select-column . 52) + (nested-statement-continuation . 20) + (statement-continuation . 20)) + ((select-clause . 52) + (nested-statement-continuation . 20) + (statement-continuation . 20)) + ((with-clause . 1) + (statement-continuation . 1)) + ((select-clause . 115) + (statement-continuation . 1)) + ((toplevel . 1)))
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr46.sql @@ -0,0 +1,8 @@ +with some_table as ( + -- a comment at the start + select col1, + col2, + col3 + from some_table) +select * + from some_table;
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr48-syn.eld @@ -0,0 +1,56 @@ +((((block-start begin) + . 1) + (toplevel . 1)) + (((in-begin-block toplevel-block "") + . 1)) + (((in-begin-block toplevel-block "") + . 1)) + (((in-begin-block toplevel-block "") + . 1)) + ((labeled-statement-start . 87) + (statement-continuation . 87)) + (((in-block loop "my_loop") + . 101)) + (((block-end loop "my_loop") + . 101) + ((in-block loop "my_loop") + . 101)) + (((in-begin-block toplevel-block "") + . 1)) + (((in-begin-block toplevel-block "") + . 1)) + (((in-begin-block toplevel-block "") + . 1)) + ((labeled-statement-start . 229) + (statement-continuation . 229)) + (((in-block loop "my_second_loop") + . 250)) + (((in-block loop "my_second_loop") + . 250)) + (((block-end loop "my_second_loop") + . 250) + ((in-block loop "my_second_loop") + . 250)) + (((in-begin-block toplevel-block "") + . 1)) + (((block-end toplevel-block "") + . 1) + ((in-begin-block toplevel-block "") + . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((toplevel . 1)))
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr48.sql @@ -0,0 +1,25 @@ +begin + goto my_loop; + dbms_output.put_line('If you read it, you''re in trouble'); + <<my_loop>> + for ind in 1..5 loop + dbms_output.put_line('ind: ' || ind); + end loop my_loop; + + dbms_output.put_line('end of my_loop'); + <<my_second_loop>> + while true loop + dbms_output.put_line('in my_second_loop'); + goto out_of_loop; + end loop my_second_loop; + dbms_output.put_line('end of my_second_loop'); +end; +/ + +-- Local Variables: +-- indent-tabs-mode: nil +-- mode: sql +-- mode: sqlind-minor +-- sql-product: oracle +-- tab-width: 2 +-- End:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr49-syn.eld @@ -0,0 +1,44 @@ +((((block-start begin) + . 1) + (toplevel . 1)) + (((in-begin-block toplevel-block "") + . 1)) + (((in-block if "") + . 9)) + (((in-block if "") + . 9)) + (((in-block loop "my_third_loop") + . 48)) + (((in-block loop "my_third_loop") + . 48)) + (((block-end loop "my_third_loop") + . 48) + ((in-block loop "my_third_loop") + . 48)) + (((in-block if "") + . 9)) + (((block-end if "") + . 9) + ((in-block if "") + . 9)) + (((block-end toplevel-block "") + . 1) + ((in-begin-block toplevel-block "") + . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((toplevel . 1)))
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr49.sql @@ -0,0 +1,19 @@ +begin + if true then + <<my_third_loop>> + while true loop + dbms_output.put_line('in my_second_loop'); + exit my_third_loop; + end loop my_third_loop; + dbms_output.put_line('end of my_second_loop'); + end if; +end; +/ + +-- Local Variables: +-- indent-tabs-mode: nil +-- mode: sql +-- mode: sqlind-minor +-- sql-product: oracle +-- tab-width: 2 +-- End:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr50-io-left.eld @@ -0,0 +1,1 @@ +(0 7 7 7 7 7 7 7 0 7 0 0 0 0 0 0 0 19 26 19 19 19 19 19 19 0 0 0 0 0 0 0 0 0 0)
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr50.sql @@ -0,0 +1,34 @@ +select distinct + atc.column_name, + atc.data_type, + data_length, + data_precision, + nullable, + data_scale, + nvl(substr(comments, 1, 100), atc.column_name) comments +from all_tab_columns atc, + all_col_comments acc +where atc.owner = acc.owner +and atc.table_name = acc.table_name +and atc.column_name = acc.column_name +and atc.owner = user +and atc.table_name = 'MY_TABLE' +and atc.column_name = p_column_name +and not exists (select 1 + from all_tab_columns atc1, + all_col_comments acc1 + where atc1.owner = acc1.owner + and atc1.table_name = acc1.table_name + and atc1.column_name = acc1.column_name + and atc1.owner = atc.owner + and atc1.table_name = atc.table_name + and acc1.column_name = acc.column_name) +; + +-- Local Variables: +-- mode: sql +-- mode: sqlind-minor +-- tab-width: 2 +-- indent-tabs-mode: nil +-- sql-product: oracle +-- End:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr52-io-left.eld @@ -0,0 +1,1 @@ +(0 4 7 0 0 0 0 0 0 0 0 0 0)
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr52.sql @@ -0,0 +1,12 @@ +select mt.myVar + || '-*-' myVarLabel, + myVar2 +from myTable mt; + +-- Local Variables: +-- mode: sql +-- mode: sqlind-minor +-- tab-width: 2 +-- indent-tabs-mode: nil +-- sql-product: oracle +-- End:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr53-io-left.eld @@ -0,0 +1,1 @@ +(0 4 7 0 0 0 0 0 0 0 0 0 0 0 0)
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr53.sql @@ -0,0 +1,14 @@ +select my_col || chr(10) + || '-*-' data_type, + x +from dual; + + +-- Local Variables: +-- mode: sql +-- mode: sqlind-minor +-- tab-width: 2 +-- indent-tabs-mode: nil +-- sql-product: oracle +-- End: +
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr54-syn.eld @@ -0,0 +1,65 @@ +(((toplevel . 1)) + (((block-start begin) + . 1) + ((defun-start "foo_1") + . 1)) + (((in-begin-block defun "foo_1") + . 1)) + (((block-end defun "foo_1") + . 1) + ((in-begin-block defun "foo_1") + . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + (((in-begin-block defun "foo_2") + . 60)) + (((block-end defun "foo_2") + . 60) + ((in-begin-block defun "foo_2") + . 60)) + ((toplevel . 1)) + ((toplevel . 1)) + (((block-start is-or-as) + . 119) + ((defun-start "foo_3") + . 119)) + (((in-begin-block defun "foo_3") + . 119)) + (((block-end defun "foo_3") + . 119) + ((in-begin-block defun "foo_3") + . 119)) + ((toplevel . 1)) + ((toplevel . 1)) + (((block-start is-or-as) + . 178) + ((defun-start "foo_4") + . 178)) + (((block-start begin) + . 178) + ((defun-start "foo_4") + . 178)) + (((in-begin-block defun "foo_4") + . 178)) + (((block-end defun "foo_4") + . 178) + ((in-begin-block defun "foo_4") + . 178)) + ((toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((toplevel . 1)))
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr54.sql @@ -0,0 +1,29 @@ +create function foo_1() returns int AS +$$ + select 5; +$$; + +create function foo_2() returns int AS $$ + select 5; +$$; + +create function foo_3() returns int +AS $$ + select 5; +$$; + +create function foo_4() returns int +AS +$$ + select 5; +$$; + +SELECT a(); + +-- Local Variables: +-- mode: sql +-- mode: sqlind-minor +-- tab-width: 2 +-- indent-tabs-mode: nil +-- sql-product: postgres +-- End:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr60-syn.eld @@ -0,0 +1,44 @@ +(((toplevel . 1)) + (((create-statement view "myview") + . 1)) + (((create-statement view "myview") + . 1)) + (((create-statement view "myview") + . 1)) + (((create-statement view "myview") + . 1)) + (((create-statement view "myview") + . 1)) + ((select-column . 112) + ((create-statement view "myview") + . 1)) + ((select-clause . 112) + ((create-statement view "myview") + . 1)) + ((select-table-continuation . 208) + ((create-statement view "myview") + . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + (((create-statement table "foo") + . 282)) + ((select-column . 328) + ((create-statement table "foo") + . 282)) + ((select-clause . 328) + ((create-statement table "foo") + . 282)) + ((select-table-continuation . 424) + ((create-statement table "foo") + . 282)) + ((toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((toplevel . 1))) + \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr60.sql @@ -0,0 +1,20 @@ +create or replace + algorithm = undefined + definer = user@localhost + sql security definer + view myview as + select distinct table1.fielda as firstfield, + table2.fieldb as secondfield + from table1 + join table2 on table1.table1id = table2.fktable1; + +create temporary table if not exists foo as + select distinct table1.fielda as firstfield, + table2.fieldb as secondfield + from table1 + join table2 on table1.table1id = table2.fktable1; + +-- local variables: +-- mode: sql +-- sql-product: mysql +-- end:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr64-syn.eld @@ -0,0 +1,93 @@ +(((toplevel . 1)) + ((select-clause . 1) + (statement-continuation . 1)) + ((select-table-continuation . 12) + (statement-continuation . 1)) + ((select-join-condition . 29) + (statement-continuation . 1)) + ((select-table-continuation . 12) + (statement-continuation . 1)) + ((select-join-condition . 70) + (statement-continuation . 1)) + ((select-table-continuation . 12) + (statement-continuation . 1)) + ((select-join-condition . 111) + (statement-continuation . 1)) + ((select-table-continuation . 12) + (statement-continuation . 1)) + ((select-join-condition . 151) + (statement-continuation . 1)) + ((select-table-continuation . 12) + (statement-continuation . 1)) + ((select-join-condition . 192) + (statement-continuation . 1)) + ((select-table-continuation . 12) + (statement-continuation . 1)) + ((select-join-condition . 233) + (statement-continuation . 1)) + ((select-table-continuation . 12) + (statement-continuation . 1)) + ((select-join-condition . 276) + (statement-continuation . 1)) + ((select-table-continuation . 12) + (statement-continuation . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((select-clause . 314) + (statement-continuation . 314)) + ((select-table-continuation . 325) + (statement-continuation . 314)) + ((select-join-condition . 342) + (statement-continuation . 314)) + ((toplevel . 1)) + ((toplevel . 1)) + ((select-clause . 376) + (statement-continuation . 376)) + ((select-table-continuation . 387) + (statement-continuation . 376)) + ((select-join-condition . 404) + (statement-continuation . 376)) + ((select-table-continuation . 387) + (statement-continuation . 376)) + ((toplevel . 1)) + ((toplevel . 1)) + ((select-clause . 447) + (statement-continuation . 447)) + ((select-table-continuation . 458) + (statement-continuation . 447)) + ((select-join-condition . 475) + (statement-continuation . 447)) + ((select-table-continuation . 458) + (statement-continuation . 447)) + ((toplevel . 1)) + ((toplevel . 1)) + ((select-clause . 519) + (statement-continuation . 519)) + ((select-table-continuation . 530) + (statement-continuation . 519)) + ((select-join-condition . 547) + (statement-continuation . 519)) + ((select-table-continuation . 530) + (statement-continuation . 519)) + ((toplevel . 1)) + ((toplevel . 1)) + ((select-clause . 591) + (statement-continuation . 591)) + ((select-table-continuation . 602) + (statement-continuation . 591)) + ((select-join-condition . 619) + (statement-continuation . 591)) + ((select-table-continuation . 602) + (statement-continuation . 591)) + ((toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((select-clause . 666) + (statement-continuation . 666)) + ((select-table-continuation . 677) + (statement-continuation . 666)) + ((select-join-condition . 694) + (statement-continuation . 666)) + ((select-table-continuation . 677) + (statement-continuation . 666)) + ((toplevel . 1))) \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr64.sql @@ -0,0 +1,53 @@ +select * + from T1 + inner join T2 + on a + cross join T3 + on b + left join T4 + on c + right join T5 + on d + cross join T6 + on e + natural join T7 + on f + join T8 + on g + ; + +select * + from T1 + inner join T2 + on a; + +select * + from T1 + left join T2 + on a + ; + +select * + from T1 + right join T2 + on a + ; + +select * + from T1 + cross join T2 + on a + ; + +select * + from T1 + natural join T2 + on a + ; + + +select * + from T1 + join T2 + on a + ;
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr66-syn.eld @@ -0,0 +1,25 @@ +((((block-start begin) + . 1) + (toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + (((block-start begin) + . 1) + (toplevel . 1)) + ((statement-continuation . 89)) + ((toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + (((block-start begin) + . 1) + (toplevel . 1)) + ((statement-continuation . 179)) + ((statement-continuation . 179)) + ((toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1))) + \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr66.sql @@ -0,0 +1,17 @@ +begin transaction; +create table my_table ( id text ); +select id from my_table; +commit; + +begin + transaction; +create table my_table ( id text ); +select id from my_table; +commit; + +begin -- a comment + + transaction; +create table my_table ( id text ); +select id from my_table; +commit;
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr67-syn.eld @@ -0,0 +1,570 @@ +(((comment-start . 1) + (toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + (((block-start begin) + . 1) + (toplevel . 1)) + ((toplevel . 1)) + (((in-begin-block toplevel nil) + . 79)) + (((in-begin-block toplevel nil) + . 79)) + (((in-begin-block toplevel nil) + . 79)) + (((in-begin-block nil "") + . 129)) + (((in-begin-block nil "") + . 129)) + (((in-block if "") + . 155)) + (((in-block if "") + . 155)) + (((block-start elsif) + . 155) + ((in-block if "") + . 155)) + ((select-clause . 231) + (nested-statement-continuation . 230) + (statement-continuation . 230)) + (((in-block elsif "") + . 224)) + (((in-block elsif "") + . 224)) + (((block-start elsif) + . 224) + ((in-block elsif "") + . 224)) + ((select-clause . 347) + (nested-statement-continuation . 346) + (statement-continuation . 346)) + ((select-clause . 347) + (nested-statement-continuation . 346) + (statement-continuation . 346)) + (((in-block elsif "") + . 340)) + (((in-block elsif "") + . 340)) + (((block-start elsif) + . 340) + ((in-block elsif "") + . 340)) + ((select-clause . 496) + (nested-statement-continuation . 495) + (statement-continuation . 495)) + ((select-table-continuation . 526) + (nested-statement-continuation . 495) + (statement-continuation . 495)) + ((select-table-continuation . 526) + (nested-statement-continuation . 495) + (statement-continuation . 495)) + ((select-clause . 496) + (nested-statement-continuation . 495) + (statement-continuation . 495)) + (((in-block elsif "") + . 489)) + (((in-block elsif "") + . 489)) + (((block-start else) + . 489) + ((in-block elsif "") + . 489)) + (((in-block else "") + . 698)) + ((statement-continuation . 709)) + ((statement-continuation . 709)) + ((statement-continuation . 709)) + ((statement-continuation . 709)) + ((statement-continuation . 709)) + ((statement-continuation . 709)) + (((in-block loop "") + . 709)) + ((statement-continuation . 877)) + ((statement-continuation . 877)) + ((statement-continuation . 877)) + ((statement-continuation . 877)) + (((block-end loop "") + . 709) + ((in-block loop "") + . 709)) + (((block-end if "") + . 155) + ((in-block else "") + . 698)) + (((block-end nil "") + . 129) + ((in-begin-block nil "") + . 129)) + ((toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + (((in-begin-block toplevel nil) + . 1113)) + (((in-begin-block toplevel nil) + . 1113)) + (((in-begin-block toplevel nil) + . 1113)) + (((in-begin-block toplevel nil) + . 1113)) + (((in-begin-block nil "") + . 1187)) + (((in-begin-block nil "") + . 1187)) + (((in-begin-block nil "") + . 1187)) + (((in-block if "") + . 1237)) + (((in-block if "") + . 1237)) + (((block-start elsif) + . 1237) + ((in-block if "") + . 1237)) + (((in-block elsif "") + . 1306)) + (((in-block elsif "") + . 1306)) + (((block-start elsif) + . 1306) + ((in-block elsif "") + . 1306)) + ((select-clause . 1388) + (nested-statement-continuation . 1387) + (statement-continuation . 1387)) + ((select-clause . 1388) + (nested-statement-continuation . 1387) + (statement-continuation . 1387)) + (((in-select-clause "where") + . 1443) + (nested-statement-continuation . 1387) + (statement-continuation . 1387)) + (((in-block elsif "") + . 1381)) + (((in-block elsif "") + . 1381)) + (((block-start elsif) + . 1381) + ((in-block elsif "") + . 1381)) + ((select-clause . 1547) + (nested-statement-continuation . 1546) + (statement-continuation . 1546)) + ((select-table-continuation . 1577) + (nested-statement-continuation . 1546) + (statement-continuation . 1546)) + ((select-table-continuation . 1577) + (nested-statement-continuation . 1546) + (statement-continuation . 1546)) + ((select-clause . 1547) + (nested-statement-continuation . 1546) + (statement-continuation . 1546)) + (((in-select-clause "where") + . 1681) + (nested-statement-continuation . 1546) + (statement-continuation . 1546)) + (((in-block elsif "") + . 1540)) + (((in-block elsif "") + . 1540)) + (((block-start elsif) + . 1540) + ((in-block elsif "") + . 1540)) + ((select-clause . 1785) + (nested-statement-continuation . 1784) + (statement-continuation . 1784)) + ((select-table-continuation . 1815) + (nested-statement-continuation . 1784) + (statement-continuation . 1784)) + ((select-table-continuation . 1815) + (nested-statement-continuation . 1784) + (statement-continuation . 1784)) + ((select-table-continuation . 1815) + (nested-statement-continuation . 1784) + (statement-continuation . 1784)) + ((select-clause . 1785) + (nested-statement-continuation . 1784) + (statement-continuation . 1784)) + (((in-select-clause "where") + . 1959) + (nested-statement-continuation . 1784) + (statement-continuation . 1784)) + (((in-block elsif "") + . 1778)) + (((in-block elsif "") + . 1778)) + (((block-start else) + . 1778) + ((in-block elsif "") + . 1778)) + (((in-block else "") + . 2057)) + ((statement-continuation . 2068)) + ((statement-continuation . 2068)) + ((statement-continuation . 2068)) + ((statement-continuation . 2068)) + ((statement-continuation . 2068)) + ((statement-continuation . 2068)) + (((in-block loop "") + . 2068)) + ((statement-continuation . 2249)) + ((statement-continuation . 2249)) + ((statement-continuation . 2249)) + ((statement-continuation . 2249)) + (((block-end loop "") + . 2068) + ((in-block loop "") + . 2068)) + (((block-end if "") + . 1237) + ((in-block else "") + . 2057)) + (((block-end nil "") + . 1187) + ((in-begin-block nil "") + . 1187)) + ((toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + (((in-begin-block toplevel nil) + . 2479)) + (((in-begin-block toplevel nil) + . 2479)) + (((in-begin-block toplevel nil) + . 2479)) + (((in-begin-block nil "") + . 2529)) + (((in-begin-block nil "") + . 2529)) + (((in-block if "") + . 2556)) + (((in-block if "") + . 2556)) + (((block-start elsif) + . 2556) + ((in-block if "") + . 2556)) + ((select-clause . 2633) + (nested-statement-continuation . 2632) + (statement-continuation . 2632)) + (((in-block elsif "") + . 2626)) + (((in-block elsif "") + . 2626)) + (((block-start elsif) + . 2626) + ((in-block elsif "") + . 2626)) + ((select-clause . 2750) + (nested-statement-continuation . 2749) + (statement-continuation . 2749)) + ((select-table-continuation . 2780) + (nested-statement-continuation . 2749) + (statement-continuation . 2749)) + ((select-clause . 2750) + (nested-statement-continuation . 2749) + (statement-continuation . 2749)) + (((in-block elsif "") + . 2743)) + (((in-block elsif "") + . 2743)) + (((block-start else) + . 2743) + ((in-block elsif "") + . 2743)) + (((in-block else "") + . 2913)) + ((statement-continuation . 2924)) + ((statement-continuation . 2924)) + ((statement-continuation . 2924)) + ((statement-continuation . 2924)) + ((statement-continuation . 2924)) + (((in-block loop "") + . 2924)) + ((statement-continuation . 3082)) + ((statement-continuation . 3082)) + ((statement-continuation . 3082)) + ((statement-continuation . 3082)) + (((block-end loop "") + . 2924) + ((in-block loop "") + . 2924)) + (((block-end if "") + . 2556) + ((in-block else "") + . 2913)) + (((block-end nil "") + . 2529) + ((in-begin-block nil "") + . 2529)) + ((toplevel . 1)) + ((toplevel . 1)) + (((in-begin-block toplevel nil) + . 3311)) + (((in-begin-block toplevel nil) + . 3311)) + (((in-begin-block toplevel nil) + . 3311)) + (((in-begin-block nil "") + . 3361)) + (((in-begin-block nil "") + . 3361)) + (((in-block if "") + . 3395)) + (((in-block if "") + . 3395)) + (((block-start elsif) + . 3395) + ((in-block if "") + . 3395)) + ((select-clause . 3472) + (nested-statement-continuation . 3471) + (statement-continuation . 3471)) + (((in-block elsif "") + . 3465)) + (((in-block elsif "") + . 3465)) + (((block-start elsif) + . 3465) + ((in-block elsif "") + . 3465)) + ((select-clause . 3589) + (nested-statement-continuation . 3588) + (statement-continuation . 3588)) + ((select-table-continuation . 3619) + (nested-statement-continuation . 3588) + (statement-continuation . 3588)) + ((select-clause . 3589) + (nested-statement-continuation . 3588) + (statement-continuation . 3588)) + (((in-block elsif "") + . 3582)) + (((in-block elsif "") + . 3582)) + (((block-start else) + . 3582) + ((in-block elsif "") + . 3582)) + (((in-block else "") + . 3752)) + ((statement-continuation . 3763)) + ((statement-continuation . 3763)) + ((statement-continuation . 3763)) + ((statement-continuation . 3763)) + ((statement-continuation . 3763)) + (((in-block loop "") + . 3763)) + ((statement-continuation . 3921)) + ((statement-continuation . 3921)) + ((statement-continuation . 3921)) + ((statement-continuation . 3921)) + (((block-end loop "") + . 3763) + ((in-block loop "") + . 3763)) + (((block-end if "") + . 3395) + ((in-block else "") + . 3752)) + (((block-end nil "") + . 3361) + ((in-begin-block nil "") + . 3361)) + (((block-end toplevel nil) + . 3311) + ((in-begin-block toplevel nil) + . 3311)) + ((toplevel . 1)) + ((toplevel . 1)) + (((in-begin-block toplevel nil) + . 4150)) + (((in-begin-block toplevel nil) + . 4150)) + (((in-begin-block toplevel nil) + . 4150)) + (((in-begin-block toplevel nil) + . 4150)) + (((in-begin-block nil "") + . 4226)) + (((in-begin-block nil "") + . 4226)) + (((in-begin-block nil "") + . 4226)) + (((in-block if "") + . 4273)) + (((in-block if "") + . 4273)) + (((block-start elsif) + . 4273) + ((in-block if "") + . 4273)) + (((in-block elsif "") + . 4343)) + (((in-block elsif "") + . 4343)) + (((block-start elsif) + . 4343) + ((in-block elsif "") + . 4343)) + ((select-clause . 4426) + (nested-statement-continuation . 4425) + (statement-continuation . 4425)) + (((in-select-clause "where") + . 4468) + (nested-statement-continuation . 4425) + (statement-continuation . 4425)) + (((in-block elsif "") + . 4419)) + (((in-block elsif "") + . 4419)) + (((block-start else) + . 4419) + ((in-block elsif "") + . 4419)) + (((in-block else "") + . 4568)) + ((statement-continuation . 4579)) + ((statement-continuation . 4579)) + (((in-block loop "") + . 4579)) + ((statement-continuation . 4670)) + ((statement-continuation . 4670)) + (((block-end loop "") + . 4579) + ((in-block loop "") + . 4579)) + (((block-end if "") + . 4273) + ((in-block else "") + . 4568)) + (((block-end nil "") + . 4226) + ((in-begin-block nil "") + . 4226)) + (((block-end toplevel nil) + . 4150) + ((in-begin-block toplevel nil) + . 4150)) + ((toplevel . 1)) + (((block-start begin) + . 1) + (toplevel . 1)) + ((toplevel . 1)) + (((in-begin-block toplevel nil) + . 4822)) + (((in-begin-block toplevel nil) + . 4822)) + (((in-begin-block toplevel nil) + . 4822)) + (((in-begin-block toplevel nil) + . 4822)) + (((in-begin-block toplevel nil) + . 4822)) + (((in-begin-block nil "") + . 4928)) + (((in-begin-block nil "") + . 4928)) + (((in-begin-block nil "") + . 4928)) + (((in-begin-block nil "") + . 4928)) + (((in-begin-block nil "") + . 4928)) + (((in-block if "") + . 5047)) + (((in-block if "") + . 5047)) + (((block-start elsif) + . 5047) + ((in-block if "") + . 5047)) + (((in-block elsif "") + . 5117)) + (((in-block elsif "") + . 5117)) + (((block-start elsif) + . 5117) + ((in-block elsif "") + . 5117)) + (((in-block elsif "") + . 5193)) + (((in-block elsif "") + . 5193)) + (((block-start else) + . 5193) + ((in-block elsif "") + . 5193)) + (((in-block else "") + . 5266)) + ((nested-statement-continuation . 5303) + (statement-continuation . 5303)) + ((nested-statement-continuation . 5303) + (statement-continuation . 5303)) + ((nested-statement-continuation . 5303) + (statement-continuation . 5303)) + ((nested-statement-continuation . 5303) + (statement-continuation . 5303)) + (((in-block else "") + . 5266)) + (((block-end if "") + . 5047) + ((in-block else "") + . 5266)) + (((block-end nil "") + . 4928) + ((in-begin-block nil "") + . 4928)) + (((block-end toplevel nil) + . 4822) + ((in-begin-block toplevel nil) + . 4822)) + ((toplevel . 1)) + ((toplevel . 1)) + (((block-start begin) + . 1) + (toplevel . 1)) + ((toplevel . 1)) + (((in-begin-block toplevel nil) + . 5627)) + (((in-begin-block toplevel nil) + . 5627)) + (((in-begin-block nil "") + . 5665)) + (((in-begin-block nil "") + . 5665)) + (((in-block if "") + . 5695)) + (((in-block if "") + . 5695)) + (((block-start elsif) + . 5695) + ((in-block if "") + . 5695)) + (((in-block elsif "") + . 5802)) + (((in-block elsif "") + . 5802)) + (((in-block elsif "") + . 5802)) + (((block-start else) + . 5802) + ((in-block elsif "") + . 5802)) + (((in-block else "") + . 5916)) + (((in-block else "") + . 5916)) + (((block-end if "") + . 5695) + ((in-block else "") + . 5916)) + (((block-end nil "") + . 5665) + ((in-begin-block nil "") + . 5665)) + (((block-end toplevel nil) + . 5627) + ((in-begin-block toplevel nil) + . 5627)) + ((toplevel . 1)) + ((toplevel . 1))) \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr67.sql @@ -0,0 +1,250 @@ +/* -*- sql-product: postgres; -*- */ +set serveroutput on; + +begin transaction; +do $$ DECLARE + v1 TABLE1.F1%TYPE; + v2 record; + BEGIN + v1 = :v_v1; + if v1 in (NULL, '') then + raise 'message1'; + rollback; + elsif (select count(F1) from TABLE1 + where F1 = v1) = 0 then + raise 'message2'; + rollback; + elsif (select count(F2) + from TABLE1 natural join TABLE2 + where F1 = v1) = 0 then + raise 'message3'; + rollback; + elsif (select count(F3) + from TABLE3 + natural join TABLE2 + natural join TABLE1 + where F1 = v1) = 0 then + raise 'message4'; + rollback; + else + for v2 in + select * + from TABLE3 + natural join TABLE1 + natural join TABLE4 + natural join TABLE2 + where F1 = v1 loop + raise info 'message5', + v2.F3, v2.F2, v2.F4 || ' ' || + v2.F9 || case when v2.F5 is NULL then '' else + ' ''' || v2.F5 || '''' end, v2.F6, + v2.F7, v2.F8; + end loop; + end if; + END; $$; +commit; + +do $$ DECLARE + v1 TABLE4.F9%TYPE; + prev1 TABLE4.F4%TYPE; + v2 record; + BEGIN + v1 := :v_v1; + prev1 := :v_prev1; + if v1 in (NULL, '') then + raise 'message6'; + rollback; + elsif prev1 in (NULL, '') then + raise 'message7'; + rollback; + elsif (select count(F10) + from TABLE4 + where F9 = v1 + and F4 = prev1) = 0 then + raise 'message8'; + rollback; + elsif (select count(F2) + from TABLE2 + natural join TABLE5 + natural join TABLE4 + where F9 = v1 + and F4 = prev1) = 0 then + raise 'message9'; + rollback; + elsif (select count(F3) + from TABLE3 + natural join TABLE2 + natural join TABLE5 + natural join TABLE4 + where F9 = v1 + and F4 = prev1) = 0 then + raise 'message10'; + rollback; + else + for v2 in select * + from TABLE4 + natural join TABLE5 + natural join TABLE3 + natural join TABLE2 + where F9 = v1 + and F4 = prev1 loop + raise info 'message11', + v2.F3, v2.F2, v2.F4 || ' ' || + v2.F9 || case when v2.F5 is NULL then '' else + ' ''' || v2.F5 || '''' end, v2.F6, + v2.F7, v2.F8; + end loop; + end if; + end; $$; + + +do $$ DECLARE + v2 record; + v3 TABLE2.F6%TYPE; + BEGIN + v3 := :v_v3; + if v3 in ('', NULL) then + raise 'message12'; + rollback; + elsif (select count(F6) from TABLE2 + where F6 = v3) = 0 then + raise 'message13'; + rollback; + elsif (select count(F3) + from TABLE3 + natural join TABLE2 + where F6 = v3) = 0 then + raise 'message14'; + rollback; + else + for v2 in select * + from TABLE4 + natural join TABLE5 + natural join TABLE3 + natural join TABLE2 + where F6 = v3 loop + raise info 'message15', + v2.F3, v2.F2, v2.F4 || ' ' || + v2.F9 || case when v2.F5 is NULL then '' else + ' ''' || v2.F5 || '''' end, v2.F6, + v2.F7, v2.F8; + end loop; + end if; + END; $$; + +do $$ DECLARE + v2 record; + v3 TABLE2.F2%TYPE; + BEGIN + v3 := :v_ouv_titre; + if v3 in ('', NULL) then + raise 'message16'; + rollback; + elsif (select count(F2) from TABLE2 + where F2 = v3) = 0 then + raise 'messaeg17'; + rollback; + elsif (select count(F3) + from TABLE3 + natural join TABLE2 + where F2 = v3) = 0 then + raise 'message18'; + rollback; + else + for v2 in select * + from TABLE4 + natural join TABLE5 + natural join TABLE3 + natural join TABLE2 + where F2 = v3 loop + raise info 'message19', + v2.F3, v2.F2, v2.F4 || ' ' || + v2.F9 || case when v2.F5 is NULL then '' else + ' ''' || v2.F5 || '''' end, v2.F6, + v2.F7, v2.F8; + end loop; + end if; + END; +$$; + +do $$ DECLARE + v1 TABLE6.F12%TYPE; + prev1 TABLE6.F13%TYPE; + v2 record; + BEGIN + v1 := :v_v1; + prev1 := :v_v2; + if v1 in ('', NULL) then + raise 'message20'; + rollback; + elsif prev1 in ('', NULL) then + raise 'message21'; + rollback; + elsif (select count(F23) from TABLE6 + where F12 = v1 + and F13 = prev1) = 0 then + raise 'message22'; + rollback; + else + for v2 in select * from TABLE6 + where F12 = v1 + and F13 = prev1 loop + raise info 'message23', + v2.F23, v2.F13 || ' ' || v2.F12, + v2.F27, v2.F28; + end loop; + end if; + END; +$$; + +begin transaction; +do $$ DECLARE + v1 TABLE6.F23%TYPE; + v1 TABLE6.F12%TYPE; + prev1 TABLE6.F13%TYPE; + v9 TABLE6.V2%TYPE; + BEGIN + select max(v2_id)+1 into v1 from t_v2ent; + v1 := :v_v2_c2; + prev1 := :v_v2_c8; + v9 := :v_v2_c9; + if v1 in ('', NULL) then + raise 'message24'; + rollback; + elsif prev1 in ('', NULL) then + raise 'message25'; + rollback; + elsif v9 in ('', NULL) then + raise 'message26'; + rollback; + else + insert into TABLE6 values (v1, :v19, timestamp 'now', + v1, prev1, :v_v2_v8, + :v_v2_c7, :v_v2_v9, + :v_v2_c8, :v_v2_v10, + :v_v2_c9, v9); + raise notice 'message27', v1; + end if; + END; +$$; +commit; + +begin transaction; +do $$ DECLARE + v1 TABLE6.F23%TYPE; + BEGIN + v1 := :v_v2_id; + if (select count(F23) from TABLE6 where F23 = v2_id) = 0 then + raise 'message28'; + rollback; + elsif (select F27 from TABLE6 where F23 = v1) is not + NULL then + raise 'message29'; + rollback; + else + delete from TABLE6 where V1 = v1; + raise notice 'message 30'; + end if; + END; +$$; +commit;
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr68-syn.eld @@ -0,0 +1,18 @@ +(((toplevel . 1)) + ((select-clause . 1) + (statement-continuation . 1)) + ((select-table-continuation . 12) + (statement-continuation . 1)) + ((nested-statement-open . 34) + (statement-continuation . 34)) + ((nested-statement-continuation . 34) + (statement-continuation . 34)) + ((select-join-condition . 61) + (nested-statement-continuation . 34) + (statement-continuation . 34)) + ((nested-statement-close . 34) + (statement-continuation . 34)) + ((select-join-condition . 29) + (statement-continuation . 1)) + ((toplevel . 1)) + ((toplevel . 1))) \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr68.sql @@ -0,0 +1,9 @@ +select * + from t1 + join ( + t2 + left join t3 + using (k2) + ) + on t1.k1 = t2.k1; +
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr7-syn.eld @@ -0,0 +1,131 @@ +(((toplevel . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + (((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + (((package "my_package") + . 1)) + (((package "my_package") + . 1)) + (((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + (((package "my_package") + . 1)) + (((package "my_package") + . 1)) + (((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + (((package "my_package") + . 1)) + (((package "my_package") + . 1)) + (((block-end package "my_package") + . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((toplevel . 1))) + + \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr7.eld @@ -0,0 +1,131 @@ +(((toplevel . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + (((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + (((package "my_package") + . 1)) + (((package "my_package") + . 1)) + (((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + (((package "my_package") + . 1)) + (((package "my_package") + . 1)) + (((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + ((package "my_package") + . 1)) + (((package "my_package") + . 1)) + (((package "my_package") + . 1)) + (((block-end package "my_package") + . 1) + ((package "my_package") + . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((toplevel . 1))) + + \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr7.sql @@ -0,0 +1,47 @@ +create or replace package my_package authid current_user + -- Author : me + -- Date : 06/05/2017 + -- Version : 715.00.0001 + -- Object : sample package + -- ---------------------------------------------------------------------------- + + ------------------------------------------------------------------------------- + -- NAME : simple_boolean_fct_1 + -- CREATED : 06/05/2017 + -- AUTHOR : + ------------------------------------------------------------------------------- + -- RET : true if all goes well, false instead + ------------------------------------------------------------------------------- + -- DESC : dummy function + ------------------------------------------------------------------------------- + -- + FUNCTION simple_boolean_fct_1(param1 in boolean) + RETURN BOOLEAN; + + ------------------------------------------------------------------------------- + -- NAME : simple_boolean_fct_2 + -- CREATED : 06/05/2017 + -- AUTHOR : + ------------------------------------------------------------------------------- + -- RET : true if all goes well, false instead + ------------------------------------------------------------------------------- + -- DESC : dummy function + ------------------------------------------------------------------------------- + FUNCTION simple_bolean_fct_2(param1 in boolean) + RETURN BOOLEAN; + + ------------------------------------------------------------------------------- + -- NAME : simple_boolean_fct_3 + -- CREATED : 06/05/2017 + -- AUTHOR : + ------------------------------------------------------------------------------- + -- RET : true if all goes well, false instead + ------------------------------------------------------------------------------- + -- DESC : dummy function + ------------------------------------------------------------------------------- + FUNCTION simple_boolean_fct_3(param1 in boolean) + RETURN BOOLEAN; +end my_package; +-- Local Variables: +-- sql-product: oracle +-- End:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr70-syn.eld @@ -0,0 +1,78 @@ +(((toplevel . 1)) + ((select-column . 1) + (statement-continuation . 1)) + ((select-clause . 1) + (statement-continuation . 1)) + ((select-table-continuation . 14) + (statement-continuation . 1)) + ((select-table-continuation . 14) + (statement-continuation . 1)) + ((select-join-condition . 34) + (statement-continuation . 1)) + ((select-join-condition . 34) + (statement-continuation . 1)) + ((comment-start . 1) + (statement-continuation . 1)) + ((select-table-continuation . 14) + (statement-continuation . 1)) + ((nested-statement-open . 132) + (statement-continuation . 132)) + ((nested-statement-continuation . 132) + (statement-continuation . 132)) + ((select-join-condition . 153) + (nested-statement-continuation . 132) + (statement-continuation . 132)) + ((select-join-condition . 153) + (nested-statement-continuation . 132) + (statement-continuation . 132)) + ((nested-statement-close . 132) + (statement-continuation . 132)) + ((select-join-condition . 127) + (statement-continuation . 1)) + ((select-join-condition . 127) + (statement-continuation . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((select-column . 389) + (statement-continuation . 389)) + ((select-clause . 389) + (statement-continuation . 389)) + ((select-table-continuation . 402) + (statement-continuation . 389)) + ((select-table-continuation . 402) + (statement-continuation . 389)) + ((select-join-condition . 422) + (statement-continuation . 389)) + ((nested-statement-continuation . 443) + (statement-continuation . 443)) + ((comment-start . 389) + (statement-continuation . 389)) + ((select-table-continuation . 402) + (statement-continuation . 389)) + ((nested-statement-open . 606) + (statement-continuation . 606)) + ((nested-statement-continuation . 606) + (statement-continuation . 606)) + ((select-join-condition . 627) + (nested-statement-continuation . 606) + (statement-continuation . 606)) + ((nested-statement-continuation . 655) + (statement-continuation . 655)) + ((nested-statement-close . 606) + (statement-continuation . 606)) + ((select-join-condition . 601) + (statement-continuation . 389)) + ((nested-statement-continuation . 771) + (statement-continuation . 771)) + ((toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((nested-statement-continuation . 874) + (statement-continuation . 874)) + ((select-join-condition . 885) + (nested-statement-continuation . 874) + (statement-continuation . 874)) + ((select-clause . 867) + (statement-continuation . 867)) + ((toplevel . 1))) + \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr70.sql @@ -0,0 +1,39 @@ +select + * + from + t1 + join t2 + on t1.k = t2.k + and t1.j = t2.j + -- here's a "nested join" + join ( + t3 + left join t4 + on t3.k = t4.k + and t3.j = t4.j -- this "and" is a select-join-condition + ) + on t1.k = t3.k + and t1.k = t4.k; -- this "and" is a select-join-condition + +select + * + from + t1 + join t2 + on (t1.k = t2.k + and t1.j = t2.j) -- this "and" is a nested-statement-continuation + -- here's a "nested join" + join ( + t3 + left join t4 + on (t3.k = t4.k + and t3.j = t4.j) -- this "and" is a nested-statement-continuation + ) + on (t1.k = t3.k + and t1.k = t4.k); -- this "and" is a nested-statement-continuation + + +select (a + join b + on a.k1 = b.k2) -- this is a select-join-condition (hey! we're not an sql parser + from a, b;
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr73-syn.eld @@ -0,0 +1,58 @@ +(((toplevel . 1)) + ((select-clause . 1) + (statement-continuation . 1)) + ((select-table-continuation . 12) + (statement-continuation . 1)) + ((select-join-condition . 30) + (statement-continuation . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((select-clause . 76) + (statement-continuation . 76)) + ((select-clause . 76) + (statement-continuation . 76)) + ((select-clause . 76) + (statement-continuation . 76)) + ((select-clause . 76) + (statement-continuation . 76)) + ((toplevel . 1)) + ((toplevel . 1)) + ((select-clause . 127) + (statement-continuation . 127)) + ((select-clause . 127) + (statement-continuation . 127)) + ((select-clause . 127) + (statement-continuation . 127)) + ((select-clause . 127) + (statement-continuation . 127)) + ((toplevel . 1)) + ((toplevel . 1)) + ((select-clause . 178) + (statement-continuation . 178)) + ((select-clause . 178) + (statement-continuation . 178)) + ((select-clause . 178) + (statement-continuation . 178)) + ((select-clause . 178) + (statement-continuation . 178)) + ((toplevel . 1)) + ((toplevel . 1)) + ((select-clause . 233) + (statement-continuation . 233)) + ((select-clause . 233) + (statement-continuation . 233)) + ((select-clause . 233) + (statement-continuation . 233)) + ((select-clause . 233) + (statement-continuation . 233)) + ((toplevel . 1)) + ((toplevel . 1)) + ((select-clause . 284) + (statement-continuation . 284)) + ((select-clause . 284) + (statement-continuation . 284)) + ((select-clause . 284) + (statement-continuation . 284)) + ((select-clause . 284) + (statement-continuation . 284)) + ((toplevel . 1))) \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr73.sql @@ -0,0 +1,34 @@ +select * + from foo + full join bar + on foo.k = bar.k; + +select id + from foo +except +select id + from bar; + +select id + from foo + union +select id + from bar; + +select id + from foo + union all +select id + from bar; + +select id + from foo + minus +select id + from bar; + +select id + from foo +intersect +select id + from bar;
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr75-oracle-syn.eld @@ -0,0 +1,51 @@ +(((toplevel . 1)) + (((create-statement temp "table") + . 1)) + (((create-statement temp "table") + . 1)) + (((create-statement temp "table") + . 1)) + (((create-statement temp "table") + . 1)) + (((create-statement temp "table") + . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + (((create-statement view "myview") + . 196)) + ((select-column . 233) + ((create-statement view "myview") + . 196)) + ((select-clause . 233) + ((create-statement view "myview") + . 196)) + ((select-table-continuation . 329) + ((create-statement view "myview") + . 196)) + ((toplevel . 1)) + ((toplevel . 1)) + (((create-statement table "foo") + . 403)) + (((create-statement table "foo") + . 403)) + (((create-statement table "foo") + . 403)) + ((select-column . 525) + ((create-statement table "foo") + . 403)) + ((select-clause . 525) + ((create-statement table "foo") + . 403)) + ((select-table-continuation . 621) + ((create-statement table "foo") + . 403)) + ((toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((toplevel . 1))) \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr75-oracle.sql @@ -0,0 +1,25 @@ +create or replace + private temp table mytable as + select distinct table1.fielda as firstfield, + table2.fieldb as secondfield + from table1 + join table2 on table1.table1id = table2.fktable1; + +create materialized view myview as + select distinct table1.fielda as firstfield, + table2.fieldb as secondfield + from table1 + join table2 on table1.table1id = table2.fktable1; + +create private -- apparently all temporary tables must be private in Oracle + temporary table if not exists foo + as + select distinct table1.fielda as firstfield, + table2.fieldb as secondfield + from table1 + join table2 on table1.table1id = table2.fktable1; + +-- local variables: +-- mode: sql +-- sql-product: oracle +-- end:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr75-postgres-syn.eld @@ -0,0 +1,67 @@ +(((toplevel . 1)) + (((create-statement table "mytable") + . 1)) + (((create-statement table "mytable") + . 1)) + ((select-column . 52) + ((create-statement table "mytable") + . 1)) + ((select-clause . 52) + ((create-statement table "mytable") + . 1)) + ((select-table-continuation . 148) + ((create-statement table "mytable") + . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + (((create-statement table "mytable") + . 222)) + ((select-column . 273) + ((create-statement table "mytable") + . 222)) + ((select-clause . 273) + ((create-statement table "mytable") + . 222)) + ((select-table-continuation . 369) + ((create-statement table "mytable") + . 222)) + ((toplevel . 1)) + ((toplevel . 1)) + (((create-statement view "myview") + . 443)) + ((select-column . 480) + ((create-statement view "myview") + . 443)) + ((select-clause . 480) + ((create-statement view "myview") + . 443)) + ((select-table-continuation . 576) + ((create-statement view "myview") + . 443)) + ((toplevel . 1)) + ((toplevel . 1)) + (((create-statement table "foo") + . 650)) + (((create-statement table "foo") + . 650)) + ((select-column . 698) + ((create-statement table "foo") + . 650)) + ((select-clause . 698) + ((create-statement table "foo") + . 650)) + ((select-table-continuation . 794) + ((create-statement table "foo") + . 650)) + ((toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((toplevel . 1))) + + \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr75-postgres.sql @@ -0,0 +1,30 @@ +create or replace + global temp table mytable as + select distinct table1.fielda as firstfield, + table2.fieldb as secondfield + from table1 + join table2 on table1.table1id = table2.fktable1; + +create local temporary unlogged table mytable as + select distinct table1.fielda as firstfield, + table2.fieldb as secondfield + from table1 + join table2 on table1.table1id = table2.fktable1; + +create materialized view myview as + select distinct table1.fielda as firstfield, + table2.fieldb as secondfield + from table1 + join table2 on table1.table1id = table2.fktable1; + +create temporary table if not exists foo + as + select distinct table1.fielda as firstfield, + table2.fieldb as secondfield + from table1 + join table2 on table1.table1id = table2.fktable1; + +-- local variables: +-- mode: sql +-- sql-product: postgres +-- end:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr80-syn.eld @@ -0,0 +1,11 @@ +(((toplevel . 1)) + ((toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((comment-start . 1) + (toplevel . 1)) + ((toplevel . 1)))
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr80.sql @@ -0,0 +1,6 @@ +drop function if exists test; + +-- local variables: +-- mode: sql +-- sql-product: postgres +-- end:
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr81-syn.eld @@ -0,0 +1,48 @@ +(((toplevel . 1)) + ((select-clause . 5) + (nested-statement-continuation . 4) + (statement-continuation . 4)) + ((select-clause . 5) + (nested-statement-continuation . 4) + (statement-continuation . 4)) + (((block-start then) + . 1) + ((in-block if "") + . 1)) + (((in-block then "") + . 70)) + (((block-start elsif) + . 70) + ((in-block then "") + . 70)) + (((in-block elsif "") + . 97)) + (((block-end if "") + . 70) + ((in-block elsif "") + . 97)) + ((toplevel . 1)) + ((toplevel . 1)) + ((select-clause . 139) + (nested-statement-continuation . 138) + (statement-continuation . 138)) + ((select-clause . 139) + (nested-statement-continuation . 138) + (statement-continuation . 138)) + (((block-start then) + . 135) + ((in-block if "") + . 135)) + (((in-block then "") + . 204)) + (((block-start elseif) + . 204) + ((in-block then "") + . 204)) + (((in-block else "") + . 231)) + (((block-end if "") + . 204) + ((in-block else "") + . 231)) + ((toplevel . 1))) \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr81.sql @@ -0,0 +1,17 @@ +IF (SELECT ID + FROM SomeTable + WHERE SomeField > 0) IS NULL +THEN + SET SomeVar = TRUE; +ELSIF + SET SomeVar = FALSE; +END IF; + +IF (SELECT ID + FROM SomeTable + WHERE SomeField > 0) IS NULL +THEN + SET SomeVar = TRUE; +ELSEIF + SET SomeVar = FALSE; +END IF;
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr83-syn.eld @@ -0,0 +1,15 @@ +(((toplevel . 1)) + ((select-column . 1) + (statement-continuation . 1)) + ((select-column . 1) + (statement-continuation . 1)) + ((comment-start . 1) + (statement-continuation . 1)) + ((select-column . 1) + (statement-continuation . 1)) + ((select-column . 1) + (statement-continuation . 1)) + ((select-clause . 1) + (statement-continuation . 1)) + ((toplevel . 1))) + \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr83.sql @@ -0,0 +1,7 @@ +SELECT + Column1, + Column2, + -- this is FROM a blog WHERE useful stuff was described + Column3, + Column4 + FROM Atable;
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr84-syn.eld @@ -0,0 +1,28 @@ +((((block-start begin) + . 1) + (toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + (((block-start begin) + . 1) + (toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + (((block-start begin) + . 1) + (toplevel . 1)) + ((statement-continuation . 76)) + ((toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + (((block-start begin) + . 1) + (toplevel . 1)) + ((statement-continuation . 163)) + ((toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1))) + \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr84.sql @@ -0,0 +1,18 @@ +begin; + select * from foo; +commit; + +begin work; +select * from foo; +commit; + +begin -- a comment + work; +select * from foo; +commit; + +begin -- a comment + transaction; +select * from foo; +commit; +
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr85-syn.eld @@ -0,0 +1,57 @@ +(((toplevel . 1)) + ((select-clause . 1) + (statement-continuation . 1)) + ((select-table-continuation . 12) + (statement-continuation . 1)) + ((select-join-condition . 30) + (statement-continuation . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((select-clause . 82) + (statement-continuation . 82)) + ((select-table-continuation . 93) + (statement-continuation . 82)) + ((select-table-continuation . 93) + (statement-continuation . 82)) + ((select-join-condition . 111) + (statement-continuation . 82)) + ((toplevel . 1)) + ((toplevel . 1)) + ((select-clause . 172) + (statement-continuation . 172)) + ((select-table-continuation . 183) + (statement-continuation . 172)) + ((select-table-continuation . 183) + (statement-continuation . 172)) + ((select-join-condition . 201) + (statement-continuation . 172)) + ((toplevel . 1)) + ((toplevel . 1)) + ((select-clause . 290) + (statement-continuation . 290)) + ((select-table-continuation . 301) + (statement-continuation . 290)) + ((select-join-condition . 319) + (statement-continuation . 290)) + ((toplevel . 1)) + ((toplevel . 1)) + ((select-clause . 372) + (statement-continuation . 372)) + ((select-table-continuation . 383) + (statement-continuation . 372)) + ((select-table-continuation . 383) + (statement-continuation . 372)) + ((select-join-condition . 401) + (statement-continuation . 372)) + ((toplevel . 1)) + ((toplevel . 1)) + ((select-clause . 496) + (statement-continuation . 496)) + ((select-table-continuation . 507) + (statement-continuation . 496)) + ((select-table-continuation . 507) + (statement-continuation . 496)) + ((select-join-condition . 525) + (statement-continuation . 496)) + ((toplevel . 1))) + \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/sql-indent-1.4/test-data/pr85.sql @@ -0,0 +1,33 @@ +select * + from foo + left outer join bar + on foo.k = bar.k; + +select * + from foo + left + outer join bar + on foo.k = bar.k; + +select * + from foo + left outer -- test + join bar + on foo.k = bar.k; + +select * + from foo + right outer join bar + on foo.k = bar.k; + +select * + from foo + right -- test + outer join bar + on foo.k = bar.k; + +select * + from foo + right outer + join bar + on foo.k = bar.k;