emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/sql-indent 9f716f6 09/13: Recognize PostgreSQL $$ quote


From: Stefan Monnier
Subject: [elpa] externals/sql-indent 9f716f6 09/13: Recognize PostgreSQL $$ quote syntax, #54 (#55)
Date: Sun, 11 Feb 2018 22:24:14 -0500 (EST)

branch: externals/sql-indent
commit 9f716f6ad8adfca9f8ea595d5b5ee71f781921c9
Author: Alex Harsányi <address@hidden>
Commit: GitHub <address@hidden>

    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.
---
 sql-indent-test.el     |  4 +++
 sql-indent.el          | 46 ++++++++++++++++++++++++++++++++---
 test-data/pr54-syn.eld | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++
 test-data/pr54.sql     | 29 ++++++++++++++++++++++
 4 files changed, 142 insertions(+), 3 deletions(-)

diff --git a/sql-indent-test.el b/sql-indent-test.el
index 8361be2..ebe8dba 100644
--- a/sql-indent-test.el
+++ b/sql-indent-test.el
@@ -362,4 +362,8 @@ information read from DATA-FILE (as generated by
 (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"))
+
 ;;; sql-indent-test.el ends here
diff --git a/sql-indent.el b/sql-indent.el
index 8d53878..fcde79f 100644
--- a/sql-indent.el
+++ b/sql-indent.el
@@ -741,11 +741,40 @@ See also `sqlind-beginning-of-block'"
                 (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))
+             (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)
+        (if (and (listp previous-block-kind)
+                 (eq (nth 0 previous-block-kind) 'defun-start))
+            (progn
+              (when (null sqlind-end-stmt-stack)
+                (throw 'finished (list 'in-begin-block 'defun (nth 1 
previous-block-kind))))
+              (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)))
+                (goto-char (cdr previous-block))))
+          ;; Assume it is an "end" statement
+          (push (list (point) '$$ "") sqlind-end-stmt-stack))))))
+
 (defconst sqlind-start-block-regexp
   (concat "\\(\\_<"
          (regexp-opt '("if" "then" "else" "elsif" "loop"
                        "begin" "declare" "create" "alter" "exception"
-                       "procedure" "function" "end" "case") t)
+                       "procedure" "function" "end" "case" "$$") t)
          "\\_>\\)\\|)")
   "Regexp to match the start of a block.")
 
@@ -770,6 +799,8 @@ reverse order (a stack) and is used to skip over nested 
blocks."
             (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))
@@ -1325,7 +1356,8 @@ not a statement-continuation POS is the same as the
     ;; context
     ((and (memq syntax-symbol '(defun-start declare-statement toplevel
                                 package package-body))
-          (looking-at "begin\\_>"))
+          (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))
@@ -1367,7 +1399,15 @@ not a statement-continuation POS is the same as the
        (push (sqlind-refine-end-syntax
               (if (equal kind "") nil (intern kind))
               label (point) context)
-             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 ()
diff --git a/test-data/pr54-syn.eld b/test-data/pr54-syn.eld
new file mode 100644
index 0000000..40abbbe
--- /dev/null
+++ b/test-data/pr54-syn.eld
@@ -0,0 +1,66 @@
+(((toplevel . 1))
+ (((block-start begin)
+   . 1)
+  ((defun-start "foo_1")
+   . 1))
+ (((in-begin-block defun "foo_1")
+   . 40))
+ (((block-end defun "foo_1")
+   . 40)
+  ((in-begin-block defun "foo_1")
+   . 40))
+ ((toplevel . 1))
+ ((toplevel . 1))
+ (((in-begin-block defun "foo_2")
+   . 99))
+ (((block-end defun "foo_2")
+   . 99)
+  ((in-begin-block defun "foo_2")
+   . 99))
+ ((toplevel . 1))
+ ((toplevel . 1))
+ (((block-start is-or-as)
+   . 197)
+  ((defun-start "foo_3")
+   . 197))
+ (((in-begin-block defun "foo_3")
+   . 236))
+ (((block-end defun "foo_3")
+   . 236)
+  ((in-begin-block defun "foo_3")
+   . 236))
+ ((toplevel . 1))
+ ((toplevel . 1))
+ (((block-start is-or-as)
+   . 262)
+  ((defun-start "foo_4")
+   . 262))
+ (((block-start begin)
+   . 262)
+  ((defun-start "foo_4")
+   . 262))
+ (((in-begin-block defun "foo_4")
+   . 301))
+ (((block-end defun "foo_4")
+   . 301)
+  ((in-begin-block defun "foo_4")
+   . 301))
+ ((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)))
+ 
\ No newline at end of file
diff --git a/test-data/pr54.sql b/test-data/pr54.sql
new file mode 100644
index 0000000..34483fa
--- /dev/null
+++ b/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:



reply via email to

[Prev in Thread] Current Thread [Next in Thread]