2024 年 PHP Conference Japan

PDO::pgsqlCopyToFile

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

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

說明

public PDO::pgsqlCopyToFile(
    字串 $tableName,
    字串 $filename,
    字串 $separator = "\t",
    字串 $nullAs = "\\\\N",
    ?字串 $fields = null
): 布林值

此方法是以下方法的別名: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