Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Function Postgres函数错误_Function_Postgresql_Csv - Fatal编程技术网

Function Postgres函数错误

Function Postgres函数错误,function,postgresql,csv,Function,Postgresql,Csv,我在postgres中创建了一个函数,出现了一个奇怪的错误。我做错了什么?我也想看看你的变种如何做到这一点 CREATE OR REPLACE FUNCTION export_csv(request TEXT, filename VARCHAR(255)) RETURNS VOID AS $$ BEGIN EXECUTE 'COPY (' || request || ') TO "/home/r90t/work/study/etl/postgres_etl/export/' || file

我在postgres中创建了一个函数,出现了一个奇怪的错误。我做错了什么?我也想看看你的变种如何做到这一点

CREATE OR REPLACE FUNCTION export_csv(request TEXT, filename VARCHAR(255))
RETURNS VOID AS 
$$
BEGIN
  EXECUTE 'COPY (' || request || ') TO "/home/r90t/work/study/etl/postgres_etl/export/' || filename || '" WITH CSV;';
END
$$
LANGUAGE plpgsql;
请求:

SELECT export_csv('SELECT * FROM orders', 'orders.csv')
错误:

psql:/tmp/vUp267V/dbext.sql:2: ERROR:  syntax error at or near ""/home/r90t/work/study/etl/postgres_etl/export/orders.csv""
LINE 1: COPY (SELECT * FROM orders) TO "/home/r90t/work/study/etl/po...
                                   ^$
QUERY:  COPY (SELECT * FROM orders) TO "/home/r90t/work/study/etl/postgres_etl/export/orders.csv" WITH CSV;
CONTEXT:  PL/pgSQL function export_csv(text,character varying) line 3 at EXECUTE statement
哦,孩子

首先,因为您复制到文件,所以您的函数必须以超级用户的身份运行,并且您正在将用户提供的SQL查询内联到该文件中。至少您必须以超级用户的身份运行查询,并且还没有对其设置安全定义器。但是,函数的全部要点是SQL注入,收益很小。我知道这有点像是个人研究,但如果以一种会使企业数据在未来面临风险的方式进行研究,那将毫无益处

特别是,我想知道如果我这样做会发生什么:

 SELECT export_csv('SELECT * FROM ORDERS TO STDOUT; DROP DATABASE critical_db; --', 'foo');
CREATE OR REPLACE FUNCTION export_csv(relation name, columns name[])
RETURNS VOID AS 
$$
DECLARE column_list text;
BEGIN
  SELECT array_to_string(cols, ', ') INTO column_list
    FROM (SELECT array_agg(quote_literal(col)) as cols
            FROM unnest(columns) col
         ) a;

  EXECUTE 'COPY (SELECT ' || column_list || ' FROM ' || quote_ident(relation) || ') 
           TO ' || quote_literal('/home/r90t/work/study/etl/postgres_etl/export/' || relation) || ' WITH CSV;';
END
$$
LANGUAGE plpgsql;

真的,真的,真的很糟糕的东西是可能与您的功能。不要这样做。这些内容现在已包含在内,但一旦有人执行以下操作,您将完全:

 ALTER FUNCTION export_csv SET SECURITY DEFINER;
更好的方法是采用一个可以引用并就地处理的参数。比如:

 SELECT export_csv('SELECT * FROM ORDERS TO STDOUT; DROP DATABASE critical_db; --', 'foo');
CREATE OR REPLACE FUNCTION export_csv(relation name, columns name[])
RETURNS VOID AS 
$$
DECLARE column_list text;
BEGIN
  SELECT array_to_string(cols, ', ') INTO column_list
    FROM (SELECT array_agg(quote_literal(col)) as cols
            FROM unnest(columns) col
         ) a;

  EXECUTE 'COPY (SELECT ' || column_list || ' FROM ' || quote_ident(relation) || ') 
           TO ' || quote_literal('/home/r90t/work/study/etl/postgres_etl/export/' || relation) || ' WITH CSV;';
END
$$
LANGUAGE plpgsql;

这将为您提供防止sql注入的保护,如果您需要将日期添加到末尾,您可以使用quote_literal调用中的内容来实现这一点。

字符串文字需要用单引号括起来,而不是双引号括起来。