MFB + Unicode:

added support for object ids in pg_lo_create() and pg_lo_import()
where available (based on code provided by Tatsuo Ishii)
This commit is contained in:
Hartmut Holzgraefe 2008-07-23 09:27:01 +00:00
parent 0225470dc5
commit d11e0df7ad
4 changed files with 219 additions and 26 deletions

View File

@ -92,6 +92,8 @@ if test "$PHP_PGSQL" != "no"; then
AC_CHECK_LIB(pq, PQescapeStringConn, AC_DEFINE(HAVE_PQESCAPE_CONN,1,[PostgreSQL 8.1.4 or later]))
AC_CHECK_LIB(pq, PQescapeByteaConn, AC_DEFINE(HAVE_PQESCAPE_BYTEA_CONN,1,[PostgreSQL 8.1.4 or later]))
AC_CHECK_LIB(pq, pg_encoding_to_char,AC_DEFINE(HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT,1,[Whether libpq is compiled with --enable-multibyte]))
AC_CHECK_LIB(pq, lo_create, AC_DEFINE(HAVE_PG_LO_CREATE,1,[PostgreSQL 8.1 or later]))
AC_CHECK_LIB(pq, lo_import_with_oid, AC_DEFINE(HAVE_PG_LO_IMPORT_WITH_OID,1,[PostgreSQL 8.4 or later]))
LIBS=$old_LIBS
LDFLAGS=$old_LDFLAGS

View File

@ -350,6 +350,7 @@ ZEND_END_ARG_INFO()
static
ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_create, 0, 0, 0)
ZEND_ARG_INFO(0, connection)
ZEND_ARG_INFO(0, large_object_id)
ZEND_END_ARG_INFO()
static
@ -392,6 +393,7 @@ static
ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_import, 0, 0, 0)
ZEND_ARG_INFO(0, connection)
ZEND_ARG_INFO(0, filename)
ZEND_ARG_INFO(0, large_object_oid)
ZEND_END_ARG_INFO()
static
@ -2978,42 +2980,86 @@ PHP_FUNCTION(pg_untrace)
}
/* }}} */
/* {{{ proto int pg_lo_create([resource connection])
/* {{{ proto mixed pg_lo_create([resource connection],[mixed large_object_oid])
Create a large object */
PHP_FUNCTION(pg_lo_create)
{
zval *pgsql_link = NULL;
PGconn *pgsql;
Oid pgsql_oid;
int id = -1, argc = ZEND_NUM_ARGS();
zval *pgsql_link = NULL, *oid = NULL;
PGconn *pgsql;
Oid pgsql_oid, wanted_oid = InvalidOid;
int id = -1, argc = ZEND_NUM_ARGS();
if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) {
if (zend_parse_parameters(argc TSRMLS_CC, "|zz", &pgsql_link, &oid) == FAILURE) {
return;
}
if ((argc == 1) && (Z_TYPE_P(pgsql_link) != IS_RESOURCE)) {
oid = pgsql_link;
pgsql_link = NULL;
}
if (argc == 0) {
if (pgsql_link == NULL) {
id = PGG(default_link);
CHECK_DEFAULT_LINK(id);
if (id == -1) {
RETURN_FALSE;
}
}
if (pgsql_link == NULL && id == -1) {
RETURN_FALSE;
}
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
/* NOTE: Archive modes not supported until I get some more data. Don't think anybody's
using it anyway. I believe it's also somehow related to the 'time travel' feature of
PostgreSQL, that's on the list of features to be removed... Create modes not supported.
What's the use of an object that can be only written to, but not read from, and vice
versa? Beats me... And the access type (r/w) must be specified again when opening
the object, probably (?) overrides this. (Jouni)
*/
if (oid) {
#ifndef HAVE_PG_LO_CREATE
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "OID value passing not supported");
#else
switch (Z_TYPE_P(oid)) {
case IS_STRING:
{
char *end_ptr;
wanted_oid = (Oid)strtoul(Z_STRVAL_P(oid), &end_ptr, 10);
if ((Z_STRVAL_P(oid)+Z_STRLEN_P(oid)) != end_ptr) {
/* wrong integer format */
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
RETURN_FALSE;
}
}
break;
case IS_UNICODE:
{
UChar *end_ptr;
wanted_oid = (Oid)zend_u_strtoul(Z_USTRVAL_P(oid), &end_ptr, 10);
if ((Z_USTRVAL_P(oid)+Z_USTRLEN_P(oid)) != end_ptr) {
/* wrong integer format */
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
RETURN_FALSE;
}
}
break;
case IS_LONG:
if (Z_LVAL_P(oid) < (long)InvalidOid) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
RETURN_FALSE;
}
wanted_oid = (Oid)Z_LVAL_P(oid);
break;
default:
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
RETURN_FALSE;
}
if ((pgsql_oid = lo_create(pgsql, wanted_oid)) == InvalidOid) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create PostgreSQL large object");
RETURN_FALSE;
}
PGSQL_RETURN_OID(pgsql_oid);
#endif
}
if ((pgsql_oid = lo_creat(pgsql, INV_READ|INV_WRITE)) == InvalidOid) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create PostgreSQL large object");
RETURN_FALSE;
}
PGSQL_RETURN_OID(pgsql_oid);
}
/* }}} */
@ -3332,26 +3378,27 @@ PHP_FUNCTION(pg_lo_read_all)
}
/* }}} */
/* {{{ proto int pg_lo_import([resource connection, ] string filename)
/* {{{ proto int pg_lo_import([resource connection, ] string filename [, mixed oid])
Import large object direct from filesystem */
PHP_FUNCTION(pg_lo_import)
{
zval *pgsql_link = NULL;
zval *pgsql_link = NULL, *oid = NULL;
char *file_in;
int id = -1, name_len;
int argc = ZEND_NUM_ARGS();
PGconn *pgsql;
Oid oid;
Oid wanted_oid, returned_oid;
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
"rs", &pgsql_link, &file_in, &name_len) == SUCCESS) {
"rs|z", &pgsql_link, &file_in, &name_len, &oid) == SUCCESS) {
;
}
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
"s", &file_in, &name_len) == SUCCESS) {
"s|z", &file_in, &name_len, &oid) == SUCCESS) {
id = PGG(default_link);
CHECK_DEFAULT_LINK(id);
}
// old calling convention, deprecated since PHP 4.2
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
"sr", &file_in, &name_len, &pgsql_link ) == SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Old API is used");
@ -3370,12 +3417,61 @@ PHP_FUNCTION(pg_lo_import)
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
oid = lo_import(pgsql, file_in);
if (oid) {
#ifndef HAVE_PG_LO_IMPORT_WITH_OID
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "OID value passing not supported");
#else
switch (Z_TYPE_P(oid)) {
case IS_STRING:
{
char *end_ptr;
wanted_oid = (Oid)strtoul(Z_STRVAL_P(oid), &end_ptr, 10);
if ((Z_STRVAL_P(oid)+Z_STRLEN_P(oid)) != end_ptr) {
/* wrong integer format, trailing non-numeric characters */
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
RETURN_FALSE;
}
}
break;
case IS_UNICODE:
{
UChar *end_ptr;
wanted_oid = (Oid)zend_u_strtoul(Z_USTRVAL_P(oid), &end_ptr, 10);
if ((Z_USTRVAL_P(oid)+Z_USTRLEN_P(oid)) != end_ptr) {
/* wrong integer format, trailing non-numeric characters */
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
RETURN_FALSE;
}
}
break;
case IS_LONG:
if (Z_LVAL_P(oid) < (long)InvalidOid) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
RETURN_FALSE;
}
wanted_oid = (Oid)Z_LVAL_P(oid);
break;
default:
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
RETURN_FALSE;
}
if (oid == InvalidOid) {
returned_oid = lo_import_with_oid(pgsql, file_in, wanted_oid);
if (returned_oid == InvalidOid) {
RETURN_FALSE;
}
PGSQL_RETURN_OID(returned_oid);
#endif
}
returned_oid = lo_import(pgsql, file_in);
if (returned_oid == InvalidOid) {
RETURN_FALSE;
}
PGSQL_RETURN_OID(oid);
PGSQL_RETURN_OID(returned_oid);
}
/* }}} */

View File

@ -0,0 +1,47 @@
--TEST--
PostgreSQL create large object with given oid
--SKIPIF--
<?php
include("skipif.inc");
$v = pg_version($conn);
if (version_compare("8.3", $v["client"]) > 0) die("skip - requires pg client >= 8.3\n");
if (version_compare("8.3", $v["server"]) > 0) die("skip - requires pg server >= 8.3\n");
?>
--FILE--
<?php
include('config.inc');
$db = pg_connect($conn_str);
echo "create LO from int\n";
pg_exec ($db, "begin");
$oid = pg_lo_create ($db, 21000);
if (!$oid) echo ("pg_lo_create() error\n");
if ($oid != 21000) echo ("pg_lo_create() wrong id\n");
pg_lo_unlink ($db, $oid);
pg_exec ($db, "commit");
echo "create LO from string\n";
pg_exec ($db, "begin");
$oid = pg_lo_create ($db, "21001");
if (!$oid) echo ("pg_lo_create() error\n");
if ($oid != 21001) echo ("pg_lo_create() wrong id\n");
pg_lo_unlink ($db, $oid);
pg_exec ($db, "commit");
echo "create LO using default connection\n";
pg_exec ("begin");
$oid = pg_lo_create (21002);
if (!$oid) echo ("pg_lo_create() error\n");
if ($oid != 21002) echo ("pg_lo_create() wrong id\n");
pg_lo_unlink ($oid);
pg_exec ("commit");
echo "OK";
?>
--EXPECT--
create LO from int
create LO from string
create LO using default connection
OK

View File

@ -0,0 +1,48 @@
--TEST--
PostgreSQL import large object with given oid
--SKIPIF--
<?php
include("skipif.inc");
$v = pg_version($conn);
if (version_compare("8.4devel", $v["client"]) > 0) die("skip - requires pg client >= 8.4\n");
if (version_compare("8.4devel", $v["server"]) > 0) die("skip - requires pg server >= 8.4\n");
?>
--FILE--
<?php
include('config.inc');
$db = pg_connect($conn_str);
echo "import LO from int\n";
pg_exec($db, 'begin');
$oid = pg_lo_import($db, __FILE__, 21003);
if (!$oid) echo ("pg_lo_import() error\n");
if ($oid != 21003) echo ("pg_lo_import() wrong id\n");
pg_lo_unlink ($db, $oid);
pg_exec($db, 'commit');
echo "import LO from string\n";
pg_exec($db, 'begin');
$oid = pg_lo_import($db, __FILE__, "21004");
if (!$oid) echo ("pg_lo_import() error\n");
if ($oid != 21004) echo ("pg_lo_import() wrong id\n");
pg_lo_unlink ($db, $oid);
pg_exec($db, 'commit');
echo "import LO using default connection\n";
pg_exec('begin');
$oid = pg_lo_import($db, __FILE__, 21005);
if (!$oid) echo ("pg_lo_import() error\n");
if ($oid != 21005) echo ("pg_lo_import() wrong id\n");
pg_lo_unlink ($oid);
pg_exec('commit');
echo "OK";
?>
--EXPECT--
import LO from int
import LO from string
import LO using default connection
OK