1212 | obtain it through the world-wide-web, please send a note to |
1313 | license@php.net so we can mail you a copy immediately. |
1414 +----------------------------------------------------------------------+
15- | Author: Edin Kadribasic <edink@emini.dk> |
15+ | Authors: Edin Kadribasic <edink@emini.dk> |
16+ | Ilia Alshanestsky <ilia@prohost.org> |
17+ | Wez Furlong <wez@php.net> |
1618 +----------------------------------------------------------------------+
1719*/
1820
@@ -108,6 +110,81 @@ static int pdo_pgsql_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *in
108110}
109111/* }}} */
110112
113+ /* {{{ pdo_pgsql_create_lob_stream */
114+ static size_t pgsql_lob_write (php_stream * stream , const char * buf , size_t count TSRMLS_DC )
115+ {
116+ struct pdo_pgsql_lob_self * self = (struct pdo_pgsql_lob_self * )stream -> abstract ;
117+ return lo_write (self -> conn , self -> lfd , (char * )buf , count );
118+ }
119+
120+ static size_t pgsql_lob_read (php_stream * stream , char * buf , size_t count TSRMLS_DC )
121+ {
122+ struct pdo_pgsql_lob_self * self = (struct pdo_pgsql_lob_self * )stream -> abstract ;
123+ return lo_read (self -> conn , self -> lfd , buf , count );
124+ }
125+
126+ static int pgsql_lob_close (php_stream * stream , int close_handle TSRMLS_DC )
127+ {
128+ struct pdo_pgsql_lob_self * self = (struct pdo_pgsql_lob_self * )stream -> abstract ;
129+ pdo_dbh_t * dbh = self -> dbh ;
130+
131+ if (close_handle ) {
132+ lo_close (self -> conn , self -> lfd );
133+ }
134+ efree (self );
135+ php_pdo_dbh_delref (dbh TSRMLS_DC );
136+ return 0 ;
137+ }
138+
139+ static int pgsql_lob_flush (php_stream * stream TSRMLS_DC )
140+ {
141+ return 0 ;
142+ }
143+
144+ static int pgsql_lob_seek (php_stream * stream , off_t offset , int whence ,
145+ off_t * newoffset TSRMLS_DC )
146+ {
147+ struct pdo_pgsql_lob_self * self = (struct pdo_pgsql_lob_self * )stream -> abstract ;
148+ int pos = lo_lseek (self -> conn , self -> lfd , offset , whence );
149+ * newoffset = pos ;
150+ return pos >= 0 ? 0 : -1 ;
151+ }
152+
153+ php_stream_ops pdo_pgsql_lob_stream_ops = {
154+ pgsql_lob_write ,
155+ pgsql_lob_read ,
156+ pgsql_lob_close ,
157+ pgsql_lob_flush ,
158+ "pdo_pgsql lob stream" ,
159+ pgsql_lob_seek ,
160+ NULL ,
161+ NULL ,
162+ NULL
163+ };
164+
165+ php_stream * pdo_pgsql_create_lob_stream (pdo_dbh_t * dbh , int lfd , Oid oid TSRMLS_DC )
166+ {
167+ php_stream * stm ;
168+ struct pdo_pgsql_lob_self * self = ecalloc (1 , sizeof (* self ));
169+ pdo_pgsql_db_handle * H = (pdo_pgsql_db_handle * )dbh -> driver_data ;
170+
171+ self -> dbh = dbh ;
172+ self -> lfd = lfd ;
173+ self -> oid = oid ;
174+ self -> conn = H -> server ;
175+
176+ stm = php_stream_alloc (& pdo_pgsql_lob_stream_ops , self , 0 , "r+b" );
177+
178+ if (stm ) {
179+ php_pdo_dbh_addref (dbh TSRMLS_CC );
180+ return stm ;
181+ }
182+
183+ efree (self );
184+ return NULL ;
185+ }
186+ /* }}} */
187+
111188static int pgsql_handle_closer (pdo_dbh_t * dbh TSRMLS_DC ) /* {{{ */
112189{
113190 pdo_pgsql_db_handle * H = (pdo_pgsql_db_handle * )dbh -> driver_data ;
@@ -397,6 +474,124 @@ static int pgsql_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
397474 return pdo_pgsql_transaction_cmd ("ROLLBACK" , dbh TSRMLS_CC );
398475}
399476
477+ /* {{{ string pgSQL::pgsqlLOBCreate()
478+ Creates a new large object, returning its identifier. Must be called inside a transaction. */
479+ static PHP_METHOD (pgSQL , pgsqlLOBCreate )
480+ {
481+ pdo_dbh_t * dbh ;
482+ pdo_pgsql_db_handle * H ;
483+ Oid lfd ;
484+
485+ dbh = zend_object_store_get_object (getThis () TSRMLS_CC );
486+ PDO_CONSTRUCT_CHECK ;
487+
488+ H = (pdo_pgsql_db_handle * )dbh -> driver_data ;
489+ lfd = lo_creat (H -> server , INV_READ |INV_WRITE );
490+
491+ if (lfd != InvalidOid ) {
492+ char * buf ;
493+ spprintf (& buf , 0 , "%lu" , lfd );
494+ RETURN_STRING (buf , 0 );
495+ }
496+
497+ pdo_pgsql_error (dbh , PGRES_FATAL_ERROR , "HY000" );
498+ RETURN_FALSE ;
499+ }
500+ /* }}} */
501+
502+ /* {{{ resource pgSQL::pgsqlLOBOpen(string oid [, string mode = 'rb'])
503+ Opens an existing large object stream. Must be called inside a transaction. */
504+ static PHP_METHOD (pgSQL , pgsqlLOBOpen )
505+ {
506+ pdo_dbh_t * dbh ;
507+ pdo_pgsql_db_handle * H ;
508+ Oid oid ;
509+ int lfd ;
510+ char * oidstr ;
511+ int oidstrlen ;
512+ char * modestr = "rb" ;
513+ int modestrlen ;
514+ int mode = INV_READ ;
515+ char * end_ptr ;
516+
517+ if (FAILURE == zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "s|s" ,
518+ & oidstr , & oidstrlen , & modestr , & modestrlen )) {
519+ RETURN_FALSE ;
520+ }
521+
522+ oid = (Oid )strtoul (oidstr , & end_ptr , 10 );
523+ if (oid == 0 && (errno == ERANGE || errno == EINVAL )) {
524+ RETURN_FALSE ;
525+ }
526+
527+ if (strpbrk (modestr , "+w" )) {
528+ mode = INV_READ |INV_WRITE ;
529+ }
530+
531+ dbh = zend_object_store_get_object (getThis () TSRMLS_CC );
532+ PDO_CONSTRUCT_CHECK ;
533+
534+ H = (pdo_pgsql_db_handle * )dbh -> driver_data ;
535+
536+ lfd = lo_open (H -> server , oid , mode );
537+
538+ if (lfd >= 0 ) {
539+ php_stream * stream = pdo_pgsql_create_lob_stream (dbh , lfd , oid TSRMLS_CC );
540+ if (stream ) {
541+ php_stream_to_zval (stream , return_value );
542+ return ;
543+ }
544+ } else {
545+ pdo_pgsql_error (dbh , PGRES_FATAL_ERROR , "HY000" );
546+ }
547+ RETURN_FALSE ;
548+ }
549+ /* }}} */
550+
551+ /* {{{ bool pgSQL::pgsqlLOBUnlink(int oid)
552+ Deletes the large object identified by oid. Must be called inside a transaction. */
553+ static PHP_METHOD (pgSQL , pgsqlLOBUnlink )
554+ {
555+ pdo_dbh_t * dbh ;
556+ pdo_pgsql_db_handle * H ;
557+ long lfd ;
558+
559+ if (FAILURE == zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "l" ,
560+ & lfd )) {
561+ RETURN_FALSE ;
562+ }
563+
564+ dbh = zend_object_store_get_object (getThis () TSRMLS_CC );
565+ PDO_CONSTRUCT_CHECK ;
566+
567+ H = (pdo_pgsql_db_handle * )dbh -> driver_data ;
568+
569+ if (1 == lo_unlink (H -> server , lfd )) {
570+ RETURN_TRUE ;
571+ }
572+ pdo_pgsql_error (dbh , PGRES_FATAL_ERROR , "HY000" );
573+ RETURN_FALSE ;
574+ }
575+
576+
577+
578+ static function_entry dbh_methods [] = {
579+ PHP_ME (pgSQL , pgsqlLOBCreate , NULL , ZEND_ACC_PUBLIC )
580+ PHP_ME (pgSQL , pgsqlLOBOpen , NULL , ZEND_ACC_PUBLIC )
581+ PHP_ME (pgSQL , pgsqlLOBUnlink , NULL , ZEND_ACC_PUBLIC )
582+ {NULL , NULL , NULL }
583+ };
584+
585+ static function_entry * pdo_pgsql_get_driver_methods (pdo_dbh_t * dbh , int kind TSRMLS_DC )
586+ {
587+ switch (kind ) {
588+ case PDO_DBH_DRIVER_METHOD_KIND_DBH :
589+ return dbh_methods ;
590+ default :
591+ return NULL ;
592+ }
593+ }
594+
400595static struct pdo_dbh_methods pgsql_methods = {
401596 pgsql_handle_closer ,
402597 pgsql_handle_preparer ,
@@ -410,7 +605,7 @@ static struct pdo_dbh_methods pgsql_methods = {
410605 pdo_pgsql_fetch_error_func ,
411606 pdo_pgsql_get_attribute ,
412607 NULL , /* check_liveness */
413- NULL /* get_driver_methods */
608+ pdo_pgsql_get_driver_methods /* get_driver_methods */
414609};
415610
416611static int pdo_pgsql_handle_factory (pdo_dbh_t * dbh , zval * driver_options TSRMLS_DC ) /* {{{ */
@@ -462,7 +657,7 @@ static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_
462657 H -> pgoid = -1 ;
463658
464659 dbh -> methods = & pgsql_methods ;
465- dbh -> alloc_own_columns = 1 ;
660+ dbh -> alloc_own_columns = 0 ;
466661 dbh -> max_escaped_char_length = 2 ;
467662
468663 ret = 1 ;
0 commit comments