alex-hhh / emacs-sql-indent Goto Github PK
View Code? Open in Web Editor NEWSyntax based indentation for SQL files inside GNU Emacs
License: GNU General Public License v3.0
Syntax based indentation for SQL files inside GNU Emacs
License: GNU General Public License v3.0
The GNU ELPA archive build process looks at an .elpaignore
file to exclude files and directories from a git repository which are not needed while using this package. The sql-indent package contains an .elpaignore
file listing test directories, but the latest ELPA built archive still contains all the test directories, so something is not working.
We need to investigate why the .elpaignore
file from the sql-indent package is not begin used.
The .elpaignore
file is used in the process-arhive
target of the GNUMakefile
on the master branch of the ELPA repository. Ultimately, the package archive is created using a "tar ... -X .elpaignore" command. If I manually run the tar command in my shell, it seems to do the right thing.
tar chf sql-indent.tar --exclude-vcs -X sql-indent/.elpaignore sql-indent/
However, I ran this command on a Windows machine and the ELPA is built on a GNU Linux machine.
I suspect that the .elpaignore
might contain Windows line endings when checking it out on GNU Linux. Perhaps all we need is a .gitattributes
file with a "* text=auto" line in it, and perhaps remove and add the .elpaignore
file again (the text=auto will not apply to an already checked in file). This would need to be validated with the ELPA build process.
Keywords used for alignment are detected inside comments. See the example below for the observed behavior
SELECT
Column1,
Column2,
-- this is FROM a blog WHERE useful stuff was described
Column3,
Column4
FROM Atable
The expected behavior is that alignment would be unaffected by comments as below
SELECT
Column1,
Column2,
-- this is FROM a blog WHERE useful stuff was described
Column3,
Column4
FROM Atable
Currently implicit inner joins (just JOIN
) isn't treated the same as an explicit INNER JOIN
.
Adding a begging of line anchor to sqlind-select-join-regexp
as demonstrated below seems to resolve the issue. I typed out the string as I don't believe there is a way to use an anchor with regexp-opt
.
I can try to create some tests for this and open a PR later today but wanted to make sure there wasn't a reason implicit inner joins weren't already accounted for.
(defconst sqlind-select-join-regexp
(concat "\\b"
"\\(cross\\|inner\\|left\\|natural\\|right\\|^\\)"
"[ \t\r\n\f]*join"
"\\b"))
i use doom emacs, when i open a sql file, then enable sql mode, it output this error
File mode specification error: (error Autoloading file /Users/xxx/.emacs.d/.local/straight/build/sql-indent/sql-indent.el failed to define function sql-indent)
Hi! I think the anchor is being detected wrong on the last line of this sample:
SELECT *
FROM t1
JOIN (
t2
LEFT JOIN t3 USING (k2)
)
ON t1.k1 = t2.k1
If I put the cursor before ON
on the last line and run sqlind-show-syntax-of-line
, I get:
((select-join-condition . 36) (statement-continuation . 1))
Position 36 is the LEFT JOIN
on the fifth line. I expected it to report position 18, the JOIN
on the third line, as the anchor. Is this behaving as expected?
I tested this using emacs -Q
, loading sql-indent.el
version 1.3 from ELPA using Emacs on macOS. emacs-version
reports:
GNU Emacs 26.1.50 (build 2, x86_64-apple-darwin17.7.0, NS appkit-1561.60 Version 10.13.6 (Build 17G65)) of 2018-08-31
Thank you for this package! Despite a few little issues I'm working out, this package is basically a miracle as far as I'm concerned. I never expected to see such intelligent and flexible SQL indenting in Emacs (or, frankly, in any editor). I am very impressed so far.
In the examples bellow the cursors aren't correctly detected (and so indented).
In the package example there is also a problem with the begin block (executed on package initialization).
declare
cursor cur1 is
select 1 dummy
from my_table
where 1 = 1
and col1 = p_col1;
p_col1 my_table.col1%type := 42;
function get_my_value(p_param1 in my_table.col1%type)
return my_table.col2%type is
cursor cur2 (p_val_col1 in my_table.col1%type) is
select col2
from my_table
where col1 = p_val_col1;
v_result my_table.col2%type;
begin
for rec in cur2(p_param1) loop
v_result := rec.col2;
end loop;
end get_my_value;
begin
for rec in cur1 loop
dbms_output.put_line(rec.dummy);
end loop;
end;
/
create or replace package body my_pacakge authid current user is
cursor cur1 is
select 1 dummy
from my_table
where 1 = 1
and col1 = p_col1;
p_col1 my_table.col1%type := 42;
function get_my_value(p_param1 in my_table.col1%type)
return my_table.col2%type is
cursor cur2 (p_val_col1 in my_table.col1%type) is
select col2
from my_table
where col1 = p_val_col1;
v_result my_table.col2%type;
begin
for rec in cur2(p_param1) loop
v_result := rec.col2;
end loop;
end get_my_value;
begin
for rec in cur1 loop
dbms_output.put_line(rec.dummy);
end loop;
dbms_output.put_line(get_my_value(p_col1));
end my_pacakge;
/
In the following example:
-- -*- sql-product: postgres; -*-
DROP FUNCTION IF EXISTS test;
| -- marker here
the marker gets indented even though it should stay at the beginning of the line. Removing IF EXISTS
fixes it.
I tried replacing FUNCTION
with each of the keywords in sqlind-good-if-candidate
and I noticed the same thing happens with PROCEDURE
too, but none of the other ones, so I guess it's conflicting with some code that handles function indentation.
Minor issue, but with a statement such as
blah as (
select
blah,
blah
from
blah
)
The syntax of the final line being ((select-table-continuation . 40) (nested-statement-continuation . 9) (statement-continuation . 9))
, adding a comment before the select statement changes the alignment:
blah as (
-- blah
select
blah,
blah
from
blah
)
The syntax of the final line being ((nested-statement-continuation . 9) (statement-continuation . 9))
A non-blank line after a blank line has no indentation.
CREATE TABLE IF NOT EXISTS vbox (
id bigint(10) unsigned NOT NULL AUTO_INCREMENT,
foo varchar(40) NOT NULL,
create_tm timestamp NOT NULL default CURRENT_TIMESTAMP,
PRIMARY KEY(id));
The DECLARE
statement in PL/pgSQL is similar to the one in PL/SQL and is used to declare variables: https://www.postgresql.org/docs/current/plpgsql-declarations.html
Test case in PostgreSQL:
-- Current behaviour
CREATE FUNCTION less_than(a text, b text) RETURNS boolean AS $$
DECLARE
local_a text := a;
local_b text := b;
BEGIN
RETURN local_a < local_b;
END;
$$ LANGUAGE plpgsql;
-- Expected behaviour
CREATE FUNCTION less_than(a text, b text) RETURNS boolean AS $$
DECLARE
local_a text := a;
local_b text := b;
BEGIN
RETURN local_a < local_b;
END;
$$ LANGUAGE plpgsql;
However, there is also a DECLARE
statement that creates a cursor: https://www.postgresql.org/docs/12/sql-declare.html
-- Current behaviour
DECLARE
liahona
CURSOR FOR
SELECT *
FROM films;
-- Expected
DECLARE
liahona
CURSOR FOR
SELECT *
FROM films;
I think sqlind-beginning-of-block
probably needs to handle the PostgreSQL case:
emacs-sql-indent/sql-indent.el
Lines 956 to 957 in 56be397
However, for the cursor use-case, I think that sqlind-maybe-declare-statement
needs to understand if it’s in-begin-block
and do something special, especially in order to recognize and indent the embedded SELECT
or VALUES
statement.
CREATE TABLE users
(id VARCHAR(20) PRIMARY KEY,
first_name VARCHAR(30),
last_name VARCHAR(30),
email VARCHAR(30),
admin BOOLEAN,
last_login TIME,
is_active BOOLEAN,
pass VARCHAR(300));
It should be:
CREATE TABLE users
(id VARCHAR(20) PRIMARY KEY,
first_name VARCHAR(30),
last_name VARCHAR(30),
email VARCHAR(30),
admin BOOLEAN,
last_login TIME,
is_active BOOLEAN,
pass VARCHAR(300));
Many thank for making sql indent. It's a great tool!
I have the pleasure(?) of working with transact-sql/ms-sql which is ... an interesting sql dialect.
One pattern that seems very common is to use temp tables like this (from here)
-- first procedure
IF OBJECT_ID ('dbo.Gloves', 'U') IS NOT NULL
DROP TABLE dbo.Gloves;
-- end if is supported
GO -- optional
-- second procedure
SELECT ProductModelID, Name
INTO dbo.Gloves
FROM Production.ProductModel
WHERE ProductModelID IN (3, 4);
GO -- optional
Unfortunately, sql-indent
gets confused with the non-terminated if
(and the ms sql server barfs at end if
).
sql-indent
indentation from emacs -q
[having evaled (setq sql-product 'ms)
]:
-- first procedure
IF OBJECT_ID ('dbo.Gloves', 'U') IS NOT NULL
DROP TABLE dbo.Gloves;
-- end if is supported
GO -- optional
-- second procedure
SELECT ProductModelID, Name
INTO dbo.Gloves
FROM Production.ProductModel
WHERE ProductModelID IN (3, 4);
GO -- optional
In more complex examples, I've also triggered the bad closing for if/case block
error, but I can't seem to reproduce this with a simple example.
I know that you (understandably) deprioritise ms-sql so it is fair if this is outside the scope of sql-indent
. OTOH, if you want, I can keep reporting ms-sql misbehaviours.
There's a different package on MELPA that has the same name that overrides this package and I haven't been able to install this package with use-package
because of it. I've tried with the :pin gnu
keyword but it doesn't seem to do anything. Currently doing this locally but it's not ideal. 😄
Create view statements are not correctly indented when some optional clause is used as shown in the following example. The optional clauses are defined in the MySQL manual.
-- without optional clauses
CREATE
VIEW MyView AS
SELECT DISTINCT table1.fieldA AS FirstField,
table2.fieldB AS SecondField
FROM table1
JOIN table2 ON table1.table1ID = table2.FKtable1;
-- with optional clauses
CREATE ALGORITHM = UNDEFINED DEFINER = user@localhost SQL SECURITY DEFINER
VIEW MyView AS
SELECT DISTINCT table1.fieldA AS FirstField,
table2.fieldB AS SecondField
FROM table1
JOIN table2 ON table1.table1ID = table2.FKtable1;
I've trouble correctly indenting recursive if / then / end if;
The attached file isn't correctly indented. Any clue to start resolving this ?
The result bellow isn't what I expect.
begin
if 1 = 0 then
if 1 = 0 then
null;
else
null;
end if;
elsif 1 = 2
if 1 = 0 then
null;
else
null;
end if;
else
null;
end if;
end;
/
[test.multi-if.sql.txt](https://github.com/alex-hhh/emacs-sql-indent/files/859318/test.multi-if.sql.txt)
I've crystalized this use case from a function I recently had to write:
USE [testdb]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[Test]
()
RETURNS
@TestBatch TABLE
(
[param] [varchar](20) NOT NULL,
[param2] [datetime] NOT NULL,
)
AS
BEGIN
DECLARE @var int;
DECLARE @var2 int;
set @var = 100;
RETURN
END
The ideal would be:
USE [testdb]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[Test]
()
RETURN
@TestBatch TABLE
(
[param] [varchar](20) NOT NULL,
[param2] [datetime] NOT NULL,
)
AS
BEGIN
DECLARE @var int;
DECLARE @var2 int;
set @var = 100;
RETURN
END
The indentation of the keyword, elseif
, used by mysql, is different from the one of the keyword elsif
used by other sql dialects, as you can see from the following example
IF (SELECT ID
FROM SomeTable
WHERE SomeField > 0) IS NULL
THEN
SET SomeVar = TRUE;
ELSIF
SET SomeVar = FALSE;
END IF;
IF (SELECT ID
FROM SomeTable
WHERE SomeField > 0) IS NULL
THEN
SET SomeVar = TRUE;
ELSEIF
SET SomeVar = FALSE;
END IF;
I think there is inconsistency between the two cases statements bellow:
select y ,
case
when foo>5 then "great"
when foo=5 then "normal"
else "poor"
end as level
from bar;
declare
dummy number;
begin
case ind
when 1 then dummy := 'Guy';
when 2 then dummy := 'Abc';
when 3 then dummy := 'Def';
else dummy := 'World';
end case;
end;
/
-- Local Variables:
-- mode: sqlind-minor
-- mode: sql
-- tab-width: 2
-- indent-tabs-mode: nil
-- sql-product: oracle
-- End:
I expected they will both indent the same way, but the second one was not detected as the first.
Indented version:
INSERT INTO tbl (col1, col2)
VALUES (1, 2)
ON CONFLICT (col1) DO
UPDATE SET col2 = EXCLUDED.col2
Expected (line 3 and 4 on the same level as values
:
INSERT INTO tbl (col1, col2)
VALUES (1, 2)
ON CONFLICT (col1) DO
UPDATE SET col2 = EXCLUDED.col2
syntax of line 3 and 4: (((in-insert-clause "values") . 52) (statement-continuation . 1))
I use sqlind-setup-style-left
style in my configuration.
sql-indent-mode
appears to be confused by the IF NOT
clause that may appear in pgSQL's CREATE EXTENSION
statement. See the following example -
CREATE EXTENSION "uuid-ossp" WITH SCHEMA public;
-- indentation is correct here
CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA public
-- invalid syntax, but this treated as a block
END;
-- indentation is correct here
CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA public;
-- autoindents to this level
sql-product
is set to postgres
.
There is problems in correctly detect syntax of instructions in exception block :
declare
dummy number;
begin
begin
if 1 = 1 then
proc1;
proc2;
else
proc3;
proc4;
end if;
exception
when no_data_found then
proc1;
proc2;
when too_many_rows then
proc3;
proc4;
when others then
proc5;
end;
end;
/
-- Local Variables:
-- mode: sqlind-minor
-- mode: sql
-- tab-width: 2
-- indent-tabs-mode: nil
-- sql-product: oracle
-- End:
Any insight into how one can have sqlind-minor-mode inside of org-mode src sql blocks?
#+BEGIN_SRC sql
SELECT
id,
name
FROM contacts
#+END_SRC
Say you highlight the text in the src block and try to indent it with TAB. I would expect it not to change (or slightly if my formatting is off) but instead it all left aligns. If I do the popout editor and do the same thing, sqlind minor mode is active and it indents correctly.
It looks like the syntax checker borks on IF EXISTS.
Trying to indent this:
ALTER TABLE x
DROP CONSTRAINT IF EXISTS not_unique_idx,
ADD CONSTRAINT unique_idx UNIQUE (this, that);
results in ADD CONSTRAINT
being aligned with the IF
from the previous line, as if it's a block IF. And indeed, sqlind-show-syntax-of-line
gives (((in-block if "") . 543))
.
Here's some sample SQL:
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
)
ON t1.k = t3.k
AND t1.k = t4.k
I've got this indenting correctly except for lines 12 and 13, ON t3.k = t4.k
and AND t3.j = t4.j
, respectively. Can you provide any help as to how I can achieve the indentation style shown above?
Here is my sql-indent config that produces the above indent, except for the ON
line which I indented above by hand. I wish this excerpt of my config were shorter, but I didn't want to leave out anything that could affect your answer. And of course I'm happy to provide additional explanation of that config, add comments where needed, etc.
All of my attempts thus far have been to try to apply the indentation I'd normally get from select-table-continuation
and select-join-continuation
inside the parentheses here as appropriate, but I've not yet been successful.
Any guidance you can provide would be appreciated. Thank you very much!
I am using Emacs from a recent build on the emacs-26
branch on macOS, using sql-indent.el
from HEAD (e511ced as of this writing).
Test case in PostgreSQL:
DO $$
BEGIN
CREATE TABLE t ();
END -- end statement closes nothing (40, 40)
$$ LANGUAGE plpgsql;
When running sqlind-indent-line
on the END
statement, sqlind-refine-end-syntax
throws the end statement closes nothing
syntax error.
It looks like after the CREATE TABLE
statement, sqlind thinks that it is back to 'toplevel
, even though it should be 'in-begin-block
.
Hi,
Is it possible to configure this package to use tabs for indentation? sqlind-basic-offset
seems to be just integer variable...
Edited to add a note about sqlind-lineup-joins-to-anchor
, below.
I would like to suggest adding "full"
to sqlind-select-join-regexp
, as in FULL JOIN
. Example:
SELECT
*
FROM
foo
FULL JOIN bar
ON foo.k = bar.k
Running on branch ah/pr70 right now, the last line gets anchored to JOIN
rather than FULL
. Adding "full"
to sqlind-select-join-regexp
anchors the last line to FULL
, which is probably what you'd expect.
Also, should function sqlind-lineup-joins-to-anchor
perhaps avail itself of sqlind-select-join-regexp
? Right now it contains its own regexp that includes \\(inner\\|outer\\|cross\\)
, which is much less comprehensive than the list of possible join types in sqlind-select-join-regexp
.
Finally, I'd also suggest adding except
to \\(union\\|intersect\\|minus\\)
in sqlind-select-clauses-regexp
. Example SQL:
SELECT
id
FROM
foo
EXCEPT
SELECT
id
FROM
bar
(I actually do use these SQL features—I promise I'm not just coming up with torture cases for you. Since I saw sql-indent suggested in (I think) Emacs 27's NEWS
file I've been testing it against random SQL files I've worked with recently. I write... a lot of SQL. 😃)
I would submit a PR but I don't have a current assignment on file with the FSF, so I'm going out of my way not to muddy the waters by submitting "tainted" code. Hopefully the changes I'm suggesting are obvious, but please let me know if you have questions!
Test case for PostgreSQL:
CREATE OR REPLACE FUNCTION s.noop()
RETURNS TRIGGER AS $$
BEGIN
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER t
AFTER INSERT OR UPDATE
ON tbl
FOR EACH ROW
EXECUTE PROCEDURE s.noop();
|
The cursor is indented to |
because there is no special handling in:
emacs-sql-indent/sql-indent.el
Lines 305 to 348 in 7f649aa
I recognize that this is not standard SQL, so maybe you don’t want to put this in. However, the for
statement isn’t standard SQL either, so I think it makes sense to handle this case.
According to the CREATE TRIGGER
documentation, this can be written in the following ways:
FOR ROW
FOR EACH ROW
FOR STATEMENT
FOR EACH STATEMENT
Similar to #73, would it make sense to modify the regexp in sqlind-lineup-joins-to-anchor
so that left outer
and right outer
are recognised? I made that change locally and was able to achieve the indentation I was after.
Hi there, wonderful package, I really like configuration, it reminds me of how configurable formatters can be.
One thing I am trying to achieve is to change this:
JOIN LATERAL jsonb_to_recordset(jsonb_path_query_array(reports.tree, 'strict $.children.report.children.images.children.*'))
AS image_descriptors("name" text, "order" text, "descriptor" jsonb)
to
JOIN LATERAL jsonb_to_recordset(jsonb_path_query_array(reports.tree, 'strict $.children.report.children.images.children.*'))
AS image_descriptors("name" text, "order" text, "descriptor" jsonb)
It makes more sense, at least to me, to see that the AS
belongs to the jsonb_to_recordset
above.
Not a big deal but I could not figure out a way - I am also a sqlind
newbie to be honest 😄
Thanks a lot in advance for your help!
In a pl/pgsql function, the if statements are ended with end if
. These currently are being indented at the body level of the if statement, or I don't have the mode configured properly.
if (not found)
then
raise notice 'Not found';
return 1;
end if;
Is there an easy configuration to make the perform keyword in pl/pgsql functions behave the same as select? Currently if I have the select-clause indent at 0, select clauses look like I want:
select
column_a,
column_b
from
table_1
where
column_a = 1;
but replace the select with perform and from and what no longer line up.
perform
column_a,
column_b
from
table_1
where
column_a = 1;
Expected behavior:
select pk_id
, case
when t1.c1 is null then '(null)'
when t1.c1 in ('a', 'b','c','d','e') then 'a'
else t1.c1
end c1_alt
from t1
limit 10
;
Actual behavior:
select pk_id
, case
when t1.c1 is null then '(null)'
when t1.c1 in ('a', 'b','c','d','e') then 'a'
else t1.c1
end c1_alt
from t1
limit 10
;
Ideal behavior:
select pk_id
, case
when t1.c1 is null then '(null)'
when t1.c1 in ('a', 'b','c','d','e') then 'a'
else t1.c1
end c1_alt
from t1
limit 10
;
The following code doesn't indent properly:
BEGIN;
SELECT * FROM foo;
COMMIT;
It works if you provide the TRANSACTION
keyword:
BEGIN TRANSACTION;
SELECT * FROM foo;
COMMIT;
I'm not sure what the standard says, but my experience has been that BEGIN;
is much more commonly used than BEGIN TRANSACTION;
. PostgreSQL also allows BEGIN WORK
, which exhibits the same problem.
The regexp "end\\|table\\|view\\|index\\|trigger\\procedude\\|function\\|package\\|body"
in sqlind-good-if-candidate
needs some attention: there seems to be a missing vertical bar before "procedure", which also looks misspelled.
Hi @alex-hhh - having been a bit frustrated with the current state of the "original" sql-indent
package by @kensanata, it's been nice to see that this one is better maintained these days (nice work!), and I'm interested in using it myself.
However, the packaging is a bit of a mess because although you're using sqlind-
internally to distinguish the symbol names, the feature , file and package names are sql-indent
, so the package in GNU ELPA clashes with the older package too. No MELPA user will easily be able to use your package, as it stands. Can we do something to straighten this out so that the two packages don't trample each other? I'd suggest renaming this to sqlind
, so that everything matches up.
P.S. You're missing a ;; Package-Requires: ((cl-lib "0.6'))
header, which users of Emacsen < 24.3 would need.
There is another way to use case in Oracle PL/SQL:
set serveroutput on
declare
dummy varchar2(25);
ind number := 2;
begin
dbms_output.enable(null);
dummy := case
when ind = 1 then 'Guy'
else 'World'
end;
dbms_output.put_line('Hello ' || dummy);
case ind
when 1 then dummy := 'Guy';
else dummy := 'World';
end case;
dbms_output.put_line('Hello ' || dummy);
end;
/
Unfortunately the indentation doesn't work for it and I was unable to find a fix.
Emacs has lots of good SQL support already by default, and this could make it even better. This would surely be a nice addition to GNU ELPA, and/or could perhaps be contributed back to Emacs itself, to make it available by default.
Firstly, thanks for your work on this!
Secondly, apologies if a GH issue is not the right place to ask this question.
Rightly or wrongly, I tend to write SQL in a rather simple form, very similar to that of Baron Schwartz, and for a long time I've been hoping to be able to use Emacs to do so. Here's a short made-up example to illustrate:
with
current_students as (
select
name as student_name,
id as student_id
from
student_table
where
current_student is true and
start_date > '2015-01-01 00:07:00' and
start_date <= '2016-01-01' and
enrolled is true
),
classes as (
select
name as class_name,
id as class_id,
student_id
from
class_table
)
select
student_id,
student_name,
class_name,
class_id
from current_students as s
left join classes as c on s.student_id = c.student_id
Given the power and granularity of your package, I'm sure that such a style is possible. However, after spending more time than I'd like to admit reading the documentation and messing around, I haven't got close. Do you have any tips on how to set the sqlind-default-indentation-offsets-alist
variable to achieve this, or something like it?
Calling align
on a statement such as
select
blah
from
blah
where
foo = 3 and
bar >= 40 and
foobar < 9 and
barfoo != 42
produces
select
blah
from
blah
where
foo = 3 and
bar > = 40 and
foobar < 9 and
barfoo ! = 42
Separating the >/!
and the =
changes the meaning of the statement, which is undesirable! An ideal (but complicated) result might be something like
select
blah
from
blah
where
foo = 3 and
bar >= 40 and
foobar < 9 and
barfoo != 42
Test case:
-- -*- mode: sql; sql-product: postgres; -*-
CREATE SCHEMA IF NOT EXISTS test;
|
The cursor is indented to |
, probably because SCHEMA
is not matched by:
emacs-sql-indent/sql-indent.el
Line 491 in 08f0417
Test case for PostgreSQL:
COMMENT ON FUNCTION hello IS 'Returns a greeting.';
COMMENT ON PROCEDURE world IS 'Creates a world.';
Sqlind gets confused because sqlind-maybe-defun-statement
thinks that these are actually defun-start
. I think the correct solution is to handle this in the same code path that checks if this is a DROP
statement:
emacs-sql-indent/sql-indent.el
Lines 815 to 821 in b694078
(save-excursion
(sqlind-backward-syntactic-ws)
;; Find out if it is a drop procedure or function statement
(forward-word -1)
(when (looking-at "drop")
;; not a procedure after all.
(throw 'exit nil))
;; Find out if it is a comment statement
(when (eq sql-product 'postgres)
(forward-word -1)
(when (looking-at "comment\\(?:[ \t\n\r\f]+\\)on")
;; not a procedure after all.
(throw 'exit nil))))
I work on a system with an extended version of the SQL language, and I'd like to be able to teach sql-indent to understand this system. There's no way to provide an external language definition, though, as one can with cc-mode. For example, we have functions that look like this. (Docstring snipped for concision.)
(defun sqlind-beginning-of-directive ()
(let ((rx (cl-case (and (boundp 'sql-product) sql-product)
(ms sqlind-ms-directive)
(sqlite sqlind-sqlite-directive)
(oracle sqlind-sqlplus-directive)
(t nil))))
(when rx
(save-excursion
(when (re-search-backward rx nil 'noerror)
(forward-line 1)
(point))))))
IMHO, it'd be better to just dispatch on the product somehow (with defgeneric, a function table, o something) instead of hardcoding the case here. This way, it'd be possible to much more easily customize the system.
When an assignment with an statement-continuation occurs below an if..then
the statement continuation is not detected.
This appends with if..then / elsif..then but not with else.
See PR #23 for files.
If you put your cursor at the beginning of -- return boolean
and hit the [tab] key you get the error :
«forward-sexp: Scan error: "Unbalanced parentheses", 151, 1»
I hanven't been able to track this error.
-- declare
-- function dummy(p_param_1 in varchar2,
-- p_param_2 in out varchar2,
-- p_param_2 out varchar2)
-- return boolean;
-- end dummy;
-- function dummy_2(p_param_1 out varchar2,
-- p_param_2 out varchar2,
-- p_param_2 out varchar2)
-- return boolean;
-- function dummy_3(p_param_1 varchar2,
-- p_param_2 in varchar2,
-- p_param_2 out varchar2)
-- return boolean;
-- var1 boolean := true;
-- var2 number := 1;
-- var42 varchar2(1) := 'Y';
-- begin
-- if dummy(p_param_1 => val1,
-- p_param_10 => val10) then
-- null;
-- end if;
-- end;
-- /
-- Local Variables:
-- mode: sql
-- tab-width: 2
-- indent-tabs-mode: nil
-- sql-product: oracle
-- eval: (sqlind-setup)
-- End:
Current behavior:
create function a() returns int AS $$
select 5
$$;
SELECT a();
Expected:
create function a() returns int AS $$
select 5
$$;
SELECT a();
Hi,
Firstly, thanks very much for creating sql-indent. It works very well, and the customization rules are simple and clear.
I think I've noticed a bug with your block detection, where a CREATE TABLE statement forces everything to outdent all the way to the left:
BEGIN TRANSACTION;
CREATE TABLE my_table ( id text );
-- I would expect this select statement to also be indented?
SELECT id FROM my_table;
COMMIT;
It still happens if I have some other statements first:
BEGIN TRANSACTION;
SELECT version();
CREATE TABLE my_table ( id text );
-- I would expect this select statement to also be indented?
SELECT id FROM my_table;
COMMIT;
Here's what happens if I have multiple blocks:
BEGIN TRANSACTION;
BEGIN TRANSACTION;
CREATE TABLE my_table ( id text );
SELECT id FROM my_table;
COMMIT;
For now I shall work around this by disabling transaction block indentation.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.