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