gpt4 book ai didi

php postgresql pdo 从标准输入复制

转载 作者:可可西里 更新时间:2023-11-01 13:23:14 24 4
gpt4 key购买 nike

COPY table_name ( field1, field2, field3) FROM STDIN CSV;
1,2,"q w"
3,4,"a s"
5,6,d
\.

如何通过 PDO 执行此查询?

更新:

问题是 PDO 驱动程序将此查询作为语句执行。
例如,如果您将它粘贴到 pgAdmin 中,它会抛出一个错误。
我需要在 psql 中执行它:

C:\Users\User>psql -e -h localhost -U postgres db_name
psql (9.1.2)
db_name=# COPY table_name ( field1, field2, field3) FROM STDIN CSV;
COPY table_name ( field1, field2, field3) FROM STDIN CSV;
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> 1,2,"q w"
>> 3,4,"a s"
>> 5,6,d
>> \.

最佳答案

感谢this book

请注意,此处提供的功能有效地绕过了安全限制,这是有原因的。您的函数应根据严格的白名单条件检查提供的文件路径和表。此示例也对 SQL 注入(inject)开放,因为它没有正确引用其输入。

创建执行COPY命令的函数

CREATE OR REPLACE FUNCTION copy_from_csv_ignoring_security(table_name text, table_fieds text, file_path text, oids boolean DEFAULT false, header boolean DEFAULT false, delimeter text DEFAULT ','::text, "null" text DEFAULT ''::text, quote text DEFAULT '"'::text, escape text DEFAULT '"'::text, force_not_null text DEFAULT ''::text)
RETURNS void AS
$BODY$

declare statement text;
begin

statement := 'COPY ' || table_name || ' (' || table_fieds || ') ' || 'FROM ''' || file_path || ''' WITH ';
IF oids THEN
statement := statement || 'OIDS ';
end if;
statement := statement || 'DELIMITER ''' || delimeter || ''' ';
statement := statement || 'NULL ''' || "null" || ''' CSV ';
IF header THEN
statement := statement || 'HEADER ';
end if;
statement := statement || 'QUOTE ''' || "quote" || ''' ';
statement := statement || 'ESCAPE ''' || "escape" || ''' ';
IF force_not_null <> '' THEN
statement := statement || 'FORCE NOT NULL ''' || force_not_null || ''' ';
end if;
execute statement;
end;
$BODY$
LANGUAGE plpgsql VOLATILE SECURITY DEFINER
COST 100;

赋予函数权限

revoke all on function copy_from_csv_ignoring_security(text, text, text, boolean, boolean, text, text, text, text, text) from public;
grant execute on function copy_from_csv_ignoring_security(text, text, text, boolean, boolean, text, text, text, text, text) to db_user;

从 PHP 执行

$dbh->exec('SELECT copy_from_csv_ignoring_security(...)');

===== 如果版本 >= 9.1.7 上面的技巧不起作用。 =====

解决方案:

创建文件 .pgpass (避免密码提示)在运行此脚本的用户的主目录中。

#.pgpass contents (chmod 600 - requred)    
host:port:db_name:user_name:password

创建 php 函数,执行 meta-command

function executeMetaCommand($dbUser, $dbName, $dbPort, $command)
{
$command = sprintf(
"psql -U %s -p %s -d %s -f - <<EOT\n%s\nEOT\n",
$dbUser, $dbPort, $dbName, $command
);
$streams = array(
array('pipe', 'r'),// stdin
array('pipe', 'w'),// stdout
array('pipe', 'w') // stderr
);
$process = proc_open($command, $streams, $pipes);
if (!is_resource($process)) {
throw new Exception("Cannot open process:\n$command");
} else {
list(, $stdout, $stderr) = $pipes;
$error = stream_get_contents($stderr);
fclose($stderr);
if (strlen($error) > 0) {
throw new Exception("Process error:\n$error");
} else {
$output = stream_get_contents($stdout);
fclose($stdout);
$returnCode = proc_close($process);
if ($returnCode === -1) {
throw new Exception("Process was completed incorrectly:\n$output");
} else {
return array(
$returnCode,
$output
);
}
}
}
}

//usage:
$command = sprintf("\\copy table(field1, field2) FROM '%s' WITH CSV", $filePath);
executeMetaCommand('postgres', 'test_db', '5432', $command);

关于php postgresql pdo 从标准输入复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9261916/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com