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