branch: externals/sql-indent
commit d59009e26b275add42e06c8245473096f9872af6
Author: Alex Harsanyi <[email protected]>
Commit: Alex Harsanyi <[email protected]>

    Don't be fooled by "if exists" statements
    
    "IF" keywords in things like "drop index if exists" statements are no longer
    considered statement starts.
---
 sql-indent-test.el          |  3 +++
 sql-indent.el               | 42 +++++++++++++++++++++++++++---------------
 test-data/if-exists-syn.eld | 19 +++++++++++++++++++
 test-data/if-exists.sql     | 12 ++++++++++++
 4 files changed, 61 insertions(+), 15 deletions(-)

diff --git a/sql-indent-test.el b/sql-indent-test.el
index 00a2355..a8786b4 100644
--- a/sql-indent-test.el
+++ b/sql-indent-test.el
@@ -308,4 +308,7 @@ information read from DATA-FILE (as generated by
 (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"))
+
 ;;; sql-indent-test.el ends here
diff --git a/sql-indent.el b/sql-indent.el
index 3857038..5b25f8d 100644
--- a/sql-indent.el
+++ b/sql-indent.el
@@ -318,9 +318,13 @@ But don't go before LIMIT."
                      (when (looking-at ";")
                        ;; Statement begins after the keyword
                        (throw 'done candidate-pos)))
-                    ((looking-at "\\b\\(if\\|elsif\\)\\b")
+                    ((looking-at "\\b\\(elsif\\)\\b")
                      ;; statement begins at the start of the keyword
                      (throw 'done (point)))
+                    ((looking-at "\\b\\(if\\)\\b")
+                     (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)
@@ -460,22 +464,30 @@ See also `sqlind-beginning-of-block'"
            (goto-char start-pos)
            nil))))))
 
+(defun sqlind-good-if-candidate ()
+  "Return true 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\\procedude\\|function\\|package\\|body")))))
+
 (defun sqlind-maybe-if-statement ()
   "If (point) is on an IF statement, report its syntax."
-  (when (looking-at "if")
-    (save-excursion
-      (sqlind-backward-syntactic-ws)
-      (forward-word -1)
-      (unless (looking-at "end")        ; we don't want to match an "end if" 
here
-        (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))))))))))
+  (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"
diff --git a/test-data/if-exists-syn.eld b/test-data/if-exists-syn.eld
new file mode 100644
index 0000000..b133374
--- /dev/null
+++ b/test-data/if-exists-syn.eld
@@ -0,0 +1,19 @@
+(((toplevel . 1))
+ ((toplevel . 1))
+ ((toplevel . 1))
+ (((create-statement index "ix1_some_table")
+   . 39))
+ ((toplevel . 1))
+ ((comment-start . 1)
+  (toplevel . 1))
+ ((comment-start . 1)
+  (toplevel . 1))
+ ((toplevel . 1))
+ (((create-statement index "if")
+   . 190))
+ ((toplevel . 1))
+ ((toplevel . 1))
+ (((create-statement index "ix3_some_table")
+   . 269))
+ ((toplevel . 1)))
+ 
\ No newline at end of file
diff --git a/test-data/if-exists.sql b/test-data/if-exists.sql
new file mode 100644
index 0000000..3e7e631
--- /dev/null
+++ b/test-data/if-exists.sql
@@ -0,0 +1,12 @@
+drop index if exists IX1_SOME_TABLE;
+
+create index IX1_SOME_TABLE
+  on SOME_TABLE(some_column);
+
+-- NOTE: syntax incorrectly detects the name of the index as being "if".  will
+-- fix later
+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);

Reply via email to