Coder Social home page Coder Social logo

alex-hhh / emacs-sql-indent Goto Github PK

View Code? Open in Web Editor NEW
117.0 117.0 18.0 351 KB

Syntax based indentation for SQL files inside GNU Emacs

License: GNU General Public License v3.0

Emacs Lisp 97.81% PLSQL 1.50% PLpgSQL 0.46% TSQL 0.23%
emacs emacs-lisp sql

emacs-sql-indent's People

Contributors

alex-hhh avatar brendan-r avatar monnier avatar pierretechoueyres avatar thejj avatar thijs avatar vbmithr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

emacs-sql-indent's Issues

Incorrect detection of exception block

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:

PostgreSQL DO blocks throws "end statement closes nothing" when encountering a CREATE statement

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.

case statement

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.

Wrong indentation in CREATE VIEW with optional clauses

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;

Incorrect indentation after "drop function if exists"

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.

Please make it easy to define new products

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.

Cannot install with use-package

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. 😄

Question: How to implement 'Schwartz Style'?

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?

indent does not work on parenthese group

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

Anchor incorrect after "parenthetical join"

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.

autoloading failed

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)

Erroneous regexp in sqlind-good-if-candidate

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.

How to indent nested joins?

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

mysql elseif keyword not recognized

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;

Create table inside transaction block

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.

Indentation fails with IF EXISTS clause

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-linegives (((in-block if "") . 543)).

Bad indentation for DECLARE in PostgreSQL

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:

(when (eq sql-product 'oracle) ; declare statements only start blocks in PL/SQL
(sqlind-maybe-declare-statement))

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.

Indentation breaks on case statements with multiple when clauses

Example

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
;

Invalid indentation for recursive if/end if

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)

`BEGIN' block never ends unless optional keywords are used

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.

Bad indentation for CREATE TRIGGER FOR ROW

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:

(defun sqlind-beginning-of-statement-1 (limit)
"Return the position of a block start, or nil.
But don't go before LIMIT."
(save-excursion
(catch 'done
(while (> (point) (or limit (point-min)))
(when (re-search-backward
";\\|:=\\|\\_<\\(declare\\|begin\\|cursor\\|for\\|while\\|loop\\|if\\|then\\|else\\|elsif\\|elseif\\)\\_>\\|)"
limit 'noerror)
(unless (sqlind-in-comment-or-string (point))
(let ((candidate-pos (match-end 0)))
(cond ((looking-at ")")
;; Skip parenthesis expressions, we don't want to find one
;; of the keywords inside one of them and think this is a
;; statement start.
(progn (forward-char 1) (forward-sexp -1)))
((looking-at "cursor\\|for\\|while")
;; statement begins at the start of the keyword
(throw 'done (point)))
((looking-at "else?if")
;; statement begins at the start of the keyword
(throw 'done (point)))
((looking-at "then\\|else")
;; then and else start statements when they are inside
;; blocks, not expressions.
(sqlind-backward-syntactic-ws)
(when (looking-at ";")
;; Statement begins after the keyword
(throw 'done candidate-pos)))
((looking-at "if")
(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)
(forward-sexp -1)
(throw 'done (point)))
((sqlind-looking-at-begin-transaction)
;; This is a "begin transaction" call, statement begins
;; at "begin", see #66
(throw 'done (point)))
((not (sqlind-in-comment-or-string (point)))
(throw 'done candidate-pos))))))))))

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

Broken indentation when altering MsSQL function

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

Incorrect detection / indentation of case conditions

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.

Properly Indent Implicit Inner Joins

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

Indentation for blocks with blank lines

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

Packaging

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.

Postgresql end if indentation

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;

Adding a few keywords

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!

PostgreSQL CREATE EXTENSION IF NOT EXISTS

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.

forward-sexp: Scan error: "Unbalanced parentheses", 151, 1

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:

Incorrect detection of cursors.

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

org-mode source blocks?

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.

Comments within CTEs, before select statements, change alignment

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

Unexpected indentation of "on conflict"

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.

.elpaignore file is not used while building the ELPA sql-indent package

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.

Here are some investigations I have done so far

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.

Bad indentation for COMMENT ON FUNCTION

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:

;; Find out if it is a drop procedure or function statement
(save-excursion
(sqlind-backward-syntactic-ws)
(forward-word -1)
(when (looking-at "drop")
;; not a procedure after all
(throw 'exit nil)))

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

Indenting with tabs

Hi,

Is it possible to configure this package to use tabs for indentation? sqlind-basic-offset seems to be just integer variable...

Align "As" within a JOIN

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!

Keywords in comments used for alignment

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

Postgresql perform keyword

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;

`align` separates multi-char comparison operators, changing meaning

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.