Postgres 函数创建中 $$ double dollars 的语法错误
Syntax error on $$ double dollars in Postgres function creation
我试图在 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
这个函数定义到底有什么问题,为什么会出现这个错误?
脚本中从 <<-EOSQL
到 EOSQL
的部分称为 "here document",该功能记录在 the Bash Reference Manual, §3.6.6 "Here Documents" 中。根据该部分:
If any part of word [in your case EOSQL
] is quoted, […] the lines in the here-document are not expanded. If word is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion, […]
换句话说——因为您没有引用 EOSQL
的任何部分,Bash 正在对 here-document 的内容执行参数扩展(和其他类似的替换),其中包括在 PostgreSQL 看到它们之前,将 $$
替换为进程 ID,并将 $func
替换为空字符串。
如果您只是将 <<-EOSQL
更改为 <<-'EOSQL'
,它不会那样做。
$func
和$$
是bash
中的变量。第一个是 shell 实例的进程 ID,它解释了错误输出中的数字;第二个只是一个普通的用户定义变量,大概是空的,所以 $test$
变成 $
(因为 $test
被一个空字符串替换)。
您可以转义 bash
认为重要的美元符号,使用 $$
和 $test$
,或者您可以使用 <<-'EOSQL'
使用单引号(不变量替换)heredoc 上的语义。
None 这与 PostgreSQL 有关,它 bash
做它认为你想做的事。
我试图在 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
这个函数定义到底有什么问题,为什么会出现这个错误?
脚本中从 <<-EOSQL
到 EOSQL
的部分称为 "here document",该功能记录在 the Bash Reference Manual, §3.6.6 "Here Documents" 中。根据该部分:
If any part of word [in your case
EOSQL
] is quoted, […] the lines in the here-document are not expanded. If word is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion, […]
换句话说——因为您没有引用 EOSQL
的任何部分,Bash 正在对 here-document 的内容执行参数扩展(和其他类似的替换),其中包括在 PostgreSQL 看到它们之前,将 $$
替换为进程 ID,并将 $func
替换为空字符串。
如果您只是将 <<-EOSQL
更改为 <<-'EOSQL'
,它不会那样做。
$func
和$$
是bash
中的变量。第一个是 shell 实例的进程 ID,它解释了错误输出中的数字;第二个只是一个普通的用户定义变量,大概是空的,所以 $test$
变成 $
(因为 $test
被一个空字符串替换)。
您可以转义 bash
认为重要的美元符号,使用 $$
和 $test$
,或者您可以使用 <<-'EOSQL'
使用单引号(不变量替换)heredoc 上的语义。
None 这与 PostgreSQL 有关,它 bash
做它认为你想做的事。