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

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

[elpa] externals/sql-indent b694078 2/9: CREATE TABLE, VIEW and INDEX do


From: Alex Harsanyi
Subject: [elpa] externals/sql-indent b694078 2/9: CREATE TABLE, VIEW and INDEX does not start a block (#89)
Date: Fri, 20 Mar 2020 19:08:02 -0400 (EDT)

branch: externals/sql-indent
commit b6940780678e95af245830dbcd897672ca0a0a4c
Author: Alex Harsanyi <address@hidden>
Commit: Alex Harsanyi <address@hidden>

    CREATE TABLE, VIEW and INDEX does not start a block (#89)
    
    A CREATE TABLE, VIEW or INDEX statement is not a block start and can confuse
    the parser if such statements appear inside BEGIN/END blocks.  See
    test-data/pr89.sql for example test cases.
    
    * sql-indent-test.el (sqlind-ert-pr89): add test case for issue #89
    
    * sql-indent.el (sqlind-maybe-create-statement): add the ALL-STATEMENTS
      argument which controls whether create table/view/index statements are
      recognized.  Defaults to false, so these statements are not considered 
block
      start statements anymore.
    
      (sqlind-maybe-$$-statement): also recognize an "end" keyword before the $$
      as marking an ending "quote"
    
      (sqlind-syntax-of-line): don't treat create table/view/index statements as
      having block context, but refine a 'statement-continuation context into a
      'create-table one, if the statement start is appropriate.
---
 sql-indent-test.el     |  5 ++++
 sql-indent.el          | 79 +++++++++++++++++++++++++++++++++-----------------
 test-data/pr89-syn.eld | 68 +++++++++++++++++++++++++++++++++++++++++++
 test-data/pr89.sql     | 31 ++++++++++++++++++++
 4 files changed, 157 insertions(+), 26 deletions(-)

diff --git a/sql-indent-test.el b/sql-indent-test.el
index 235fa7f..38af1c0 100644
--- a/sql-indent-test.el
+++ b/sql-indent-test.el
@@ -427,4 +427,9 @@ information read from DATA-FILE (as generated by
    "test-data/pr87.sql"
    "test-data/pr87-syn.eld"))
 
+(ert-deftest sqlind-ert-pr89 ()
+  (sqlind-ert-check-file-syntax
+   "test-data/pr89.sql"
+   "test-data/pr89-syn.eld"))
+
 ;;; sql-indent-test.el ends here
diff --git a/sql-indent.el b/sql-indent.el
index d77a73c..0496a53 100644
--- a/sql-indent.el
+++ b/sql-indent.el
@@ -721,9 +721,14 @@ present."
             (sqlind-forward-syntactic-ws))
            (t (throw 'finished nil))))))))
 
-(defun sqlind-maybe-create-statement ()
+(defun sqlind-maybe-create-statement (&optional all-statements)
   "If (point) is on a CREATE statement, report its syntax.
-See also `sqlind-beginning-of-block'"
+See also `sqlind-beginning-of-block'
+
+Normally, only block start create statements are considered (such
+as creation of procedures).  In particular, create
+table/view/index statements are ignored unless the ALL-STATEMENTS
+argument is t"
   (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
@@ -755,30 +760,34 @@ See also `sqlind-beginning-of-block'"
           (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))))))))
+         (cond
+            ((memq what '(procedure function package package-body))
+             ;; check is name is in the form user.name, if so then suppress 
user part.
+            (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))))))
+            ((memq what '(table view index))
+             ;; Table, view and index creations do not begin blocks and they
+             ;; are ignored unless the ALL-STATEMENTS parameter is t
+             (when all-statements
+               (throw 'finished (list 'create-statement what name))))
+            (t
+            (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.
@@ -868,6 +877,12 @@ See also `sqlind-beginning-of-block'"
                ;; which ends another statement)
                (push (list saved-pos '$$ "") sqlind-end-stmt-stack)
                (goto-char saved-pos))
+              ((progn (forward-word -1)
+                      (looking-at "end"))
+               ;; Assume the $$ is ending a statement (previous line contains
+               ;; an "end" keyword)
+               (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
@@ -1604,6 +1619,10 @@ procedure block."
         (goto-char context-start)
         (when (or (>= context-start pos)
                   (and (looking-at sqlind-start-block-regexp)
+                       ;; create table/view/index statements are not block
+                       ;; contexts
+                       (or (not (looking-at "\\(create\\)\\|\\(alter\\)"))
+                           (catch 'finished (sqlind-maybe-create-statement) 
nil))
                        (not (sqlind-looking-at-begin-transaction))))
           (goto-char pos)
           ;; if we are at the start of a statement, or the nearest statement
@@ -1626,6 +1645,14 @@ procedure block."
               (setq context-start (point))
               (setq context (list (cons block-info context-start))))))
 
+        (goto-char context-start)
+        (when (and (eq 'statement-continuation (sqlind-syntax-symbol context))
+                   (looking-at "\\(create\\)\\|\\(alter\\)"))
+          (let ((create-info (catch 'finished (sqlind-maybe-create-statement 
t) nil)))
+            (when create-info
+              (pop context)         ; remove the statement continuation syntax
+              (push (cons create-info context-start) context))))
+
         (let ((parse-info (syntax-ppss pos)))
           (cond ((nth 4 parse-info)   ; inside a comment
                  (push (cons 'comment-continuation (nth 8 parse-info)) 
context))
diff --git a/test-data/pr89-syn.eld b/test-data/pr89-syn.eld
new file mode 100644
index 0000000..2f0a245
--- /dev/null
+++ b/test-data/pr89-syn.eld
@@ -0,0 +1,68 @@
+(((comment-start . 1)
+  (toplevel . 1))
+ ((toplevel . 1))
+ ((statement-continuation . 46))
+ (((in-begin-block nil "")
+   . 54))
+ (((block-end nil "")
+   . 54)
+  ((in-begin-block nil "")
+   . 54))
+ (((block-end toplevel nil)
+   . 46)
+  ((in-begin-block toplevel nil)
+   . 46))
+ ((toplevel . 1))
+ ((toplevel . 1))
+ ((statement-continuation . 111))
+ (((in-begin-block nil "")
+   . 119))
+ (((create-statement table "t")
+   . 129))
+ (((block-end nil "")
+   . 119)
+  ((in-begin-block nil "")
+   . 119))
+ (((block-end toplevel nil)
+   . 111)
+  ((in-begin-block toplevel nil)
+   . 111))
+ ((toplevel . 1))
+ ((toplevel . 1))
+ ((statement-continuation . 199))
+ (((in-begin-block nil "")
+   . 207))
+ (((create-statement view "t")
+   . 217))
+ ((select-clause . 240)
+  ((create-statement view "t")
+   . 217))
+ (((block-end nil "")
+   . 207)
+  ((in-begin-block nil "")
+   . 207))
+ (((block-end toplevel nil)
+   . 199)
+  ((in-begin-block toplevel nil)
+   . 199))
+ ((toplevel . 1))
+ ((toplevel . 1))
+ ((statement-continuation . 295))
+ (((in-begin-block nil "")
+   . 303))
+ (((block-end nil "")
+   . 303)
+  ((in-begin-block nil "")
+   . 303))
+ (((block-end toplevel nil)
+   . 295)
+  ((in-begin-block toplevel nil)
+   . 295))
+ ((toplevel . 1))
+ ((toplevel . 1))
+ (((create-statement view "t")
+   . 369))
+ ((select-clause . 388)
+  ((create-statement view "t")
+   . 369))
+ ((toplevel . 1)))
diff --git a/test-data/pr89.sql b/test-data/pr89.sql
new file mode 100644
index 0000000..cf37d7a
--- /dev/null
+++ b/test-data/pr89.sql
@@ -0,0 +1,31 @@
+-- -*- mode: sql; sql-product: postgres; -*-
+do $$
+  begin
+    create table t ();
+  end
+$$ language plpgsql;
+
+do $$
+  begin
+    alter table t
+      add column c integer;
+  end
+$$ language plpgsql;
+
+do $$
+  begin
+    create view t as
+      select *
+        from foo;
+  end
+$$ language plpgsql;
+
+do $$
+  begin
+    create index t on foo(bar);
+  end
+$$ language plpgsql;
+
+create view t as
+  select *
+    from foo;



reply via email to

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