Reputation: 619
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
Upvotes: 47
Views: 27645
Reputation: 104
I have postgresSQL15 in my system and running trigger with liquibase sql script
Table name: test
Table name history: test_history
1:- Create you history table
--changeset praveen.singh:1
CREATE TABLE IF NOT EXISTS test_history
(
id serial primary key,
original_test_id BIGINT NOT NULL,
operation VARCHAR(10),
change_timestamp TIMESTAMP without time zone DEFAULT CURRENT_TIMESTAMP,
dummy_data VARCHAR(15) NOT NULL
);
--rollback drop table test_history;
--changeset praveen.singh:2 failOnError:true splitStatements:false
CREATE OR REPLACE FUNCTION test_history_trigger()
RETURNS TRIGGER LANGUAGE plpgsql AS $$
BEGIN
IF (TG_OP = 'UPDATE') THEN
INSERT INTO test_history (original_test_id, operation, change_timestamp, dummy_data)
VALUES (OLD.id, 'UPDATE', NOW(), OLD. dummy_data);
ELSIF (TG_OP = 'DELETE') THEN
INSERT INTO test_history (original_test_id, operation, change_timestamp, dummy_data)
VALUES (OLD.id, 'DELETE', NOW(), OLD. dummy_data);
END IF;
IF (TG_OP = 'UPDATE') THEN
RETURN NEW;
ELSIF (TG_OP = 'DELETE') THEN
RETURN OLD;
END IF;
END;
$$;
CREATE TRIGGER test_history_trigger
AFTER UPDATE OR DELETE
ON test
FOR EACH ROW
EXECUTE FUNCTION test_history_trigger();
2:- Run command liquibase
mvn liquibase:update -Dusername=<USER_NAME> -Dpassword= -Durl='jdbc:postgresql://localhost:5432/<DB_NAME>?currentSchema=<SCHEMA_NAME>'
Hope it will work for you all!!!
Upvotes: 1
Reputation: 41
You should understand why this happened. The typical anonynous plsql-block contains many semicolons. Each semicolon by default is recognized by liquibase as a delimiter of a different SQL-statement in one transaction.
So, the database received 1-st query:
CREATE OR REPLACE FUNCTION my_schema.function-name()
RETURNS smallint AS
$BODY$
DECLARE
v_next_gen_id smallint := 0
This statement has no closing $BODY$ token. And we have an exception from DB.
The right way is setup changeset do not split statement by any delimiter. Just set splitStatements flag in chageset declaration. For example:
--liquibase formatted sql
--changeset Author-BB:20231101-001 failOnError:true splitStatements:false
Upvotes: 1
Reputation: 1371
You can set splitStatements attribute to false to avoid this error
<changeSet author="authour_name" id="your_id">
<sql splitStatements="false">
...
</sql>
</changeSet>
Upvotes: 4
Reputation: 1237
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>
Upvotes: 1
Reputation: 191
Add splitStatements:false
to changeset
Like this --changeset splitStatements:false
Upvotes: 19
Reputation: 3515
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:
$
will be '
$BODY$
will be '
'
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;'
Upvotes: 37
Reputation: 13
I had the same error. Replacing the $function$
and $body$
with $$
solved the problem.
Upvotes: -3
Reputation: 1
If your are using SQL Changelog file then you can replace $ Sign with Single Quote and Single Quote with double Single Quote ''
Upvotes: 0
Reputation: 191
Use <createProcedure>
tag instead of <sql>
in your <changeSet>
definition
Upvotes: 19
Reputation: 788
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.
Upvotes: 46