branch: externals/sql-indent commit dccd194560c82d412213f85a2c43b0dc67534b71 Author: Alex Harsányi <alex-...@users.noreply.github.com> Commit: GitHub <nore...@github.com>
Recognize `select-join-condition` syntax inside nested statements #70 (#71) Updated syntax parser to recognize some JOIN condition keywords as `select-join-condition` syntax, even inside nested statements. Updated some non-related tests (m, pr17 and pr68), as this syntax was not recognized when these tests were written. While this change will modify the indentation in such cases, it allows more refined control over the indention. * sql-indent.el (sqlind-join-condition-regexp): keywords that constitute JOIN conditions (sqlind-syntax-in-select): match `sqlind-join-condition-regexp` when looking for join condition keywords (sqlind-refine-syntax): try to refine a `nested-statement-continuation into a `select-join-condition` if there is a JOIN in the nested statement. --- sql-indent-test.el | 3 ++ sql-indent.el | 24 +++++++++++-- test-data/m-io.eld | 2 +- test-data/m-syn.eld | 6 ++-- test-data/pr17-io-default.eld | 2 +- test-data/pr17-io-left.eld | 2 +- test-data/pr17-io-right.eld | 2 +- test-data/pr17-syn.eld | 8 ++--- test-data/pr68-syn.eld | 7 ++-- test-data/pr68.sql | 12 ++++--- test-data/pr70-syn.eld | 78 +++++++++++++++++++++++++++++++++++++++++++ test-data/pr70.sql | 39 ++++++++++++++++++++++ 12 files changed, 165 insertions(+), 20 deletions(-) diff --git a/sql-indent-test.el b/sql-indent-test.el index df79c07..ef5d050 100644 --- a/sql-indent-test.el +++ b/sql-indent-test.el @@ -381,4 +381,7 @@ information read from DATA-FILE (as generated by (ert-deftest sqlind-ert-pr68 () (sqlind-ert-check-file-syntax "test-data/pr68.sql" "test-data/pr68-syn.eld")) +(ert-deftest sqlind-ert-pr70 () + (sqlind-ert-check-file-syntax "test-data/pr70.sql" "test-data/pr70-syn.eld")) + ;;; sql-indent-test.el ends here diff --git a/sql-indent.el b/sql-indent.el index 562485d..4e0fd34 100644 --- a/sql-indent.el +++ b/sql-indent.el @@ -963,6 +963,9 @@ reverse order (a stack) and is used to skip over nested blocks." (defconst sqlind-select-join-regexp (regexp-opt '("inner" "left" "right" "natural" "cross") 'symbols)) +(defconst sqlind-join-condition-regexp + (regexp-opt '("on" "using" "and" "or") 'symbols)) + (defun sqlind-syntax-in-select (pos start) "Return the syntax ar POS which is inside a \"select\" statement at START." (save-excursion @@ -1007,8 +1010,8 @@ reverse order (a stack) and is used to skip over nested blocks." ;; or the previous line ends with 'on' we have a join ;; condition (goto-char pos) - (when (or (looking-at "on") - (progn (forward-word -1) (looking-at "on"))) + (when (or (looking-at sqlind-join-condition-regexp) + (progn (forward-word -1) (looking-at sqlind-select-join-regexp))) ;; look for the join start, that will be the anchor (when (sqlind-search-backward (point) "\\bjoin\\b" start) (let ((candidate (point))) @@ -1412,6 +1415,23 @@ not a statement-continuation POS is the same as the (when (looking-at "case") (push (sqlind-syntax-in-case pos (point)) context)))))) + (when (eq (sqlind-syntax-symbol context) 'nested-statement-continuation) + (save-excursion + ;; Look for a join expression inside a nested statement, see #70 + (goto-char pos) + (when (or (looking-at sqlind-join-condition-regexp) + (progn (forward-word -1) (looking-at sqlind-join-condition-regexp))) + ;; look for the join start, that will be the anchor + (when (sqlind-search-backward (point) "\\bjoin\\b" anchor) + (let ((candidate (point))) + (forward-char -1) + (sqlind-backward-syntactic-ws) + (backward-word) + (push (if (looking-at sqlind-select-join-regexp) + (cons 'select-join-condition (point)) + (cons 'select-join-condition candidate)) + context)))))) + )) ;; create block start syntax if needed diff --git a/test-data/m-io.eld b/test-data/m-io.eld index 403dd43..20a2c0f 100644 --- a/test-data/m-io.eld +++ b/test-data/m-io.eld @@ -1 +1 @@ -(0 4 4 6 6 4 0 4 4 4 4 4 4 4 10 4 4 4 8 4 4 0 0 10 16 16 16 16 20 20 20 16 12 16 10 1 5 0 0 0 6 6 2 6 0 4 0 4 0) +(0 4 4 6 6 4 0 4 4 4 4 4 4 4 10 4 4 4 8 4 4 0 0 10 16 16 16 16 20 20 20 16 12 16 10 1 5 0 0 0 6 6 2 6 0 8 0 4 0) diff --git a/test-data/m-syn.eld b/test-data/m-syn.eld index 1bd9c80..fc31b9c 100644 --- a/test-data/m-syn.eld +++ b/test-data/m-syn.eld @@ -103,13 +103,13 @@ (statement-continuation . 926)) ((nested-statement-close . 926) (statement-continuation . 926)) - ((select-table-continuation . 411) + ((select-join-condition . 908) (statement-continuation . 1)) ((select-clause . 80) (statement-continuation . 1)) (((in-select-clause "group by") - . 1047) + . 1051) (statement-continuation . 1)) (((in-select-clause "group by") - . 1047) + . 1051) (statement-continuation . 1))) diff --git a/test-data/pr17-io-default.eld b/test-data/pr17-io-default.eld index 78f87b1..f68308b 100644 --- a/test-data/pr17-io-default.eld +++ b/test-data/pr17-io-default.eld @@ -1 +1 @@ -(0 0 0 0 0 0 0 0 9 9 9 7 9 2 1 8 4 0 0 7 7 7 7 7 7 2 9 1 4 4 4 4 4 4 25 32 24 27 27 27 27 27 8 0 0 1 8 15 8 8 0 0 3 10 1 7 13 7 7 0 0 12 12 12 0 7 7 7 7 7 7 24 7 24 7 2 31 31 51 51 26 10 10 29 24 10 1 10 1 10 10 0 0 0 0) +(0 0 0 0 0 0 0 0 9 9 9 7 9 2 1 8 4 0 0 7 7 7 7 7 7 2 9 1 4 4 4 4 4 4 25 32 24 27 27 27 27 27 8 0 0 1 8 15 8 8 0 0 3 10 1 7 13 7 7 0 0 12 12 12 0 7 7 7 7 7 7 24 7 24 7 2 31 31 51 51 26 10 10 29 24 14 1 10 1 10 10 0 0 0 0) diff --git a/test-data/pr17-io-left.eld b/test-data/pr17-io-left.eld index 4942879..e055a8e 100644 --- a/test-data/pr17-io-left.eld +++ b/test-data/pr17-io-left.eld @@ -1 +1 @@ -(0 0 0 0 0 0 0 0 10 10 10 7 4 0 0 12 0 0 0 7 7 7 7 7 7 0 7 0 0 0 0 0 0 0 19 26 19 19 19 19 19 19 0 0 0 0 0 7 0 0 0 0 0 7 0 0 6 0 0 0 0 2 3 3 0 7 7 7 7 7 7 24 7 24 7 0 29 29 49 49 22 7 2 21 14 2 0 9 0 9 0 0 0 0 0) +(0 0 0 0 0 0 0 0 10 10 10 7 4 0 0 12 0 0 0 7 7 7 7 7 7 0 7 0 0 0 0 0 0 0 19 26 19 19 19 19 19 19 0 0 0 0 0 7 0 0 0 0 0 7 0 0 6 0 0 0 0 2 3 3 0 7 7 7 7 7 7 24 7 24 7 0 29 29 49 49 22 7 2 21 14 6 0 9 0 9 0 0 0 0 0) diff --git a/test-data/pr17-io-right.eld b/test-data/pr17-io-right.eld index 9a16743..6466e33 100644 --- a/test-data/pr17-io-right.eld +++ b/test-data/pr17-io-right.eld @@ -1 +1 @@ -(0 0 0 0 0 0 0 0 10 10 10 7 4 2 1 13 4 0 0 7 7 7 7 7 7 2 9 1 4 4 4 4 4 4 25 32 24 27 27 27 27 27 1 0 0 1 4 11 4 1 0 0 3 10 1 3 9 3 1 0 0 12 12 12 0 7 7 7 7 7 7 24 7 24 7 2 31 31 51 51 26 10 10 29 24 10 1 10 1 10 1 0 0 0 0) \ No newline at end of file +(0 0 0 0 0 0 0 0 10 10 10 7 4 2 1 13 4 0 0 7 7 7 7 7 7 2 9 1 4 4 4 4 4 4 25 32 24 27 27 27 27 27 1 0 0 1 4 11 4 1 0 0 3 10 1 3 9 3 1 0 0 12 12 12 0 7 7 7 7 7 7 24 7 24 7 2 31 31 51 51 26 10 10 29 24 14 1 10 1 10 1 0 0 0 0) \ No newline at end of file diff --git a/test-data/pr17-syn.eld b/test-data/pr17-syn.eld index ce23662..1e8db9b 100644 --- a/test-data/pr17-syn.eld +++ b/test-data/pr17-syn.eld @@ -190,20 +190,20 @@ ((select-clause . 2650) (nested-statement-continuation . 2649) (statement-continuation . 2649)) - ((select-table-continuation . 2271) + ((select-join-condition . 2638) (statement-continuation . 1800)) ((select-clause . 1902) (statement-continuation . 1800)) (((in-select-clause "group by") - . 2769) + . 2773) (statement-continuation . 1800)) ((select-clause . 1902) (statement-continuation . 1800)) (((in-select-clause "order by") - . 2798) + . 2802) (statement-continuation . 1800)) (((in-select-clause "order by") - . 2798) + . 2802) (statement-continuation . 1800)) ((comment-start . 33) (toplevel . 33)) diff --git a/test-data/pr68-syn.eld b/test-data/pr68-syn.eld index a3fdcc2..5167ac3 100644 --- a/test-data/pr68-syn.eld +++ b/test-data/pr68-syn.eld @@ -7,9 +7,12 @@ (statement-continuation . 34)) ((nested-statement-continuation . 34) (statement-continuation . 34)) + ((select-join-condition . 61) + (nested-statement-continuation . 34) + (statement-continuation . 34)) ((nested-statement-close . 34) (statement-continuation . 34)) ((select-join-condition . 29) (statement-continuation . 1)) - ((select-table-continuation . 12) - (statement-continuation . 1))) \ No newline at end of file + ((toplevel . 1)) + ((toplevel . 1))) \ No newline at end of file diff --git a/test-data/pr68.sql b/test-data/pr68.sql index 313fa8a..04fef4c 100644 --- a/test-data/pr68.sql +++ b/test-data/pr68.sql @@ -1,7 +1,9 @@ -SELECT * - FROM t1 - JOIN ( +select * + from t1 + join ( t2 - LEFT JOIN t3 USING (k2) + left join t3 + using (k2) ) - ON t1.k1 = t2.k1 + on t1.k1 = t2.k1; + diff --git a/test-data/pr70-syn.eld b/test-data/pr70-syn.eld new file mode 100644 index 0000000..8b0612f --- /dev/null +++ b/test-data/pr70-syn.eld @@ -0,0 +1,78 @@ +(((toplevel . 1)) + ((select-column . 1) + (statement-continuation . 1)) + ((select-clause . 1) + (statement-continuation . 1)) + ((select-table-continuation . 14) + (statement-continuation . 1)) + ((select-table-continuation . 14) + (statement-continuation . 1)) + ((select-join-condition . 34) + (statement-continuation . 1)) + ((select-join-condition . 34) + (statement-continuation . 1)) + ((comment-start . 1) + (statement-continuation . 1)) + ((select-table-continuation . 14) + (statement-continuation . 1)) + ((nested-statement-open . 132) + (statement-continuation . 132)) + ((nested-statement-continuation . 132) + (statement-continuation . 132)) + ((select-join-condition . 153) + (nested-statement-continuation . 132) + (statement-continuation . 132)) + ((select-join-condition . 153) + (nested-statement-continuation . 132) + (statement-continuation . 132)) + ((nested-statement-close . 132) + (statement-continuation . 132)) + ((select-join-condition . 127) + (statement-continuation . 1)) + ((select-join-condition . 127) + (statement-continuation . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((select-column . 389) + (statement-continuation . 389)) + ((select-clause . 389) + (statement-continuation . 389)) + ((select-table-continuation . 402) + (statement-continuation . 389)) + ((select-table-continuation . 402) + (statement-continuation . 389)) + ((select-join-condition . 422) + (statement-continuation . 389)) + ((nested-statement-continuation . 443) + (statement-continuation . 443)) + ((comment-start . 389) + (statement-continuation . 389)) + ((select-table-continuation . 402) + (statement-continuation . 389)) + ((nested-statement-open . 606) + (statement-continuation . 606)) + ((nested-statement-continuation . 606) + (statement-continuation . 606)) + ((select-join-condition . 627) + (nested-statement-continuation . 606) + (statement-continuation . 606)) + ((nested-statement-continuation . 655) + (statement-continuation . 655)) + ((nested-statement-close . 606) + (statement-continuation . 606)) + ((select-join-condition . 601) + (statement-continuation . 389)) + ((nested-statement-continuation . 771) + (statement-continuation . 771)) + ((toplevel . 1)) + ((toplevel . 1)) + ((toplevel . 1)) + ((nested-statement-continuation . 874) + (statement-continuation . 874)) + ((select-join-condition . 885) + (nested-statement-continuation . 874) + (statement-continuation . 874)) + ((select-clause . 867) + (statement-continuation . 867)) + ((toplevel . 1))) + \ No newline at end of file diff --git a/test-data/pr70.sql b/test-data/pr70.sql new file mode 100644 index 0000000..b480b48 --- /dev/null +++ b/test-data/pr70.sql @@ -0,0 +1,39 @@ +select + * + from + t1 + join t2 + on t1.k = t2.k + and t1.j = t2.j + -- here's a "nested join" + join ( + t3 + left join t4 + on t3.k = t4.k + and t3.j = t4.j -- this "and" is a select-join-condition + ) + on t1.k = t3.k + and t1.k = t4.k; -- this "and" is a select-join-condition + +select + * + from + t1 + join t2 + on (t1.k = t2.k + and t1.j = t2.j) -- this "and" is a nested-statement-continuation + -- here's a "nested join" + join ( + t3 + left join t4 + on (t3.k = t4.k + and t3.j = t4.j) -- this "and" is a nested-statement-continuation + ) + on (t1.k = t3.k + and t1.k = t4.k); -- this "and" is a nested-statement-continuation + + +select (a + join b + on a.k1 = b.k2) -- this is a select-join-condition (hey! we're not an sql parser + from a, b;