PHP Conference Japan 2024

PDO::pgsqlCopyToFile

(PHP 5 >= 5.3.3, PHP 7, PHP 8)

PDO::pgsqlCopyToFile Pdo\Pgsql::copyToFile() 的别名

描述

public PDO::pgsqlCopyToFile(
    string $tableName,
    string $filename,
    string $separator = "\t",
    string $nullAs = "\\\\N",
    ?string $fields = null
): bool

此方法是以下方法的别名:Pdo\Pgsql::copyToFile()

添加注释

用户贡献的注释 1 条注释

sage at sage dot sk
3 个月前
因此,我一直在尝试使用 COPY (SELECT...) TO STDOUT WITH (FORMAT CSV, HEADER),但是

- PDO::query() 使用 prepare,而 COPY 不支持
- PDO::exec() 不返回结果
- PDO::pgsqlCopyToFile() 不支持其他参数,仅支持分隔符和空值(以及列)

但是您知道它支持什么吗?SQL 注入!

https://github.com/php/php-src/blob/7dfbf4d1b74b5e629f2331261944fa072a92e1cb/ext/pdo_pgsql/pgsql_driver.c#L870

spprintf(&query, 0, "COPY %s TO STDIN WITH DELIMITER E'%c' NULL AS E'%s'", ...

没有任何转义,因此您可以像这样调用此方法

<?php
$db
->pgsqlCopyToFile("(select * from t1 cross join t2 using (whatever))", '/tmp/test.csv', ',', '\' header--');
?>

这实际上会产生

COPY (select...) TO STDIN WITH DELIMITER E',' NULL AS E'' header--

它仍然使用本地文件系统,我可以接受,但至少我不必绕过 CSV 标头。

如果有人知道在不将(在我的情况下是巨大的)结果集复制到数组和 fputcsv() 的情况下执行此操作的更好方法,我洗耳恭听。我尝试了 pg_query 和 pg_copy_to 的所有组合,但都无济于事。
To Top