summaryrefslogtreecommitdiff
path: root/ext/pdo_pgsql/pgsql_driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pdo_pgsql/pgsql_driver.c')
-rw-r--r--ext/pdo_pgsql/pgsql_driver.c223
1 files changed, 214 insertions, 9 deletions
diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c
index 99c37d681..8568d3697 100644
--- a/ext/pdo_pgsql/pgsql_driver.c
+++ b/ext/pdo_pgsql/pgsql_driver.c
@@ -2,21 +2,23 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2005 The PHP Group |
+ | Copyright (c) 1997-2006 The PHP Group |
+----------------------------------------------------------------------+
- | This source file is subject to version 3.0 of the PHP license, |
+ | This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_0.txt. |
+ | http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Author: Edin Kadribasic <edink@emini.dk> |
+ | Authors: Edin Kadribasic <edink@emini.dk> |
+ | Ilia Alshanestsky <ilia@prohost.org> |
+ | Wez Furlong <wez@php.net> |
+----------------------------------------------------------------------+
*/
-/* $Id: pgsql_driver.c,v 1.53.2.1 2005/11/25 03:35:04 wez Exp $ */
+/* $Id: pgsql_driver.c,v 1.53.2.10 2006/01/01 12:50:12 sniper Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -28,6 +30,11 @@
#include "pdo/php_pdo.h"
#include "pdo/php_pdo_driver.h"
+#undef PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#undef PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#undef PACKAGE_VERSION
#include "pg_config.h" /* needed for PG_VERSION */
#include "php_pdo_pgsql.h"
#include "php_pdo_pgsql_int.h"
@@ -108,6 +115,81 @@ static int pdo_pgsql_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *in
}
/* }}} */
+/* {{{ pdo_pgsql_create_lob_stream */
+static size_t pgsql_lob_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
+{
+ struct pdo_pgsql_lob_self *self = (struct pdo_pgsql_lob_self*)stream->abstract;
+ return lo_write(self->conn, self->lfd, (char*)buf, count);
+}
+
+static size_t pgsql_lob_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
+{
+ struct pdo_pgsql_lob_self *self = (struct pdo_pgsql_lob_self*)stream->abstract;
+ return lo_read(self->conn, self->lfd, buf, count);
+}
+
+static int pgsql_lob_close(php_stream *stream, int close_handle TSRMLS_DC)
+{
+ struct pdo_pgsql_lob_self *self = (struct pdo_pgsql_lob_self*)stream->abstract;
+ pdo_dbh_t *dbh = self->dbh;
+
+ if (close_handle) {
+ lo_close(self->conn, self->lfd);
+ }
+ efree(self);
+ php_pdo_dbh_delref(dbh TSRMLS_CC);
+ return 0;
+}
+
+static int pgsql_lob_flush(php_stream *stream TSRMLS_DC)
+{
+ return 0;
+}
+
+static int pgsql_lob_seek(php_stream *stream, off_t offset, int whence,
+ off_t *newoffset TSRMLS_DC)
+{
+ struct pdo_pgsql_lob_self *self = (struct pdo_pgsql_lob_self*)stream->abstract;
+ int pos = lo_lseek(self->conn, self->lfd, offset, whence);
+ *newoffset = pos;
+ return pos >= 0 ? 0 : -1;
+}
+
+php_stream_ops pdo_pgsql_lob_stream_ops = {
+ pgsql_lob_write,
+ pgsql_lob_read,
+ pgsql_lob_close,
+ pgsql_lob_flush,
+ "pdo_pgsql lob stream",
+ pgsql_lob_seek,
+ NULL,
+ NULL,
+ NULL
+};
+
+php_stream *pdo_pgsql_create_lob_stream(pdo_dbh_t *dbh, int lfd, Oid oid TSRMLS_DC)
+{
+ php_stream *stm;
+ struct pdo_pgsql_lob_self *self = ecalloc(1, sizeof(*self));
+ pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
+
+ self->dbh = dbh;
+ self->lfd = lfd;
+ self->oid = oid;
+ self->conn = H->server;
+
+ stm = php_stream_alloc(&pdo_pgsql_lob_stream_ops, self, 0, "r+b");
+
+ if (stm) {
+ php_pdo_dbh_addref(dbh TSRMLS_CC);
+ return stm;
+ }
+
+ efree(self);
+ return NULL;
+}
+/* }}} */
+
static int pgsql_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
{
pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
@@ -133,11 +215,9 @@ static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len,
pdo_pgsql_stmt *S = ecalloc(1, sizeof(pdo_pgsql_stmt));
int scrollable;
#if HAVE_PQPREPARE
- PGresult *res;
int ret;
char *nsql = NULL;
int nsql_len = 0;
- ExecStatusType status;
#endif
S->H = H;
@@ -397,6 +477,131 @@ static int pgsql_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
return pdo_pgsql_transaction_cmd("ROLLBACK", dbh TSRMLS_CC);
}
+/* {{{ proto string PDO::pgsqlLOBCreate()
+ Creates a new large object, returning its identifier. Must be called inside a transaction. */
+static PHP_METHOD(PDO, pgsqlLOBCreate)
+{
+ pdo_dbh_t *dbh;
+ pdo_pgsql_db_handle *H;
+ Oid lfd;
+
+ dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
+ PDO_CONSTRUCT_CHECK;
+
+ H = (pdo_pgsql_db_handle *)dbh->driver_data;
+ lfd = lo_creat(H->server, INV_READ|INV_WRITE);
+
+ if (lfd != InvalidOid) {
+ char *buf;
+ spprintf(&buf, 0, "%lu", (long) lfd);
+ RETURN_STRING(buf, 0);
+ }
+
+ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "HY000");
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto resource PDO::pgsqlLOBOpen(string oid [, string mode = 'rb'])
+ Opens an existing large object stream. Must be called inside a transaction. */
+static PHP_METHOD(PDO, pgsqlLOBOpen)
+{
+ pdo_dbh_t *dbh;
+ pdo_pgsql_db_handle *H;
+ Oid oid;
+ int lfd;
+ char *oidstr;
+ int oidstrlen;
+ char *modestr = "rb";
+ int modestrlen;
+ int mode = INV_READ;
+ char *end_ptr;
+
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s",
+ &oidstr, &oidstrlen, &modestr, &modestrlen)) {
+ RETURN_FALSE;
+ }
+
+ oid = (Oid)strtoul(oidstr, &end_ptr, 10);
+ if (oid == 0 && (errno == ERANGE || errno == EINVAL)) {
+ RETURN_FALSE;
+ }
+
+ if (strpbrk(modestr, "+w")) {
+ mode = INV_READ|INV_WRITE;
+ }
+
+ dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
+ PDO_CONSTRUCT_CHECK;
+
+ H = (pdo_pgsql_db_handle *)dbh->driver_data;
+
+ lfd = lo_open(H->server, oid, mode);
+
+ if (lfd >= 0) {
+ php_stream *stream = pdo_pgsql_create_lob_stream(dbh, lfd, oid TSRMLS_CC);
+ if (stream) {
+ php_stream_to_zval(stream, return_value);
+ return;
+ }
+ } else {
+ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "HY000");
+ }
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto bool PDO::pgsqlLOBUnlink(string oid)
+ Deletes the large object identified by oid. Must be called inside a transaction. */
+static PHP_METHOD(PDO, pgsqlLOBUnlink)
+{
+ pdo_dbh_t *dbh;
+ pdo_pgsql_db_handle *H;
+ Oid oid;
+ char *oidstr, *end_ptr;
+ int oidlen;
+
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
+ &oidstr, &oidlen)) {
+ RETURN_FALSE;
+ }
+
+ oid = (Oid)strtoul(oidstr, &end_ptr, 10);
+ if (oid == 0 && (errno == ERANGE || errno == EINVAL)) {
+ RETURN_FALSE;
+ }
+
+ dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
+ PDO_CONSTRUCT_CHECK;
+
+ H = (pdo_pgsql_db_handle *)dbh->driver_data;
+
+ if (1 == lo_unlink(H->server, oid)) {
+ RETURN_TRUE;
+ }
+ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "HY000");
+ RETURN_FALSE;
+}
+/* }}} */
+
+
+static zend_function_entry dbh_methods[] = {
+ PHP_ME(PDO, pgsqlLOBCreate, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(PDO, pgsqlLOBOpen, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(PDO, pgsqlLOBUnlink, NULL, ZEND_ACC_PUBLIC)
+ {NULL, NULL, NULL}
+};
+
+static zend_function_entry *pdo_pgsql_get_driver_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC)
+{
+ switch (kind) {
+ case PDO_DBH_DRIVER_METHOD_KIND_DBH:
+ return dbh_methods;
+ default:
+ return NULL;
+ }
+}
+
static struct pdo_dbh_methods pgsql_methods = {
pgsql_handle_closer,
pgsql_handle_preparer,
@@ -410,7 +615,7 @@ static struct pdo_dbh_methods pgsql_methods = {
pdo_pgsql_fetch_error_func,
pdo_pgsql_get_attribute,
NULL, /* check_liveness */
- NULL /* get_driver_methods */
+ pdo_pgsql_get_driver_methods /* get_driver_methods */
};
static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
@@ -462,7 +667,7 @@ static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_
H->pgoid = -1;
dbh->methods = &pgsql_methods;
- dbh->alloc_own_columns = 1;
+ dbh->alloc_own_columns = 0;
dbh->max_escaped_char_length = 2;
ret = 1;