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