如何使用 pg_read_file 和 missing_ok=true 读取完整文件?
How to read full file with pg_read_file and missing_ok=true?
pg_read_file() 的以下所有用法都运行 没问题:
select pg_read_file('myFile.txt'); -- ok full file
select pg_read_file('myFile-notExists',0,10,true); -- NULL is Ok!
但这些都是有问题的:
select pg_read_file('myFile-notExists.txt'); -- ERROR... It is not what I need
select pg_read_file('myFile.txt',0,10,true); -- ok not null, but need full file!
...我尝试用换行函数解决问题:
CREATE or replace FUNCTION pg_read_file(f text, missing_ok boolean) RETURNS text AS $$
SELECT pg_read_file(f,0,922337203,missing_ok)
-- the max 9223372036854775807 is too large, also 9223372036854775800, ....
$$ LANGUAGE SQL IMMUTABLE;
但它说 “错误:请求的长度太大” 用于最大长度测试...所以我使用了随机常数。 问题 1:“最大文件大小”值是多少?
select pg_read_file('myFile-notExists.txt',true); -- Ok! NULL is what I need
select pg_read_file('myFile.txt',true); -- Ok! full file.
问题2:请问还有其他方法可以解决这个问题吗?
在标准的 PostgreSQL v12 \df pg_read_file
中说:
Schema | Name | Result data type | Argument data types | Type
------------+--------------+------------------+-------------------------------+------
pg_catalog | pg_read_file | text | text | func
pg_catalog | pg_read_file | text | text, bigint, bigint | func
pg_catalog | pg_read_file | text | text, bigint, bigint, boolean | func
为什么pg_read_file(text,boolean)
不在pg_catalog中?会和其他模块或扩展产生一些不一致吗?
使用 pg_stat_file 来测试它的存在怎么样?
CREATE or replace FUNCTION pg_read_file(f text, missing_ok boolean) RETURNS text AS $$
SELECT case
when pg_stat_file(f,missing_ok) is NULL then NULL
else pg_read_file(f) end
$$ LANGUAGE SQL IMMUTABLE;
这里存在竞争条件,文件可能在 pg_stat_file 之后但在 pg_read_file 之前消失,导致错误而不是 NULL return。
这是一个 Wiki,请编辑以增强此答案!
PS: 也检查 this discussion, performance questions and this alternative.
这是一个 pg_read_file()
错误...对于解决方法,没有真正好的解决方案 没有竞争条件( @jjanes 之前记得)。 Real-time 申请需要谨慎。
这里换一种方法,检索pg_stat_file
的信息,避免丢失CPU。
这是一个品味问题,我认为 RECORD 很难用,我更喜欢 JSONb。
想象一下您正在使用 JSONb 的场景,例如使用 PostgREST...
构建 back-end
重用pg_stat_file
CREATE or replace FUNCTION jsonb_read_stat_file(
f text,
missing_ok boolean DEFAULT false
) RETURNS JSONb AS $f$
SELECT j || jsonb_build_object( 'file',f, 'content',pg_read_file(f) )
FROM to_jsonb( pg_stat_file(f,missing_ok) ) t(j)
WHERE j IS NOT NULL
$f$ LANGUAGE SQL IMMUTABLE;
要仅获取内容,模拟纯 read_file(x,true)
,您可以使用 jsonb_read_stat_file('/tmp/text.txt',true)->>'content'
。
使用示例:
echo "Hello world!" > /tmp/text.txt
psql mydb -c "SELECT jsonb_read_stat_file('/tmp/text-ERROR.txt',true) IS NULL" # true
psql mydb -c "SELECT jsonb_read_stat_file('/tmp/text.txt',true)"
{
"file": "/tmp/text.txt",
"size": 13,
"isdir": false,
"access": "2020-08-09T14:44:28+00:00",
"change": "2020-08-09T14:44:28+00:00",
"content": "Hello world!\n",
"creation": null,
"modification": "2020-08-09T14:44:28+00:00"
}
pg_read_file() 的以下所有用法都运行 没问题:
select pg_read_file('myFile.txt'); -- ok full file
select pg_read_file('myFile-notExists',0,10,true); -- NULL is Ok!
但这些都是有问题的:
select pg_read_file('myFile-notExists.txt'); -- ERROR... It is not what I need
select pg_read_file('myFile.txt',0,10,true); -- ok not null, but need full file!
...我尝试用换行函数解决问题:
CREATE or replace FUNCTION pg_read_file(f text, missing_ok boolean) RETURNS text AS $$
SELECT pg_read_file(f,0,922337203,missing_ok)
-- the max 9223372036854775807 is too large, also 9223372036854775800, ....
$$ LANGUAGE SQL IMMUTABLE;
但它说 “错误:请求的长度太大” 用于最大长度测试...所以我使用了随机常数。 问题 1:“最大文件大小”值是多少?
select pg_read_file('myFile-notExists.txt',true); -- Ok! NULL is what I need
select pg_read_file('myFile.txt',true); -- Ok! full file.
问题2:请问还有其他方法可以解决这个问题吗?
在标准的 PostgreSQL v12 \df pg_read_file
中说:
Schema | Name | Result data type | Argument data types | Type
------------+--------------+------------------+-------------------------------+------
pg_catalog | pg_read_file | text | text | func
pg_catalog | pg_read_file | text | text, bigint, bigint | func
pg_catalog | pg_read_file | text | text, bigint, bigint, boolean | func
为什么pg_read_file(text,boolean)
不在pg_catalog中?会和其他模块或扩展产生一些不一致吗?
使用 pg_stat_file 来测试它的存在怎么样?
CREATE or replace FUNCTION pg_read_file(f text, missing_ok boolean) RETURNS text AS $$
SELECT case
when pg_stat_file(f,missing_ok) is NULL then NULL
else pg_read_file(f) end
$$ LANGUAGE SQL IMMUTABLE;
这里存在竞争条件,文件可能在 pg_stat_file 之后但在 pg_read_file 之前消失,导致错误而不是 NULL return。
这是一个 Wiki,请编辑以增强此答案!
PS: 也检查 this discussion, performance questions and this alternative.
这是一个 pg_read_file()
错误...对于解决方法,没有真正好的解决方案 没有竞争条件( @jjanes 之前记得)。 Real-time 申请需要谨慎。
这里换一种方法,检索pg_stat_file
的信息,避免丢失CPU。
这是一个品味问题,我认为 RECORD 很难用,我更喜欢 JSONb。
想象一下您正在使用 JSONb 的场景,例如使用 PostgREST...
构建 back-end重用pg_stat_file
CREATE or replace FUNCTION jsonb_read_stat_file(
f text,
missing_ok boolean DEFAULT false
) RETURNS JSONb AS $f$
SELECT j || jsonb_build_object( 'file',f, 'content',pg_read_file(f) )
FROM to_jsonb( pg_stat_file(f,missing_ok) ) t(j)
WHERE j IS NOT NULL
$f$ LANGUAGE SQL IMMUTABLE;
要仅获取内容,模拟纯 read_file(x,true)
,您可以使用 jsonb_read_stat_file('/tmp/text.txt',true)->>'content'
。
使用示例:
echo "Hello world!" > /tmp/text.txt
psql mydb -c "SELECT jsonb_read_stat_file('/tmp/text-ERROR.txt',true) IS NULL" # true
psql mydb -c "SELECT jsonb_read_stat_file('/tmp/text.txt',true)"
{
"file": "/tmp/text.txt",
"size": 13,
"isdir": false,
"access": "2020-08-09T14:44:28+00:00",
"change": "2020-08-09T14:44:28+00:00",
"content": "Hello world!\n",
"creation": null,
"modification": "2020-08-09T14:44:28+00:00"
}