]> granicus.if.org Git - php/commitdiff
added support for object ids in pg_lo_create() and pg_lo_import() where available
authorHartmut Holzgraefe <hholzgra@php.net>
Wed, 23 Jul 2008 00:17:19 +0000 (00:17 +0000)
committerHartmut Holzgraefe <hholzgra@php.net>
Wed, 23 Jul 2008 00:17:19 +0000 (00:17 +0000)
(based on code provided by Tatsuo Ishii)

ext/pgsql/config.m4
ext/pgsql/pgsql.c
ext/pgsql/tests/27large_object_oid.phpt [new file with mode: 0644]

index c0aa0f97b996e0fbd0a893f921d18a67aaaa7dd9..16c81f22080ffd50c4de821af871b208ad095e47 100644 (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
 
index 53a12e6ecd6ca813d56c9eb84fdedb2de66e9e30..7f999391507f129f49f1f8267a20c0bd519fc331 100644 (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
@@ -2992,42 +2994,75 @@ 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_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);    
 }
 /* }}} */
@@ -3347,26 +3382,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");
@@ -3389,12 +3425,50 @@ 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 */
+                               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;
+        }
+
+       returned_oid = lo_import_with_oid(pgsql, file_in, wanted_oid);
 
-       if (oid == InvalidOid) {
+          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);
 }
 /* }}} */
 
diff --git a/ext/pgsql/tests/27large_object_oid.phpt b/ext/pgsql/tests/27large_object_oid.phpt
new file mode 100644 (file)
index 0000000..7d935ca
--- /dev/null
@@ -0,0 +1,70 @@
+--TEST--
+PostgreSQL large object with given oid
+--SKIPIF--
+<?php include("skipif.inc"); ?>
+--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 "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--
+create LO from int
+create LO from string
+create LO using default connection
+import LO from int
+import LO from string
+import LO using default connection
+OK