sql-indent-left.el (12306B)
1 ;;; sql-indent-left.el --- configuration options to indent sql -*- lexical-binding: t -*- 2 3 ;; Copyright (C) 2017 Free Software Foundation, Inc 4 5 ;; Filename: sql-indent-left.el 6 ;; Description: 7 ;; Author: pierre.techoueyres@free.fr 8 ;; Maintainer: pierre.techoueyres@free.fr 9 ;; Created: 10 ;; Version: pierre.techoueyres@free.fr 11 ;; Last-Updated: 12 ;; By: 13 ;; Update #: 0 14 ;; URL: 15 ;; Keywords: language sql indentation 16 ;; Compatibility: 17 ;; 18 ;; Features that might be required by this library: 19 ;; 20 ;; None 21 22 ;; This program is free software; you can redistribute it and/or modify 23 ;; it under the terms of the GNU General Public License as published by 24 ;; the Free Software Foundation; either version 3 of the License, or 25 ;; (at your option) any later version. 26 ;; 27 ;; This program is distributed in the hope that it will be useful, 28 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 29 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 ;; GNU General Public License for more details. 31 ;; 32 ;; You should have received a copy of the GNU General Public License 33 ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. 34 35 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 36 ;; 37 ;;; Commentary: 38 ;; 39 ;; Set configuration options to indent sql my way. 40 ;; 41 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 42 ;; 43 ;;; Change log: 44 ;; 45 ;; 46 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 47 ;; 48 ;; This program is free software; you can redistribute it and/or 49 ;; modify it under the terms of the GNU General Public License as 50 ;; published by the Free Software Foundation; either version 3, or 51 ;; (at your option) any later version. 52 ;; 53 ;; This program is distributed in the hope that it will be useful, 54 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 55 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 56 ;; General Public License for more details. 57 ;; 58 ;; You should have received a copy of the GNU General Public License 59 ;; along with this program; see the file COPYING. If not, write to 60 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth 61 ;; Floor, Boston, MA 02110-1301, USA. 62 ;; 63 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 64 ;; 65 ;;; Code: 66 67 (require 'sql-indent) 68 69 (defun indent-case-statement-items (syntax base-indentation) 70 "Look for a SYNTAX of ((block-start when) (in-block case \"\") ...) 71 or ((block-start else) (in-block case \"\") ...)." 72 (let ((outer (sqlind-outer-context syntax))) 73 (if (and (eq 'in-block (sqlind-syntax-symbol outer)) 74 (eq 'case (sqlind-syntax-keyword outer)) 75 (eq 'block-start (sqlind-syntax-symbol syntax)) 76 (memq (sqlind-syntax-keyword syntax) '(when else))) 77 (+ base-indentation sqlind-basic-offset) 78 base-indentation))) 79 80 (defvar sqlind-indentation-right-offsets-alist 81 `((select-column-continuation sqlind-indent-select-column 82 sqlind-adjust-operator 83 sqlind-lone-semicolon) 84 (in-select-clause sqlind-lineup-to-clause-end 85 sqlind-adjust-operator 86 sqlind-right-justify-logical-operator 87 sqlind-lone-semicolon) 88 (in-delete-clause sqlind-lineup-to-clause-end 89 sqlind-adjust-operator 90 sqlind-right-justify-logical-operator 91 sqlind-lone-semicolon) 92 (in-insert-clause sqlind-lineup-to-clause-end 93 sqlind-adjust-operator 94 sqlind-right-justify-logical-operator 95 sqlind-lone-semicolon) 96 (in-update-clause sqlind-lineup-to-clause-end 97 sqlind-adjust-operator 98 sqlind-right-justify-logical-operator 99 sqlind-lone-semicolon) 100 ;; mandatory 101 (select-table-continuation sqlind-indent-select-table + 102 sqlind-lone-semicolon) 103 ;; rest picked up from the original indentation offsets 104 ,@sqlind-default-indentation-offsets-alist) 105 "Align sql code like this : 106 107 clear columns 108 set linesize 2500 109 set trimout on trimspool on 110 111 select atc.column_name, 112 atc.data_type, 113 data_length, 114 data_precision, 115 nullable, 116 data_scale, 117 nvl(substr(comments, 1, 100), atc.column_name) comments 118 from all_tab_columns atc, 119 all_col_comments acc 120 where atc.owner = acc.owner 121 and atc.table_name = acc.table_name 122 and atc.column_name = acc.column_name 123 and atc.owner = user 124 and atc.table_name = 'MY_TABLE' 125 and atc.column_name = p_column_name 126 and not exists (select 1 127 from all_tab_columns atc1, 128 all_col_comments acc1 129 where atc1.owner = acc1.owner 130 and atc1.table_name = acc1.table_name 131 and atc1.column_name = acc1.column_name 132 and atc1.owner = atc.owner 133 and atc1.table_name = atc.table_name 134 and acc1.column_name = acc.column_name) 135 ; 136 137 delete from my_table mt 138 where col_1 = v_col1 139 and ( col_2 = v_col2 140 or col_3 = v_col3) 141 and col_42 = '42' 142 ; 143 144 update my_table 145 set col1_has_a_long_name = value1, 146 col2_is_short = value2 147 where cond1 is not null 148 and ( col_2 = v_col2 149 or col_3 = v_col3) 150 and col_42 = '42' 151 ; 152 153 insert into xyzxx 154 ( aaa, xxx, bbb, ccc, 155 ddd, eee, fff, ggg, 156 hhh ) 157 select aaa, 158 xxx, 159 max (m.b1) as bbb, 160 min (m.b1) as ccc, 161 coalesce (max (n.c2), 0) as ddd, 162 coalesce (min (n.c2), 0) as eee, 163 max (m.b1) over ( partition by c2 164 order by aaa desc ) as fff, 165 min (m.b1) over ( partition by c2 166 order by aaa desc ) as ggg, 167 avg (n.c2) as hhh 168 from (select * from (select aaa, 169 jjj + kkk as b1, 170 row_number () over ( partition by qqq 171 order by rrr, 172 sss ) as rn 173 from mno) 174 where rn = 1) m 175 inner join (select aaa, 176 nnn + ooo as c2 177 from pqr) n 178 using (aaa), 179 group by aaa, 180 xxx 181 order by xxx desc, 182 aaa asc 183 ;") 184 185 (defvar sqlind-indentation-left-offsets-alist 186 `((select-clause 0) 187 (insert-clause 0) 188 (delete-clause 0) 189 (update-clause 0) 190 (case-clause-item-cont 0) 191 (block-start indent-case-statement-items) 192 (begin-block 0) 193 (case-clause +) 194 (package +) 195 (package-body +) 196 (statement-continuation + sqlind-adjust-operator) 197 (nested-statement-open 1) 198 (nested-statement-continuation 1) 199 (nested-statement-close sqlind-use-anchor-indentation) 200 (string-continuation 0) ;; or should it be a beginning of line or aligned with the previous block ? 201 ;; Anyway. It's really *BAD* to continue a string across lines. 202 (select-column sqlind-indent-select-column-alt 203 sqlind-adjust-operator 204 sqlind-lone-semicolon) 205 (select-column-continuation sqlind-indent-select-column-alt 206 sqlind-adjust-operator 207 sqlind-lone-semicolon) 208 (in-select-clause sqlind-lineup-to-clause-end 209 sqlind-adjust-operator 210 sqlind-left-justify-logical-operator 211 sqlind-lone-semicolon) 212 (in-delete-clause sqlind-lineup-to-clause-end 213 sqlind-adjust-operator 214 sqlind-left-justify-logical-operator 215 sqlind-lone-semicolon) 216 (in-insert-clause + 217 sqlind-adjust-operator 218 sqlind-left-justify-logical-operator 219 sqlind-lone-semicolon) 220 (in-update-clause sqlind-lineup-to-clause-end 221 sqlind-adjust-operator 222 sqlind-left-justify-logical-operator 223 sqlind-lone-semicolon) 224 (select-table-continuation + sqlind-lone-semicolon) 225 ;; rest picked up from the original indentation offsets 226 ,@sqlind-default-indentation-offsets-alist) 227 "Align sql code like this : 228 229 clear columns 230 set linesize 2500 231 set trimout on trimspool on 232 233 select DISTINCT 234 atc.column_name, 235 atc.data_type, 236 data_length, 237 data_precision, 238 nullable, 239 data_scale, 240 nvl(substr(comments, 1, 100), atc.column_name) comments 241 from all_tab_columns atc, 242 all_col_comments acc 243 where atc.owner = acc.owner 244 and atc.table_name = acc.table_name 245 and atc.column_name = acc.column_name 246 and atc.owner = user 247 and atc.table_name = 'MY_TABLE' 248 and atc.column_name = p_column_name 249 and not exists (select 1 250 from all_tab_columns atc1, 251 all_col_comments acc1 252 where atc1.owner = acc1.owner 253 and atc1.table_name = acc1.table_name 254 and atc1.column_name = acc1.column_name 255 and atc1.owner = atc.owner 256 and atc1.table_name = atc.table_name 257 and acc1.column_name = acc.column_name) 258 ; 259 260 delete from my_table mt 261 where col_1 = v_col1 262 and ( col_2 = v_col2 263 or col_3 = v_col3) 264 and col_42 = '42' 265 ; 266 267 update my_table 268 set col1_has_a_long_name = value1, 269 col2_is_short = value2 270 where cond1 is not null 271 and ( col_2 = v_col2 272 or col_3 = v_col3) 273 and col_42 = '42' 274 ; 275 276 insert into xyzxx 277 ( aaa, xxx, bbb, ccc, 278 ddd, eee, fff, ggg, 279 hhh ) 280 select aaa, 281 xxx, 282 max (m.b1) as bbb, 283 min (m.b1) as ccc, 284 coalesce (max (n.c2), 0) as ddd, 285 coalesce (min (n.c2), 0) as eee, 286 max (m.b1) over ( partition by c2 287 order by aaa desc ) as fff, 288 min (m.b1) over ( partition by c2 289 order by aaa desc ) as ggg, 290 avg (n.c2) as hhh 291 from (select * from (select aaa, 292 jjj + kkk as b1, 293 row_number () over ( partition by qqq 294 order by rrr, 295 sss ) as rn 296 from mno) 297 where rn = 1) m 298 inner join (select aaa, 299 nnn + ooo as c2 300 from pqr) n 301 using (aaa), 302 group by aaa, 303 xxx 304 order by xxx desc, 305 aaa asc 306 ;") 307 308 (defun sqlind-indent-select-column-alt (syntax base-indentation) 309 "Return the indentation for a column after a SELECT DISTINCT clause. 310 311 SYNTAX is the syntax of the current line, BASE-INDENTATION is the 312 current indentation, which we need to update. 313 314 Like `sqlind-indent-select-column' but we try to align to the KEYWORD, 315 but if we are the first column after the SELECT clause we simply 316 add `sqlind-basic-offset'." 317 (save-excursion 318 (goto-char (sqlind-anchor-point syntax)) 319 (when (looking-at "select\\s *\\(top\\s +[0-9]+\\|distinct\\|unique\\)?") 320 (if (match-beginning 1) 321 (goto-char (match-beginning 1)) 322 (goto-char (match-end 0)))) 323 (skip-syntax-forward " ") 324 (if (or (looking-at sqlind-comment-start-skip) 325 (looking-at "$")) 326 (+ base-indentation sqlind-basic-offset) 327 (current-column)))) 328 329 ;;;###autoload 330 (defun sqlind-setup-style-left () 331 "Define an sql-indentation style where keywords are left aligned." 332 (interactive) 333 (setq sqlind-indentation-offsets-alist sqlind-indentation-left-offsets-alist)) 334 335 ;;;###autoload 336 (defun sqlind-setup-style-right () 337 "Define an sql-indentation style where keywords are right aligned." 338 (interactive) 339 (setq sqlind-indentation-offsets-alist sqlind-indentation-right-offsets-alist)) 340 341 342 ;;;###autoload 343 (defun sqlind-setup-style-default () 344 "Define an sql-indentation style where keywords are right aligned." 345 (interactive) 346 (setq sqlind-indentation-offsets-alist sqlind-default-indentation-offsets-alist)) 347 348 349 (provide 'sql-indent-left) 350 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 351 ;;; sql-indent-left.el ends here