Problemet var inte syntaxen, eftersom syntaxen fungerade perfekt med flyway eller direkt i PostgreSQL CLI. Problemet var med Hibernate, speciellt med att analysera importfilen. Hur Hibernate fungerar är att det exekverar varje uttryck från filerna individuellt, inte hela innehållet som ett enda uttryck. Jag försökte lägga alla funktionsdefinitioner på en rad och det fungerade, men det gick inte att läsa. Så jag upptäckte att det finns en konfiguration för Hibernate för att tala om att uttryck kan vara flerradiga, men $$
avgränsare var fortfarande okänd när den användes i multi-line.
Så lösningen var att definiera kommandot med '
avgränsare och undvik sedan de enskilda citattecken där det behövs med ytterligare en '
.
Lösningen är att ställa in spring.jpa.properties.hibernate.hbm2ddl.import_files_sql_extractor
för att använda org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor
. MultipleLinesSqlCommandExtractor extraherar SQL-uttrycket från flera rader och stoppar när ett semikolon finns. Det är slutet på uttrycket. Genom att linda funktionens brödtext i en sträng med ett citattecken, kommer Hibernate att behandla denna radbrytning som en enda rad.
data.sql
CREATE OR REPLACE FUNCTION insert_timeout_configuration() RETURNS bigint AS '
DECLARE created_id bigint;
BEGIN
INSERT INTO timeout_configuration (id, version, timeout)
VALUES (nextval(''my_sequence''), 0, 300)
RETURNING id INTO created_id;
return created_id;
END;
' language plpgsql;
CREATE OR REPLACE FUNCTION insert_url_configuration() RETURNS bigint AS '
DECLARE created_id bigint;
BEGIN
INSERT INTO url_configuration (id, version, my_url)
VALUES (nextval(''my_sequence''), 0,''http://localhost:8080/'')
RETURNING id INTO created_id;
return created_id;
END;
' language plpgsql;
DO '
INSERT INTO global_configuration(id, version, name, timeout_configuration_id, url_configuration_id)
VALUES (nextval(''my_sequence''), 0, ''My global config'', insert_timeout_configuration(), insert_url_configuration());
-- do some other code
END
';
drop function insert_timeout_configuration();
drop function insert_url_configuration();
Jag måste alltid ha i åtanke för att undvika enstaka citattecken i uttrycken, men nu kan jag ha en mer mänskligt läsbar fröfil.