我正在尝试在postgres实例启动期间创建一个简单的函数。我这样做是通过将某些.sh
文件映射到/docker-entrypoint-initdb.d
目录。
我通过这个简单的功能不断遇到问题。
#!/bin/bash
set -e
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
CREATE OR REPLACE FUNCTION hi() RETURNS TEXT AS $$
BEGIN
RETURN 'hi'
END;
$$;
EOSQL
2020-01-29 05:12:30.817 UTC [62] ERROR: syntax error at or near "1" at character 49
2020-01-29 05:12:30.817 UTC [62] STATEMENT: CREATE OR REPLACE FUNCTION hi() RETURNS TEXT AS 1
BEGIN
RETURN 'hi'
END;
ERROR: syntax error at or near "1"
LINE 1: CREATE OR REPLACE FUNCTION hi() RETURNS TEXT AS 1
如果我将其更改为具有实际内容的内容:
#!/bin/bash
set -e
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
CREATE OR REPLACE FUNCTION hi() RETURNS TEXT AS $func$
BEGIN
RETURN 'hi'
END;
$func$;
EOSQL
我在同一地方遇到另一个错误:
2020-01-29 05:17:36.161 UTC [62] ERROR: syntax error at or near "$" at character 49
2020-01-29 05:17:36.161 UTC [62] STATEMENT: CREATE OR REPLACE FUNCTION hi() RETURNS TEXT AS $
BEGIN
RETURN 'hi'
END;
ERROR: syntax error at or near "$"
LINE 1: CREATE OR REPLACE FUNCTION hi() RETURNS TEXT AS $
运行最新的postgres版本:12.1
此函数定义到底有什么问题,为什么会出现此错误?
Bash的此处文档(从<<-EOSQL
到EOSQL
)默认情况下支持参数替换(以及其他类似的扩展);因此$$
将被进程ID取代,而$func
将被空字符串取代,而PostgreSQL才看到它们。
要禁用该功能,只需将<<-EOSQL
更改为<<-'EOSQL'
。
((相关文档:https://www.gnu.org/software/bash/manual/bash.html#Here-Documents。]
$func
和$$
是bash
中的变量。第一个是shell实例的进程ID,它解释错误输出中的数字;第二个只是普通的用户定义变量,大概为空,因此$test$
变为$
(因为$test
被空字符串替换)。
[您可以使用bash
和\$\$
来逃避\$test\$
发现的美元符号,也可以使用<<-'EOSQL'
在heredoc上使用单引号(无变量替换)语义。
这与PostgreSQL无关,它是bash
做您想做的事。