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