Repository: ariga/atlas
Pull request #2362 (2023-12-11 13:09:40)

sql/migrate: skip compound statements if delimiter is set


Patch:
diff --git a/sql/migrate/lex.go b/sql/migrate/lex.go
index 89d1fbf4..a1fb5a83 100644
--- a/sql/migrate/lex.go
+++ b/sql/migrate/lex.go
@@ -217,13 +217,13 @@ Scan:
 			s.comment("--", "\n")
 		case r == '/' && s.next() == '*':
 			s.comment("/*", "*/")
-		case s.MatchBeginAtomic && reBeginAtomic.MatchString(s.input[s.pos-1:]):
+		case s.delim == delimiter && s.MatchBeginAtomic && reBeginAtomic.MatchString(s.input[s.pos-1:]):
 			if err := s.skipBeginAtomic(); err != nil {
 				return nil, err
 			}
 			text = s.input[:s.pos]
 			break Scan
-		case s.MatchBegin && reBegin.MatchString(s.input[s.pos-1:]):
+		case s.delim == delimiter && s.MatchBegin && reBegin.MatchString(s.input[s.pos-1:]):
 			if err := s.skipBegin(); err != nil {
 				return nil, err
 			}


Test patch:
diff --git a/sql/migrate/testdata/lex/15_dollar_quote.sql b/sql/migrate/testdata/lex/15_dollar_quote.sql
index 201af985..da728683 100644
--- a/sql/migrate/testdata/lex/15_dollar_quote.sql
+++ b/sql/migrate/testdata/lex/15_dollar_quote.sql
@@ -124,4 +124,14 @@ CREATE FUNCTION my_function() RETURNS void AS $$
 BEGIN
    -- function body here
 END;
-$$ LANGUAGE plpgsql;
\ No newline at end of file
+$$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION f1(target regclass)
+  RETURNS VOID AS $BEGIN$
+DECLARE
+table_name TEXT := quote_ident(target :: text);
+BEGIN
+EXECUTE 'alter table ' || table_name || ' add column id serial';
+END;
+$BEGIN$
+LANGUAGE plpgsql;
\ No newline at end of file
diff --git a/sql/migrate/testdata/lex/15_dollar_quote.sql.golden b/sql/migrate/testdata/lex/15_dollar_quote.sql.golden
index dbe356f7..6acebcea 100644
--- a/sql/migrate/testdata/lex/15_dollar_quote.sql.golden
+++ b/sql/migrate/testdata/lex/15_dollar_quote.sql.golden
@@ -131,4 +131,14 @@ CREATE FUNCTION my_function() RETURNS void AS $$
 BEGIN
    -- function body here
 END;
-$$ LANGUAGE plpgsql;
\ No newline at end of file
+$$ LANGUAGE plpgsql;
+-- end --
+CREATE OR REPLACE FUNCTION f1(target regclass)
+  RETURNS VOID AS $BEGIN$
+DECLARE
+table_name TEXT := quote_ident(target :: text);
+BEGIN
+EXECUTE 'alter table ' || table_name || ' add column id serial';
+END;
+$BEGIN$
+LANGUAGE plpgsql;
\ No newline at end of file
diff --git a/sql/migrate/testdata/lexgroup/3_delimiter.sql b/sql/migrate/testdata/lexgroup/3_delimiter.sql
new file mode 100644
index 00000000..d0afb6b2
--- /dev/null
+++ b/sql/migrate/testdata/lexgroup/3_delimiter.sql
@@ -0,0 +1,18 @@
+-- delimiter should not conflict with compound statements scanning.
+
+create function `add2` (a int, b int) returns int deterministic no sql return a + b;
+create function `add3` (a int, b int, c int) returns int deterministic no sql return a + b + c;
+delimiter |
+-- error 1418
+create function fn1(x int) returns int deterministic
+begin
+       insert into t1 values (x);
+       return x+2;
+end|
+create function fn2(x int) returns int deterministic
+begin
+       insert into t1 values (x);
+       return x+2;
+end|
+delimiter ;
+create function `add4` (a int, b int, c int, d int) returns int deterministic no sql return a + b + c + d;
\ No newline at end of file
diff --git a/sql/migrate/testdata/lexgroup/3_delimiter.sql.golden b/sql/migrate/testdata/lexgroup/3_delimiter.sql.golden
new file mode 100644
index 00000000..f16478a6
--- /dev/null
+++ b/sql/migrate/testdata/lexgroup/3_delimiter.sql.golden
@@ -0,0 +1,17 @@
+create function `add2` (a int, b int) returns int deterministic no sql return a + b;
+-- end --
+create function `add3` (a int, b int, c int) returns int deterministic no sql return a + b + c;
+-- end --
+create function fn1(x int) returns int deterministic
+begin
+       insert into t1 values (x);
+       return x+2;
+end
+-- end --
+create function fn2(x int) returns int deterministic
+begin
+       insert into t1 values (x);
+       return x+2;
+end
+-- end --
+create function `add4` (a int, b int, c int, d int) returns int deterministic no sql return a + b + c + d;
\ No newline at end of file