Open
Description
Bug report
- I confirm this is a bug with Supabase, not with my own application.
- I confirm I have searched the Docs, GitHub Discussions, and Discord.
Describe the bug
If I start to edit functions, frequently but not always, the following error message appears even if the code is correct:
Invalid statement: unterminated dollar-quoted string at or near "$$

To Reproduce
I was not able to reproduce it. It happens frequently, but I could not find a pattern yet.
Expected behavior
$$ quotes are correct code.
Screenshots
If applicable, add screenshots to help explain your problem.
System information
- OS: windows 11
- editor: vs-code
- pls: 0.5.0
Additional context
Probably related to #327 ?
An other idea of mine is that it might be connected to plpgsql functions.
It appears in a file which I use to test different generated types of the supabase type generator. Probably this could help as context or test cases.
-- Drop all functions
DROP FUNCTION if EXISTS return_row_type (int);
DROP FUNCTION if EXISTS return_setof_rows (int);
DROP FUNCTION if EXISTS return_setof_rows_sql (int);
DROP FUNCTION if EXISTS return_in_out (int);
DROP FUNCTION if EXISTS return_out (int);
DROP FUNCTION if EXISTS return_composite (int);
DROP FUNCTION if EXISTS return_composite_sql (int);
DROP FUNCTION if EXISTS return_setof_composite (int);
DROP FUNCTION if EXISTS return_setof_composite_sql (int);
DROP FUNCTION if EXISTS return_composite_with_row_constructor (int);
DROP FUNCTION if EXISTS return_table (int);
DROP FUNCTION if EXISTS return_table_sql (int);
DROP FUNCTION if EXISTS return_out_ddl_table_ref (int);
DROP FUNCTION if EXISTS return_table_ddl_table_ref (int);
DROP FUNCTION if EXISTS return_dynamic_record (int);
DROP TYPE if EXISTS group_composite;
DROP TABLE IF EXISTS public.groups;
CREATE TABLE groups (id int, name text);
CREATE TYPE group_composite AS (id int, name text);
INSERT INTO
groups (id, name)
VALUES
(1, 'Group 1');
CREATE FUNCTION return_row_type (group_id int) returns groups -- bedeutet: Rückgabe eines Rowtypes der Tabelle 'groups'
language plpgsql AS $$
DECLARE
group_record groups%ROWTYPE;
BEGIN
SELECT *
INTO group_record
FROM groups
WHERE id = group_id;
RETURN group_record;
END;
$$;
CREATE FUNCTION return_setof_rows (group_id int) returns setof groups -- bedeutet: Rückgabe mehrerer rows vom Typ 'groups'
language plpgsql AS $$
BEGIN
RETURN QUERY
SELECT *
FROM groups
WHERE id = group_id;
END;
$$;
CREATE FUNCTION return_setof_rows_sql (group_id int) returns setof groups language sql AS $$
SELECT *
FROM groups
WHERE id = group_id;
$$;
CREATE FUNCTION return_in_out (IN group_id int, OUT id int, OUT name text) language plpgsql AS $$
BEGIN
SELECT g.id, g.name
INTO id, name
FROM groups g
WHERE g.id = group_id;
END;
$$;
CREATE FUNCTION return_out (group_id int, OUT id int, OUT name text) language plpgsql AS $$
BEGIN
SELECT g.id, g.name
INTO id, name
FROM groups g
WHERE g.id = group_id;
END;
$$;
CREATE FUNCTION return_composite (group_id int) returns group_composite language plpgsql AS $$
DECLARE
result group_composite;
BEGIN
SELECT g.id, g.name
INTO result.id, result.name
FROM groups g
WHERE g.id = group_id;
RETURN result;
END;
$$;
CREATE FUNCTION return_composite_sql (group_id int) returns group_composite language sql AS $$
SELECT g.id, g.name
FROM groups g
WHERE g.id = group_id;
$$;
CREATE FUNCTION return_setof_composite (group_id int) returns setof group_composite language plpgsql AS $$
BEGIN
RETURN QUERY
SELECT g.id, g.name
FROM groups g
WHERE g.id = group_id;
END;
$$;
CREATE FUNCTION return_setof_composite_sql (group_id int) returns setof group_composite language sql AS $$
SELECT g.id, g.name
FROM groups g
WHERE g.id = group_id;
$$;
CREATE FUNCTION return_composite_with_row_constructor (group_id int) returns group_composite language plpgsql AS $$
DECLARE
found_id int;
found_name text;
BEGIN
SELECT g.id, g.name
INTO found_id, found_name
FROM groups g
WHERE g.id = group_id;
RETURN ROW(found_id, found_name)::group_composite;
END;
$$;
CREATE FUNCTION return_table (group_id int) returns TABLE (id int, name text) language plpgsql AS $$
BEGIN
RETURN QUERY
SELECT g.id, g.name
FROM groups g
WHERE g.id = group_id;
END;
$$;
CREATE FUNCTION return_table_sql (group_id int) returns TABLE (id int, name text) language sql AS $$
SELECT g.id, g.name
FROM groups g
WHERE g.id = group_id;
$$;
CREATE FUNCTION return_out_ddl_table_ref (
group_id int,
OUT id groups.id % type,
OUT name groups.name % type
) language plpgsql AS $$
BEGIN
SELECT g.id, g.name
INTO id, name
FROM groups g
WHERE g.id = group_id;
END;
$$;
CREATE FUNCTION return_table_ddl_table_ref (group_id int) returns TABLE (id groups.id % type, name groups.name % type) language plpgsql AS $$
BEGIN
RETURN QUERY
SELECT g.id, g.name
FROM groups g
WHERE g.id = group_id;
END;
$$;
CREATE FUNCTION return_dynamic_record (group_id int) returns record language plpgsql AS $$
DECLARE
result RECORD;
BEGIN
SELECT g.id, g.name
INTO result
FROM groups g
WHERE g.id = group_id;
RETURN result;
END;
$$;