[PHP-users 4000] Re: データのファイルへの吐き出しについて
Youichi Iwakiri
php-users@php.gr.jp
Thu, 29 Nov 2001 17:53:50 +0900
いわきりです
Haruhisa Fujita wrote in <20011128155505.C56A.HARUO-F@ai-e.aisin.co.jp>:
>PostgreSQLのバックスラッシュコマンド「\copy」を
>使おうとしているのですが、phpからこのコマンドは実行
>できないものでしょうか?
>助言お願いします。
以下のパッチを書いたんですけど使えますかね?
#テストが十分でないからちょっと怖いですが (^^;
ご希望の動作は結果からファイルを作成する事のようですので
こんな感じになるのかも
fwrite(fp, implode("\n", pg_copy_out("table_name")));
patchの内容
pgsql拡張ライブラリに関数を追加
array pg_copy_out(int connection_id,
string table_name [, string delimiter [, string null_as]])
戻り値
array型 レコード単位でarrayに格納
error時はFALSEを返す
使用例
<script language="php">
$conn = pg_connect("host=localhost dbname=test_db");
$result = pg_copy_out($conn, "t1");
print_r($result);
$result = pg_copy_out($conn, "t1", ':');
print_r($result);
$result = pg_copy_out($conn, "t1", "\t", "\0");
print_r($result);
pg_close($conn);
</script>
結果
Array
(
[0] => 0 \N
[1] => 2 0
[2] => 4 2
[3] => 5 3
[4] => 6 4
[5] => 7 0
[6] => 8 7
[7] => 9 0
[8] => 3 9
)
Array
(
[0] => 0:\N
[1] => 2:0
[2] => 4:2
[3] => 5:3
[4] => 6:4
[5] => 7:0
[6] => 8:7
[7] => 9:0
[8] => 3:9
)
Array
(
[0] => 0
[1] => 2 0
[2] => 4 2
[3] => 5 3
[4] => 6 4
[5] => 7 0
[6] => 8 7
[7] => 9 0
[8] => 3 9
)
以下、パッチです
PHP-4.0.6に付属のpgsql拡張モジュール用です
PHP-4.0.6 + PostgreSQL 7.1.3で動作確認を行いました。
patchの当て方
% cd $PHP_SRC_DIR/ext/pgsql
% patch < patch_file
--- pgsql.c Mon Jun 4 17:06:30 2001
+++ pgsql.c.with_copy_func Thu Nov 29 16:38:57 2001
@@ -83,6 +83,8 @@
PHP_FE(pg_loreadall, NULL)
PHP_FE(pg_loimport, NULL)
PHP_FE(pg_loexport, NULL)
+/* This function support '\\COPY' in psql internal commands */
+ PHP_FE(pg_copy_out, NULL)
PHP_FE(pg_put_line, NULL)
PHP_FE(pg_end_copy, NULL)
#if HAVE_PQCLIENTENCODING
@@ -777,6 +779,138 @@
RETURN_FALSE;
}
RETURN_TRUE;
+}
+/* }}} */
+
+#define COPYBUFSIZ 8192
+
+/* {{{ proto int pg_copy_out(int connection, string table_name [, string delimiter [, string null_as]])
+ Send null-terminated string to backend server*/
+PHP_FUNCTION(pg_copy_out)
+{
+ zval **table_name, **pgsql_link = NULL, **delimiter, **null_as;
+ char *query;
+ char pg_delimiter = '\t';
+ char *pg_null_as = "\\\\N";
+ static char *query_template = "COPY \"\" TO STDOUT DELIMITERS ':' WITH NULL AS ''";
+ int id = -1;
+ PGconn *pgsql;
+ PGresult *pgsql_result;
+ ExecStatusType status;
+ int result = 0;
+ int copydone = 0;
+ char copybuf[COPYBUFSIZ];
+ char *csv = (char *)NULL;
+ int ret;
+ PGLS_FETCH();
+
+ switch(ZEND_NUM_ARGS()) {
+ case 2:
+ if (zend_get_parameters_ex(2, &pgsql_link, &table_name)==FAILURE) {
+ RETURN_FALSE;
+ }
+ break;
+ case 3:
+ if (zend_get_parameters_ex(3, &pgsql_link, &table_name, &delimiter)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_string_ex(delimiter);
+ pg_delimiter = *Z_STRVAL_PP(delimiter);
+ break;
+ case 4:
+ if (zend_get_parameters_ex(4, &pgsql_link, &table_name, &delimiter, &null_as)==FAILURE) {
+ RETURN_FALSE;
+ }
+ pg_delimiter = *Z_STRVAL_PP(delimiter);
+ pg_null_as = emalloc(sizeof(strlen(Z_STRVAL_PP(null_as))+1));
+ strcpy(pg_null_as, Z_STRVAL_PP(null_as));
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL link", le_link, le_plink);
+
+ convert_to_string_ex(table_name);
+ /* create SQL
+ "COPY table_name TO STDOUT DELIMITERS '\t' WITH NULL AS 'null string'"
+ */
+ query = emalloc(sizeof(query_template) + sizeof(strlen(Z_STRVAL_PP(table_name))) + sizeof(strlen(Z_STRVAL_PP(null_as))) + 1);
+ sprintf(query, "COPY \"%s\" TO STDOUT DELIMITERS '%c' WITH NULL AS '%s'",
+ Z_STRVAL_PP(table_name),
+ pg_delimiter,
+ pg_null_as);
+
+ pgsql_result = PQexec(pgsql, query);
+
+ efree(query);
+
+ if (pgsql_result) {
+ status = PQresultStatus(pgsql_result);
+ } else {
+ status = (ExecStatusType) PQstatus(pgsql);
+ }
+
+ switch (status) {
+ case PGRES_COPY_OUT: /* successful command that did not return rows */
+ if (pgsql_result) {
+ /* Initialize return array */
+ if (array_init(return_value) == FAILURE) {
+ RETURN_FALSE;
+ }
+ while (!copydone)
+ {
+ ret = PQgetline(pgsql, copybuf, COPYBUFSIZ);
+
+ if (copybuf[0] == '\\' &&
+ copybuf[1] == '.' &&
+ copybuf[2] == '\0')
+ {
+ copydone = 1; /* we're at the end */
+ }
+ else
+ {
+ if (csv == (char *)NULL) {
+ csv = (char *)emalloc(sizeof(char)*(COPYBUFSIZ+1));
+ strcpy(csv, copybuf);
+ } else {
+ csv = (char *)erealloc(csv, strlen(csv) + sizeof(char)*COPYBUFSIZ);
+ strcat(csv, copybuf);
+ }
+
+
+ switch (ret)
+ {
+ case EOF:
+ copydone = 1;
+ /* FALLTHROUGH */
+ case 0:
+ add_next_index_string(return_value, csv, 1);
+ efree(csv);
+ csv = (char *)NULL;
+ break;
+ case 1:
+ break;
+ }
+ }
+ }
+ ret = !PQendcopy(pgsql);
+ } else {
+ RETURN_FALSE;
+ }
+ break;
+ case PGRES_EMPTY_QUERY:
+ case PGRES_BAD_RESPONSE:
+ case PGRES_NONFATAL_ERROR:
+ case PGRES_FATAL_ERROR:
+ case PGRES_COMMAND_OK:
+ case PGRES_COPY_IN:
+ default:
+ php_error(E_WARNING, "PostgreSQL query failed: %s", PQerrorMessage(pgsql));
+ RETURN_FALSE;
+ break;
+ }
}
/* }}} */
--- php_pgsql.h Sun May 6 10:34:56 2001
+++ php_pgsql.h.with_copy_func Thu Nov 29 14:04:24 2001
@@ -88,6 +88,7 @@
PHP_FUNCTION(pg_loexport);
PHP_FUNCTION(pg_lolseek);
PHP_FUNCTION(pg_lotell);
+PHP_FUNCTION(pg_copy_out);
PHP_FUNCTION(pg_put_line);
PHP_FUNCTION(pg_end_copy);
#if HAVE_PQCLIENTENCODING