35
Liquibase error: unterminated dollar-quoted string at or near "$BODY$`

Chaneg log xml has one entry: see below include file="/home/dev/....../admin_script.sql"

content of the file:

...............
CREATE OR REPLACE FUNCTION my_schema.function-name()
RETURNS smallint AS
$BODY$
   DECLARE
      v_next_gen_id smallint := 0;
   BEGIN
..........

Exception:

liquibase.exception.DatabaseException: Error executing SQL CREATE OR REPLACE FUNCTION function name()
ETURNS smallint AS
$BODY$
   DECLARE
      v_next_gen_id smallint := 0: ERROR: unterminated dollar-quoted string at or near "$BODY$

Appreciate any help to resolve this

Dmitriy Popov
  • 2,150
  • 3
  • 25
  • 34
Vibin
  • 489
  • 1
  • 5
  • 10
  • Possible duplicate of [ERROR: unterminated quoted string at or near](https://stackoverflow.com/questions/3499483/error-unterminated-quoted-string-at-or-near) – Andremoniy May 22 '17 at 16:07

8 Answers8

38

I just encountered the same issue days ago.

It does not work if we add the changeset into changelog.xml file using the format below:
<include file="path/to/sqlfile" />

To work around, I use another format:

<changeSet author="authour_name" id="your_id">
    <sqlFile path="path/to/sqlfile" splitStatements="false"/>
</changeSet>

Here is the link which gives a brief explanation to Problem with dollar-quoted-in-postgresql.

Shaohua Huang
  • 698
  • 5
  • 19
  • 1
    In case you don't want to define an absolute path to your sql script file, you can use attribute: `relativeToChangelogFile="true"` – Andrey Sarul Apr 16 '18 at 10:01
  • 3
    So the key point is having splitStatements="false", why do I even need to split statements. False should be default. – X.Y. Dec 07 '21 at 01:05
  • "splitStatements": false in Liquibase's changelog can help avoid issues with unterminated dollar quotes or other syntax errors in SQL statements, by allowing Liquibase to read the entire statement as a single unit instead of splitting it into separate statements based on semicolons. This can be particularly useful for complex SQL statements or stored procedures that use advanced features like dollar-quoted strings or nested statements. – Shender Ramos Feb 22 '23 at 22:30
22

The solution below is from official Liquibase forum.

If you want to use SQL changelog fully, this solution works fine (tested and confirmed):

If you are using SQL Changelog file then you can replace $ Sign with Single Quote and Single Quote with double Single Quote ''

So to elaborate:

  1. $ will be '
  2. $BODY$ will be '
  3. ' will be ''

Example:

CREATE OR REPLACE FUNCTION public.testingfunctions()
RETURNS TABLE("DistributorCode" character varying)
LANGUAGE plpgsql
AS '
begin
    RETURN QUERY
    select * from testtable;
    
    -- .
    -- .
    -- . somewhere in the function
    RAISE NOTICE ''OPEN deleted customer_avatar'';
END;'
Dmitriy Popov
  • 2,150
  • 3
  • 25
  • 34
cool
  • 3,225
  • 3
  • 33
  • 58
  • 4
    This is the correct answer. See https://forum.liquibase.org/t/unterminated-dollar-quote-started/4553/3 – James Jun 18 '21 at 20:57
  • What is the reason why this works? – danbtl Nov 18 '21 at 21:21
  • @danbtl It seems its related with dollar-quoting when we are talking about postgresql. For some kind of reason using $$/$BODY$ does not work properly with liquibase (im not sure are they preprocessing anything before feeding sql into the database) – cool Nov 19 '21 at 13:45
  • 1
    Thanks for that solution works fine! One word of caution if you just do search & replace ```LANGUAGE 'plpgsql'``` can also have single quotes and e.g. ```DEFAULT ''::character``` in the header. so the `3.` above only applies to the PLPGSQL/SQL block between the BEGIN & END ;) – Markus Feb 16 '23 at 10:30
17

Use <createProcedure> tag instead of <sql> in your <changeSet> definition

yegor256
  • 102,010
  • 123
  • 446
  • 597
Jiri
  • 171
  • 1
  • 2
12

Add splitStatements:false to changeset

Like this --changeset splitStatements:false

Mister1Burger
  • 121
  • 1
  • 5
1

I've encountered similar error while using sql-maven-plugin. Adding below attributes fixed the issue

<execution>
    ...
    <configuration>
        ...
        <delimiter>/</delimiter>
        <delimiterType>normal</delimiterType>
    </configuration>
</execution>
Yuvaraj G
  • 1,157
  • 9
  • 17
0

If your are using SQL Changelog file then you can replace $ Sign with Single Quote and Single Quote with double Single Quote ''

0

You can set splitStatements attribute to false to avoid this error

<changeSet author="authour_name" id="your_id">
    <sql splitStatements="false">
    ...
    </sql>
</changeSet>
Yacine MEDDAH
  • 1,211
  • 13
  • 17
-3

I had the same error. Replacing the $function$ and $body$ with $$ solved the problem.

Dmitriy Popov
  • 2,150
  • 3
  • 25
  • 34