Skip to content

Commit 162a311

Browse files
committed
ext/pgsql: adding pg_put_copy_data/pg_put_copy_end.
pg_put_copy_data allows to send COPY commands to the server. pg_put_copy_end signals the end of the n commands. Both return 3 states ; 1, 0 and -1 when 1 is success, 0 the buffer queue is full then -1 for errors. Close phpGH-14325
1 parent cc6d952 commit 162a311

File tree

6 files changed

+153
-1
lines changed

6 files changed

+153
-1
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,8 @@ PHP NEWS
195195
. Added pg_result_memory_size to get the query result memory usage.
196196
(KentarouTakeda)
197197
. Added pg_change_password to alter an user's password. (David Carlier)
198+
. Added pg_put_copy_data/pg_put_copy_end to send COPY commands and signal
199+
the end of the COPY. (David Carlier)
198200

199201
- Phar:
200202
. Fixed bug GH-12532 (PharData created from zip has incorrect timestamp).

UPGRADING

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,8 @@ PHP 8.4 UPGRADE NOTES
541541
- PGSQL:
542542
. Added pg_change_password to alter a given user's password. It handles
543543
transparently the password encryption from the database settings.
544+
. Added pg_put_copy_data to send COPY commands and pg_put_copy_end to send
545+
end-of-data to the server.
544546

545547
- Sodium:
546548
. Added the sodium_crypto_aead_aegis128l_*() and sodium_crypto_aead_aegis256l_*()

ext/pgsql/pgsql.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6123,3 +6123,45 @@ PHP_FUNCTION(pg_change_password)
61236123
}
61246124

61256125
#endif
6126+
6127+
PHP_FUNCTION(pg_put_copy_data)
6128+
{
6129+
zval *pgsql_link;
6130+
pgsql_link_handle *link;
6131+
zend_string *cmd;
6132+
6133+
ZEND_PARSE_PARAMETERS_START(2, 2)
6134+
Z_PARAM_OBJECT_OF_CLASS(pgsql_link, pgsql_link_ce)
6135+
Z_PARAM_STR(cmd)
6136+
ZEND_PARSE_PARAMETERS_END();
6137+
6138+
link = Z_PGSQL_LINK_P(pgsql_link);
6139+
CHECK_PGSQL_LINK(link);
6140+
6141+
// PQputCopyData accepts empty buffers as well
6142+
6143+
RETURN_LONG((zend_long)PQputCopyData(link->conn, ZSTR_VAL(cmd), ZSTR_LEN(cmd)));
6144+
}
6145+
6146+
PHP_FUNCTION(pg_put_copy_end)
6147+
{
6148+
zval *pgsql_link;
6149+
pgsql_link_handle *link;
6150+
zend_string *error;
6151+
char *err = NULL;
6152+
6153+
ZEND_PARSE_PARAMETERS_START(1, 2)
6154+
Z_PARAM_OBJECT_OF_CLASS(pgsql_link, pgsql_link_ce)
6155+
Z_PARAM_OPTIONAL
6156+
Z_PARAM_STR_OR_NULL(error)
6157+
ZEND_PARSE_PARAMETERS_END();
6158+
6159+
link = Z_PGSQL_LINK_P(pgsql_link);
6160+
CHECK_PGSQL_LINK(link);
6161+
6162+
if (error != NULL && ZSTR_LEN(error) != 0) {
6163+
err = ZSTR_VAL(error);
6164+
}
6165+
6166+
RETURN_LONG((zend_long)PQputCopyEnd(link->conn, err));
6167+
}

ext/pgsql/pgsql.stub.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,9 @@ function pg_result_memory_size(PgSql\Result $result): int {}
949949
#endif
950950

951951
function pg_change_password(PgSql\Connection $connection, string $user, #[\SensitiveParameter] string $password): bool {}
952+
953+
function pg_put_copy_data(PgSql\Connection $connection, string $cmd): int {}
954+
function pg_put_copy_end(PgSql\Connection $connection, string $error = null): int {}
952955
}
953956

954957
namespace PgSql {

ext/pgsql/pgsql_arginfo.h

Lines changed: 15 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/pgsql/tests/pg_put_copy.phpt

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
--TEST--
2+
PostgreSQL pg_put_copy_data/pg_end_copy_end
3+
--EXTENSIONS--
4+
pgsql
5+
--SKIPIF--
6+
<?php include("inc/skipif.inc"); ?>
7+
--FILE--
8+
<?php
9+
10+
include('inc/config.inc');
11+
$db = pg_connect($conn_str);
12+
13+
pg_query($db, "CREATE TABLE copystdin(id int, val text)");
14+
pg_query($db, "COPY copystdin(id, val) FROM STDIN");
15+
16+
var_dump(pg_put_copy_data($db, "0\tFooBar\n"));
17+
var_dump(pg_put_copy_data($db, "1\tBarFoo\n"));
18+
var_dump(pg_put_copy_data($db, ""));
19+
var_dump(pg_put_copy_end($db));
20+
21+
var_dump(pg_get_result($db));
22+
23+
var_dump(pg_fetch_all(pg_query($db, "SELECT * FROM copystdin ORDER BY id")));
24+
var_dump(pg_put_copy_data($db, "Error\t1"));
25+
var_dump(pg_put_copy_end($db));
26+
var_dump(pg_last_error($db));
27+
28+
pg_query($db, "COPY copystdin(id, val) FROM STDIN");
29+
var_dump(pg_put_copy_data($db, "Error\t1"));
30+
var_dump(pg_put_copy_end($db));
31+
32+
var_dump(pg_get_result($db));
33+
34+
var_dump(pg_fetch_all(pg_query($db, "SELECT * FROM copystdin ORDER BY id")));
35+
?>
36+
--CLEAN--
37+
<?php
38+
include('inc/config.inc');
39+
40+
$db = pg_connect($conn_str);
41+
pg_query($db, "DROP TABLE IF EXISTS copystdin");
42+
?>
43+
--EXPECT--
44+
int(1)
45+
int(1)
46+
int(1)
47+
int(1)
48+
object(PgSql\Result)#2 (0) {
49+
}
50+
array(2) {
51+
[0]=>
52+
array(2) {
53+
["id"]=>
54+
string(1) "0"
55+
["val"]=>
56+
string(6) "FooBar"
57+
}
58+
[1]=>
59+
array(2) {
60+
["id"]=>
61+
string(1) "1"
62+
["val"]=>
63+
string(6) "BarFoo"
64+
}
65+
}
66+
int(-1)
67+
int(-1)
68+
string(39) "no COPY in progress
69+
no COPY in progress"
70+
int(1)
71+
int(1)
72+
object(PgSql\Result)#2 (0) {
73+
}
74+
array(2) {
75+
[0]=>
76+
array(2) {
77+
["id"]=>
78+
string(1) "0"
79+
["val"]=>
80+
string(6) "FooBar"
81+
}
82+
[1]=>
83+
array(2) {
84+
["id"]=>
85+
string(1) "1"
86+
["val"]=>
87+
string(6) "BarFoo"
88+
}
89+
}

0 commit comments

Comments
 (0)