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);