Проблемът не беше в синтаксиса, защото синтаксисът работеше перфектно с flyway или директно в PostgreSQL CLI. Проблемът беше с Hibernate, по-специално с анализа на файла за импортиране. Начинът, по който Hibernate работи е, че изпълнява всеки израз от файловете поотделно, а не цялото съдържание като един израз. Опитах се да сложа всички дефиниции на функции в един ред и се получи, но не се чете. Така че открих, че има конфигурация за Hibernate, която да му каже, че изразите могат да бъдат многоредови, но $$
разделителят все още беше неразпознат, когато се използва в многоредов.
Така че решението беше да дефинирате командата с '
разделител и след това избягвайте единичните кавички, където е необходимо, с допълнителен '
.
Решението е да зададете spring.jpa.properties.hibernate.hbm2ddl.import_files_sql_extractor
да използвате org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor
. MultipleLinesSqlCommandExtractor извлича SQL израза от множество реда и спира, когато има точка и запетая. Това е краят на израза. Чрез обвиване на тялото на функцията в низ с единични кавички, Hibernate ще третира това обвиване като един ред.
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();
Винаги трябва да имам предвид, за да избягам от единичните кавички в изразите, но сега мога да имам по-четим от човека начален файл.