Problemem nie była składnia, ponieważ składnia doskonale działała z flyway lub bezpośrednio w PostgreSQL CLI. Problem dotyczył Hibernate, a konkretnie parsowania pliku importu. Sposób działania Hibernate polega na tym, że wykonuje każde wyrażenie z plików indywidualnie, a nie całą zawartość jako pojedyncze wyrażenie. Próbowałem umieścić wszystkie definicje funkcji w jednym wierszu i zadziałało, ale nie było to czytelne. Odkryłem więc, że istnieje konfiguracja dla Hibernate, która mówi mu, że wyrażenia mogą być wieloliniowe, ale $$
separator był nadal nierozpoznawany, gdy był używany w wielu wierszach.
Więc rozwiązaniem było zdefiniowanie polecenia za pomocą '
separatora, a następnie w razie potrzeby pomiń pojedyncze cudzysłowy z dodatkowym '
.
Rozwiązaniem jest ustawienie spring.jpa.properties.hibernate.hbm2ddl.import_files_sql_extractor
aby użyć org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor
. MultipleLinesSqlCommandExtractor wyodrębnia wyrażenie SQL z wielu wierszy i zatrzymuje się, gdy występuje średnik. To koniec wyrażenia. Zawijając ciało funkcji w pojedynczy łańcuch cudzysłowu, Hibernate potraktuje to zawijanie jako pojedynczy wiersz.
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();
Zawsze muszę pamiętać, aby uniknąć pojedynczych cudzysłowów w wyrażeniach, ale teraz mogę mieć plik źródłowy bardziej czytelny dla człowieka.