O problema não era a sintaxe, pois a sintaxe funcionava perfeitamente com flyway ou diretamente na CLI do PostgreSQL. O problema era com o Hibernate, especificamente com a análise do arquivo de importação. A maneira como o Hibernate funciona é que ele executa cada expressão dos arquivos individualmente, não todo o conteúdo como uma única expressão. Tentei colocar todas as definições de função em uma linha e funcionou, mas não ficou legível. Então eu descobri que existe uma configuração para o Hibernate para dizer que as expressões podem ser multi-linhas, mas o
$$
delimitador ainda não foi reconhecido quando usado em várias linhas. Então a solução foi definir o comando com
'
delimitador e, em seguida, escape das aspas simples quando necessário com um '
adicional . A solução é definir o
spring.jpa.properties.hibernate.hbm2ddl.import_files_sql_extractor
para usar org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor
. MultipleLinesSqlCommandExtractor extrai a expressão SQL de várias linhas e para quando um ponto e vírgula está presente. Esse é o fim da expressão. Ao envolver o corpo da função em uma string de aspas simples, o Hibernate tratará essa quebra como uma única linha. 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();
Eu tenho que sempre ter em mente escapar das aspas simples nas expressões, mas agora eu posso ter um arquivo de semente mais legível para humanos.