34
34
#include "zend_exceptions.h"
35
35
#include "pgsql_driver_arginfo.h"
36
36
37
+ static bool pgsql_handle_in_transaction (pdo_dbh_t * dbh );
38
+
37
39
static char * _pdo_pgsql_trim_message (const char * message , int persistent )
38
40
{
39
41
size_t i = strlen (message )- 1 ;
@@ -139,10 +141,12 @@ static ssize_t pgsql_lob_read(php_stream *stream, char *buf, size_t count)
139
141
static int pgsql_lob_close (php_stream * stream , int close_handle )
140
142
{
141
143
struct pdo_pgsql_lob_self * self = (struct pdo_pgsql_lob_self * )stream -> abstract ;
144
+ pdo_pgsql_db_handle * H = (pdo_pgsql_db_handle * )(Z_PDO_DBH_P (& self -> dbh ))-> driver_data ;
142
145
143
146
if (close_handle ) {
144
147
lo_close (self -> conn , self -> lfd );
145
148
}
149
+ zend_hash_index_del (H -> lob_streams , php_stream_get_resource_id (stream ));
146
150
zval_ptr_dtor (& self -> dbh );
147
151
efree (self );
148
152
return 0 ;
@@ -193,6 +197,7 @@ php_stream *pdo_pgsql_create_lob_stream(zval *dbh, int lfd, Oid oid)
193
197
194
198
if (stm ) {
195
199
Z_ADDREF_P (dbh );
200
+ zend_hash_index_add_ptr (H -> lob_streams , php_stream_get_resource_id (stm ), stm -> res );
196
201
return stm ;
197
202
}
198
203
@@ -201,10 +206,29 @@ php_stream *pdo_pgsql_create_lob_stream(zval *dbh, int lfd, Oid oid)
201
206
}
202
207
/* }}} */
203
208
209
+ void pdo_pgsql_close_lob_streams (pdo_dbh_t * dbh )
210
+ {
211
+ zend_resource * res ;
212
+ pdo_pgsql_db_handle * H = (pdo_pgsql_db_handle * )dbh -> driver_data ;
213
+ if (H -> lob_streams ) {
214
+ ZEND_HASH_REVERSE_FOREACH_PTR (H -> lob_streams , res ) {
215
+ if (res -> type >= 0 ) {
216
+ zend_list_close (res );
217
+ }
218
+ } ZEND_HASH_FOREACH_END ();
219
+ }
220
+ }
221
+
204
222
static void pgsql_handle_closer (pdo_dbh_t * dbh ) /* {{{ */
205
223
{
206
224
pdo_pgsql_db_handle * H = (pdo_pgsql_db_handle * )dbh -> driver_data ;
207
225
if (H ) {
226
+ if (H -> lob_streams ) {
227
+ pdo_pgsql_close_lob_streams (dbh );
228
+ zend_hash_destroy (H -> lob_streams );
229
+ pefree (H -> lob_streams , dbh -> is_persistent );
230
+ H -> lob_streams = NULL ;
231
+ }
208
232
if (H -> server ) {
209
233
PQfinish (H -> server );
210
234
H -> server = NULL ;
@@ -294,6 +318,8 @@ static zend_long pgsql_handle_doer(pdo_dbh_t *dbh, const zend_string *sql)
294
318
zend_long ret = 1 ;
295
319
ExecStatusType qs ;
296
320
321
+ bool in_trans = pgsql_handle_in_transaction (dbh );
322
+
297
323
if (!(res = PQexec (H -> server , ZSTR_VAL (sql )))) {
298
324
/* fatal error */
299
325
pdo_pgsql_error (dbh , PGRES_FATAL_ERROR , NULL );
@@ -312,6 +338,9 @@ static zend_long pgsql_handle_doer(pdo_dbh_t *dbh, const zend_string *sql)
312
338
ret = Z_L (0 );
313
339
}
314
340
PQclear (res );
341
+ if (in_trans && !pgsql_handle_in_transaction (dbh )) {
342
+ pdo_pgsql_close_lob_streams (dbh );
343
+ }
315
344
316
345
return ret ;
317
346
}
@@ -502,9 +531,7 @@ static zend_result pdo_pgsql_check_liveness(pdo_dbh_t *dbh)
502
531
503
532
static bool pgsql_handle_in_transaction (pdo_dbh_t * dbh )
504
533
{
505
- pdo_pgsql_db_handle * H ;
506
-
507
- H = (pdo_pgsql_db_handle * )dbh -> driver_data ;
534
+ pdo_pgsql_db_handle * H = (pdo_pgsql_db_handle * )dbh -> driver_data ;
508
535
509
536
return PQtransactionStatus (H -> server ) > PQTRANS_IDLE ;
510
537
}
@@ -537,7 +564,9 @@ static bool pgsql_handle_commit(pdo_dbh_t *dbh)
537
564
538
565
/* When deferred constraints are used the commit could
539
566
fail, and a ROLLBACK implicitly ran. See bug #67462 */
540
- if (!ret ) {
567
+ if (ret ) {
568
+ pdo_pgsql_close_lob_streams (dbh );
569
+ } else {
541
570
dbh -> in_txn = pgsql_handle_in_transaction (dbh );
542
571
}
543
572
@@ -546,7 +575,13 @@ static bool pgsql_handle_commit(pdo_dbh_t *dbh)
546
575
547
576
static bool pgsql_handle_rollback (pdo_dbh_t * dbh )
548
577
{
549
- return pdo_pgsql_transaction_cmd ("ROLLBACK" , dbh );
578
+ int ret = pdo_pgsql_transaction_cmd ("ROLLBACK" , dbh );
579
+
580
+ if (ret ) {
581
+ pdo_pgsql_close_lob_streams (dbh );
582
+ }
583
+
584
+ return ret ;
550
585
}
551
586
552
587
/* {{{ Returns true if the copy worked fine or false if error */
@@ -1241,6 +1276,8 @@ static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{
1241
1276
}
1242
1277
1243
1278
H -> server = PQconnectdb (conn_str );
1279
+ H -> lob_streams = (HashTable * ) pemalloc (sizeof (HashTable ), dbh -> is_persistent );
1280
+ zend_hash_init (H -> lob_streams , 0 , NULL , NULL , 1 );
1244
1281
1245
1282
if (tmp_user ) {
1246
1283
zend_string_release_ex (tmp_user , 0 );
0 commit comments