dcd7e75d782bd50d2b52b14e79065a1f6904fa34
[m6w6/ext-pq] / src / php_pq.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: pq |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2013, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
16
17 #include <php.h>
18 #include <Zend/zend_interfaces.h>
19 #include <ext/standard/info.h>
20 #include <ext/spl/spl_array.h>
21
22 #include <libpq-events.h>
23 #include <libpq/libpq-fs.h>
24 #include <fnmatch.h>
25
26 #include "php_pq.h"
27
28 typedef int STATUS; /* SUCCESS/FAILURE */
29
30 static char *PHP_PQerrorMessage(PGconn *c) {
31 char *e = PQerrorMessage(c);
32 size_t l = strlen(e);
33
34 while (l-- > 0 && e[l] == '\n') {
35 e[l] = '\0';
36 }
37
38 return e;
39 }
40
41 /*
42 ZEND_DECLARE_MODULE_GLOBALS(pq)
43 */
44
45
46 /* {{{ PHP_INI
47 */
48 /* Remove comments and fill if you need to have entries in php.ini
49 PHP_INI_BEGIN()
50 STD_PHP_INI_ENTRY("pq.global_value", "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_pq_globals, pq_globals)
51 STD_PHP_INI_ENTRY("pq.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_pq_globals, pq_globals)
52 PHP_INI_END()
53 */
54 /* }}} */
55
56 /* {{{ php_pq_init_globals
57 */
58 /* Uncomment this function if you have INI entries
59 static void php_pq_init_globals(zend_pq_globals *pq_globals)
60 {
61 pq_globals->global_value = 0;
62 pq_globals->global_string = NULL;
63 }
64 */
65 /* }}} */
66
67 static zend_class_entry *php_pqconn_class_entry;
68 static zend_class_entry *php_pqtypes_class_entry;
69 static zend_class_entry *php_pqres_class_entry;
70 static zend_class_entry *php_pqstm_class_entry;
71 static zend_class_entry *php_pqtxn_class_entry;
72 static zend_class_entry *php_pqcancel_class_entry;
73 static zend_class_entry *php_pqevent_class_entry;
74 static zend_class_entry *php_pqlob_class_entry;
75
76 static zend_object_handlers php_pqconn_object_handlers;
77 static zend_object_handlers php_pqtypes_object_handlers;
78 static zend_object_handlers php_pqres_object_handlers;
79 static zend_object_handlers php_pqstm_object_handlers;
80 static zend_object_handlers php_pqtxn_object_handlers;
81 static zend_object_handlers php_pqcancel_object_handlers;
82 static zend_object_handlers php_pqevent_object_handlers;
83 static zend_object_handlers php_pqlob_object_handlers;
84
85 typedef struct php_pq_callback {
86 zend_fcall_info fci;
87 zend_fcall_info_cache fcc;
88 void *data;
89 } php_pq_callback_t;
90
91 typedef struct php_pq_object {
92 zend_object zo;
93 zend_object_value zv;
94 HashTable *prophandler;
95 void *intern;
96 } php_pq_object_t;
97
98 typedef struct php_pqconn {
99 PGconn *conn;
100 int (*poller)(PGconn *);
101 HashTable listeners;
102 HashTable eventhandlers;
103 php_pq_callback_t onevent;
104 unsigned unbuffered:1;
105 } php_pqconn_t;
106
107 typedef struct php_pqconn_object {
108 zend_object zo;
109 zend_object_value zv;
110 HashTable *prophandler;
111 php_pqconn_t *intern;
112 } php_pqconn_object_t;
113
114 typedef struct php_pqtypes {
115 HashTable types;
116 php_pqconn_object_t *conn;
117 } php_pqtypes_t;
118
119 typedef struct php_pqtypes_object {
120 zend_object zo;
121 zend_object_value zv;
122 HashTable *prophandler;
123 php_pqtypes_t *intern;
124 } php_pqtypes_object_t;
125
126 typedef struct php_pqconn_event_data {
127 php_pqconn_object_t *obj;
128 #ifdef ZTS
129 void ***ts;
130 #endif
131 } php_pqconn_event_data_t;
132
133 typedef enum php_pqres_fetch {
134 PHP_PQRES_FETCH_ARRAY,
135 PHP_PQRES_FETCH_ASSOC,
136 PHP_PQRES_FETCH_OBJECT
137 } php_pqres_fetch_t;
138
139 typedef struct php_pqres_iterator {
140 zend_object_iterator zi;
141 zval *current_val;
142 unsigned index;
143 php_pqres_fetch_t fetch_type;
144 } php_pqres_iterator_t;
145
146 typedef struct php_pqres {
147 PGresult *res;
148 php_pqres_iterator_t *iter;
149 } php_pqres_t;
150
151 typedef struct php_pqres_object {
152 zend_object zo;
153 zend_object_value zv;
154 HashTable *prophandler;
155 php_pqres_t *intern;
156 } php_pqres_object_t;
157
158 typedef struct php_pqstm {
159 php_pqconn_object_t *conn;
160 char *name;
161 } php_pqstm_t;
162
163 typedef struct php_pqstm_object {
164 zend_object zo;
165 zend_object_value zv;
166 HashTable *prophandler;
167 php_pqstm_t *intern;
168 } php_pqstm_object_t;
169
170 typedef enum php_pqtxn_isolation {
171 PHP_PQTXN_READ_COMMITTED,
172 PHP_PQTXN_REPEATABLE_READ,
173 PHP_PQTXN_SERIALIZABLE,
174 } php_pqtxn_isolation_t;
175
176 typedef struct php_pqtxn {
177 php_pqconn_object_t *conn;
178 php_pqtxn_isolation_t isolation;
179 unsigned readonly:1;
180 unsigned deferrable:1;
181 } php_pqtxn_t;
182
183 typedef struct php_pqtxn_object {
184 zend_object zo;
185 zend_object_value zv;
186 HashTable *prophandler;
187 php_pqtxn_t *intern;
188 } php_pqtxn_object_t;
189
190 typedef struct php_pqcancel {
191 PGcancel *cancel;
192 php_pqconn_object_t *conn;
193 } php_pqcancel_t;
194
195 typedef struct php_pqcancel_object {
196 zend_object zo;
197 zend_object_value zv;
198 HashTable *prophandler;
199 php_pqcancel_t *intern;
200 } php_pqcancel_object_t;
201
202 typedef struct php_pqevent {
203 php_pq_callback_t cb;
204 php_pqconn_object_t *conn;
205 char *type;
206 } php_pqevent_t;
207
208 typedef struct php_pqevent_object {
209 zend_object zo;
210 zend_object_value zv;
211 HashTable *prophandler;
212 php_pqevent_t *intern;
213 } php_pqevent_object_t;
214
215 typedef struct php_pqlob {
216 int lofd;
217 Oid loid;
218 php_pqtxn_object_t *txn;
219 } php_pqlob_t;
220
221 typedef struct php_pqlob_object {
222 zend_object zo;
223 zend_object_value zv;
224 HashTable *prophandler;
225 php_pqlob_t *intern;
226 } php_pqlob_object_t;
227
228 static HashTable php_pqconn_object_prophandlers;
229 static HashTable php_pqtypes_object_prophandlers;
230 static HashTable php_pqres_object_prophandlers;
231 static HashTable php_pqstm_object_prophandlers;
232 static HashTable php_pqtxn_object_prophandlers;
233 static HashTable php_pqcancel_object_prophandlers;
234 static HashTable php_pqevent_object_prophandlers;
235 static HashTable php_pqlob_object_prophandlers;
236
237 typedef void (*php_pq_object_prophandler_func_t)(zval *object, void *o, zval *return_value TSRMLS_DC);
238
239 typedef struct php_pq_object_prophandler {
240 php_pq_object_prophandler_func_t read;
241 php_pq_object_prophandler_func_t write;
242 } php_pq_object_prophandler_t;
243
244 static zend_object_iterator_funcs php_pqres_iterator_funcs;
245
246 static zend_object_iterator *php_pqres_iterator_init(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
247 {
248 php_pqres_iterator_t *iter;
249 zval *prop, *zfetch_type;
250
251 iter = ecalloc(1, sizeof(*iter));
252 iter->zi.funcs = &php_pqres_iterator_funcs;
253 iter->zi.data = object;
254 Z_ADDREF_P(object);
255
256 zfetch_type = prop = zend_read_property(ce, object, ZEND_STRL("fetchType"), 0 TSRMLS_CC);
257 if (Z_TYPE_P(zfetch_type) != IS_LONG) {
258 convert_to_long_ex(&zfetch_type);
259 }
260 iter->fetch_type = Z_LVAL_P(zfetch_type);
261 if (zfetch_type != prop) {
262 zval_ptr_dtor(&zfetch_type);
263 }
264 if (Z_REFCOUNT_P(prop)) {
265 zval_ptr_dtor(&prop);
266 } else {
267 zval_dtor(prop);
268 FREE_ZVAL(prop);
269 }
270
271 return (zend_object_iterator *) iter;
272 }
273
274 static void php_pqres_iterator_dtor(zend_object_iterator *i TSRMLS_DC)
275 {
276 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
277
278 if (iter->current_val) {
279 zval_ptr_dtor(&iter->current_val);
280 iter->current_val = NULL;
281 }
282 zval_ptr_dtor((zval **) &iter->zi.data);
283 efree(iter);
284 }
285
286 static STATUS php_pqres_iterator_valid(zend_object_iterator *i TSRMLS_DC)
287 {
288 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
289 php_pqres_object_t *obj = zend_object_store_get_object(iter->zi.data TSRMLS_CC);
290
291 if (PQresultStatus(obj->intern->res) != PGRES_TUPLES_OK) {
292 return FAILURE;
293 }
294 if (PQntuples(obj->intern->res) <= iter->index) {
295 return FAILURE;
296 }
297
298 return SUCCESS;
299 }
300
301 static zval *php_pqres_row_to_zval(PGresult *res, unsigned row, php_pqres_fetch_t fetch_type TSRMLS_DC)
302 {
303 zval *data;
304 int c, cols;
305
306 MAKE_STD_ZVAL(data);
307 if (PHP_PQRES_FETCH_OBJECT == fetch_type) {
308 object_init(data);
309 } else {
310 array_init(data);
311 }
312
313 for (c = 0, cols = PQnfields(res); c < cols; ++c) {
314 if (PQgetisnull(res, row, c)) {
315 switch (fetch_type) {
316 case PHP_PQRES_FETCH_OBJECT:
317 add_property_null(data, PQfname(res, c));
318 break;
319
320 case PHP_PQRES_FETCH_ASSOC:
321 add_assoc_null(data, PQfname(res, c));
322 break;
323
324 case PHP_PQRES_FETCH_ARRAY:
325 add_index_null(data, c);
326 break;
327 }
328 } else {
329 char *val = PQgetvalue(res, row, c);
330 int len = PQgetlength(res, row, c);
331
332 switch (fetch_type) {
333 case PHP_PQRES_FETCH_OBJECT:
334 add_property_stringl(data, PQfname(res, c), val, len, 1);
335 break;
336
337 case PHP_PQRES_FETCH_ASSOC:
338 add_assoc_stringl(data, PQfname(res, c), val, len, 1);
339 break;
340
341 case PHP_PQRES_FETCH_ARRAY:
342 add_index_stringl(data, c, val, len ,1);
343 break;
344 }
345 }
346 }
347
348 return data;
349 }
350
351 static void php_pqres_iterator_current(zend_object_iterator *i, zval ***data_ptr TSRMLS_DC)
352 {
353 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
354 php_pqres_object_t *obj = zend_object_store_get_object(iter->zi.data TSRMLS_CC);
355
356 if (iter->current_val) {
357 zval_ptr_dtor(&iter->current_val);
358 }
359 iter->current_val = php_pqres_row_to_zval(obj->intern->res, iter->index, iter->fetch_type TSRMLS_CC);
360 *data_ptr = &iter->current_val;
361 }
362
363 static int php_pqres_iterator_key(zend_object_iterator *i, char **key_str, uint *key_len, ulong *key_num TSRMLS_DC)
364 {
365 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
366
367 *key_num = (ulong) iter->index;
368
369 return HASH_KEY_IS_LONG;
370 }
371
372 static void php_pqres_iterator_next(zend_object_iterator *i TSRMLS_DC)
373 {
374 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
375
376 ++iter->index;
377 }
378
379 static void php_pqres_iterator_rewind(zend_object_iterator *i TSRMLS_DC)
380 {
381 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
382
383 iter->index = 0;
384 }
385
386 static zend_object_iterator_funcs php_pqres_iterator_funcs = {
387 php_pqres_iterator_dtor,
388 /* check for end of iteration (FAILURE or SUCCESS if data is valid) */
389 php_pqres_iterator_valid,
390 /* fetch the item data for the current element */
391 php_pqres_iterator_current,
392 /* fetch the key for the current element (return HASH_KEY_IS_STRING or HASH_KEY_IS_LONG) (optional, may be NULL) */
393 php_pqres_iterator_key,
394 /* step forwards to next element */
395 php_pqres_iterator_next,
396 /* rewind to start of data (optional, may be NULL) */
397 php_pqres_iterator_rewind,
398 /* invalidate current value/key (optional, may be NULL) */
399 NULL
400 };
401
402 static STATUS php_pqres_success(PGresult *res TSRMLS_DC)
403 {
404 switch (PQresultStatus(res)) {
405 case PGRES_BAD_RESPONSE:
406 case PGRES_NONFATAL_ERROR:
407 case PGRES_FATAL_ERROR:
408 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", PQresultErrorMessage(res));
409 return FAILURE;
410 default:
411 return SUCCESS;
412 }
413 }
414
415 static void php_pq_callback_dtor(php_pq_callback_t *cb) {
416 if (cb->fci.size > 0) {
417 zend_fcall_info_args_clear(&cb->fci, 1);
418 zval_ptr_dtor(&cb->fci.function_name);
419 if (cb->fci.object_ptr) {
420 zval_ptr_dtor(&cb->fci.object_ptr);
421 }
422 }
423 cb->fci.size = 0;
424 }
425
426 static void php_pq_callback_addref(php_pq_callback_t *cb)
427 {
428 Z_ADDREF_P(cb->fci.function_name);
429 if (cb->fci.object_ptr) {
430 Z_ADDREF_P(cb->fci.object_ptr);
431 }
432 }
433
434 static void php_pq_object_to_zval(void *o, zval **zv TSRMLS_DC)
435 {
436 php_pq_object_t *obj = o;
437
438 if (!*zv) {
439 MAKE_STD_ZVAL(*zv);
440 }
441
442 zend_objects_store_add_ref_by_handle(obj->zv.handle TSRMLS_CC);
443
444 (*zv)->type = IS_OBJECT;
445 (*zv)->value.obj = obj->zv;
446 }
447
448 static void php_pq_object_addref(void *o TSRMLS_DC)
449 {
450 php_pq_object_t *obj = o;
451 zend_objects_store_add_ref_by_handle(obj->zv.handle TSRMLS_CC);
452 }
453
454 static void php_pq_object_delref(void *o TSRMLS_DC)
455 {
456 php_pq_object_t *obj = o;
457 zend_objects_store_del_ref_by_handle_ex(obj->zv.handle, obj->zv.handlers TSRMLS_CC);
458 }
459
460 static void php_pqconn_object_free(void *o TSRMLS_DC)
461 {
462 php_pqconn_object_t *obj = o;
463
464 if (obj->intern) {
465 PQfinish(obj->intern->conn);
466 php_pq_callback_dtor(&obj->intern->onevent);
467 zend_hash_destroy(&obj->intern->listeners);
468 zend_hash_destroy(&obj->intern->eventhandlers);
469 efree(obj->intern);
470 obj->intern = NULL;
471 }
472 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
473 efree(obj);
474 }
475
476 static void php_pqtypes_object_free(void *o TSRMLS_DC)
477 {
478 php_pqtypes_object_t *obj = o;
479
480 if (obj->intern) {
481 zend_hash_destroy(&obj->intern->types);
482 php_pq_object_delref(obj->intern->conn TSRMLS_CC);
483 efree(obj->intern);
484 obj->intern = NULL;
485 }
486 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
487 efree(obj);
488 }
489
490 static int php_pqconn_event(PGEventId id, void *e, void *data);
491
492 static void php_pqres_object_free(void *o TSRMLS_DC)
493 {
494 php_pqres_object_t *obj = o;
495
496 if (obj->intern) {
497 if (obj->intern->res) {
498 zval *res = PQresultInstanceData(obj->intern->res, php_pqconn_event);
499 if (res) {
500 PQresultSetInstanceData(obj->intern->res, php_pqconn_event, NULL);
501 zval_ptr_dtor(&res);
502 } else {
503 PQclear(obj->intern->res);
504 obj->intern->res = NULL;
505 }
506 }
507
508 if (obj->intern->iter) {
509 php_pqres_iterator_dtor((zend_object_iterator *) obj->intern->iter TSRMLS_CC);
510 obj->intern->iter = NULL;
511 }
512
513 efree(obj->intern);
514 obj->intern = NULL;
515 }
516 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
517 efree(obj);
518 }
519
520 static void php_pqstm_object_free(void *o TSRMLS_DC)
521 {
522 php_pqstm_object_t *obj = o;
523
524 if (obj->intern) {
525 php_pq_object_delref(obj->intern->conn TSRMLS_CC);
526 efree(obj->intern->name);
527 efree(obj->intern);
528 obj->intern = NULL;
529 }
530 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
531 efree(obj);
532 }
533
534 static void php_pqtxn_object_free(void *o TSRMLS_DC)
535 {
536 php_pqtxn_object_t *obj = o;
537
538 if (obj->intern) {
539 php_pq_object_delref(obj->intern->conn TSRMLS_CC);
540 efree(obj->intern);
541 obj->intern = NULL;
542 }
543 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
544 efree(obj);
545 }
546
547 static void php_pqcancel_object_free(void *o TSRMLS_DC)
548 {
549 php_pqcancel_object_t *obj = o;
550
551 if (obj->intern) {
552 PQfreeCancel(obj->intern->cancel);
553 php_pq_object_delref(obj->intern->conn TSRMLS_CC);
554 efree(obj->intern);
555 obj->intern = NULL;
556 }
557 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
558 efree(obj);
559 }
560
561 static void php_pqevent_object_free(void *o TSRMLS_DC)
562 {
563 php_pqevent_object_t *obj = o;
564
565 if (obj->intern) {
566 php_pq_callback_dtor(&obj->intern->cb);
567 php_pq_object_delref(obj->intern->conn TSRMLS_CC);
568 efree(obj->intern->type);
569 efree(obj->intern);
570 obj->intern = NULL;
571 }
572 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
573 efree(obj);
574 }
575
576 static void php_pqlob_object_free(void *o TSRMLS_DC)
577 {
578 php_pqlob_object_t *obj = o;
579
580 if (obj->intern) {
581 if (obj->intern->lofd) {
582 lo_close(obj->intern->txn->intern->conn->intern->conn, obj->intern->lofd);
583 }
584 php_pq_object_delref(obj->intern->txn TSRMLS_CC);
585 efree(obj->intern);
586 obj->intern = NULL;
587 }
588 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
589 efree(obj);
590 }
591
592 static zend_object_value php_pqconn_create_object_ex(zend_class_entry *ce, php_pqconn_t *intern, php_pqconn_object_t **ptr TSRMLS_DC)
593 {
594 php_pqconn_object_t *o;
595
596 o = ecalloc(1, sizeof(*o));
597 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
598 object_properties_init((zend_object *) o, ce);
599 o->prophandler = &php_pqconn_object_prophandlers;
600
601 if (ptr) {
602 *ptr = o;
603 }
604
605 if (intern) {
606 o->intern = intern;
607 }
608
609 o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqconn_object_free, NULL TSRMLS_CC);
610 o->zv.handlers = &php_pqconn_object_handlers;
611
612 return o->zv;
613 }
614
615 static zend_object_value php_pqtypes_create_object_ex(zend_class_entry *ce, php_pqtypes_t *intern, php_pqtypes_object_t **ptr TSRMLS_DC)
616 {
617 php_pqtypes_object_t *o;
618
619 o = ecalloc(1, sizeof(*o));
620 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
621 object_properties_init((zend_object *) o, ce);
622 o->prophandler = &php_pqtypes_object_prophandlers;
623
624 if (ptr) {
625 *ptr = o;
626 }
627
628 if (intern) {
629 o->intern = intern;
630 }
631
632 o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqtypes_object_free, NULL TSRMLS_CC);
633 o->zv.handlers = &php_pqtypes_object_handlers;
634
635 return o->zv;
636 }
637
638 static zend_object_value php_pqres_create_object_ex(zend_class_entry *ce, php_pqres_t *intern, php_pqres_object_t **ptr TSRMLS_DC)
639 {
640 php_pqres_object_t *o;
641
642 o = ecalloc(1, sizeof(*o));
643 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
644 object_properties_init((zend_object *) o, ce);
645 o->prophandler = &php_pqres_object_prophandlers;
646
647 if (ptr) {
648 *ptr = o;
649 }
650
651 if (intern) {
652 o->intern = intern;
653 }
654
655 o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqres_object_free, NULL TSRMLS_CC);
656 o->zv.handlers = &php_pqres_object_handlers;
657
658 return o->zv;
659 }
660
661 static zend_object_value php_pqstm_create_object_ex(zend_class_entry *ce, php_pqstm_t *intern, php_pqstm_object_t **ptr TSRMLS_DC)
662 {
663 php_pqstm_object_t *o;
664
665 o = ecalloc(1, sizeof(*o));
666 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
667 object_properties_init((zend_object *) o, ce);
668 o->prophandler = &php_pqstm_object_prophandlers;
669
670 if (ptr) {
671 *ptr = o;
672 }
673
674 if (intern) {
675 o->intern = intern;
676 }
677
678 o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqstm_object_free, NULL TSRMLS_CC);
679 o->zv.handlers = &php_pqstm_object_handlers;
680
681 return o->zv;
682 }
683
684 static zend_object_value php_pqtxn_create_object_ex(zend_class_entry *ce, php_pqtxn_t *intern, php_pqtxn_object_t **ptr TSRMLS_DC)
685 {
686 php_pqtxn_object_t *o;
687
688 o = ecalloc(1, sizeof(*o));
689 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
690 object_properties_init((zend_object *) o, ce);
691 o->prophandler = &php_pqtxn_object_prophandlers;
692
693 if (ptr) {
694 *ptr = o;
695 }
696
697 if (intern) {
698 o->intern = intern;
699 }
700
701 o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqtxn_object_free, NULL TSRMLS_CC);
702 o->zv.handlers = &php_pqtxn_object_handlers;
703
704 return o->zv;
705 }
706
707 static zend_object_value php_pqcancel_create_object_ex(zend_class_entry *ce, php_pqcancel_t *intern, php_pqcancel_object_t **ptr TSRMLS_DC)
708 {
709 php_pqcancel_object_t *o;
710
711 o = ecalloc(1, sizeof(*o));
712 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
713 object_properties_init((zend_object *) o, ce);
714 o->prophandler = &php_pqcancel_object_prophandlers;
715
716 if (ptr) {
717 *ptr = o;
718 }
719
720 if (intern) {
721 o->intern = intern;
722 }
723
724 o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqcancel_object_free, NULL TSRMLS_CC);
725 o->zv.handlers = &php_pqcancel_object_handlers;
726
727 return o->zv;
728 }
729
730 static zend_object_value php_pqevent_create_object_ex(zend_class_entry *ce, php_pqevent_t *intern, php_pqevent_object_t **ptr TSRMLS_DC)
731 {
732 php_pqevent_object_t *o;
733
734 o = ecalloc(1, sizeof(*o));
735 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
736 object_properties_init((zend_object *) o, ce);
737 o->prophandler = &php_pqevent_object_prophandlers;
738
739 if (ptr) {
740 *ptr = o;
741 }
742
743 if (intern) {
744 o->intern = intern;
745 }
746
747 o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqevent_object_free, NULL TSRMLS_CC);
748 o->zv.handlers = &php_pqevent_object_handlers;
749
750 return o->zv;
751 }
752
753 static zend_object_value php_pqlob_create_object_ex(zend_class_entry *ce, php_pqlob_t *intern, php_pqlob_object_t **ptr TSRMLS_DC)
754 {
755 php_pqlob_object_t *o;
756
757 o = ecalloc(1, sizeof(*o));
758 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
759 object_properties_init((zend_object *) o, ce);
760 o->prophandler = &php_pqlob_object_prophandlers;
761
762 if (ptr) {
763 *ptr = o;
764 }
765
766 if (intern) {
767 o->intern = intern;
768 }
769
770 o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqlob_object_free, NULL TSRMLS_CC);
771 o->zv.handlers = &php_pqlob_object_handlers;
772
773 return o->zv;
774 }
775
776 static zend_object_value php_pqconn_create_object(zend_class_entry *class_type TSRMLS_DC)
777 {
778 return php_pqconn_create_object_ex(class_type, NULL, NULL TSRMLS_CC);
779 }
780
781 static zend_object_value php_pqtypes_create_object(zend_class_entry *class_type TSRMLS_DC)
782 {
783 return php_pqtypes_create_object_ex(class_type, NULL, NULL TSRMLS_CC);
784 }
785
786 static zend_object_value php_pqres_create_object(zend_class_entry *class_type TSRMLS_DC)
787 {
788 return php_pqres_create_object_ex(class_type, NULL, NULL TSRMLS_CC);
789 }
790
791 static zend_object_value php_pqstm_create_object(zend_class_entry *class_type TSRMLS_DC)
792 {
793 return php_pqstm_create_object_ex(class_type, NULL, NULL TSRMLS_CC);
794 }
795
796 static zend_object_value php_pqtxn_create_object(zend_class_entry *class_type TSRMLS_DC)
797 {
798 return php_pqtxn_create_object_ex(class_type, NULL, NULL TSRMLS_CC);
799 }
800
801 static zend_object_value php_pqcancel_create_object(zend_class_entry *class_type TSRMLS_DC)
802 {
803 return php_pqcancel_create_object_ex(class_type, NULL, NULL TSRMLS_CC);
804 }
805
806 static zend_object_value php_pqevent_create_object(zend_class_entry *class_type TSRMLS_DC)
807 {
808 return php_pqevent_create_object_ex(class_type, NULL, NULL TSRMLS_CC);
809 }
810
811 static zend_object_value php_pqlob_create_object(zend_class_entry *class_type TSRMLS_DC)
812 {
813 return php_pqlob_create_object_ex(class_type, NULL, NULL TSRMLS_CC);
814 }
815
816 static int apply_ph_to_debug(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
817 {
818 php_pq_object_prophandler_t *ph = p;
819 HashTable *ht = va_arg(argv, HashTable *);
820 zval **return_value, *object = va_arg(argv, zval *);
821 php_pq_object_t *obj = va_arg(argv, php_pq_object_t *);
822
823 if (SUCCESS == zend_hash_find(ht, key->arKey, key->nKeyLength, (void *) &return_value)) {
824
825 if (ph->read) {
826 zval_ptr_dtor(return_value);
827 MAKE_STD_ZVAL(*return_value);
828 ZVAL_NULL(*return_value);
829
830 ph->read(object, obj, *return_value TSRMLS_CC);
831 }
832 }
833
834 return ZEND_HASH_APPLY_KEEP;
835 }
836
837 static int apply_pi_to_debug(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
838 {
839 zend_property_info *pi = p;
840 HashTable *ht = va_arg(argv, HashTable *);
841 zval *object = va_arg(argv, zval *);
842 php_pq_object_t *obj = va_arg(argv, php_pq_object_t *);
843 zval *property = zend_read_property(obj->zo.ce, object, pi->name, pi->name_length, 0 TSRMLS_CC);
844
845 if (!Z_REFCOUNT_P(property)) {
846 Z_ADDREF_P(property);
847 }
848 zend_hash_add(ht, pi->name, pi->name_length + 1, (void *) &property, sizeof(zval *), NULL);
849
850 return ZEND_HASH_APPLY_KEEP;
851 }
852
853 static HashTable *php_pq_object_debug_info(zval *object, int *temp TSRMLS_DC)
854 {
855 HashTable *ht;
856 php_pq_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
857
858 *temp = 1;
859 ALLOC_HASHTABLE(ht);
860 ZEND_INIT_SYMTABLE(ht);
861
862 zend_hash_apply_with_arguments(&obj->zo.ce->properties_info TSRMLS_CC, apply_pi_to_debug, 3, ht, object, obj);
863 zend_hash_apply_with_arguments(obj->prophandler TSRMLS_CC, apply_ph_to_debug, 3, ht, object, obj);
864
865 return ht;
866 }
867
868 static void php_pqconn_object_read_status(zval *object, void *o, zval *return_value TSRMLS_DC)
869 {
870 php_pqconn_object_t *obj = o;
871
872 RETVAL_LONG(PQstatus(obj->intern->conn));
873 }
874
875 static void php_pqconn_object_read_transaction_status(zval *object, void *o, zval *return_value TSRMLS_DC)
876 {
877 php_pqconn_object_t *obj = o;
878
879 RETVAL_LONG(PQtransactionStatus(obj->intern->conn));
880 }
881
882 static void php_pqconn_object_read_error_message(zval *object, void *o, zval *return_value TSRMLS_DC)
883 {
884 php_pqconn_object_t *obj = o;
885 char *error = PHP_PQerrorMessage(obj->intern->conn);
886
887 if (error) {
888 RETVAL_STRING(error, 1);
889 } else {
890 RETVAL_NULL();
891 }
892 }
893
894 static int apply_notify_listener(void *p, void *arg TSRMLS_DC)
895 {
896 php_pq_callback_t *listener = p;
897 PGnotify *nfy = arg;
898 zval *zpid, *zchannel, *zmessage;
899
900 MAKE_STD_ZVAL(zpid);
901 ZVAL_LONG(zpid, nfy->be_pid);
902 MAKE_STD_ZVAL(zchannel);
903 ZVAL_STRING(zchannel, nfy->relname, 1);
904 MAKE_STD_ZVAL(zmessage);
905 ZVAL_STRING(zmessage, nfy->extra, 1);
906
907 zend_fcall_info_argn(&listener->fci TSRMLS_CC, 3, &zchannel, &zmessage, &zpid);
908 zend_fcall_info_call(&listener->fci, &listener->fcc, NULL, NULL TSRMLS_CC);
909
910 zval_ptr_dtor(&zchannel);
911 zval_ptr_dtor(&zmessage);
912 zval_ptr_dtor(&zpid);
913
914 return ZEND_HASH_APPLY_KEEP;
915 }
916
917 static int apply_notify_listeners(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
918 {
919 HashTable *listeners = p;
920 PGnotify *nfy = va_arg(argv, PGnotify *);
921
922 if (0 == fnmatch(key->arKey, nfy->relname, 0)) {
923 zend_hash_apply_with_argument(listeners, apply_notify_listener, nfy TSRMLS_CC);
924 }
925
926 return ZEND_HASH_APPLY_KEEP;
927 }
928
929 static void php_pqconn_notify_listeners(php_pqconn_object_t *obj TSRMLS_DC)
930 {
931 PGnotify *nfy;
932
933 while ((nfy = PQnotifies(obj->intern->conn))) {
934 zend_hash_apply_with_arguments(&obj->intern->listeners TSRMLS_CC, apply_notify_listeners, 1, nfy);
935 PQfreemem(nfy);
936 }
937 }
938
939 static void php_pqconn_object_read_busy(zval *object, void *o, zval *return_value TSRMLS_DC)
940 {
941 php_pqconn_object_t *obj = o;
942
943 RETVAL_BOOL(PQisBusy(obj->intern->conn));
944 }
945
946 static void php_pqconn_object_read_encoding(zval *object, void *o, zval *return_value TSRMLS_DC)
947 {
948 php_pqconn_object_t *obj = o;
949
950 RETVAL_STRING(pg_encoding_to_char(PQclientEncoding(obj->intern->conn)), 1);
951 }
952
953 static void php_pqconn_object_write_encoding(zval *object, void *o, zval *value TSRMLS_DC)
954 {
955 php_pqconn_object_t *obj = o;
956 zval *zenc = value;
957
958 if (Z_TYPE_P(value) != IS_STRING) {
959 convert_to_string_ex(&zenc);
960 }
961
962 if (0 > PQsetClientEncoding(obj->intern->conn, Z_STRVAL_P(zenc))) {
963 zend_error(E_NOTICE, "Unrecognized encoding '%s'", Z_STRVAL_P(zenc));
964 }
965
966 if (zenc != value) {
967 zval_ptr_dtor(&zenc);
968 }
969 }
970
971 static void php_pqconn_object_read_unbuffered(zval *object, void *o, zval *return_value TSRMLS_DC)
972 {
973 php_pqconn_object_t *obj = o;
974
975 RETVAL_BOOL(obj->intern->unbuffered);
976 }
977
978 static void php_pqconn_object_write_unbuffered(zval *object, void *o, zval *value TSRMLS_DC)
979 {
980 php_pqconn_object_t *obj = o;
981
982 obj->intern->unbuffered = zend_is_true(value);
983 }
984
985 static void php_pqconn_object_read_db(zval *objec, void *o, zval *return_value TSRMLS_DC)
986 {
987 php_pqconn_object_t *obj = o;
988 char *db = PQdb(obj->intern->conn);
989
990 if (db) {
991 RETVAL_STRING(db, 1);
992 } else {
993 RETVAL_EMPTY_STRING();
994 }
995 }
996
997 static void php_pqconn_object_read_user(zval *objec, void *o, zval *return_value TSRMLS_DC)
998 {
999 php_pqconn_object_t *obj = o;
1000 char *user = PQuser(obj->intern->conn);
1001
1002 if (user) {
1003 RETVAL_STRING(user, 1);
1004 } else {
1005 RETVAL_EMPTY_STRING();
1006 }
1007 }
1008
1009 static void php_pqconn_object_read_pass(zval *objec, void *o, zval *return_value TSRMLS_DC)
1010 {
1011 php_pqconn_object_t *obj = o;
1012 char *pass = PQpass(obj->intern->conn);
1013
1014 if (pass) {
1015 RETVAL_STRING(pass, 1);
1016 } else {
1017 RETVAL_EMPTY_STRING();
1018 }
1019 }
1020
1021 static void php_pqconn_object_read_host(zval *objec, void *o, zval *return_value TSRMLS_DC)
1022 {
1023 php_pqconn_object_t *obj = o;
1024 char *host = PQhost(obj->intern->conn);
1025
1026 if (host) {
1027 RETVAL_STRING(host, 1);
1028 } else {
1029 RETVAL_EMPTY_STRING();
1030 }
1031 }
1032
1033 static void php_pqconn_object_read_port(zval *objec, void *o, zval *return_value TSRMLS_DC)
1034 {
1035 php_pqconn_object_t *obj = o;
1036 char *port = PQport(obj->intern->conn);
1037
1038 if (port) {
1039 RETVAL_STRING(port, 1);
1040 } else {
1041 RETVAL_EMPTY_STRING();
1042 }
1043 }
1044
1045 static void php_pqconn_object_read_options(zval *objec, void *o, zval *return_value TSRMLS_DC)
1046 {
1047 php_pqconn_object_t *obj = o;
1048 char *options = PQoptions(obj->intern->conn);
1049
1050 if (options) {
1051 RETVAL_STRING(options, 1);
1052 } else {
1053 RETVAL_EMPTY_STRING();
1054 }
1055 }
1056
1057 static void php_pqtypes_object_read_connection(zval *object, void *o, zval *return_value TSRMLS_DC)
1058 {
1059 php_pqtypes_object_t *obj = o;
1060
1061 php_pq_object_to_zval(obj->intern->conn, &return_value TSRMLS_CC);
1062 }
1063
1064 static int has_dimension(HashTable *ht, zval *member, char **key_str, int *key_len, long *index TSRMLS_DC)
1065 {
1066 long lval = 0;
1067 zval *tmp = member;
1068
1069 switch (Z_TYPE_P(member)) {
1070 default:
1071 convert_to_string_ex(&tmp);
1072 /* no break */
1073 case IS_STRING:
1074 if (!is_numeric_string(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), &lval, NULL, 0)) {
1075 if (member != tmp) {
1076 zval_ptr_dtor(&tmp);
1077 }
1078 if (key_str) {
1079 *key_str = estrndup(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
1080 if (key_len) {
1081 *key_len = Z_STRLEN_P(tmp) + 1;
1082 }
1083 }
1084 return zend_hash_exists(ht, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp) + 1);
1085 }
1086 /* no break */
1087 case IS_LONG:
1088 lval = Z_LVAL_P(member);
1089 break;
1090 }
1091
1092 if (member != tmp) {
1093 zval_ptr_dtor(&tmp);
1094 }
1095 if (index) {
1096 *index = lval;
1097 }
1098 return zend_hash_index_exists(ht, lval);
1099 }
1100
1101 static int php_pqtypes_object_has_dimension(zval *object, zval *member, int check_empty TSRMLS_DC)
1102 {
1103 php_pqtypes_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
1104 char *key_str = NULL;
1105 int key_len = 0;
1106 long index = 0;
1107
1108 if (check_empty) {
1109 if (has_dimension(&obj->intern->types, member, &key_str, &key_len, &index TSRMLS_CC)) {
1110 zval **data;
1111
1112 if (key_str && key_len) {
1113 if (SUCCESS == zend_hash_find(&obj->intern->types, key_str, key_len, (void *) &data)) {
1114 efree(key_str);
1115 return Z_TYPE_PP(data) != IS_NULL;
1116 }
1117 efree(key_str);
1118 } else {
1119 if (SUCCESS == zend_hash_index_find(&obj->intern->types, index, (void *) data)) {
1120 return Z_TYPE_PP(data) != IS_NULL;
1121 }
1122 }
1123 }
1124 } else {
1125 return has_dimension(&obj->intern->types, member, NULL, NULL, NULL TSRMLS_CC);
1126 }
1127
1128 return 0;
1129 }
1130
1131 static zval *php_pqtypes_object_read_dimension(zval *object, zval *member, int type TSRMLS_DC)
1132 {
1133 long index = 0;
1134 char *key_str = NULL;
1135 int key_len = 0;
1136 php_pqtypes_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
1137
1138 if (has_dimension(&obj->intern->types, member, &key_str, &key_len, &index TSRMLS_CC)) {
1139 zval **data;
1140
1141 if (key_str && key_len) {
1142 if (SUCCESS == zend_hash_find(&obj->intern->types, key_str, key_len, (void *) &data)) {
1143 efree(key_str);
1144 return *data;
1145 }
1146 } else {
1147 if (SUCCESS == zend_hash_index_find(&obj->intern->types, index, (void *) &data)) {
1148 return *data;
1149 }
1150 }
1151 }
1152
1153 return NULL;
1154 }
1155
1156 static void php_pqres_object_read_status(zval *object, void *o, zval *return_value TSRMLS_DC)
1157 {
1158 php_pqres_object_t *obj = o;
1159
1160 RETVAL_LONG(PQresultStatus(obj->intern->res));
1161 }
1162
1163 static void php_pqres_object_read_error_message(zval *object, void *o, zval *return_value TSRMLS_DC)
1164 {
1165 php_pqres_object_t *obj = o;
1166 char *error = PQresultErrorMessage(obj->intern->res);
1167
1168 if (error) {
1169 RETVAL_STRING(error, 1);
1170 } else {
1171 RETVAL_NULL();
1172 }
1173 }
1174
1175 static void php_pqres_object_read_num_rows(zval *object, void *o, zval *return_value TSRMLS_DC)
1176 {
1177 php_pqres_object_t *obj = o;
1178
1179 RETVAL_LONG(PQntuples(obj->intern->res));
1180 }
1181
1182 static void php_pqres_object_read_num_cols(zval *object, void *o, zval *return_value TSRMLS_DC)
1183 {
1184 php_pqres_object_t *obj = o;
1185
1186 RETVAL_LONG(PQnfields(obj->intern->res));
1187 }
1188
1189 static void php_pqres_object_read_affected_rows(zval *object, void *o, zval *return_value TSRMLS_DC)
1190 {
1191 php_pqres_object_t *obj = o;
1192
1193 RETVAL_LONG(atoi(PQcmdTuples(obj->intern->res)));
1194 }
1195
1196 static void php_pqres_object_read_fetch_type(zval *object, void *o, zval *return_value TSRMLS_DC)
1197 {
1198 php_pqres_object_t *obj = o;
1199
1200 if (obj->intern->iter) {
1201 RETVAL_LONG(obj->intern->iter->fetch_type);
1202 } else {
1203 RETVAL_LONG(PHP_PQRES_FETCH_ARRAY);
1204 }
1205 }
1206
1207 static void php_pqres_object_write_fetch_type(zval *object, void *o, zval *value TSRMLS_DC)
1208 {
1209 php_pqres_object_t *obj = o;
1210 zval *zfetch_type = value;
1211
1212 if (Z_TYPE_P(zfetch_type) != IS_LONG) {
1213 convert_to_long_ex(&zfetch_type);
1214 }
1215
1216 if (!obj->intern->iter) {
1217 obj->intern->iter = (php_pqres_iterator_t *) php_pqres_iterator_init(Z_OBJCE_P(object), object, 0 TSRMLS_CC);
1218 obj->intern->iter->zi.funcs->rewind((zend_object_iterator *) obj->intern->iter TSRMLS_CC);
1219 }
1220 obj->intern->iter->fetch_type = Z_LVAL_P(zfetch_type);
1221
1222 if (zfetch_type != value) {
1223 zval_ptr_dtor(&zfetch_type);
1224 }
1225 }
1226
1227 static void php_pqstm_object_read_name(zval *object, void *o, zval *return_value TSRMLS_DC)
1228 {
1229 php_pqstm_object_t *obj = o;
1230
1231 RETVAL_STRING(obj->intern->name, 1);
1232 }
1233
1234 static void php_pqstm_object_read_connection(zval *object, void *o, zval *return_value TSRMLS_DC)
1235 {
1236 php_pqstm_object_t *obj = o;
1237
1238 php_pq_object_to_zval(obj->intern->conn, &return_value TSRMLS_CC);
1239 }
1240
1241 static void php_pqtxn_object_read_connection(zval *object, void *o, zval *return_value TSRMLS_DC)
1242 {
1243 php_pqtxn_object_t *obj = o;
1244
1245 php_pq_object_to_zval(obj->intern->conn, &return_value TSRMLS_CC);
1246 }
1247
1248 static void php_pqtxn_object_read_isolation(zval *object, void *o, zval *return_value TSRMLS_DC)
1249 {
1250 php_pqtxn_object_t *obj = o;
1251
1252 RETVAL_LONG(obj->intern->isolation);
1253 }
1254
1255 static void php_pqtxn_object_read_readonly(zval *object, void *o, zval *return_value TSRMLS_DC)
1256 {
1257 php_pqtxn_object_t *obj = o;
1258
1259 RETVAL_LONG(obj->intern->readonly);
1260 }
1261
1262 static void php_pqtxn_object_read_deferrable(zval *object, void *o, zval *return_value TSRMLS_DC)
1263 {
1264 php_pqtxn_object_t *obj = o;
1265
1266 RETVAL_LONG(obj->intern->deferrable);
1267 }
1268
1269 static void php_pqtxn_object_write_isolation(zval *object, void *o, zval *value TSRMLS_DC)
1270 {
1271 php_pqtxn_object_t *obj = o;
1272 php_pqtxn_isolation_t orig = obj->intern->isolation;
1273 zval *zisolation = value;
1274 PGresult *res;
1275
1276 if (Z_TYPE_P(zisolation) != IS_LONG) {
1277 convert_to_long_ex(&zisolation);
1278 }
1279
1280 switch ((obj->intern->isolation = Z_LVAL_P(zisolation))) {
1281 case PHP_PQTXN_READ_COMMITTED:
1282 res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION READ COMMITED");
1283 break;
1284 case PHP_PQTXN_REPEATABLE_READ:
1285 res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION REPEATABLE READ");
1286 break;
1287 case PHP_PQTXN_SERIALIZABLE:
1288 res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION SERIALIZABLE");
1289 break;
1290 default:
1291 obj->intern->isolation = orig;
1292 res = NULL;
1293 break;
1294 }
1295
1296 if (zisolation != value) {
1297 zval_ptr_dtor(&zisolation);
1298 }
1299
1300 if (res) {
1301 php_pqres_success(res TSRMLS_CC);
1302 PQclear(res);
1303 }
1304 }
1305
1306 static void php_pqtxn_object_write_readonly(zval *object, void *o, zval *value TSRMLS_DC)
1307 {
1308 php_pqtxn_object_t *obj = o;
1309 PGresult *res;
1310
1311 if ((obj->intern->readonly = zend_is_true(value))) {
1312 res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION READ ONLY");
1313 } else {
1314 res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION READ WRITE");
1315 }
1316
1317 if (res) {
1318 php_pqres_success(res TSRMLS_CC);
1319 PQclear(res);
1320 }
1321 }
1322
1323 static void php_pqtxn_object_write_deferrable(zval *object, void *o, zval *value TSRMLS_DC)
1324 {
1325 php_pqtxn_object_t *obj = o;
1326 PGresult *res;
1327
1328 if ((obj->intern->deferrable = zend_is_true(value))) {
1329 res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION DEFERRABLE");
1330 } else {
1331 res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION NOT DEFERRABLE");
1332 }
1333
1334 if (res) {
1335 php_pqres_success(res TSRMLS_CC);
1336 PQclear(res);
1337 }
1338 }
1339
1340 static void php_pqcancel_object_read_connection(zval *object, void *o, zval *return_value TSRMLS_DC)
1341 {
1342 php_pqcancel_object_t *obj = o;
1343
1344 php_pq_object_to_zval(obj->intern->conn, &return_value TSRMLS_CC);
1345 }
1346
1347 static void php_pqevent_object_read_connection(zval *object, void *o, zval *return_value TSRMLS_DC)
1348 {
1349 php_pqevent_object_t *obj = o;
1350
1351 php_pq_object_to_zval(obj->intern->conn, &return_value TSRMLS_CC);
1352 }
1353
1354 static void php_pqevent_object_read_type(zval *object, void *o, zval *return_value TSRMLS_DC)
1355 {
1356 php_pqevent_object_t *obj = o;
1357
1358 RETVAL_STRING(obj->intern->type, 1);
1359 }
1360
1361 static void php_pqlob_object_read_transaction(zval *object, void *o, zval *return_value TSRMLS_DC)
1362 {
1363 php_pqlob_object_t *obj = o;
1364
1365 php_pq_object_to_zval(obj->intern->txn, &return_value TSRMLS_CC);
1366 }
1367
1368 static void php_pqlob_object_read_oid(zval *object, void *o, zval *return_value TSRMLS_DC)
1369 {
1370 php_pqlob_object_t *obj = o;
1371
1372 RETVAL_LONG(obj->intern->loid);
1373 }
1374
1375 static zend_class_entry *ancestor(zend_class_entry *ce) {
1376 while (ce->parent) {
1377 ce = ce->parent;
1378 }
1379 return ce;
1380 }
1381
1382 static zval *php_pq_object_read_prop(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
1383 {
1384 php_pq_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
1385 php_pq_object_prophandler_t *handler;
1386 zval *return_value;
1387
1388 if (!obj->intern) {
1389 zend_error(E_WARNING, "%s not initialized", ancestor(obj->zo.ce)->name);
1390 } else if ((SUCCESS == zend_hash_find(obj->prophandler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void *) &handler)) && handler->read) {
1391 if (type == BP_VAR_R) {
1392 ALLOC_ZVAL(return_value);
1393 Z_SET_REFCOUNT_P(return_value, 0);
1394 Z_UNSET_ISREF_P(return_value);
1395
1396 handler->read(object, obj, return_value TSRMLS_CC);
1397 } else {
1398 zend_error(E_ERROR, "Cannot access %s properties by reference or array key/index", ancestor(obj->zo.ce)->name);
1399 return_value = NULL;
1400 }
1401 } else {
1402 return_value = zend_get_std_object_handlers()->read_property(object, member, type, key TSRMLS_CC);
1403 }
1404
1405 return return_value;
1406 }
1407
1408 static void php_pq_object_write_prop(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
1409 {
1410 php_pq_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
1411 php_pq_object_prophandler_t *handler;
1412
1413 if (SUCCESS == zend_hash_find(obj->prophandler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void *) &handler)) {
1414 if (handler->write) {
1415 handler->write(object, obj, value TSRMLS_CC);
1416 }
1417 } else {
1418 zend_get_std_object_handlers()->write_property(object, member, value, key TSRMLS_CC);
1419 }
1420 }
1421
1422 static STATUS php_pqconn_update_socket(zval *this_ptr, php_pqconn_object_t *obj TSRMLS_DC)
1423 {
1424 zval *zsocket, zmember;
1425 php_stream *stream;
1426 STATUS retval;
1427 int socket;
1428
1429 if (!obj) {
1430 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1431 }
1432
1433 INIT_PZVAL(&zmember);
1434 ZVAL_STRINGL(&zmember, "socket", sizeof("socket")-1, 0);
1435 MAKE_STD_ZVAL(zsocket);
1436
1437 if ((CONNECTION_BAD != PQstatus(obj->intern->conn))
1438 && (-1 < (socket = PQsocket(obj->intern->conn)))
1439 && (stream = php_stream_fopen_from_fd(socket, "r+b", NULL))) {
1440 php_stream_to_zval(stream, zsocket);
1441 retval = SUCCESS;
1442 } else {
1443 ZVAL_NULL(zsocket);
1444 retval = FAILURE;
1445 }
1446 zend_get_std_object_handlers()->write_property(getThis(), &zmember, zsocket, NULL TSRMLS_CC);
1447 zval_ptr_dtor(&zsocket);
1448
1449 return retval;
1450 }
1451
1452 #ifdef ZTS
1453 # define TSRMLS_DF(d) TSRMLS_D = (d)->ts
1454 # define TSRMLS_CF(d) (d)->ts = TSRMLS_C
1455 #else
1456 # define TSRMLS_DF(d)
1457 # define TSRMLS_CF(d)
1458 #endif
1459
1460 static void php_pqconn_event_register(PGEventRegister *event, php_pqconn_event_data_t *data)
1461 {
1462 PQsetInstanceData(event->conn, php_pqconn_event, data);
1463 }
1464
1465 static void php_pqconn_event_conndestroy(PGEventConnDestroy *event, php_pqconn_event_data_t *data)
1466 {
1467 PQsetInstanceData(event->conn, php_pqconn_event, NULL);
1468 efree(data);
1469 }
1470
1471 static int apply_event(void *p, void *a TSRMLS_DC)
1472 {
1473 zval **evh = p;
1474 zval *args = a;
1475 zval *retval = NULL;
1476
1477 zend_call_method_with_1_params(evh, Z_OBJCE_PP(evh), NULL, "trigger", &retval, args);
1478 if (retval) {
1479 zval_ptr_dtor(&retval);
1480 }
1481
1482 return ZEND_HASH_APPLY_KEEP;
1483 }
1484
1485 static void php_pqconn_event_connreset(PGEventConnReset *event, php_pqconn_event_data_t *data)
1486 {
1487 zval **evhs;
1488 TSRMLS_DF(data);
1489
1490 if (SUCCESS == zend_hash_find(&data->obj->intern->eventhandlers, ZEND_STRS("reset"), (void *) &evhs)) {
1491 zval *args, *connection = NULL;
1492
1493 MAKE_STD_ZVAL(args);
1494 array_init(args);
1495 php_pq_object_to_zval(data->obj, &connection TSRMLS_CC);
1496 add_next_index_zval(args, connection);
1497 zend_hash_apply_with_argument(Z_ARRVAL_PP(evhs), apply_event, args TSRMLS_CC);
1498 zval_ptr_dtor(&args);
1499 }
1500 }
1501
1502 static zval *result_instance_zval(PGresult *res TSRMLS_DC)
1503 {
1504 zval *rid = PQresultInstanceData(res, php_pqconn_event);
1505
1506 if (!rid) {
1507 php_pqres_t *r = ecalloc(1, sizeof(*r));
1508
1509 MAKE_STD_ZVAL(rid);
1510 r->res = res;
1511 rid->type = IS_OBJECT;
1512 rid->value.obj = php_pqres_create_object_ex(php_pqres_class_entry, r, NULL TSRMLS_CC);
1513
1514 PQresultSetInstanceData(res, php_pqconn_event, rid);
1515 }
1516
1517 Z_ADDREF_P(rid);
1518 return rid;
1519 }
1520
1521 static void php_pqconn_event_resultcreate(PGEventResultCreate *event, php_pqconn_event_data_t *data)
1522 {
1523 zval **evhs;
1524 TSRMLS_DF(data);
1525
1526 /* event listener */
1527 if (SUCCESS == zend_hash_find(&data->obj->intern->eventhandlers, ZEND_STRS("result"), (void *) &evhs)) {
1528 zval *args, *connection = NULL, *res = result_instance_zval(event->result TSRMLS_CC);
1529
1530 MAKE_STD_ZVAL(args);
1531 array_init(args);
1532 php_pq_object_to_zval(data->obj, &connection TSRMLS_CC);
1533 add_next_index_zval(args, connection);
1534 add_next_index_zval(args, res);
1535 zend_hash_apply_with_argument(Z_ARRVAL_PP(evhs), apply_event, args TSRMLS_CC);
1536 zval_ptr_dtor(&args);
1537 }
1538
1539 /* async callback */
1540 if (data->obj->intern->onevent.fci.size > 0) {
1541 zval *res = result_instance_zval(event->result TSRMLS_CC);
1542
1543 zend_fcall_info_argn(&data->obj->intern->onevent.fci TSRMLS_CC, 1, &res);
1544 zend_fcall_info_call(&data->obj->intern->onevent.fci, &data->obj->intern->onevent.fcc, NULL, NULL TSRMLS_CC);
1545 zval_ptr_dtor(&res);
1546 }
1547 }
1548
1549 static int php_pqconn_event(PGEventId id, void *e, void *data)
1550 {
1551 switch (id) {
1552 case PGEVT_REGISTER:
1553 php_pqconn_event_register(e, data);
1554 break;
1555 case PGEVT_CONNDESTROY:
1556 php_pqconn_event_conndestroy(e, data);
1557 break;
1558 case PGEVT_CONNRESET:
1559 php_pqconn_event_connreset(e, data);
1560 break;
1561 case PGEVT_RESULTCREATE:
1562 php_pqconn_event_resultcreate(e, data);
1563 break;
1564 default:
1565 break;
1566 }
1567
1568 return 1;
1569 }
1570
1571 static php_pqconn_event_data_t *php_pqconn_event_data_init(php_pqconn_object_t *obj TSRMLS_DC)
1572 {
1573 php_pqconn_event_data_t *data = emalloc(sizeof(*data));
1574
1575 data->obj = obj;
1576 TSRMLS_CF(data);
1577
1578 return data;
1579 }
1580
1581 static void php_pqconn_notice_recv(void *p, const PGresult *res)
1582 {
1583 php_pqconn_event_data_t *data = p;
1584 zval **evhs;
1585 TSRMLS_DF(data);
1586
1587 if (SUCCESS == zend_hash_find(&data->obj->intern->eventhandlers, ZEND_STRS("notice"), (void *) &evhs)) {
1588 zval *args, *connection = NULL;
1589
1590 MAKE_STD_ZVAL(args);
1591 array_init(args);
1592 php_pq_object_to_zval(data->obj, &connection TSRMLS_CC);
1593 add_next_index_zval(args, connection);
1594 add_next_index_string(args, PQresultErrorMessage(res), 1);
1595 zend_hash_apply_with_argument(Z_ARRVAL_PP(evhs), apply_event, args TSRMLS_CC);
1596 zval_ptr_dtor(&args);
1597 }
1598 }
1599
1600 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_construct, 0, 0, 1)
1601 ZEND_ARG_INFO(0, dsn)
1602 ZEND_ARG_INFO(0, async)
1603 ZEND_END_ARG_INFO();
1604 static PHP_METHOD(pqconn, __construct) {
1605 zend_error_handling zeh;
1606 char *dsn_str = "";
1607 int dsn_len = 0;
1608 zend_bool async = 0;
1609
1610 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
1611 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sb", &dsn_str, &dsn_len, &async)) {
1612 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1613 php_pqconn_event_data_t *data = php_pqconn_event_data_init(obj TSRMLS_CC);
1614
1615 obj->intern = ecalloc(1, sizeof(*obj->intern));
1616
1617 zend_hash_init(&obj->intern->listeners, 0, NULL, (dtor_func_t) zend_hash_destroy, 0);
1618 zend_hash_init(&obj->intern->eventhandlers, 0, NULL, ZVAL_PTR_DTOR, 0);
1619
1620
1621 if (async) {
1622 obj->intern->conn = PQconnectStart(dsn_str);
1623 obj->intern->poller = (int (*)(PGconn*)) PQconnectPoll;
1624 } else {
1625 obj->intern->conn = PQconnectdb(dsn_str);
1626 }
1627
1628 PQsetNoticeReceiver(obj->intern->conn, php_pqconn_notice_recv, data);
1629 PQregisterEventProc(obj->intern->conn, php_pqconn_event, "ext-pq", data);
1630
1631 if (SUCCESS != php_pqconn_update_socket(getThis(), obj TSRMLS_CC)) {
1632 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection failed (%s)", PHP_PQerrorMessage(obj->intern->conn));
1633 }
1634 }
1635 zend_restore_error_handling(&zeh TSRMLS_CC);
1636 }
1637
1638 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_reset, 0, 0, 0)
1639 ZEND_END_ARG_INFO();
1640 static PHP_METHOD(pqconn, reset) {
1641 if (SUCCESS == zend_parse_parameters_none()) {
1642 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1643
1644 if (obj->intern) {
1645 PQreset(obj->intern->conn);
1646
1647 if (CONNECTION_OK == PQstatus(obj->intern->conn)) {
1648 RETURN_TRUE;
1649 } else {
1650 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection reset failed: (%s)", PHP_PQerrorMessage(obj->intern->conn));
1651 }
1652 } else {
1653 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
1654 }
1655 RETURN_FALSE;
1656 }
1657 }
1658
1659 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_reset_async, 0, 0, 0)
1660 ZEND_END_ARG_INFO();
1661 static PHP_METHOD(pqconn, resetAsync) {
1662 if (SUCCESS == zend_parse_parameters_none()) {
1663 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1664
1665 if (obj->intern) {
1666 if (PQresetStart(obj->intern->conn)) {
1667 obj->intern->poller = (int (*)(PGconn*)) PQresetPoll;
1668 RETURN_TRUE;
1669 }
1670 } else {
1671 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
1672 }
1673 RETURN_FALSE;
1674 }
1675 }
1676
1677 static void php_pqconn_add_listener(php_pqconn_object_t *obj, const char *channel_str, size_t channel_len, php_pq_callback_t *listener TSRMLS_DC)
1678 {
1679 HashTable ht, *existing_listeners;
1680
1681 php_pq_callback_addref(listener);
1682
1683 if (SUCCESS == zend_hash_find(&obj->intern->listeners, channel_str, channel_len + 1, (void *) &existing_listeners)) {
1684 zend_hash_next_index_insert(existing_listeners, (void *) listener, sizeof(*listener), NULL);
1685 } else {
1686 zend_hash_init(&ht, 1, NULL, (dtor_func_t) php_pq_callback_dtor, 0);
1687 zend_hash_next_index_insert(&ht, (void *) listener, sizeof(*listener), NULL);
1688 zend_hash_add(&obj->intern->listeners, channel_str, channel_len + 1, (void *) &ht, sizeof(HashTable), NULL);
1689 }
1690 }
1691
1692 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_listen, 0, 0, 0)
1693 ZEND_ARG_INFO(0, channel)
1694 ZEND_ARG_INFO(0, callable)
1695 ZEND_END_ARG_INFO();
1696 static PHP_METHOD(pqconn, listen) {
1697 char *channel_str = NULL;
1698 int channel_len = 0;
1699 php_pq_callback_t listener;
1700
1701 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sf", &channel_str, &channel_len, &listener.fci, &listener.fcc)) {
1702 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1703
1704 obj->intern->poller = PQconsumeInput;
1705
1706 if (obj->intern) {
1707 char *quoted_channel = PQescapeIdentifier(obj->intern->conn, channel_str, channel_len);
1708
1709 if (quoted_channel) {
1710 PGresult *res;
1711 char *cmd;
1712
1713 spprintf(&cmd, 0, "LISTEN %s", channel_str);
1714 res = PQexec(obj->intern->conn, cmd);
1715
1716 efree(cmd);
1717 PQfreemem(quoted_channel);
1718
1719 if (res) {
1720 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
1721 php_pqconn_add_listener(obj, channel_str, channel_len, &listener TSRMLS_CC);
1722 RETVAL_TRUE;
1723 } else {
1724 RETVAL_FALSE;
1725 }
1726 PQclear(res);
1727 } else {
1728 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not install listener (%s)", PHP_PQerrorMessage(obj->intern->conn));
1729 RETVAL_FALSE;
1730 }
1731
1732 php_pqconn_notify_listeners(obj TSRMLS_CC);
1733 } else {
1734 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not escape channel identifier (%s)", PHP_PQerrorMessage(obj->intern->conn));
1735 }
1736 } else {
1737 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
1738 RETVAL_FALSE;
1739 }
1740 }
1741 }
1742
1743 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_notify, 0, 0, 2)
1744 ZEND_ARG_INFO(0, channel)
1745 ZEND_ARG_INFO(0, message)
1746 ZEND_END_ARG_INFO();
1747 static PHP_METHOD(pqconn, notify) {
1748 char *channel_str, *message_str;
1749 int channel_len, message_len;
1750
1751 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &channel_str, &channel_len, &message_str, &message_len)) {
1752 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1753
1754 if (obj->intern) {
1755 PGresult *res;
1756 char *params[2] = {channel_str, message_str};
1757
1758 res = PQexecParams(obj->intern->conn, "select pg_notify($1, $2)", 2, NULL, (const char *const*) params, NULL, NULL, 0);
1759
1760 if (res) {
1761 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
1762 RETVAL_TRUE;
1763 } else {
1764 RETVAL_FALSE;
1765 }
1766 PQclear(res);
1767 } else {
1768 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not notify listeners (%s)", PHP_PQerrorMessage(obj->intern->conn));
1769 RETVAL_FALSE;
1770 }
1771
1772 php_pqconn_notify_listeners(obj TSRMLS_CC);
1773
1774 } else {
1775 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
1776 RETVAL_FALSE;
1777 }
1778 }
1779 }
1780
1781 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_poll, 0, 0, 0)
1782 ZEND_END_ARG_INFO();
1783 static PHP_METHOD(pqconn, poll) {
1784 if (SUCCESS == zend_parse_parameters_none()) {
1785 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1786
1787 if (obj->intern) {
1788 if (obj->intern->poller) {
1789 if (obj->intern->poller == PQconsumeInput) {
1790 RETVAL_LONG(obj->intern->poller(obj->intern->conn) * PGRES_POLLING_OK);
1791 php_pqconn_notify_listeners(obj TSRMLS_CC);
1792 return;
1793 } else {
1794 RETURN_LONG(obj->intern->poller(obj->intern->conn));
1795 }
1796 } else {
1797 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No asynchronous operation active");
1798 }
1799 } else {
1800 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
1801 }
1802 RETURN_FALSE;
1803 }
1804 }
1805
1806 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec, 0, 0, 1)
1807 ZEND_ARG_INFO(0, query)
1808 ZEND_END_ARG_INFO();
1809 static PHP_METHOD(pqconn, exec) {
1810 zend_error_handling zeh;
1811 char *query_str;
1812 int query_len;
1813
1814 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
1815 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &query_str, &query_len)) {
1816 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1817
1818 if (obj->intern) {
1819 PGresult *res = PQexec(obj->intern->conn, query_str);
1820
1821 php_pqconn_notify_listeners(obj TSRMLS_CC);
1822
1823 if (res) {
1824 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
1825 php_pqres_t *r = ecalloc(1, sizeof(*r));
1826
1827 r->res = res;
1828 return_value->type = IS_OBJECT;
1829 return_value->value.obj = php_pqres_create_object_ex(php_pqres_class_entry, r, NULL TSRMLS_CC);
1830 }
1831 } else {
1832 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
1833 }
1834 } else {
1835 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
1836 }
1837 }
1838 zend_restore_error_handling(&zeh TSRMLS_CC);
1839 }
1840
1841 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_get_result, 0, 0, 0)
1842 ZEND_END_ARG_INFO();
1843 static PHP_METHOD(pqconn, getResult) {
1844 if (SUCCESS == zend_parse_parameters_none()) {
1845 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1846
1847 if (obj->intern) {
1848 PGresult *res = PQgetResult(obj->intern->conn);
1849
1850 if (res) {
1851 php_pqres_t *r = ecalloc(1, sizeof(*r));
1852
1853 r->res = res;
1854 return_value->type = IS_OBJECT;
1855 return_value->value.obj = php_pqres_create_object_ex(php_pqres_class_entry, r, NULL TSRMLS_CC);
1856 } else {
1857 RETVAL_NULL();
1858 }
1859 } else {
1860 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
1861 RETVAL_FALSE;
1862 }
1863 }
1864 }
1865
1866 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_async, 0, 0, 1)
1867 ZEND_ARG_INFO(0, query)
1868 ZEND_ARG_INFO(0, callable)
1869 ZEND_END_ARG_INFO();
1870 static PHP_METHOD(pqconn, execAsync) {
1871 zend_error_handling zeh;
1872 php_pq_callback_t resolver = {{0}};
1873 char *query_str;
1874 int query_len;
1875
1876 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
1877 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|f", &query_str, &query_len, &resolver.fci, &resolver.fcc)) {
1878 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1879
1880 if (obj->intern) {
1881 php_pq_callback_dtor(&obj->intern->onevent);
1882 if (resolver.fci.size > 0) {
1883 obj->intern->onevent = resolver;
1884 php_pq_callback_addref(&obj->intern->onevent);
1885 }
1886
1887 obj->intern->poller = PQconsumeInput;
1888
1889 if (PQsendQuery(obj->intern->conn, query_str)) {
1890 if (obj->intern->unbuffered) {
1891 if (!PQsetSingleRowMode(obj->intern->conn)) {
1892 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Could not enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn));
1893 }
1894 }
1895 RETVAL_TRUE;
1896 } else {
1897 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
1898 RETVAL_FALSE;
1899 }
1900 } else {
1901 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
1902 RETVAL_FALSE;
1903 }
1904 }
1905 zend_restore_error_handling(&zeh TSRMLS_CC);
1906 }
1907
1908 static int apply_to_oid(void *p, void *arg TSRMLS_DC)
1909 {
1910 Oid **types = arg;
1911 zval **ztype = p;
1912
1913 if (Z_TYPE_PP(ztype) != IS_LONG) {
1914 convert_to_long_ex(ztype);
1915 }
1916
1917 **types = Z_LVAL_PP(ztype);
1918 ++*types;
1919
1920 if (*ztype != *(zval **)p) {
1921 zval_ptr_dtor(ztype);
1922 }
1923 return ZEND_HASH_APPLY_KEEP;
1924 }
1925
1926 static int apply_to_param(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
1927 {
1928 char ***params;
1929 HashTable *zdtor;
1930 zval **zparam = p;
1931
1932 params = (char ***) va_arg(argv, char ***);
1933 zdtor = (HashTable *) va_arg(argv, HashTable *);
1934
1935 if (Z_TYPE_PP(zparam) == IS_NULL) {
1936 **params = NULL;
1937 ++*params;
1938 } else {
1939 if (Z_TYPE_PP(zparam) != IS_STRING) {
1940 convert_to_string_ex(zparam);
1941 }
1942
1943 **params = Z_STRVAL_PP(zparam);
1944 ++*params;
1945
1946 if (*zparam != *(zval **)p) {
1947 zend_hash_next_index_insert(zdtor, zparam, sizeof(zval *), NULL);
1948 }
1949 }
1950 return ZEND_HASH_APPLY_KEEP;
1951 }
1952
1953 static int php_pq_types_to_array(HashTable *ht, Oid **types TSRMLS_DC)
1954 {
1955 int count = zend_hash_num_elements(ht);
1956
1957 *types = NULL;
1958
1959 if (count) {
1960 Oid *tmp;
1961
1962 /* +1 for when less types than params are specified */
1963 *types = tmp = ecalloc(count + 1, sizeof(Oid));
1964 zend_hash_apply_with_argument(ht, apply_to_oid, &tmp TSRMLS_CC);
1965 }
1966
1967 return count;
1968 }
1969
1970 static int php_pq_params_to_array(HashTable *ht, char ***params, HashTable *zdtor TSRMLS_DC)
1971 {
1972 int count = zend_hash_num_elements(ht);
1973
1974 *params = NULL;
1975
1976 if (count) {
1977 char **tmp;
1978
1979 *params = tmp = ecalloc(count, sizeof(char *));
1980 zend_hash_apply_with_arguments(ht TSRMLS_CC, apply_to_param, 2, &tmp, zdtor);
1981 }
1982
1983 return count;
1984 }
1985
1986 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_params, 0, 0, 2)
1987 ZEND_ARG_INFO(0, query)
1988 ZEND_ARG_ARRAY_INFO(0, params, 0)
1989 ZEND_ARG_ARRAY_INFO(0, types, 1)
1990 ZEND_END_ARG_INFO();
1991 static PHP_METHOD(pqconn, execParams) {
1992 zend_error_handling zeh;
1993 char *query_str;
1994 int query_len;
1995 zval *zparams;
1996 zval *ztypes = NULL;
1997
1998 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
1999 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|a/!", &query_str, &query_len, &zparams, &ztypes)) {
2000 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2001
2002 if (obj->intern) {
2003 PGresult *res;
2004 int count;
2005 Oid *types = NULL;
2006 char **params = NULL;
2007 HashTable zdtor;
2008
2009 ZEND_INIT_SYMTABLE(&zdtor);
2010 count = php_pq_params_to_array(Z_ARRVAL_P(zparams), &params, &zdtor TSRMLS_CC);
2011
2012 if (ztypes) {
2013 php_pq_types_to_array(Z_ARRVAL_P(ztypes), &types TSRMLS_CC);
2014 }
2015
2016 res = PQexecParams(obj->intern->conn, query_str, count, types, (const char *const*) params, NULL, NULL, 0);
2017
2018 zend_hash_destroy(&zdtor);
2019 if (types) {
2020 efree(types);
2021 }
2022 if (params) {
2023 efree(params);
2024 }
2025
2026 php_pqconn_notify_listeners(obj TSRMLS_CC);
2027
2028 if (res) {
2029 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
2030 php_pqres_t *r = ecalloc(1, sizeof(*r));
2031
2032 r->res = res;
2033 return_value->type = IS_OBJECT;
2034 return_value->value.obj = php_pqres_create_object_ex(php_pqres_class_entry, r, NULL TSRMLS_CC);
2035 }
2036 } else {
2037 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
2038 RETVAL_FALSE;
2039 }
2040 } else {
2041 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
2042 RETVAL_FALSE;
2043 }
2044 }
2045 zend_restore_error_handling(&zeh TSRMLS_CC);
2046 }
2047
2048 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_params_async, 0, 0, 2)
2049 ZEND_ARG_INFO(0, query)
2050 ZEND_ARG_ARRAY_INFO(0, params, 0)
2051 ZEND_ARG_ARRAY_INFO(0, types, 1)
2052 ZEND_ARG_INFO(0, callable)
2053 ZEND_END_ARG_INFO();
2054 static PHP_METHOD(pqconn, execParamsAsync) {
2055 zend_error_handling zeh;
2056 php_pq_callback_t resolver = {{0}};
2057 char *query_str;
2058 int query_len;
2059 zval *zparams;
2060 zval *ztypes = NULL;
2061
2062 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
2063 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|a/!f", &query_str, &query_len, &zparams, &ztypes, &resolver.fci, &resolver.fcc)) {
2064 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2065
2066 if (obj->intern) {
2067 int count;
2068 Oid *types = NULL;
2069 char **params = NULL;
2070 HashTable zdtor;
2071
2072 ZEND_INIT_SYMTABLE(&zdtor);
2073 count = php_pq_params_to_array(Z_ARRVAL_P(zparams), &params, &zdtor TSRMLS_CC);
2074
2075 if (ztypes) {
2076 php_pq_types_to_array(Z_ARRVAL_P(ztypes), &types TSRMLS_CC);
2077 }
2078
2079 php_pq_callback_dtor(&obj->intern->onevent);
2080 if (resolver.fci.size > 0) {
2081 obj->intern->onevent = resolver;
2082 php_pq_callback_addref(&obj->intern->onevent);
2083 }
2084
2085 obj->intern->poller = PQconsumeInput;
2086
2087 if (PQsendQueryParams(obj->intern->conn, query_str, count, types, (const char *const*) params, NULL, NULL, 0)) {
2088 if (obj->intern->unbuffered) {
2089 if (!PQsetSingleRowMode(obj->intern->conn)) {
2090 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Could not enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn));
2091 }
2092 }
2093 RETVAL_TRUE;
2094 } else {
2095 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
2096 RETVAL_FALSE;
2097 }
2098
2099 zend_hash_destroy(&zdtor);
2100 if (types) {
2101 efree(types);
2102 }
2103 if (params) {
2104 efree(params);
2105 }
2106
2107 php_pqconn_notify_listeners(obj TSRMLS_CC);
2108
2109 } else {
2110 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
2111 RETVAL_FALSE;
2112 }
2113 }
2114 zend_restore_error_handling(&zeh TSRMLS_CC);
2115 }
2116
2117 static STATUS php_pqconn_prepare(zval *object, php_pqconn_object_t *obj, const char *name, const char *query, HashTable *typest TSRMLS_DC)
2118 {
2119 Oid *types = NULL;
2120 int count = 0;
2121 PGresult *res;
2122 STATUS rv;
2123
2124 if (!obj) {
2125 obj = zend_object_store_get_object(object TSRMLS_CC);
2126 }
2127
2128 if (typest) {
2129 count = zend_hash_num_elements(typest);
2130 php_pq_types_to_array(typest, &types TSRMLS_CC);
2131 }
2132
2133 res = PQprepare(obj->intern->conn, name, query, count, types);
2134
2135 if (types) {
2136 efree(types);
2137 }
2138
2139 if (res) {
2140 rv = php_pqres_success(res TSRMLS_CC);
2141 PQclear(res);
2142 } else {
2143 rv = FAILURE;
2144 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not prepare statement (%s)", PHP_PQerrorMessage(obj->intern->conn));
2145 }
2146
2147 return rv;
2148 }
2149
2150 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_prepare, 0, 0, 2)
2151 ZEND_ARG_INFO(0, type)
2152 ZEND_ARG_INFO(0, query)
2153 ZEND_ARG_ARRAY_INFO(0, types, 1)
2154 ZEND_END_ARG_INFO();
2155 static PHP_METHOD(pqconn, prepare) {
2156 zend_error_handling zeh;
2157 zval *ztypes = NULL;
2158 char *name_str, *query_str;
2159 int name_len, *query_len;
2160
2161 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
2162 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!", &name_str, &name_len, &query_str, &query_len, &ztypes)) {
2163 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2164
2165 if (obj->intern) {
2166 if (SUCCESS == php_pqconn_prepare(getThis(), obj, name_str, query_str, ztypes ? Z_ARRVAL_P(ztypes) : NULL TSRMLS_CC)) {
2167 php_pqstm_t *stm = ecalloc(1, sizeof(*stm));
2168
2169 php_pq_object_addref(obj TSRMLS_CC);
2170 stm->conn = obj;
2171 stm->name = estrdup(name_str);
2172
2173 return_value->type = IS_OBJECT;
2174 return_value->value.obj = php_pqstm_create_object_ex(php_pqstm_class_entry, stm, NULL TSRMLS_CC);
2175 }
2176 php_pqconn_notify_listeners(obj TSRMLS_CC);
2177 } else {
2178 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
2179 }
2180 }
2181 zend_restore_error_handling(&zeh TSRMLS_CC);
2182 }
2183
2184 static STATUS php_pqconn_prepare_async(zval *object, php_pqconn_object_t *obj, const char *name, const char *query, HashTable *typest TSRMLS_DC)
2185 {
2186 STATUS rv;
2187 int count;
2188 Oid *types = NULL;
2189
2190 if (!obj) {
2191 obj = zend_object_store_get_object(object TSRMLS_CC);
2192 }
2193
2194 if (typest) {
2195 count = php_pq_types_to_array(typest, &types TSRMLS_CC);
2196 }
2197
2198 if (PQsendPrepare(obj->intern->conn, name, query, count, types)) {
2199 if (obj->intern->unbuffered) {
2200 if (!PQsetSingleRowMode(obj->intern->conn)) {
2201 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Could not enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn));
2202 }
2203 }
2204 rv = SUCCESS;
2205 } else {
2206 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not prepare statement (%s)", PHP_PQerrorMessage(obj->intern->conn));
2207 rv = FAILURE;
2208 }
2209
2210 if (types) {
2211 efree(types);
2212 }
2213
2214 return rv;
2215 }
2216
2217 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_prepare_async, 0, 0, 2)
2218 ZEND_ARG_INFO(0, type)
2219 ZEND_ARG_INFO(0, query)
2220 ZEND_ARG_ARRAY_INFO(0, types, 1)
2221 ZEND_END_ARG_INFO();
2222 static PHP_METHOD(pqconn, prepareAsync) {
2223 zend_error_handling zeh;
2224 zval *ztypes = NULL;
2225 char *name_str, *query_str;
2226 int name_len, *query_len;
2227
2228 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
2229 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!", &name_str, &name_len, &query_str, &query_len, &ztypes)) {
2230 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2231
2232 if (obj->intern) {
2233 obj->intern->poller = PQconsumeInput;
2234 if (SUCCESS == php_pqconn_prepare_async(getThis(), obj, name_str, query_str, ztypes ? Z_ARRVAL_P(ztypes) : NULL TSRMLS_CC)) {
2235 php_pqstm_t *stm = ecalloc(1, sizeof(*stm));
2236
2237 php_pq_object_addref(obj TSRMLS_CC);
2238 stm->conn = obj;
2239 stm->name = estrdup(name_str);
2240
2241 return_value->type = IS_OBJECT;
2242 return_value->value.obj = php_pqstm_create_object_ex(php_pqstm_class_entry, stm, NULL TSRMLS_CC);
2243 }
2244 php_pqconn_notify_listeners(obj TSRMLS_CC);
2245 } else {
2246 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
2247 }
2248 }
2249 zend_restore_error_handling(&zeh TSRMLS_CC);
2250 }
2251
2252 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_quote, 0, 0, 1)
2253 ZEND_ARG_INFO(0, string)
2254 ZEND_END_ARG_INFO();
2255 static PHP_METHOD(pqconn, quote) {
2256 char *str;
2257 int len;
2258
2259 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len)) {
2260 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2261
2262 if (obj->intern) {
2263 char *quoted = PQescapeLiteral(obj->intern->conn, str, len);
2264
2265 if (quoted) {
2266 RETVAL_STRING(quoted, 1);
2267 PQfreemem(quoted);
2268 } else {
2269 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not quote string (%s)", PHP_PQerrorMessage(obj->intern->conn));
2270 RETVAL_FALSE;
2271 }
2272 } else {
2273 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
2274 RETVAL_FALSE;
2275 }
2276 }
2277 }
2278
2279 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_quote_name, 0, 0, 1)
2280 ZEND_ARG_INFO(0, type)
2281 ZEND_END_ARG_INFO();
2282 static PHP_METHOD(pqconn, quoteName) {
2283 char *str;
2284 int len;
2285
2286 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len)) {
2287 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2288
2289 if (obj->intern) {
2290 char *quoted = PQescapeIdentifier(obj->intern->conn, str, len);
2291
2292 if (quoted) {
2293 RETVAL_STRING(quoted, 1);
2294 PQfreemem(quoted);
2295 } else {
2296 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not quote name (%s)", PHP_PQerrorMessage(obj->intern->conn));
2297 RETVAL_FALSE;
2298 }
2299 } else {
2300 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
2301 RETVAL_FALSE;
2302 }
2303 }
2304 }
2305
2306 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_escape_bytea, 0, 0, 1)
2307 ZEND_ARG_INFO(0, bytea)
2308 ZEND_END_ARG_INFO();
2309 static PHP_METHOD(pqconn, escapeBytea) {
2310 char *str;
2311 int len;
2312
2313 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len)) {
2314 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2315
2316 if (obj->intern) {
2317 size_t escaped_len;
2318 char *escaped_str = (char *) PQescapeByteaConn(obj->intern->conn, (unsigned char *) str, len, &escaped_len);
2319
2320 if (escaped_str) {
2321 RETVAL_STRINGL(escaped_str, escaped_len - 1, 1);
2322 PQfreemem(escaped_str);
2323 } else {
2324 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not escape bytea (%s)", PHP_PQerrorMessage(obj->intern->conn));
2325 RETVAL_FALSE;
2326 }
2327 } else {
2328 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
2329 RETVAL_FALSE;
2330 }
2331 }
2332 }
2333
2334 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_unescape_bytea, 0, 0, 1)
2335 ZEND_ARG_INFO(0, bytea)
2336 ZEND_END_ARG_INFO();
2337 static PHP_METHOD(pqconn, unescapeBytea) {
2338 char *str;
2339 int len;
2340
2341 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len)) {
2342 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2343
2344 if (obj->intern) {
2345 size_t unescaped_len;
2346 char *unescaped_str = (char *) PQunescapeBytea((unsigned char *)str, &unescaped_len);
2347
2348 if (unescaped_str) {
2349 RETVAL_STRINGL(unescaped_str, unescaped_len, 1);
2350 PQfreemem(unescaped_str);
2351 } else {
2352 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not unescape bytea (%s)", PHP_PQerrorMessage(obj->intern->conn));
2353 RETVAL_FALSE;
2354 }
2355 } else {
2356 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
2357 RETVAL_FALSE;
2358 }
2359 }
2360 }
2361
2362 static const char *isolation_level(long *isolation) {
2363 switch (*isolation) {
2364 case PHP_PQTXN_SERIALIZABLE:
2365 return "SERIALIZABLE";
2366 case PHP_PQTXN_REPEATABLE_READ:
2367 return "REPEATABLE READ";
2368 default:
2369 *isolation = PHP_PQTXN_READ_COMMITTED;
2370 /* no break */
2371 case PHP_PQTXN_READ_COMMITTED:
2372 return "READ COMMITTED";
2373 }
2374 }
2375
2376 static STATUS php_pqconn_start_transaction(zval *zconn, php_pqconn_object_t *conn_obj, long isolation, zend_bool readonly, zend_bool deferrable TSRMLS_DC)
2377 {
2378 if (!conn_obj) {
2379 conn_obj = zend_object_store_get_object(zconn TSRMLS_CC);
2380 }
2381
2382 if (conn_obj->intern) {
2383 PGresult *res;
2384 char *cmd;
2385
2386 spprintf(&cmd, 0, "START TRANSACTION ISOLATION LEVEL %s, READ %s, %s DEFERRABLE",
2387 isolation_level(&isolation), readonly ? "ONLY" : "WRITE", deferrable ? "": "NOT");
2388
2389 res = PQexec(conn_obj->intern->conn, cmd);
2390
2391 efree(cmd);
2392
2393 if (res) {
2394 STATUS rv = php_pqres_success(res TSRMLS_CC);
2395
2396 PQclear(res);
2397 return rv;
2398 } else {
2399 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not start transaction (%s)", PHP_PQerrorMessage(conn_obj->intern->conn));
2400 return FAILURE;
2401 }
2402 } else {
2403 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
2404 return FAILURE;
2405 }
2406 }
2407
2408 static STATUS php_pqconn_start_transaction_async(zval *zconn, php_pqconn_object_t *conn_obj, long isolation, zend_bool readonly, zend_bool deferrable TSRMLS_DC)
2409 {
2410 if (!conn_obj) {
2411 conn_obj = zend_object_store_get_object(zconn TSRMLS_CC);
2412 }
2413
2414 if (conn_obj->intern->conn) {
2415 char *cmd;
2416
2417 spprintf(&cmd, 0, "START TRANSACTION ISOLATION LEVEL %s, READ %s, %s DEFERRABLE",
2418 isolation_level(&isolation), readonly ? "ONLY" : "WRITE", deferrable ? "": "NOT");
2419
2420 if (PQsendQuery(conn_obj->intern->conn, cmd)) {
2421 conn_obj->intern->poller = PQconsumeInput;
2422 efree(cmd);
2423 return SUCCESS;
2424 } else {
2425 efree(cmd);
2426 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not start transaction (%s)", PHP_PQerrorMessage(conn_obj->intern->conn));
2427 return FAILURE;
2428 }
2429 } else {
2430 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
2431 return FAILURE;
2432 }
2433 }
2434
2435 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_start_transaction, 0, 0, 0)
2436 ZEND_ARG_INFO(0, isolation)
2437 ZEND_ARG_INFO(0, readonly)
2438 ZEND_ARG_INFO(0, deferrable)
2439 ZEND_END_ARG_INFO();
2440 static PHP_METHOD(pqconn, startTransaction) {
2441 zend_error_handling zeh;
2442 long isolation = PHP_PQTXN_READ_COMMITTED;
2443 zend_bool readonly = 0, deferrable = 0;
2444
2445 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
2446 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lbb", &isolation, &readonly, &deferrable)) {
2447 STATUS rv;
2448 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2449
2450 rv = php_pqconn_start_transaction(getThis(), obj, isolation, readonly, deferrable TSRMLS_CC);
2451
2452 if (SUCCESS == rv) {
2453 php_pqtxn_t *txn = ecalloc(1, sizeof(*txn));
2454
2455 php_pq_object_addref(obj TSRMLS_CC);
2456 txn->conn = obj;
2457 txn->isolation = isolation;
2458 txn->readonly = readonly;
2459 txn->deferrable = deferrable;
2460
2461 return_value->type = IS_OBJECT;
2462 return_value->value.obj = php_pqtxn_create_object_ex(php_pqtxn_class_entry, txn, NULL TSRMLS_CC);
2463 }
2464 }
2465 zend_restore_error_handling(&zeh TSRMLS_CC);
2466 }
2467
2468
2469 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_start_transaction_async, 0, 0, 0)
2470 ZEND_ARG_INFO(0, isolation)
2471 ZEND_ARG_INFO(0, readonly)
2472 ZEND_ARG_INFO(0, deferrable)
2473 ZEND_END_ARG_INFO();
2474 static PHP_METHOD(pqconn, startTransactionAsync) {
2475 zend_error_handling zeh;
2476 long isolation = PHP_PQTXN_READ_COMMITTED;
2477 zend_bool readonly = 0, deferrable = 0;
2478
2479 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
2480 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lbb", &isolation, &readonly, &deferrable)) {
2481 STATUS rv;
2482 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2483
2484 rv = php_pqconn_start_transaction_async(getThis(), obj, isolation, readonly, deferrable TSRMLS_CC);
2485
2486 if (SUCCESS == rv) {
2487 php_pqtxn_t *txn = ecalloc(1, sizeof(*txn));
2488
2489 php_pq_object_addref(obj TSRMLS_CC);
2490 txn->conn = obj;
2491 txn->isolation = isolation;
2492 txn->readonly = readonly;
2493 txn->deferrable = deferrable;
2494
2495 return_value->type = IS_OBJECT;
2496 return_value->value.obj = php_pqtxn_create_object_ex(php_pqtxn_class_entry, txn, NULL TSRMLS_CC);
2497 }
2498 }
2499 zend_restore_error_handling(&zeh TSRMLS_CC);
2500 }
2501
2502 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_trace, 0, 0, 0)
2503 ZEND_ARG_INFO(0, stdio_stream)
2504 ZEND_END_ARG_INFO();
2505 static PHP_METHOD(pqconn, trace) {
2506 zval *zstream = NULL;
2507
2508 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r!", &zstream)) {
2509 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2510 if (obj->intern) {
2511 if (zstream) {
2512 FILE *fp;
2513 php_stream *stream = NULL;
2514
2515 php_stream_from_zval(stream, &zstream);
2516
2517 if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void *) &fp, REPORT_ERRORS)) {
2518 stream->flags |= PHP_STREAM_FLAG_NO_CLOSE;
2519 PQtrace(obj->intern->conn, fp);
2520 RETVAL_TRUE;
2521 } else {
2522 RETVAL_FALSE;
2523 }
2524 } else {
2525 PQuntrace(obj->intern->conn);
2526 RETVAL_TRUE;
2527 }
2528 } else {
2529 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
2530 RETVAL_FALSE;
2531 }
2532 }
2533 }
2534
2535 static zend_function_entry php_pqconn_methods[] = {
2536 PHP_ME(pqconn, __construct, ai_pqconn_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
2537 PHP_ME(pqconn, reset, ai_pqconn_reset, ZEND_ACC_PUBLIC)
2538 PHP_ME(pqconn, resetAsync, ai_pqconn_reset_async, ZEND_ACC_PUBLIC)
2539 PHP_ME(pqconn, poll, ai_pqconn_poll, ZEND_ACC_PUBLIC)
2540 PHP_ME(pqconn, exec, ai_pqconn_exec, ZEND_ACC_PUBLIC)
2541 PHP_ME(pqconn, execAsync, ai_pqconn_exec_async, ZEND_ACC_PUBLIC)
2542 PHP_ME(pqconn, execParams, ai_pqconn_exec_params, ZEND_ACC_PUBLIC)
2543 PHP_ME(pqconn, execParamsAsync, ai_pqconn_exec_params_async, ZEND_ACC_PUBLIC)
2544 PHP_ME(pqconn, prepare, ai_pqconn_prepare, ZEND_ACC_PUBLIC)
2545 PHP_ME(pqconn, prepareAsync, ai_pqconn_prepare_async, ZEND_ACC_PUBLIC)
2546 PHP_ME(pqconn, listen, ai_pqconn_listen, ZEND_ACC_PUBLIC)
2547 PHP_ME(pqconn, notify, ai_pqconn_notify, ZEND_ACC_PUBLIC)
2548 PHP_ME(pqconn, getResult, ai_pqconn_get_result, ZEND_ACC_PUBLIC)
2549 PHP_ME(pqconn, quote, ai_pqconn_quote, ZEND_ACC_PUBLIC)
2550 PHP_ME(pqconn, quoteName, ai_pqconn_quote_name, ZEND_ACC_PUBLIC)
2551 PHP_ME(pqconn, escapeBytea, ai_pqconn_escape_bytea, ZEND_ACC_PUBLIC)
2552 PHP_ME(pqconn, unescapeBytea, ai_pqconn_unescape_bytea, ZEND_ACC_PUBLIC)
2553 PHP_ME(pqconn, startTransaction, ai_pqconn_start_transaction, ZEND_ACC_PUBLIC)
2554 PHP_ME(pqconn, startTransactionAsync, ai_pqconn_start_transaction_async, ZEND_ACC_PUBLIC)
2555 PHP_ME(pqconn, trace, ai_pqconn_trace, ZEND_ACC_PUBLIC)
2556 {0}
2557 };
2558
2559 ZEND_BEGIN_ARG_INFO_EX(ai_pqtypes_construct, 0, 0, 1)
2560 ZEND_ARG_OBJ_INFO(0, connection, pq\\Connection, 0)
2561 ZEND_END_ARG_INFO();
2562 static PHP_METHOD(pqtypes, __construct) {
2563 zend_error_handling zeh;
2564 zval *zconn;
2565
2566 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
2567 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zconn, php_pqconn_class_entry)) {
2568 php_pqconn_object_t *conn_obj = zend_object_store_get_object(zconn TSRMLS_CC);
2569
2570 if (conn_obj->intern) {
2571 zval *retval = NULL;
2572 php_pqtypes_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2573
2574 obj->intern = ecalloc(1, sizeof(*obj->intern));
2575 obj->intern->conn = conn_obj;
2576 php_pq_object_addref(conn_obj TSRMLS_CC);
2577 zend_hash_init(&obj->intern->types, 300, NULL, ZVAL_PTR_DTOR, 0);
2578
2579 zend_call_method_with_0_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "refresh", &retval);
2580 if (retval) {
2581 zval_ptr_dtor(&retval);
2582 }
2583 } else {
2584 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
2585 }
2586 }
2587 zend_restore_error_handling(&zeh TSRMLS_CC);
2588 }
2589
2590 #define PHP_PQ_TYPES_QUERY \
2591 "select t.oid, t.* " \
2592 "from pg_type t join pg_namespace n on t.typnamespace=n.oid " \
2593 "where typisdefined " \
2594 "and typrelid=0 " \
2595 "and nspname in ('public', 'pg_catalog')"
2596
2597 ZEND_BEGIN_ARG_INFO_EX(ai_pqtypes_refresh, 0, 0, 0)
2598 ZEND_END_ARG_INFO();
2599 static PHP_METHOD(pqtypes, refresh) {
2600 if (SUCCESS == zend_parse_parameters_none()) {
2601 php_pqtypes_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2602
2603 if (obj->intern) {
2604 PGresult *res = PQexec(obj->intern->conn->intern->conn, PHP_PQ_TYPES_QUERY);
2605
2606 php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC);
2607
2608 if (res) {
2609 if (PGRES_TUPLES_OK == PQresultStatus(res)) {
2610 int r, rows;
2611
2612 for (r = 0, rows = PQntuples(res); r < rows; ++r) {
2613 zval *row = php_pqres_row_to_zval(res, r, PHP_PQRES_FETCH_OBJECT TSRMLS_CC);
2614 long oid = atol(PQgetvalue(res, r, 0 ));
2615 char *name = PQgetvalue(res, r, 1);
2616
2617 Z_ADDREF_P(row);
2618
2619 zend_hash_index_update(&obj->intern->types, oid, (void *) &row, sizeof(zval *), NULL);
2620 zend_hash_add(&obj->intern->types, name, strlen(name) + 1, (void *) &row, sizeof(zval *), NULL);
2621 }
2622 } else {
2623 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not fetch types: %s", PQresultErrorMessage(res));
2624 }
2625 PQclear(res);
2626 } else {
2627 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not fetch types (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
2628 }
2629
2630 } else {
2631 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Types not initialized");
2632 }
2633 }
2634 }
2635
2636 static zend_function_entry php_pqtypes_methods[] = {
2637 PHP_ME(pqtypes, __construct, ai_pqtypes_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
2638 PHP_ME(pqtypes, refresh, ai_pqtypes_refresh, ZEND_ACC_PUBLIC)
2639 {0}
2640 };
2641
2642 static zval **php_pqres_iteration(zval *this_ptr, php_pqres_object_t *obj, php_pqres_fetch_t fetch_type TSRMLS_DC)
2643 {
2644 zval **row = NULL;
2645 php_pqres_fetch_t orig_fetch;
2646
2647 if (!obj) {
2648 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2649 }
2650
2651 if (!obj->intern->iter) {
2652 obj->intern->iter = (php_pqres_iterator_t *) php_pqres_iterator_init(Z_OBJCE_P(getThis()), getThis(), 0 TSRMLS_CC);
2653 obj->intern->iter->zi.funcs->rewind((zend_object_iterator *) obj->intern->iter TSRMLS_CC);
2654 }
2655 orig_fetch = obj->intern->iter->fetch_type;
2656 obj->intern->iter->fetch_type = fetch_type;
2657 if (SUCCESS == obj->intern->iter->zi.funcs->valid((zend_object_iterator *) obj->intern->iter TSRMLS_CC)) {
2658 obj->intern->iter->zi.funcs->get_current_data((zend_object_iterator *) obj->intern->iter, &row TSRMLS_CC);
2659 obj->intern->iter->zi.funcs->move_forward((zend_object_iterator *) obj->intern->iter TSRMLS_CC);
2660 }
2661 obj->intern->iter->fetch_type = orig_fetch;
2662
2663 return row ? row : NULL;
2664 }
2665
2666 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_row, 0, 0, 0)
2667 ZEND_ARG_INFO(0, fetch_type)
2668 ZEND_END_ARG_INFO();
2669 static PHP_METHOD(pqres, fetchRow) {
2670 zend_error_handling zeh;
2671 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2672 long fetch_type = obj->intern->iter ? obj->intern->iter->fetch_type : PHP_PQRES_FETCH_ARRAY;
2673
2674 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
2675 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &fetch_type)) {
2676 zval **row = php_pqres_iteration(getThis(), obj, fetch_type TSRMLS_CC);
2677
2678 if (row) {
2679 RETVAL_ZVAL(*row, 1, 0);
2680 } else {
2681 RETVAL_FALSE;
2682 }
2683 }
2684 zend_restore_error_handling(&zeh TSRMLS_CC);
2685 }
2686
2687 static zval **column_at(zval *row, int col TSRMLS_DC)
2688 {
2689 zval **data = NULL;
2690 HashTable *ht = HASH_OF(row);
2691 int count = zend_hash_num_elements(ht);
2692
2693 if (col < count) {
2694 zend_hash_internal_pointer_reset(ht);
2695 while (col-- > 0) {
2696 zend_hash_move_forward(ht);
2697 }
2698 zend_hash_get_current_data(ht, (void *) &data);
2699 } else {
2700 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Column index %d exceeds column count %d", col, count);
2701 }
2702 return data;
2703 }
2704
2705 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_col, 0, 0, 0)
2706 ZEND_ARG_INFO(0, col_num)
2707 ZEND_END_ARG_INFO();
2708 static PHP_METHOD(pqres, fetchCol) {
2709 zend_error_handling zeh;
2710 long fetch_col = 0;
2711
2712 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
2713 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &fetch_col)) {
2714 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2715 zval **row = php_pqres_iteration(getThis(), obj, obj->intern->iter ? obj->intern->iter->fetch_type : 0 TSRMLS_CC);
2716
2717 if (row) {
2718 zval **col = column_at(*row, fetch_col TSRMLS_CC);
2719
2720 if (col) {
2721 RETVAL_ZVAL(*col, 1, 0);
2722 } else {
2723 RETVAL_FALSE;
2724 }
2725 } else {
2726 RETVAL_FALSE;
2727 }
2728 }
2729 zend_restore_error_handling(&zeh TSRMLS_CC);
2730
2731 }
2732
2733 static zend_function_entry php_pqres_methods[] = {
2734 PHP_ME(pqres, fetchRow, ai_pqres_fetch_row, ZEND_ACC_PUBLIC)
2735 PHP_ME(pqres, fetchCol, ai_pqres_fetch_col, ZEND_ACC_PUBLIC)
2736 {0}
2737 };
2738
2739 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_construct, 0, 0, 3)
2740 ZEND_ARG_OBJ_INFO(0, Connection, pq\\Connection, 0)
2741 ZEND_ARG_INFO(0, type)
2742 ZEND_ARG_INFO(0, query)
2743 ZEND_ARG_ARRAY_INFO(0, types, 1)
2744 ZEND_ARG_INFO(0, async)
2745 ZEND_END_ARG_INFO();
2746 static PHP_METHOD(pqstm, __construct) {
2747 zend_error_handling zeh;
2748 zval *zconn, *ztypes = NULL;
2749 char *name_str, *query_str;
2750 int name_len, *query_len;
2751 zend_bool async = 0;
2752
2753 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
2754 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oss|a/!b", &zconn, php_pqconn_class_entry, &name_str, &name_len, &query_str, &query_len, &ztypes, &async)) {
2755 php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2756 php_pqconn_object_t *conn_obj = zend_object_store_get_object(zconn TSRMLS_CC);
2757
2758 if (conn_obj->intern) {
2759 STATUS rv;
2760 if (async) {
2761 conn_obj->intern->poller = PQconsumeInput;
2762 rv = php_pqconn_prepare_async(zconn, conn_obj, name_str, query_str, ztypes ? Z_ARRVAL_P(ztypes) : NULL TSRMLS_CC);
2763 } else {
2764 rv = php_pqconn_prepare(zconn, conn_obj, name_str, query_str, ztypes ? Z_ARRVAL_P(ztypes) : NULL TSRMLS_CC);
2765 php_pqconn_notify_listeners(conn_obj TSRMLS_CC);
2766 }
2767
2768 if (SUCCESS == rv) {
2769 php_pqstm_t *stm = ecalloc(1, sizeof(*stm));
2770
2771 php_pq_object_addref(conn_obj TSRMLS_CC);
2772 stm->conn = conn_obj;
2773 stm->name = estrdup(name_str);
2774 obj->intern = stm;
2775 }
2776 } else {
2777 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
2778 }
2779 }
2780 zend_restore_error_handling(&zeh TSRMLS_CC);
2781 }
2782
2783 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_exec, 0, 0, 0)
2784 ZEND_ARG_ARRAY_INFO(0, params, 1)
2785 ZEND_END_ARG_INFO();
2786 static PHP_METHOD(pqstm, exec) {
2787 zend_error_handling zeh;
2788 zval *zparams = NULL;
2789
2790 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
2791 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a/!", &zparams)) {
2792 php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2793
2794 if (obj->intern) {
2795 if (obj->intern->conn->intern) {
2796 int count = 0;
2797 char **params = NULL;
2798 HashTable zdtor;
2799 PGresult *res;
2800
2801 if (zparams) {
2802 ZEND_INIT_SYMTABLE(&zdtor);
2803 count = php_pq_params_to_array(Z_ARRVAL_P(zparams), &params, &zdtor TSRMLS_CC);
2804 }
2805
2806 res = PQexecPrepared(obj->intern->conn->intern->conn, obj->intern->name, count, (const char *const*) params, NULL, NULL, 0);
2807
2808 if (params) {
2809 efree(params);
2810 }
2811 if (zparams) {
2812 zend_hash_destroy(&zdtor);
2813 }
2814
2815 php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC);
2816
2817 if (res) {
2818 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
2819 php_pqres_t *r = ecalloc(1, sizeof(*r));
2820
2821 r->res = res;
2822 return_value->type = IS_OBJECT;
2823 return_value->value.obj = php_pqres_create_object_ex(php_pqres_class_entry, r, NULL TSRMLS_CC);
2824 }
2825 } else {
2826 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
2827 }
2828 } else {
2829 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
2830 }
2831 } else {
2832 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Statement not initialized");
2833 }
2834 }
2835 zend_restore_error_handling(&zeh TSRMLS_CC);
2836 }
2837
2838 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_exec_async, 0, 0, 0)
2839 ZEND_ARG_ARRAY_INFO(0, params, 1)
2840 ZEND_ARG_INFO(0, callable)
2841 ZEND_END_ARG_INFO();
2842 static PHP_METHOD(pqstm, execAsync) {
2843 zend_error_handling zeh;
2844 zval *zparams = NULL;
2845 php_pq_callback_t resolver = {{0}};
2846
2847 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
2848 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a/!f", &zparams, &resolver.fci, &resolver.fcc)) {
2849 php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2850
2851 if (obj->intern) {
2852 if (obj->intern->conn->intern) {
2853 int count;
2854 char **params = NULL;
2855 HashTable zdtor;
2856
2857 if (zparams) {
2858 ZEND_INIT_SYMTABLE(&zdtor);
2859 count = php_pq_params_to_array(Z_ARRVAL_P(zparams), &params, &zdtor TSRMLS_CC);
2860 }
2861
2862 php_pq_callback_dtor(&obj->intern->conn->intern->onevent);
2863 if (resolver.fci.size > 0) {
2864 obj->intern->conn->intern->onevent = resolver;
2865 php_pq_callback_addref(&obj->intern->conn->intern->onevent);
2866 }
2867
2868 obj->intern->conn->intern->poller = PQconsumeInput;
2869
2870 if (PQsendQueryPrepared(obj->intern->conn->intern->conn, obj->intern->name, count, (const char *const*) params, NULL, NULL, 0)) {
2871 if (obj->intern->conn->intern->unbuffered) {
2872 if (!PQsetSingleRowMode(obj->intern->conn->intern->conn)) {
2873 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Could not enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
2874 }
2875 }
2876 RETVAL_TRUE;
2877 } else {
2878 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
2879 RETVAL_FALSE;
2880 }
2881
2882 if (params) {
2883 efree(params);
2884 }
2885 if (zparams) {
2886 zend_hash_destroy(&zdtor);
2887 }
2888
2889 php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC);
2890
2891 } else {
2892 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
2893 RETVAL_FALSE;
2894 }
2895 } else {
2896 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Statement not initialized");
2897 RETVAL_FALSE;
2898 }
2899 }
2900 zend_restore_error_handling(&zeh TSRMLS_CC);
2901 }
2902
2903 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_desc, 0, 0, 0)
2904 ZEND_END_ARG_INFO();
2905 static PHP_METHOD(pqstm, desc) {
2906 zend_error_handling zeh;
2907
2908 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
2909 if (SUCCESS == zend_parse_parameters_none()) {
2910 php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2911
2912 if (obj->intern) {
2913 if (obj->intern->conn->intern) {
2914 PGresult *res = PQdescribePrepared(obj->intern->conn->intern->conn, obj->intern->name);
2915
2916 php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC);
2917
2918 if (res) {
2919 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
2920 int p, params;
2921
2922 array_init(return_value);
2923 for (p = 0, params = PQnparams(res); p < params; ++p) {
2924 add_next_index_long(return_value, PQparamtype(res, p));
2925 }
2926 }
2927 } else {
2928 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not describe statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
2929 }
2930 } else {
2931 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
2932 }
2933 } else {
2934 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Statement not initialized");
2935 }
2936 }
2937 zend_restore_error_handling(&zeh TSRMLS_CC);
2938 }
2939
2940 static zend_function_entry php_pqstm_methods[] = {
2941 PHP_ME(pqstm, __construct, ai_pqstm_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
2942 PHP_ME(pqstm, exec, ai_pqstm_exec, ZEND_ACC_PUBLIC)
2943 PHP_ME(pqstm, desc, ai_pqstm_desc, ZEND_ACC_PUBLIC)
2944 PHP_ME(pqstm, execAsync, ai_pqstm_exec_async, ZEND_ACC_PUBLIC)
2945 {0}
2946 };
2947
2948 ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_construct, 0, 0, 1)
2949 ZEND_ARG_OBJ_INFO(0, connection, pq\\Connection, 0)
2950 ZEND_ARG_INFO(0, async)
2951 ZEND_ARG_INFO(0, isolation)
2952 ZEND_ARG_INFO(0, readonly)
2953 ZEND_ARG_INFO(0, deferrable)
2954 ZEND_END_ARG_INFO();
2955 static PHP_METHOD(pqtxn, __construct) {
2956 zend_error_handling zeh;
2957 zval *zconn;
2958 long isolation = PHP_PQTXN_READ_COMMITTED;
2959 zend_bool async = 0, readonly = 0, deferrable = 0;
2960
2961 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
2962 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|blbb", &zconn, php_pqconn_class_entry, &async, &isolation, &readonly, &deferrable)) {
2963 STATUS rv;
2964 php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2965 php_pqconn_object_t *conn_obj = zend_object_store_get_object(zconn TSRMLS_CC);
2966
2967 if (conn_obj->intern) {
2968 if (async) {
2969 rv = php_pqconn_start_transaction_async(zconn, conn_obj, isolation, readonly, deferrable TSRMLS_CC);
2970 } else {
2971 rv = php_pqconn_start_transaction(zconn, conn_obj, isolation, readonly, deferrable TSRMLS_CC);
2972 }
2973
2974 if (SUCCESS == rv) {
2975 obj->intern = ecalloc(1, sizeof(*obj->intern));
2976
2977 php_pq_object_addref(conn_obj TSRMLS_CC);
2978 obj->intern->conn = conn_obj;
2979 obj->intern->isolation = isolation;
2980 obj->intern->readonly = readonly;
2981 obj->intern->deferrable = deferrable;
2982 }
2983 } else {
2984 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
2985 }
2986 }
2987 zend_restore_error_handling(&zeh TSRMLS_CC);
2988 }
2989
2990 ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_commit, 0, 0, 0)
2991 ZEND_END_ARG_INFO();
2992 static PHP_METHOD(pqtxn, commit) {
2993 zend_error_handling zeh;
2994
2995 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
2996 if (SUCCESS == zend_parse_parameters_none()) {
2997 php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
2998
2999 if (obj->intern) {
3000
3001 if (obj->intern->conn->intern) {
3002 PGresult *res = PQexec(obj->intern->conn->intern->conn, "COMMIT");
3003
3004 if (res) {
3005 php_pqres_success(res TSRMLS_CC);
3006 PQclear(res);
3007 } else {
3008 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not commit transaction (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
3009 }
3010 } else {
3011 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not intialized");
3012 }
3013 } else {
3014 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
3015 }
3016 }
3017 zend_restore_error_handling(&zeh TSRMLS_CC);
3018 }
3019
3020 ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_commit_async, 0, 0, 0)
3021 ZEND_END_ARG_INFO();
3022 static PHP_METHOD(pqtxn, commitAsync) {
3023 zend_error_handling zeh;
3024
3025 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
3026 if (SUCCESS == zend_parse_parameters_none()) {
3027 php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
3028
3029 if (obj->intern) {
3030 if (obj->intern->conn->intern) {
3031 obj->intern->conn->intern->poller = PQconsumeInput;
3032
3033 if (!PQsendQuery(obj->intern->conn->intern->conn, "COMMIT")) {
3034 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not commit transaction (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
3035 }
3036 } else {
3037 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not intialized");
3038 }
3039 } else {
3040 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
3041 }
3042 }
3043 zend_restore_error_handling(&zeh TSRMLS_CC);
3044 }
3045
3046 ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_rollback, 0, 0, 0)
3047 ZEND_END_ARG_INFO();
3048 static PHP_METHOD(pqtxn, rollback) {
3049 zend_error_handling zeh;
3050
3051 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
3052 if (SUCCESS == zend_parse_parameters_none()) {
3053 php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
3054
3055 if (obj->intern) {
3056 if (obj->intern->conn->intern) {
3057 PGresult *res = PQexec(obj->intern->conn->intern->conn, "ROLLBACK");
3058
3059 if (res) {
3060 php_pqres_success(res TSRMLS_CC);
3061 PQclear(res);
3062 } else {
3063 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not rollback transaction (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
3064 }
3065 } else {
3066 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not intialized");
3067 }
3068 } else {
3069 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
3070 }
3071 }
3072 zend_restore_error_handling(&zeh TSRMLS_CC);
3073 }
3074
3075 ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_rollback_async, 0, 0, 0)
3076 ZEND_END_ARG_INFO();
3077 static PHP_METHOD(pqtxn, rollbackAsync) {
3078 zend_error_handling zeh;
3079
3080 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
3081 if (SUCCESS == zend_parse_parameters_none()) {
3082 php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
3083
3084 if (obj->intern) {
3085 if (obj->intern->conn->intern) {
3086 obj->intern->conn->intern->poller = PQconsumeInput;
3087 if (!PQsendQuery(obj->intern->conn->intern->conn, "REOLLBACK")) {
3088 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not rollback transaction (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
3089 }
3090 } else {
3091 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not intialized");
3092 }
3093 } else {
3094 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
3095 }
3096 }
3097 zend_restore_error_handling(&zeh TSRMLS_CC);
3098 }
3099
3100 ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_open_lob, 0, 0, 1)
3101 ZEND_ARG_INFO(0, oid)
3102 ZEND_ARG_INFO(0, mode)
3103 ZEND_END_ARG_INFO();
3104 static PHP_METHOD(pqtxn, openLOB) {
3105 zend_error_handling zeh;
3106 long mode = INV_WRITE|INV_READ, loid;
3107
3108 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
3109 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &loid, &mode)) {
3110 php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
3111
3112 if (obj->intern) {
3113 int lofd = lo_open(obj->intern->conn->intern->conn, loid, mode);
3114
3115 if (lofd >= 0) {
3116 php_pqlob_t *lob = ecalloc(1, sizeof(*lob));
3117
3118 lob->lofd = lofd;
3119 lob->loid = loid;
3120 php_pq_object_addref(obj TSRMLS_CC);
3121 lob->txn = obj;
3122
3123 return_value->type = IS_OBJECT;
3124 return_value->value.obj = php_pqlob_create_object_ex(php_pqlob_class_entry, lob, NULL TSRMLS_CC);
3125 } else {
3126 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to open large object with mode '%s' (%s)",
3127 (mode & (INV_READ|INV_WRITE) ? "rw" :
3128 (mode & INV_READ ? "r" :
3129 (mode & INV_WRITE ? "w" : "-"))),
3130 PHP_PQerrorMessage(obj->intern->conn->intern->conn)
3131 );
3132 }
3133 } else {
3134 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
3135 }
3136 }
3137 zend_restore_error_handling(&zeh TSRMLS_CC);
3138 }
3139
3140 ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_create_lob, 0, 0, 0)
3141 ZEND_ARG_INFO(0, mode)
3142 ZEND_END_ARG_INFO();
3143 static PHP_METHOD(pqtxn, createLOB) {
3144 zend_error_handling zeh;
3145 long mode = INV_WRITE|INV_READ;
3146
3147 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
3148 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &mode)) {
3149 php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
3150
3151 if (obj->intern) {
3152 Oid loid = lo_creat(obj->intern->conn->intern->conn, mode);
3153
3154 if (loid != InvalidOid) {
3155 int lofd = lo_open(obj->intern->conn->intern->conn, loid, mode);
3156
3157 if (lofd >= 0) {
3158 php_pqlob_t *lob = ecalloc(1, sizeof(*lob));
3159 lob->lofd = lofd;
3160 lob->loid = loid;
3161 php_pq_object_addref(obj TSRMLS_CC);
3162 lob->txn = obj;
3163
3164 return_value->type = IS_OBJECT;
3165 return_value->value.obj = php_pqlob_create_object_ex(php_pqlob_class_entry, lob, NULL TSRMLS_CC);
3166 } else {
3167 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to open large object with mode '%s': %s",
3168 (mode & (INV_READ|INV_WRITE) ? "rw" :
3169 (mode & INV_READ ? "r" :
3170 (mode & INV_WRITE ? "w" : "-"))),
3171 PHP_PQerrorMessage(obj->intern->conn->intern->conn)
3172 );
3173 }
3174 } else {
3175 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to create large object with mode '%s': %s",
3176 (mode & (INV_READ|INV_WRITE) ? "rw" :
3177 (mode & INV_READ ? "r" :
3178 (mode & INV_WRITE ? "w" : "-"))),
3179 PHP_PQerrorMessage(obj->intern->conn->intern->conn)
3180 );
3181 }
3182 } else {
3183 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
3184 }
3185 }
3186 zend_restore_error_handling(&zeh TSRMLS_CC);
3187 }
3188
3189 ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_unlink_lob, 0, 0, 1)
3190 ZEND_ARG_INFO(0, oid)
3191 ZEND_END_ARG_INFO();
3192 static PHP_METHOD(pqtxn, unlinkLOB) {
3193 long loid;
3194
3195 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &loid)) {
3196 php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
3197
3198 if (obj->intern) {
3199 if (1 == lo_unlink(obj->intern->conn->intern->conn, loid)) {
3200 RETVAL_TRUE;
3201 } else {
3202 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to unlink LOB (oid=%ld): %s", loid, PHP_PQerrorMessage(obj->intern->conn->intern->conn));
3203 RETVAL_FALSE;
3204 }
3205 } else {
3206 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
3207 RETVAL_FALSE;
3208 }
3209 }
3210 }
3211
3212 static zend_function_entry php_pqtxn_methods[] = {
3213 PHP_ME(pqtxn, __construct, ai_pqtxn_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
3214 PHP_ME(pqtxn, commit, ai_pqtxn_commit, ZEND_ACC_PUBLIC)
3215 PHP_ME(pqtxn, rollback, ai_pqtxn_rollback, ZEND_ACC_PUBLIC)
3216 PHP_ME(pqtxn, commitAsync, ai_pqtxn_commit_async, ZEND_ACC_PUBLIC)
3217 PHP_ME(pqtxn, rollbackAsync, ai_pqtxn_rollback_async, ZEND_ACC_PUBLIC)
3218 PHP_ME(pqtxn, openLOB, ai_pqtxn_open_lob, ZEND_ACC_PUBLIC)
3219 PHP_ME(pqtxn, createLOB, ai_pqtxn_create_lob, ZEND_ACC_PUBLIC)
3220 PHP_ME(pqtxn, unlinkLOB, ai_pqtxn_unlink_lob, ZEND_ACC_PUBLIC)
3221 {0}
3222 };
3223
3224 ZEND_BEGIN_ARG_INFO_EX(ai_pqcancel_construct, 0, 0, 1)
3225 ZEND_ARG_OBJ_INFO(0, connection, pq\\Connection, 0)
3226 ZEND_END_ARG_INFO();
3227 static PHP_METHOD(pqcancel, __construct) {
3228 zend_error_handling zeh;
3229 zval *zconn;
3230
3231 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
3232 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zconn, php_pqconn_class_entry)) {
3233 php_pqconn_object_t *conn_obj = zend_object_store_get_object(zconn TSRMLS_CC);
3234
3235 if (conn_obj->intern) {
3236 PGcancel *cancel = PQgetCancel(conn_obj->intern->conn);
3237
3238 if (cancel) {
3239 php_pqcancel_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
3240
3241 obj->intern = ecalloc(1, sizeof(*obj->intern));
3242 obj->intern->cancel = cancel;
3243 php_pq_object_addref(conn_obj TSRMLS_CC);
3244 obj->intern->conn = conn_obj;
3245 } else {
3246 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not acquire cancel (%s)", PHP_PQerrorMessage(conn_obj->intern->conn));
3247 }
3248 } else {
3249 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
3250 }
3251 }
3252 zend_restore_error_handling(&zeh TSRMLS_CC);
3253 }
3254
3255 ZEND_BEGIN_ARG_INFO_EX(ai_pqcancel_cancel, 0, 0, 0)
3256 ZEND_END_ARG_INFO();
3257 static PHP_METHOD(pqcancel, cancel) {
3258 zend_error_handling zeh;
3259
3260 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
3261 if (SUCCESS == zend_parse_parameters_none()) {
3262 php_pqcancel_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
3263
3264 if (obj->intern) {
3265 char err[256];
3266
3267 if (!PQcancel(obj->intern->cancel, err, sizeof(err))) {
3268 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not request cancellation: %s", err);
3269 }
3270 } else {
3271 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Cancel not initialized");
3272 }
3273 }
3274 zend_restore_error_handling(&zeh TSRMLS_CC);
3275 }
3276
3277 static zend_function_entry php_pqcancel_methods[] = {
3278 PHP_ME(pqcancel, __construct, ai_pqcancel_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
3279 PHP_ME(pqcancel, cancel, ai_pqcancel_cancel, ZEND_ACC_PUBLIC)
3280 {0}
3281 };
3282
3283 static void php_pqconn_add_eventhandler(zval *zconn, php_pqconn_object_t *conn_obj, const char *type_str, size_t type_len, zval *zevent TSRMLS_DC)
3284 {
3285 zval **evhs;
3286
3287 if (SUCCESS == zend_hash_find(&conn_obj->intern->eventhandlers, type_str, type_len + 1, (void *) &evhs)) {
3288 Z_ADDREF_P(zevent);
3289 add_next_index_zval(*evhs, zevent);
3290 } else {
3291 zval *evh;
3292
3293 MAKE_STD_ZVAL(evh);
3294 array_init(evh);
3295 Z_ADDREF_P(zevent);
3296 add_next_index_zval(evh, zevent);
3297 zend_hash_add(&conn_obj->intern->eventhandlers, type_str, type_len + 1, (void *) &evh, sizeof(zval *), NULL);
3298 }
3299 }
3300
3301 ZEND_BEGIN_ARG_INFO_EX(ai_pqevent_construct, 0, 0, 3)
3302 ZEND_ARG_OBJ_INFO(0, connection, pq\\Connection, 0)
3303 ZEND_ARG_INFO(0, type)
3304 ZEND_ARG_INFO(0, callable)
3305 ZEND_END_ARG_INFO();
3306 static PHP_METHOD(pqevent, __construct) {
3307 zend_error_handling zeh;
3308 zval *zconn;
3309 char *type_str;
3310 int type_len;
3311 php_pq_callback_t cb;
3312
3313 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
3314 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Osf", &zconn, php_pqconn_class_entry, &type_str, &type_len, &cb.fci, &cb.fcc)) {
3315 php_pqconn_object_t *conn_obj = zend_object_store_get_object(zconn TSRMLS_CC);
3316
3317 if (conn_obj->intern) {
3318 php_pqevent_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
3319
3320 obj->intern = ecalloc(1, sizeof(*obj->intern));
3321 php_pq_callback_addref(&cb);
3322 obj->intern->cb = cb;
3323 php_pq_object_addref(conn_obj TSRMLS_CC);
3324 obj->intern->conn = conn_obj;
3325 obj->intern->type = estrdup(type_str);
3326
3327 php_pqconn_add_eventhandler(zconn, conn_obj, type_str, type_len, getThis() TSRMLS_CC);
3328
3329 } else {
3330 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
3331 }
3332 }
3333 zend_restore_error_handling(&zeh TSRMLS_CC);
3334 }
3335
3336 ZEND_BEGIN_ARG_INFO_EX(ai_pqevent_trigger, 0, 0, 1)
3337 ZEND_ARG_ARRAY_INFO(0, args, 1)
3338 ZEND_END_ARG_INFO();
3339 static PHP_METHOD(pqevent, trigger) {
3340 zval *args;
3341
3342 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &args)) {
3343 php_pqevent_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
3344
3345 if (obj->intern) {
3346 zval *rv = NULL;
3347
3348 if (SUCCESS == zend_fcall_info_call(&obj->intern->cb.fci, &obj->intern->cb.fcc, &rv, args TSRMLS_CC)) {
3349 if (rv) {
3350 RETVAL_ZVAL(rv, 0, 1);
3351 } else {
3352 RETVAL_TRUE;
3353 }
3354 }
3355 } else {
3356 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Event not initialized");
3357 RETVAL_FALSE;
3358 }
3359 }
3360 }
3361
3362 static zend_function_entry php_pqevent_methods[] = {
3363 PHP_ME(pqevent, __construct, ai_pqevent_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
3364 PHP_ME(pqevent, trigger, ai_pqevent_trigger, ZEND_ACC_PUBLIC)
3365 {0}
3366 };
3367
3368 ZEND_BEGIN_ARG_INFO_EX(ai_pqlob_construct, 0, 0, 1)
3369 ZEND_ARG_OBJ_INFO(0, transaction, pq\\Transaction, 0)
3370 ZEND_ARG_INFO(0, oid)
3371 ZEND_ARG_INFO(0, mode)
3372 ZEND_END_ARG_INFO();
3373 static PHP_METHOD(pqlob, __construct) {
3374 zend_error_handling zeh;
3375 zval *ztxn;
3376 long mode = INV_WRITE|INV_READ, loid = InvalidOid;
3377
3378 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
3379 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|ll", &ztxn, php_pqtxn_class_entry, &loid, &mode)) {
3380 php_pqtxn_object_t *txn_obj = zend_object_store_get_object(ztxn TSRMLS_CC);
3381
3382 if (txn_obj->intern) {
3383
3384 if (loid == InvalidOid) {
3385 loid = lo_creat(txn_obj->intern->conn->intern->conn, mode);
3386 }
3387
3388 if (loid != InvalidOid) {
3389 int lofd = lo_open(txn_obj->intern->conn->intern->conn, loid, mode);
3390
3391 if (lofd >= 0) {
3392 php_pqlob_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
3393
3394 obj->intern = ecalloc(1, sizeof(*obj->intern));
3395 obj->intern->lofd = lofd;
3396 obj->intern->loid = loid;
3397 php_pq_object_addref(txn_obj TSRMLS_CC);
3398 obj->intern->txn = txn_obj;
3399 } else {
3400 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to open large object with mode '%s' (%s)",
3401 (mode & (INV_READ|INV_WRITE) ? "rw" :
3402 (mode & INV_READ ? "r" :
3403 (mode & INV_WRITE ? "w" : "-"))),
3404 PHP_PQerrorMessage(txn_obj->intern->conn->intern->conn)
3405 );
3406 }
3407 } else {
3408 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to create large object with mode '%s' (%s)",
3409 (mode & (INV_READ|INV_WRITE) ? "rw" :
3410 (mode & INV_READ ? "r" :
3411 (mode & INV_WRITE ? "w" : "-"))),
3412 PHP_PQerrorMessage(txn_obj->intern->conn->intern->conn)
3413 );
3414 }
3415 } else {
3416 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
3417 }
3418 }
3419 zend_restore_error_handling(&zeh TSRMLS_CC);
3420 }
3421
3422 ZEND_BEGIN_ARG_INFO_EX(ai_pqlob_write, 0, 0, 1)
3423 ZEND_ARG_INFO(0, data)
3424 ZEND_END_ARG_INFO();
3425 static PHP_METHOD(pqlob, write) {
3426 char *data_str;
3427 int data_len;
3428
3429 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data_str, &data_len)) {
3430 php_pqlob_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
3431
3432 if (obj->intern) {
3433 int written = lo_write(obj->intern->txn->intern->conn->intern->conn, obj->intern->lofd, data_str, data_len);
3434
3435 if (written >= 0) {
3436 RETVAL_LONG(written);
3437 } else {
3438 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write to LOB, oid=%d (%s)", obj->intern->loid,
3439 PHP_PQerrorMessage(obj->intern->txn->intern->conn->intern->conn));
3440 RETVAL_FALSE;
3441 }
3442 } else {
3443 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\LOB not initialized");
3444 RETVAL_FALSE;
3445 }
3446 }
3447 }
3448
3449 ZEND_BEGIN_ARG_INFO_EX(ai_pqlob_read, 0, 0, 0)
3450 ZEND_ARG_INFO(0, length)
3451 ZEND_ARG_INFO(1, read)
3452 ZEND_END_ARG_INFO();
3453 static PHP_METHOD(pqlob, read) {
3454 long length = 0x1000;
3455 zval *zread = NULL;
3456
3457 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lz!", &length, &zread)) {
3458 php_pqlob_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
3459
3460 if (obj->intern) {
3461 char *buffer = emalloc(length + 1);
3462 int read = lo_read(obj->intern->txn->intern->conn->intern->conn, obj->intern->lofd, buffer, length);
3463
3464 if (read >= 0) {
3465 if (zread) {
3466 zval_dtor(zread);
3467 ZVAL_LONG(zread, read);
3468 }
3469 buffer[read] = '\0';
3470 RETVAL_STRINGL(buffer, read, 0);
3471 } else {
3472 efree(buffer);
3473 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to read from LOB, oid=%d (%s)", obj->intern->loid,
3474 PHP_PQerrorMessage(obj->intern->txn->intern->conn->intern->conn));
3475 RETVAL_FALSE;
3476 }
3477
3478 } else {
3479 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\LOB not initialized");
3480 RETVAL_FALSE;
3481 }
3482 }
3483 }
3484
3485 ZEND_BEGIN_ARG_INFO_EX(ai_pqlob_seek, 0, 0, 1)
3486 ZEND_ARG_INFO(0, offset)
3487 ZEND_ARG_INFO(0, whence)
3488 ZEND_END_ARG_INFO();
3489 static PHP_METHOD(pqlob, seek) {
3490 long offset, whence = SEEK_SET;
3491
3492 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &offset, &whence)) {
3493 php_pqlob_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
3494
3495 if (obj->intern) {
3496 int position = lo_lseek(obj->intern->txn->intern->conn->intern->conn, obj->intern->lofd, offset, whence);
3497
3498 if (position >= 0) {
3499 RETVAL_LONG(position);
3500 } else {
3501 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to seek offset in LOB, oid=%d (%s)", obj->intern->loid,
3502 PHP_PQerrorMessage(obj->intern->txn->intern->conn->intern->conn));
3503 RETVAL_FALSE;
3504 }
3505 } else {
3506 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\LOB not initialized");
3507 RETVAL_FALSE;
3508 }
3509 }
3510 }
3511
3512 ZEND_BEGIN_ARG_INFO_EX(ai_pqlob_tell, 0, 0, 0)
3513 ZEND_END_ARG_INFO();
3514 static PHP_METHOD(pqlob, tell) {
3515 if (SUCCESS == zend_parse_parameters_none()) {
3516 php_pqlob_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
3517
3518 if (obj->intern) {
3519 int position = lo_tell(obj->intern->txn->intern->conn->intern->conn, obj->intern->lofd);
3520
3521 if (position >= 0) {
3522 RETVAL_LONG(position);
3523 } else {
3524 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to tell offset in LOB (oid=%d): %s", obj->intern->loid,
3525 PHP_PQerrorMessage(obj->intern->txn->intern->conn->intern->conn));
3526 RETVAL_FALSE;
3527 }
3528 } else {
3529 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\LOB not initialized");
3530 RETVAL_FALSE;
3531 }
3532 }
3533 }
3534
3535 ZEND_BEGIN_ARG_INFO_EX(ai_pqlob_truncate, 0, 0, 0)
3536 ZEND_ARG_INFO(0, length)
3537 ZEND_END_ARG_INFO();
3538 static PHP_METHOD(pqlob, truncate) {
3539 long length = 0;
3540
3541 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &length)) {
3542 php_pqlob_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
3543
3544 if (obj->intern) {
3545 if (0 == lo_truncate(obj->intern->txn->intern->conn->intern->conn, obj->intern->lofd, length)) {
3546 RETVAL_TRUE;
3547 } else {
3548 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to truncate LOB (oid=%d): %s", obj->intern->loid,
3549 PHP_PQerrorMessage(obj->intern->txn->intern->conn->intern->conn));
3550 RETVAL_FALSE;
3551 }
3552 } else {
3553 php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\LOB not initialized");
3554 RETVAL_FALSE;
3555 }
3556 }
3557 }
3558
3559 static zend_function_entry php_pqlob_methods[] = {
3560 PHP_ME(pqlob, __construct, ai_pqlob_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
3561 PHP_ME(pqlob, write, ai_pqlob_write, ZEND_ACC_PUBLIC)
3562 PHP_ME(pqlob, read, ai_pqlob_read, ZEND_ACC_PUBLIC)
3563 PHP_ME(pqlob, seek, ai_pqlob_seek, ZEND_ACC_PUBLIC)
3564 PHP_ME(pqlob, tell, ai_pqlob_tell, ZEND_ACC_PUBLIC)
3565 PHP_ME(pqlob, truncate, ai_pqlob_truncate, ZEND_ACC_PUBLIC)
3566 {0}
3567 };
3568
3569 /* {{{ PHP_MINIT_FUNCTION
3570 */
3571 static PHP_MINIT_FUNCTION(pq)
3572 {
3573 zend_class_entry ce = {0};
3574 php_pq_object_prophandler_t ph = {0};
3575
3576 INIT_NS_CLASS_ENTRY(ce, "pq", "Connection", php_pqconn_methods);
3577 php_pqconn_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
3578 php_pqconn_class_entry->create_object = php_pqconn_create_object;
3579
3580 memcpy(&php_pqconn_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
3581 php_pqconn_object_handlers.read_property = php_pq_object_read_prop;
3582 php_pqconn_object_handlers.write_property = php_pq_object_write_prop;
3583 php_pqconn_object_handlers.clone_obj = NULL;
3584 php_pqconn_object_handlers.get_property_ptr_ptr = NULL;
3585 php_pqconn_object_handlers.get_debug_info = php_pq_object_debug_info;
3586
3587 zend_hash_init(&php_pqconn_object_prophandlers, 13, NULL, NULL, 1);
3588
3589 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("status"), CONNECTION_BAD, ZEND_ACC_PUBLIC TSRMLS_CC);
3590 ph.read = php_pqconn_object_read_status;
3591 zend_hash_add(&php_pqconn_object_prophandlers, "status", sizeof("status"), (void *) &ph, sizeof(ph), NULL);
3592
3593 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("transactionStatus"), PQTRANS_UNKNOWN, ZEND_ACC_PUBLIC TSRMLS_CC);
3594 ph.read = php_pqconn_object_read_transaction_status;
3595 zend_hash_add(&php_pqconn_object_prophandlers, "transactionStatus", sizeof("transactionStatus"), (void *) &ph, sizeof(ph), NULL);
3596
3597 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("socket"), ZEND_ACC_PUBLIC TSRMLS_CC);
3598 ph.read = NULL; /* forward to std prophandler */
3599 zend_hash_add(&php_pqconn_object_prophandlers, "socket", sizeof("socket"), (void *) &ph, sizeof(ph), NULL);
3600
3601 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC TSRMLS_CC);
3602 ph.read = php_pqconn_object_read_error_message;
3603 zend_hash_add(&php_pqconn_object_prophandlers, "errorMessage", sizeof("errorMessage"), (void *) &ph, sizeof(ph), NULL);
3604
3605 zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("busy"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
3606 ph.read = php_pqconn_object_read_busy;
3607 zend_hash_add(&php_pqconn_object_prophandlers, "busy", sizeof("busy"), (void *) &ph, sizeof(ph), NULL);
3608
3609 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("encoding"), ZEND_ACC_PUBLIC TSRMLS_CC);
3610 ph.read = php_pqconn_object_read_encoding;
3611 ph.write = php_pqconn_object_write_encoding;
3612 zend_hash_add(&php_pqconn_object_prophandlers, "encoding", sizeof("encoding"), (void *) &ph, sizeof(ph), NULL);
3613 ph.write = NULL;
3614
3615 zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("unbuffered"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
3616 ph.read = php_pqconn_object_read_unbuffered;
3617 ph.write = php_pqconn_object_write_unbuffered;
3618 zend_hash_add(&php_pqconn_object_prophandlers, "unbuffered", sizeof("unbuffered"), (void *) &ph, sizeof(ph), NULL);
3619 ph.write = NULL;
3620
3621 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("db"), ZEND_ACC_PUBLIC TSRMLS_CC);
3622 ph.read = php_pqconn_object_read_db;
3623 zend_hash_add(&php_pqconn_object_prophandlers, "db", sizeof("db"), (void *) &ph, sizeof(ph), NULL);
3624
3625 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("user"), ZEND_ACC_PUBLIC TSRMLS_CC);
3626 ph.read = php_pqconn_object_read_user;
3627 zend_hash_add(&php_pqconn_object_prophandlers, "user", sizeof("user"), (void *) &ph, sizeof(ph), NULL);
3628
3629 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("pass"), ZEND_ACC_PUBLIC TSRMLS_CC);
3630 ph.read = php_pqconn_object_read_pass;
3631 zend_hash_add(&php_pqconn_object_prophandlers, "pass", sizeof("pass"), (void *) &ph, sizeof(ph), NULL);
3632
3633 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("host"), ZEND_ACC_PUBLIC TSRMLS_CC);
3634 ph.read = php_pqconn_object_read_host;
3635 zend_hash_add(&php_pqconn_object_prophandlers, "host", sizeof("host"), (void *) &ph, sizeof(ph), NULL);
3636
3637 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("port"), ZEND_ACC_PUBLIC TSRMLS_CC);
3638 ph.read = php_pqconn_object_read_port;
3639 zend_hash_add(&php_pqconn_object_prophandlers, "port", sizeof("port"), (void *) &ph, sizeof(ph), NULL);
3640
3641 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("options"), ZEND_ACC_PUBLIC TSRMLS_CC);
3642 ph.read = php_pqconn_object_read_options;
3643 zend_hash_add(&php_pqconn_object_prophandlers, "options", sizeof("options"), (void *) &ph, sizeof(ph), NULL);
3644
3645 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("OK"), CONNECTION_OK TSRMLS_CC);
3646 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("BAD"), CONNECTION_BAD TSRMLS_CC);
3647 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("STARTED"), CONNECTION_STARTED TSRMLS_CC);
3648 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("MADE"), CONNECTION_MADE TSRMLS_CC);
3649 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("AWAITING_RESPONSE"), CONNECTION_AWAITING_RESPONSE TSRMLS_CC);
3650 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("AUTH_OK"), CONNECTION_AUTH_OK TSRMLS_CC);
3651 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("SSL_STARTUP"), CONNECTION_SSL_STARTUP TSRMLS_CC);
3652 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("SETENV"), CONNECTION_SETENV TSRMLS_CC);
3653
3654 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_IDLE"), PQTRANS_IDLE TSRMLS_CC);
3655 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_ACTIVE"), PQTRANS_ACTIVE TSRMLS_CC);
3656 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_INTRANS"), PQTRANS_INTRANS TSRMLS_CC);
3657 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_INERROR"), PQTRANS_INERROR TSRMLS_CC);
3658 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_UNKNOWN"), PQTRANS_UNKNOWN TSRMLS_CC);
3659
3660 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_FAILED"), PGRES_POLLING_FAILED TSRMLS_CC);
3661 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_READING"), PGRES_POLLING_READING TSRMLS_CC);
3662 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_WRITING"), PGRES_POLLING_WRITING TSRMLS_CC);
3663 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_OK"), PGRES_POLLING_OK TSRMLS_CC);
3664
3665 memset(&ce, 0, sizeof(ce));
3666 INIT_NS_CLASS_ENTRY(ce, "pq", "Types", php_pqtypes_methods);
3667 php_pqtypes_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
3668 php_pqtypes_class_entry->create_object = php_pqtypes_create_object;
3669
3670 memcpy(&php_pqtypes_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
3671 php_pqtypes_object_handlers.read_property = php_pq_object_read_prop;
3672 php_pqtypes_object_handlers.write_property = php_pq_object_write_prop;
3673 php_pqtypes_object_handlers.clone_obj = NULL;
3674 php_pqtypes_object_handlers.get_property_ptr_ptr = NULL;
3675 php_pqtypes_object_handlers.get_debug_info = php_pq_object_debug_info;
3676 php_pqtypes_object_handlers.has_dimension = php_pqtypes_object_has_dimension;
3677 php_pqtypes_object_handlers.read_dimension = php_pqtypes_object_read_dimension;
3678 php_pqtypes_object_handlers.unset_dimension = NULL;
3679 php_pqtypes_object_handlers.write_dimension = NULL;
3680
3681 zend_hash_init(&php_pqtypes_object_prophandlers, 1, NULL, NULL, 1);
3682
3683 zend_declare_property_null(php_pqtypes_class_entry, ZEND_STRL("connection"), ZEND_ACC_PUBLIC TSRMLS_CC);
3684 ph.read = php_pqtypes_object_read_connection;
3685 zend_hash_add(&php_pqtypes_object_prophandlers, "connection", sizeof("connection"), (void *) &ph, sizeof(ph), NULL);
3686
3687 memset(&ce, 0, sizeof(ce));
3688 INIT_NS_CLASS_ENTRY(ce, "pq", "Result", php_pqres_methods);
3689 php_pqres_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
3690 php_pqres_class_entry->create_object = php_pqres_create_object;
3691 php_pqres_class_entry->iterator_funcs.funcs = &php_pqres_iterator_funcs;
3692 php_pqres_class_entry->get_iterator = php_pqres_iterator_init;
3693 zend_class_implements(php_pqres_class_entry TSRMLS_CC, 1, zend_ce_traversable);
3694
3695 memcpy(&php_pqres_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
3696 php_pqres_object_handlers.read_property = php_pq_object_read_prop;
3697 php_pqres_object_handlers.write_property = php_pq_object_write_prop;
3698 php_pqres_object_handlers.clone_obj = NULL;
3699 php_pqres_object_handlers.get_property_ptr_ptr = NULL;
3700 php_pqres_object_handlers.get_debug_info = php_pq_object_debug_info;
3701
3702 zend_hash_init(&php_pqres_object_prophandlers, 6, NULL, NULL, 1);
3703
3704 zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("status"), ZEND_ACC_PUBLIC TSRMLS_CC);
3705 ph.read = php_pqres_object_read_status;
3706 zend_hash_add(&php_pqres_object_prophandlers, "status", sizeof("status"), (void *) &ph, sizeof(ph), NULL);
3707
3708 zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC TSRMLS_CC);
3709 ph.read = php_pqres_object_read_error_message;
3710 zend_hash_add(&php_pqres_object_prophandlers, "errorMessage", sizeof("errorMessage"), (void *) &ph, sizeof(ph), NULL);
3711
3712 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("numRows"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
3713 ph.read = php_pqres_object_read_num_rows;
3714 zend_hash_add(&php_pqres_object_prophandlers, "numRows", sizeof("numRows"), (void *) &ph, sizeof(ph), NULL);
3715
3716 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("numCols"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
3717 ph.read = php_pqres_object_read_num_cols;
3718 zend_hash_add(&php_pqres_object_prophandlers, "numCols", sizeof("numCols"), (void *) &ph, sizeof(ph), NULL);
3719
3720 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("affectedRows"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
3721 ph.read = php_pqres_object_read_affected_rows;
3722 zend_hash_add(&php_pqres_object_prophandlers, "affectedRows", sizeof("affectedRows"), (void *) &ph, sizeof(ph), NULL);
3723
3724 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("fetchType"), PHP_PQRES_FETCH_ARRAY, ZEND_ACC_PUBLIC TSRMLS_CC);
3725 ph.read = php_pqres_object_read_fetch_type;
3726 ph.write = php_pqres_object_write_fetch_type;
3727 zend_hash_add(&php_pqres_object_prophandlers, "fetchType", sizeof("fetchType"), (void *) &ph, sizeof(ph), NULL);
3728 ph.write = NULL;
3729
3730 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("EMPTY_QUERY"), PGRES_EMPTY_QUERY TSRMLS_CC);
3731 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COMMAND_OK"), PGRES_COMMAND_OK TSRMLS_CC);
3732 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("TUPLES_OK"), PGRES_TUPLES_OK TSRMLS_CC);
3733 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_OUT"), PGRES_COPY_OUT TSRMLS_CC);
3734 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_IN"), PGRES_COPY_IN TSRMLS_CC);
3735 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("BAD_RESPONSE"), PGRES_BAD_RESPONSE TSRMLS_CC);
3736 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("NONFATAL_ERROR"), PGRES_NONFATAL_ERROR TSRMLS_CC);
3737 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FATAL_ERROR"), PGRES_FATAL_ERROR TSRMLS_CC);
3738 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_BOTH"), PGRES_COPY_BOTH TSRMLS_CC);
3739 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("SINGLE_TUPLE"), PGRES_SINGLE_TUPLE TSRMLS_CC);
3740
3741 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_ARRAY"), PHP_PQRES_FETCH_ARRAY TSRMLS_CC);
3742 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_ASSOC"), PHP_PQRES_FETCH_ASSOC TSRMLS_CC);
3743 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_OBJECT"), PHP_PQRES_FETCH_OBJECT TSRMLS_CC);
3744
3745 memset(&ce, 0, sizeof(ce));
3746 INIT_NS_CLASS_ENTRY(ce, "pq", "Statement", php_pqstm_methods);
3747 php_pqstm_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
3748 php_pqstm_class_entry->create_object = php_pqstm_create_object;
3749
3750 memcpy(&php_pqstm_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
3751 php_pqstm_object_handlers.read_property = php_pq_object_read_prop;
3752 php_pqstm_object_handlers.write_property = php_pq_object_write_prop;
3753 php_pqstm_object_handlers.clone_obj = NULL;
3754 php_pqstm_object_handlers.get_property_ptr_ptr = NULL;
3755 php_pqstm_object_handlers.get_debug_info = php_pq_object_debug_info;
3756
3757 zend_hash_init(&php_pqstm_object_prophandlers, 2, NULL, NULL, 1);
3758
3759 zend_declare_property_null(php_pqstm_class_entry, ZEND_STRL("name"), ZEND_ACC_PUBLIC TSRMLS_CC);
3760 ph.read = php_pqstm_object_read_name;
3761 zend_hash_add(&php_pqstm_object_prophandlers, "name", sizeof("name"), (void *) &ph, sizeof(ph), NULL);
3762
3763 zend_declare_property_null(php_pqstm_class_entry, ZEND_STRL("connection"), ZEND_ACC_PUBLIC TSRMLS_CC);
3764 ph.read = php_pqstm_object_read_connection;
3765 zend_hash_add(&php_pqstm_object_prophandlers, "connection", sizeof("connection"), (void *) &ph, sizeof(ph), NULL);
3766
3767 memset(&ce, 0, sizeof(ce));
3768 INIT_NS_CLASS_ENTRY(ce, "pq", "Transaction", php_pqtxn_methods);
3769 php_pqtxn_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
3770 php_pqtxn_class_entry->create_object = php_pqtxn_create_object;
3771
3772 memcpy(&php_pqtxn_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
3773 php_pqtxn_object_handlers.read_property = php_pq_object_read_prop;
3774 php_pqtxn_object_handlers.write_property = php_pq_object_write_prop;
3775 php_pqtxn_object_handlers.clone_obj = NULL;
3776 php_pqtxn_object_handlers.get_property_ptr_ptr = NULL;
3777 php_pqtxn_object_handlers.get_debug_info = php_pq_object_debug_info;
3778
3779 zend_hash_init(&php_pqtxn_object_prophandlers, 4, NULL, NULL, 1);
3780
3781 zend_declare_property_null(php_pqtxn_class_entry, ZEND_STRL("connection"), ZEND_ACC_PUBLIC TSRMLS_CC);
3782 ph.read = php_pqtxn_object_read_connection;
3783 zend_hash_add(&php_pqtxn_object_prophandlers, "connection", sizeof("connection"), (void *) &ph, sizeof(ph), NULL);
3784
3785 zend_declare_property_null(php_pqtxn_class_entry, ZEND_STRL("isolation"), ZEND_ACC_PUBLIC TSRMLS_CC);
3786 ph.read = php_pqtxn_object_read_isolation;
3787 ph.write = php_pqtxn_object_write_isolation;
3788 zend_hash_add(&php_pqtxn_object_prophandlers, "isolation", sizeof("isolation"), (void *) &ph, sizeof(ph), NULL);
3789
3790 zend_declare_property_null(php_pqtxn_class_entry, ZEND_STRL("readonly"), ZEND_ACC_PUBLIC TSRMLS_CC);
3791 ph.read = php_pqtxn_object_read_readonly;
3792 ph.write = php_pqtxn_object_write_readonly;
3793 zend_hash_add(&php_pqtxn_object_prophandlers, "readonly", sizeof("readonly"), (void *) &ph, sizeof(ph), NULL);
3794
3795 zend_declare_property_null(php_pqtxn_class_entry, ZEND_STRL("deferrable"), ZEND_ACC_PUBLIC TSRMLS_CC);
3796 ph.read = php_pqtxn_object_read_deferrable;
3797 ph.write = php_pqtxn_object_write_deferrable;
3798 zend_hash_add(&php_pqtxn_object_prophandlers, "deferrable", sizeof("deferrable"), (void *) &ph, sizeof(ph), NULL);
3799 ph.write = NULL;
3800
3801 zend_declare_class_constant_long(php_pqtxn_class_entry, ZEND_STRL("READ_COMMITTED"), PHP_PQTXN_READ_COMMITTED TSRMLS_CC);
3802 zend_declare_class_constant_long(php_pqtxn_class_entry, ZEND_STRL("REPEATABLE READ"), PHP_PQTXN_REPEATABLE_READ TSRMLS_CC);
3803 zend_declare_class_constant_long(php_pqtxn_class_entry, ZEND_STRL("SERIALIZABLE"), PHP_PQTXN_SERIALIZABLE TSRMLS_CC);
3804
3805 memset(&ce, 0, sizeof(ce));
3806 INIT_NS_CLASS_ENTRY(ce, "pq", "Cancel", php_pqcancel_methods);
3807 php_pqcancel_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
3808 php_pqcancel_class_entry->create_object = php_pqcancel_create_object;
3809
3810 memcpy(&php_pqcancel_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
3811 php_pqcancel_object_handlers.read_property = php_pq_object_read_prop;
3812 php_pqcancel_object_handlers.write_property = php_pq_object_write_prop;
3813 php_pqcancel_object_handlers.clone_obj = NULL;
3814 php_pqcancel_object_handlers.get_property_ptr_ptr = NULL;
3815 php_pqcancel_object_handlers.get_debug_info = php_pq_object_debug_info;
3816
3817 zend_hash_init(&php_pqcancel_object_prophandlers, 1, NULL, NULL, 1);
3818
3819 zend_declare_property_null(php_pqcancel_class_entry, ZEND_STRL("connection"), ZEND_ACC_PUBLIC TSRMLS_CC);
3820 ph.read = php_pqcancel_object_read_connection;
3821 zend_hash_add(&php_pqcancel_object_prophandlers, "connection", sizeof("connection"), (void *) &ph, sizeof(ph), NULL);
3822
3823 memset(&ce, 0, sizeof(ce));
3824 INIT_NS_CLASS_ENTRY(ce, "pq", "Event", php_pqevent_methods);
3825 php_pqevent_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
3826 php_pqevent_class_entry->create_object = php_pqevent_create_object;
3827
3828 memcpy(&php_pqevent_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
3829 php_pqevent_object_handlers.read_property = php_pq_object_read_prop;
3830 php_pqevent_object_handlers.write_property = php_pq_object_write_prop;
3831 php_pqevent_object_handlers.clone_obj = NULL;
3832 php_pqevent_object_handlers.get_property_ptr_ptr = NULL;
3833 php_pqevent_object_handlers.get_debug_info = php_pq_object_debug_info;
3834
3835 zend_hash_init(&php_pqevent_object_prophandlers, 2, NULL, NULL, 1);
3836
3837 zend_declare_property_null(php_pqevent_class_entry, ZEND_STRL("connection"), ZEND_ACC_PUBLIC TSRMLS_CC);
3838 ph.read = php_pqevent_object_read_connection;
3839 zend_hash_add(&php_pqevent_object_prophandlers, "connection", sizeof("connection"), (void *) &ph, sizeof(ph), NULL);
3840
3841 zend_declare_property_null(php_pqevent_class_entry, ZEND_STRL("type"), ZEND_ACC_PUBLIC TSRMLS_CC);
3842 ph.read = php_pqevent_object_read_type;
3843 zend_hash_add(&php_pqevent_object_prophandlers, "type", sizeof("type"), (void *) &ph, sizeof(ph), NULL);
3844
3845 zend_declare_class_constant_stringl(php_pqevent_class_entry, ZEND_STRL("NOTICE"), ZEND_STRL("notice") TSRMLS_CC);
3846 zend_declare_class_constant_stringl(php_pqevent_class_entry, ZEND_STRL("RESULT"), ZEND_STRL("result") TSRMLS_CC);
3847 zend_declare_class_constant_stringl(php_pqevent_class_entry, ZEND_STRL("RESET"), ZEND_STRL("reset") TSRMLS_CC);
3848
3849 memset(&ce, 0, sizeof(ce));
3850 INIT_NS_CLASS_ENTRY(ce, "pq", "LOB", php_pqlob_methods);
3851 php_pqlob_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
3852 php_pqlob_class_entry->create_object = php_pqlob_create_object;
3853
3854 memcpy(&php_pqlob_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
3855 php_pqlob_object_handlers.read_property = php_pq_object_read_prop;
3856 php_pqlob_object_handlers.write_property = php_pq_object_write_prop;
3857 php_pqlob_object_handlers.clone_obj = NULL;
3858 php_pqlob_object_handlers.get_property_ptr_ptr = NULL;
3859 php_pqlob_object_handlers.get_debug_info = php_pq_object_debug_info;
3860
3861 zend_hash_init(&php_pqlob_object_prophandlers, 2, NULL, NULL, 1);
3862
3863 zend_declare_property_null(php_pqlob_class_entry, ZEND_STRL("transaction"), ZEND_ACC_PUBLIC TSRMLS_CC);
3864 ph.read = php_pqlob_object_read_transaction;
3865 zend_hash_add(&php_pqlob_object_prophandlers, "transaction", sizeof("transaction"), (void *) &ph, sizeof(ph), NULL);
3866
3867 zend_declare_property_long(php_pqlob_class_entry, ZEND_STRL("oid"), InvalidOid, ZEND_ACC_PUBLIC TSRMLS_CC);
3868 ph.read = php_pqlob_object_read_oid;
3869 zend_hash_add(&php_pqlob_object_prophandlers, "oid", sizeof("oid"), (void *) &ph, sizeof(ph), NULL);
3870
3871 zend_declare_class_constant_long(php_pqlob_class_entry, ZEND_STRL("INVALID_OID"), InvalidOid TSRMLS_CC);
3872 zend_declare_class_constant_long(php_pqlob_class_entry, ZEND_STRL("R"), INV_READ TSRMLS_CC);
3873 zend_declare_class_constant_long(php_pqlob_class_entry, ZEND_STRL("W"), INV_WRITE TSRMLS_CC);
3874 zend_declare_class_constant_long(php_pqlob_class_entry, ZEND_STRL("RW"), INV_READ|INV_WRITE TSRMLS_CC);
3875
3876 /*
3877 REGISTER_INI_ENTRIES();
3878 */
3879 return SUCCESS;
3880 }
3881 /* }}} */
3882
3883 /* {{{ PHP_MSHUTDOWN_FUNCTION
3884 */
3885 static PHP_MSHUTDOWN_FUNCTION(pq)
3886 {
3887 /* uncomment this line if you have INI entries
3888 UNREGISTER_INI_ENTRIES();
3889 */
3890 return SUCCESS;
3891 }
3892 /* }}} */
3893
3894 /* {{{ PHP_MINFO_FUNCTION
3895 */
3896 static PHP_MINFO_FUNCTION(pq)
3897 {
3898 php_info_print_table_start();
3899 php_info_print_table_header(2, "pq support", "enabled");
3900 php_info_print_table_end();
3901
3902 /* Remove comments if you have entries in php.ini
3903 DISPLAY_INI_ENTRIES();
3904 */
3905 }
3906 /* }}} */
3907
3908 const zend_function_entry pq_functions[] = {
3909 {0}
3910 };
3911
3912 /* {{{ pq_module_entry
3913 */
3914 zend_module_entry pq_module_entry = {
3915 STANDARD_MODULE_HEADER,
3916 "pq",
3917 pq_functions,
3918 PHP_MINIT(pq),
3919 PHP_MSHUTDOWN(pq),
3920 NULL,/*PHP_RINIT(pq),*/
3921 NULL,/*PHP_RSHUTDOWN(pq),*/
3922 PHP_MINFO(pq),
3923 PHP_PQ_EXT_VERSION,
3924 STANDARD_MODULE_PROPERTIES
3925 };
3926 /* }}} */
3927
3928 #ifdef COMPILE_DL_PQ
3929 ZEND_GET_MODULE(pq)
3930 #endif
3931
3932
3933 /*
3934 * Local variables:
3935 * tab-width: 4
3936 * c-basic-offset: 4
3937 * End:
3938 * vim600: noet sw=4 ts=4 fdm=marker
3939 * vim<600: noet sw=4 ts=4
3940 */