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