12
12
| obtain it through the world-wide-web, please send a note to |
13
13
| license@php.net so we can mail you a copy immediately. |
14
14
+----------------------------------------------------------------------+
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> |
16
18
+----------------------------------------------------------------------+
17
19
*/
18
20
@@ -108,6 +110,81 @@ static int pdo_pgsql_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *in
108
110
}
109
111
/* }}} */
110
112
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
+
111
188
static int pgsql_handle_closer (pdo_dbh_t * dbh TSRMLS_DC ) /* {{{ */
112
189
{
113
190
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)
397
474
return pdo_pgsql_transaction_cmd ("ROLLBACK" , dbh TSRMLS_CC );
398
475
}
399
476
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
+
400
595
static struct pdo_dbh_methods pgsql_methods = {
401
596
pgsql_handle_closer ,
402
597
pgsql_handle_preparer ,
@@ -410,7 +605,7 @@ static struct pdo_dbh_methods pgsql_methods = {
410
605
pdo_pgsql_fetch_error_func ,
411
606
pdo_pgsql_get_attribute ,
412
607
NULL , /* check_liveness */
413
- NULL /* get_driver_methods */
608
+ pdo_pgsql_get_driver_methods /* get_driver_methods */
414
609
};
415
610
416
611
static 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_
462
657
H -> pgoid = -1 ;
463
658
464
659
dbh -> methods = & pgsql_methods ;
465
- dbh -> alloc_own_columns = 1 ;
660
+ dbh -> alloc_own_columns = 0 ;
466
661
dbh -> max_escaped_char_length = 2 ;
467
662
468
663
ret = 1 ;
0 commit comments