[英]Read binary file with PostgreSQL without pg_read_file
I need a solution to the following problem with a clear PostgreSQL 9.4:我需要一个明确的 PostgreSQL 9.4 来解决以下问题:
EDIT:编辑:
The file is outside cluster path, so normal functions raise:该文件位于集群路径之外,因此正常功能会引发:
SQL Error: ERROR: absolute path not allowed SQL 错误:错误:不允许绝对路径
Here is a simple function get_file_contents(filename text) returns bytea
for the job.这是一个简单的 function
get_file_contents(filename text) returns bytea
。
create or replace function get_file_contents(filename text) returns bytea as
$fn$
declare
lo_oid oid;
retval bytea;
begin
lo_oid := lo_import(filename);
retval := lo_get(lo_oid);
perform lo_unlink(lo_oid);
return retval;
end;
$fn$ language plpgsql;
-- Read the great work of Sun Tzu
select get_file_contents('/media/data/ForeignData/The Art Of War.pdf');
-- Insert into a table, update a table
insert into mytable (mycolumn[,<others>]) values (get_file_contents(myfilename)[,<others>]);
update mytable set mycolumn = get_file_contents(myfilename) where <whatever there>;
After a lot o research, I came out with the following function:经过大量研究,我得出以下 function:
CREATE OR REPLACE FUNCTION file_read(file text)
RETURNS bytea AS $$
DECLARE
content text;
tmp text;
BEGIN
file := quote_literal(file);
tmp := quote_ident(md5(random()::text));
-- create tmp table using random name
EXECUTE 'CREATE TEMP TABLE ' || tmp || ' (id oid, file_name text, content bytea)';
-- add given filename
EXECUTE 'INSERT INTO '|| tmp ||' (file_name) VALUES('|| file ||')';
-- add the document to large object storage and return the link id
BEGIN
EXECUTE 'UPDATE ' || tmp || ' SET id = lo_import(file_name) ';
EXCEPTION WHEN OTHERS THEN
RETURN NULL;
END;
-- pull document from large object storage
EXECUTE 'UPDATE ' || tmp || ' SET content = lo_get(id) ';
-- delete the file from large object storage
EXECUTE 'SELECT lo_unlink(id) FROM ' || tmp;
-- save data to content variable
EXECUTE 'SELECT content FROM ' || tmp INTO content;
-- drop tmp table
EXECUTE 'DROP TABLE ' || tmp;
-- return
RETURN content;
END;
$$ LANGUAGE plpgsql VOLATILE;
Sample use case:示例用例:
Read from file从文件中读取
select file_read(concat('/tmp/', '28528026bc302546d17ce7e82400ab7e.zip')
Update column更新栏
update custom_table set content = file_read(filename)
Use the built-in function pg_read_binary_file()
.使用内置的 function
pg_read_binary_file()
。 It's available since Postgres 9.1 and does exactly what you want.它从 Postgres 9.1 开始可用,并且完全符合您的要求。 The manual:
手册:
Returns all or part of a file.
返回文件的全部或部分。 This function is identical to
pg_read_file
except that it can read arbitrary binary data, returning the result asbytea
nottext
;这个 function 与
pg_read_file
相同,只是它可以读取任意二进制数据,返回结果为bytea
而不是text
; accordingly, no encoding checks are performed.因此,不执行编码检查。
This function is restricted to superusers by default, but other users can be granted
EXECUTE
to run the function.默认情况下,此 function 仅限于超级用户,但其他用户可以被授予
EXECUTE
以运行 function。
So to...所以要...
Read a zipped file from server into a
bytea
column将压缩文件从服务器读取到
bytea
列
UPDATE custom_table
SET content = pg_read_binary_file('/tmp/28528026bc302546d17ce7e82400ab7e.zip')
WHERE id = 123;
Considerably faster than any workaround.比任何解决方法都要快得多。
Note this restriction, quoting the manual :请注意此限制,引用手册:
Only files within the database cluster directory and the log_directory can be accessed.
只能访问数据库集群目录和 log_directory 中的文件。 Use a relative path for files in the cluster directory, and a path matching the log_directory configuration setting for log files.
对集群目录中的文件使用相对路径,并为日志文件使用与 log_directory 配置设置匹配的路径。
You can overcome the path restriction with a symlink from your db directory to any other directory.您可以使用从 db 目录到任何其他目录的符号链接来克服路径限制。 Be wary of possible security implications, though.
不过要警惕可能的安全隐患。 See:
看:
Also, consider upgrading to a current version of Postgres Postgres 9.4 has reached EOL on February 13, 2020 .此外,请考虑升级到 Postgres 的当前版本Postgres 9.4 已于 2020 年 2 月 13 日达到 EOL 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.