convert zend_hash_apply_with_argument(s)
[m6w6/ext-pq] / src / php_pqconn.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
19 #define SMART_STR_PREALLOC 256
20 #include <ext/standard/php_smart_str.h>
21
22 #include <libpq-events.h>
23 #include <fnmatch.h>
24
25 #include "php_pq.h"
26 #include "php_pq_misc.h"
27 #include "php_pq_object.h"
28 #include "php_pqexc.h"
29 #include "php_pqconn.h"
30 #include "php_pqconn_event.h"
31 #include "php_pqres.h"
32 #include "php_pqstm.h"
33 #include "php_pqtxn.h"
34 #include "php_pqcur.h"
35
36 zend_class_entry *php_pqconn_class_entry;
37 static zend_object_handlers php_pqconn_object_handlers;
38 static HashTable php_pqconn_object_prophandlers;
39
40 /*
41 static void php_pqconn_del_eventhandler(php_pqconn_object_t *obj, const char *type_str, size_t type_len, ulong id TSRMLS_DC)
42 {
43 zval **evhs;
44
45 if (SUCCESS == zend_hash_find(&obj->intern->eventhandlers, type_str, type_len + 1, (void *) &evhs)) {
46 zend_hash_index_del(Z_ARRVAL_PP(evhs), id);
47 }
48 }
49 */
50
51 static ulong php_pqconn_add_eventhandler(php_pqconn_object_t *obj, const char *type_str, size_t type_len, php_pq_callback_t *cb TSRMLS_DC)
52 {
53 ulong h;
54 HashTable *evhs;
55
56 if (SUCCESS != zend_hash_find(&obj->intern->eventhandlers, type_str, type_len + 1, (void *) &evhs)) {
57 HashTable evh;
58
59 zend_hash_init(&evh, 1, NULL, (dtor_func_t) php_pq_callback_dtor, 0);
60 zend_hash_add(&obj->intern->eventhandlers, type_str, type_len + 1, (void *) &evh, sizeof(evh), (void *) &evhs);
61 }
62
63 php_pq_callback_addref(cb);
64 h = zend_hash_next_free_element(evhs);
65 zend_hash_index_update(evhs, h, (void *) cb, sizeof(*cb), NULL);
66
67 return h;
68 }
69
70 static void php_pqconn_object_free(void *o TSRMLS_DC)
71 {
72 php_pqconn_object_t *obj = o;
73 #if DBG_GC
74 fprintf(stderr, "FREE conn(#%d) %p\n", obj->zv.handle, obj);
75 #endif
76 if (obj->intern) {
77 php_pq_callback_dtor(&obj->intern->onevent);
78 php_resource_factory_handle_dtor(&obj->intern->factory, obj->intern->conn TSRMLS_CC);
79 php_resource_factory_dtor(&obj->intern->factory);
80 zend_hash_destroy(&obj->intern->listeners);
81 zend_hash_destroy(&obj->intern->converters);
82 zend_hash_destroy(&obj->intern->eventhandlers);
83 efree(obj->intern);
84 obj->intern = NULL;
85 }
86 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
87 efree(obj);
88 }
89
90
91 zend_object_value php_pqconn_create_object_ex(zend_class_entry *ce, php_pqconn_t *intern, php_pqconn_object_t **ptr TSRMLS_DC)
92 {
93 php_pqconn_object_t *o;
94
95 o = ecalloc(1, sizeof(*o));
96 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
97 object_properties_init((zend_object *) o, ce);
98 o->prophandler = &php_pqconn_object_prophandlers;
99
100 if (ptr) {
101 *ptr = o;
102 }
103
104 if (intern) {
105 o->intern = intern;
106 }
107
108 o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqconn_object_free, NULL TSRMLS_CC);
109 o->zv.handlers = &php_pqconn_object_handlers;
110
111 return o->zv;
112 }
113
114 static zend_object_value php_pqconn_create_object(zend_class_entry *class_type TSRMLS_DC)
115 {
116 return php_pqconn_create_object_ex(class_type, NULL, NULL TSRMLS_CC);
117 }
118
119 static void php_pqconn_object_read_status(zval *object, void *o, zval *return_value TSRMLS_DC)
120 {
121 php_pqconn_object_t *obj = o;
122
123 RETVAL_LONG(PQstatus(obj->intern->conn));
124 }
125
126 static void php_pqconn_object_read_transaction_status(zval *object, void *o, zval *return_value TSRMLS_DC)
127 {
128 php_pqconn_object_t *obj = o;
129
130 RETVAL_LONG(PQtransactionStatus(obj->intern->conn));
131 }
132
133 static void php_pqconn_object_read_error_message(zval *object, void *o, zval *return_value TSRMLS_DC)
134 {
135 php_pqconn_object_t *obj = o;
136 char *error = PHP_PQerrorMessage(obj->intern->conn);
137
138 if (error) {
139 RETVAL_STRING(error, 1);
140 } else {
141 RETVAL_NULL();
142 }
143 }
144
145 static int apply_notify_listener(void *p, void *arg TSRMLS_DC)
146 {
147 php_pq_callback_t *listener = p;
148 PGnotify *nfy = arg;
149 zval *zpid, *zchannel, *zmessage;
150
151 MAKE_STD_ZVAL(zpid);
152 ZVAL_LONG(zpid, nfy->be_pid);
153 MAKE_STD_ZVAL(zchannel);
154 ZVAL_STRING(zchannel, nfy->relname, 1);
155 MAKE_STD_ZVAL(zmessage);
156 ZVAL_STRING(zmessage, nfy->extra, 1);
157
158 zend_fcall_info_argn(&listener->fci TSRMLS_CC, 3, &zchannel, &zmessage, &zpid);
159 zend_fcall_info_call(&listener->fci, &listener->fcc, NULL, NULL TSRMLS_CC);
160
161 zval_ptr_dtor(&zchannel);
162 zval_ptr_dtor(&zmessage);
163 zval_ptr_dtor(&zpid);
164
165 return ZEND_HASH_APPLY_KEEP;
166 }
167
168 static int apply_notify_listeners(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
169 {
170 HashTable *listeners = p;
171 PGnotify *nfy = va_arg(argv, PGnotify *);
172
173 if (0 == fnmatch(key->arKey, nfy->relname, 0)) {
174 zend_hash_apply_with_argument(listeners, apply_notify_listener, nfy TSRMLS_CC);
175 }
176
177 return ZEND_HASH_APPLY_KEEP;
178 }
179
180 void php_pqconn_notify_listeners(php_pqconn_object_t *obj TSRMLS_DC)
181 {
182 PGnotify *nfy;
183
184 while ((nfy = PQnotifies(obj->intern->conn))) {
185 zend_hash_apply_with_arguments(&obj->intern->listeners TSRMLS_CC, apply_notify_listeners, 1, nfy);
186 PQfreemem(nfy);
187 }
188 }
189
190 static void php_pqconn_object_read_busy(zval *object, void *o, zval *return_value TSRMLS_DC)
191 {
192 php_pqconn_object_t *obj = o;
193
194 RETVAL_BOOL(PQisBusy(obj->intern->conn));
195 }
196
197 static void php_pqconn_object_read_encoding(zval *object, void *o, zval *return_value TSRMLS_DC)
198 {
199 php_pqconn_object_t *obj = o;
200
201 RETVAL_STRING(pg_encoding_to_char(PQclientEncoding(obj->intern->conn)), 1);
202 }
203
204 static void php_pqconn_object_write_encoding(zval *object, void *o, zval *value TSRMLS_DC)
205 {
206 php_pqconn_object_t *obj = o;
207 zval *zenc = value;
208
209 if (Z_TYPE_P(value) != IS_STRING) {
210 if (Z_REFCOUNT_P(value) > 1) {
211 zval *tmp;
212 MAKE_STD_ZVAL(tmp);
213 ZVAL_ZVAL(tmp, zenc, 1, 0);
214 convert_to_string(tmp);
215 zenc = tmp;
216 } else {
217 convert_to_string_ex(&zenc);
218 }
219 }
220
221 if (0 > PQsetClientEncoding(obj->intern->conn, Z_STRVAL_P(zenc))) {
222 php_error(E_NOTICE, "Unrecognized encoding '%s'", Z_STRVAL_P(zenc));
223 }
224
225 if (zenc != value) {
226 zval_ptr_dtor(&zenc);
227 }
228 }
229
230 static void php_pqconn_object_read_unbuffered(zval *object, void *o, zval *return_value TSRMLS_DC)
231 {
232 php_pqconn_object_t *obj = o;
233
234 RETVAL_BOOL(obj->intern->unbuffered);
235 }
236
237 static void php_pqconn_object_write_unbuffered(zval *object, void *o, zval *value TSRMLS_DC)
238 {
239 php_pqconn_object_t *obj = o;
240
241 obj->intern->unbuffered = z_is_true(value);
242 }
243
244 static void php_pqconn_object_read_db(zval *object, void *o, zval *return_value TSRMLS_DC)
245 {
246 php_pqconn_object_t *obj = o;
247 char *db = PQdb(obj->intern->conn);
248
249 if (db) {
250 RETVAL_STRING(db, 1);
251 } else {
252 RETVAL_EMPTY_STRING();
253 }
254 }
255
256 static void php_pqconn_object_read_user(zval *object, void *o, zval *return_value TSRMLS_DC)
257 {
258 php_pqconn_object_t *obj = o;
259 char *user = PQuser(obj->intern->conn);
260
261 if (user) {
262 RETVAL_STRING(user, 1);
263 } else {
264 RETVAL_EMPTY_STRING();
265 }
266 }
267
268 static void php_pqconn_object_read_pass(zval *object, void *o, zval *return_value TSRMLS_DC)
269 {
270 php_pqconn_object_t *obj = o;
271 char *pass = PQpass(obj->intern->conn);
272
273 if (pass) {
274 RETVAL_STRING(pass, 1);
275 } else {
276 RETVAL_EMPTY_STRING();
277 }
278 }
279
280 static void php_pqconn_object_read_host(zval *object, void *o, zval *return_value TSRMLS_DC)
281 {
282 php_pqconn_object_t *obj = o;
283 char *host = PQhost(obj->intern->conn);
284
285 if (host) {
286 RETVAL_STRING(host, 1);
287 } else {
288 RETVAL_EMPTY_STRING();
289 }
290 }
291
292 static void php_pqconn_object_read_port(zval *object, void *o, zval *return_value TSRMLS_DC)
293 {
294 php_pqconn_object_t *obj = o;
295 char *port = PQport(obj->intern->conn);
296
297 if (port) {
298 RETVAL_STRING(port, 1);
299 } else {
300 RETVAL_EMPTY_STRING();
301 }
302 }
303
304 static void php_pqconn_object_read_options(zval *object, void *o, zval *return_value TSRMLS_DC)
305 {
306 php_pqconn_object_t *obj = o;
307 char *options = PQoptions(obj->intern->conn);
308
309 if (options) {
310 RETVAL_STRING(options, 1);
311 } else {
312 RETVAL_EMPTY_STRING();
313 }
314 }
315
316 static int apply_read_event_handler_ex(void *p, void *arg TSRMLS_DC)
317 {
318 HashTable *rv = arg;
319 zval *zcb = php_pq_callback_to_zval(p);
320
321 zend_hash_next_index_insert(rv, &zcb, sizeof(zval *), NULL);
322
323 return ZEND_HASH_APPLY_KEEP;
324 }
325
326 static int apply_read_event_handlers(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
327 {
328 HashTable *evhs = p, *rv = va_arg(argv, HashTable *);
329 zval *entry, **entry_ptr;
330
331 MAKE_STD_ZVAL(entry);
332 array_init_size(entry, zend_hash_num_elements(evhs));
333
334 if (key->nKeyLength) {
335 zend_hash_add(rv, key->arKey, key->nKeyLength, &entry, sizeof(zval *), (void *) &entry_ptr);
336 } else {
337 zend_hash_index_update(rv, key->h, &entry, sizeof(zval *), (void *) &entry_ptr);
338 }
339
340 zend_hash_apply_with_argument(evhs, apply_read_event_handler_ex, Z_ARRVAL_PP(entry_ptr) TSRMLS_CC);
341
342 return ZEND_HASH_APPLY_KEEP;
343 }
344 static void php_pqconn_object_read_event_handlers(zval *object, void *o, zval *return_value TSRMLS_DC)
345 {
346 php_pqconn_object_t *obj = o;
347
348 array_init(return_value);
349 zend_hash_apply_with_arguments(&obj->intern->eventhandlers TSRMLS_CC, apply_read_event_handlers, 1, Z_ARRVAL_P(return_value) TSRMLS_CC);
350 }
351
352 static void php_pqconn_object_read_def_fetch_type(zval *object, void *o, zval *return_value TSRMLS_DC)
353 {
354 php_pqconn_object_t *obj = o;
355
356 RETVAL_LONG(obj->intern->default_fetch_type);
357 }
358 static void php_pqconn_object_write_def_fetch_type(zval *object, void *o, zval *value TSRMLS_DC)
359 {
360 php_pqconn_object_t *obj = o;
361 zval *zft = value;
362
363 if (Z_TYPE_P(zft) != IS_LONG) {
364 if (Z_REFCOUNT_P(zft) > 1) {
365 zval *tmp;
366 MAKE_STD_ZVAL(tmp);
367 ZVAL_ZVAL(tmp, zft, 1, 0);
368 convert_to_long(tmp);
369 zft = tmp;
370 } else {
371 convert_to_long_ex(&zft);
372 }
373 }
374
375 obj->intern->default_fetch_type = Z_LVAL_P(zft) & 0x3; /* two bits only */
376
377 if (zft != value) {
378 zval_ptr_dtor(&zft);
379 }
380 }
381
382 static void php_pqconn_object_read_def_txn_isolation(zval *object, void *o, zval *return_value TSRMLS_DC)
383 {
384 php_pqconn_object_t *obj = o;
385
386 RETVAL_LONG(obj->intern->default_txn_isolation);
387 }
388 static void php_pqconn_object_write_def_txn_isolation(zval *object, void *o, zval *value TSRMLS_DC)
389 {
390 php_pqconn_object_t *obj = o;
391 zval *zti = value;
392
393 if (Z_TYPE_P(zti) != IS_LONG) {
394 if (Z_REFCOUNT_P(zti) > 1) {
395 zval *tmp;
396 MAKE_STD_ZVAL(tmp);
397 ZVAL_ZVAL(tmp, zti, 1, 0);
398 convert_to_long(tmp);
399 zti = tmp;
400 } else {
401 convert_to_long_ex(&zti);
402 }
403 }
404
405 obj->intern->default_txn_isolation = Z_LVAL_P(zti) & 0x3; /* two bits only */
406
407 if (zti != value) {
408 zval_ptr_dtor(&zti);
409 }
410 }
411
412 static void php_pqconn_object_read_def_txn_readonly(zval *object, void *o, zval *return_value TSRMLS_DC)
413 {
414 php_pqconn_object_t *obj = o;
415
416 RETVAL_BOOL(obj->intern->default_txn_readonly);
417 }
418 static void php_pqconn_object_write_def_txn_readonly(zval *object, void *o, zval *value TSRMLS_DC)
419 {
420 php_pqconn_object_t *obj = o;
421
422 obj->intern->default_txn_readonly = zend_is_true(value);
423 }
424
425 static void php_pqconn_object_read_def_txn_deferrable(zval *object, void *o, zval *return_value TSRMLS_DC)
426 {
427 php_pqconn_object_t *obj = o;
428
429 RETVAL_BOOL(obj->intern->default_txn_deferrable);
430 }
431 static void php_pqconn_object_write_def_txn_deferrable(zval *object, void *o, zval *value TSRMLS_DC)
432 {
433 php_pqconn_object_t *obj = o;
434
435 obj->intern->default_txn_deferrable = zend_is_true(value);
436 }
437
438 static void php_pqconn_object_read_def_auto_conv(zval *object, void *o, zval *return_value TSRMLS_DC)
439 {
440 php_pqconn_object_t *obj = o;
441
442 RETVAL_LONG(obj->intern->default_auto_convert);
443 }
444 static void php_pqconn_object_write_def_auto_conv(zval*object, void *o, zval *value TSRMLS_DC)
445 {
446 php_pqconn_object_t *obj = o;
447 zval *zac = value;
448
449 if (Z_TYPE_P(zac) != IS_LONG) {
450 if (Z_REFCOUNT_P(zac) > 1) {
451 zval *tmp;
452 MAKE_STD_ZVAL(tmp);
453 ZVAL_ZVAL(tmp, zac, 1, 0);
454 convert_to_long(tmp);
455 zac = tmp;
456 } else {
457 convert_to_long_ex(&zac);
458 }
459 }
460
461 obj->intern->default_auto_convert = Z_LVAL_P(zac) & PHP_PQRES_CONV_ALL;
462
463 if (zac != value) {
464 zval_ptr_dtor(&zac);
465 }
466 }
467
468 static STATUS php_pqconn_update_socket(zval *this_ptr, php_pqconn_object_t *obj TSRMLS_DC)
469 {
470 zval *zsocket, zmember;
471 php_stream *stream;
472 STATUS retval;
473 int socket;
474
475 if (!obj) {
476 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
477 }
478
479 INIT_PZVAL(&zmember);
480 ZVAL_STRINGL(&zmember, "socket", sizeof("socket")-1, 0);
481 MAKE_STD_ZVAL(zsocket);
482
483 if ((CONNECTION_BAD != PQstatus(obj->intern->conn))
484 && (-1 < (socket = PQsocket(obj->intern->conn)))
485 && (stream = php_stream_fopen_from_fd(socket, "r+b", NULL))) {
486 stream->flags |= PHP_STREAM_FLAG_NO_CLOSE;
487 php_stream_to_zval(stream, zsocket);
488 retval = SUCCESS;
489 } else {
490 ZVAL_NULL(zsocket);
491 retval = FAILURE;
492 }
493 zend_get_std_object_handlers()->write_property(getThis(), &zmember, zsocket, NULL TSRMLS_CC);
494 zval_ptr_dtor(&zsocket);
495
496 return retval;
497 }
498
499 static void *php_pqconn_resource_factory_ctor(void *data, void *init_arg TSRMLS_DC)
500 {
501 php_pqconn_resource_factory_data_t *o = init_arg;
502 PGconn *conn = NULL;;
503
504 if (o->flags & PHP_PQCONN_ASYNC) {
505 conn = PQconnectStart(o->dsn);
506 } else {
507 conn = PQconnectdb(o->dsn);
508 }
509
510 if (conn) {
511 PQregisterEventProc(conn, php_pqconn_event, "ext-pq", NULL);
512 }
513
514 return conn;
515 }
516
517 static void php_pqconn_resource_factory_dtor(void *opaque, void *handle TSRMLS_DC)
518 {
519 php_pqconn_event_data_t *evdata = PQinstanceData(handle, php_pqconn_event);
520
521 /* we don't care for anything, except free'ing evdata */
522 if (evdata) {
523 PQsetInstanceData(handle, php_pqconn_event, NULL);
524 memset(evdata, 0, sizeof(*evdata));
525 efree(evdata);
526 }
527
528 PQfinish(handle);
529 }
530
531 static php_resource_factory_ops_t php_pqconn_resource_factory_ops = {
532 php_pqconn_resource_factory_ctor,
533 NULL,
534 php_pqconn_resource_factory_dtor
535 };
536
537 php_resource_factory_ops_t *php_pqconn_get_resource_factory_ops(void)
538 {
539 return &php_pqconn_resource_factory_ops;
540 }
541
542 static void php_pqconn_wakeup(php_persistent_handle_factory_t *f, void **handle TSRMLS_DC)
543 {
544 PGresult *res = PQexec(*handle, "");
545 PHP_PQclear(res);
546
547 if (CONNECTION_OK != PQstatus(*handle)) {
548 PQreset(*handle);
549 }
550 }
551
552 static inline PGresult *unlisten(PGconn *conn, const char *channel_str, size_t channel_len TSRMLS_DC)
553 {
554 char *quoted_channel = PQescapeIdentifier(conn, channel_str, channel_len);
555 PGresult *res = NULL;
556
557 if (quoted_channel) {
558 smart_str cmd = {0};
559
560 smart_str_appends(&cmd, "UNLISTEN ");
561 smart_str_appends(&cmd, quoted_channel);
562 smart_str_0(&cmd);
563
564 res = PQexec(conn, cmd.c);
565
566 smart_str_free(&cmd);
567 PQfreemem(quoted_channel);
568 }
569
570 return res;
571 }
572
573 static int apply_unlisten(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
574 {
575 php_pqconn_object_t *obj = va_arg(argv, php_pqconn_object_t *);
576 PGresult *res = unlisten(obj->intern->conn, key->arKey, key->nKeyLength - 1);
577
578 if (res) {
579 PHP_PQclear(res);
580 }
581
582 return ZEND_HASH_APPLY_REMOVE;
583 }
584
585 static void php_pqconn_retire(php_persistent_handle_factory_t *f, void **handle TSRMLS_DC)
586 {
587 php_pqconn_event_data_t *evdata = PQinstanceData(*handle, php_pqconn_event);
588 PGcancel *cancel;
589 PGresult *res;
590
591 /* go away */
592 PQsetInstanceData(*handle, php_pqconn_event, NULL);
593
594 /* ignore notices */
595 PQsetNoticeReceiver(*handle, php_pqconn_notice_ignore, NULL);
596
597 /* cancel async queries */
598 if (PQisBusy(*handle) && (cancel = PQgetCancel(*handle))) {
599 char err[256] = {0};
600
601 PQcancel(cancel, err, sizeof(err));
602 PQfreeCancel(cancel);
603 }
604 /* clean up async results */
605 while ((res = PQgetResult(*handle))) {
606 PHP_PQclear(res);
607 }
608
609 /* clean up transaction & session */
610 switch (PQtransactionStatus(*handle)) {
611 case PQTRANS_IDLE:
612 res = PQexec(*handle, "RESET ALL");
613 break;
614 default:
615 res = PQexec(*handle, "ROLLBACK; RESET ALL");
616 break;
617 }
618
619 if (res) {
620 PHP_PQclear(res);
621 }
622
623 if (evdata) {
624 /* clean up notify listeners */
625 zend_hash_apply_with_arguments(&evdata->obj->intern->listeners TSRMLS_CC, apply_unlisten, 1, evdata->obj);
626
627 /* release instance data */
628 efree(evdata);
629 }
630 }
631
632 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_construct, 0, 0, 1)
633 ZEND_ARG_INFO(0, dsn)
634 ZEND_ARG_INFO(0, async)
635 ZEND_END_ARG_INFO();
636 static PHP_METHOD(pqconn, __construct) {
637 zend_error_handling zeh;
638 char *dsn_str = "";
639 int dsn_len = 0;
640 long flags = 0;
641 STATUS rv;
642
643 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
644 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sl", &dsn_str, &dsn_len, &flags);
645 zend_restore_error_handling(&zeh TSRMLS_CC);
646
647 if (SUCCESS == rv) {
648 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
649
650 if (obj->intern) {
651 throw_exce(EX_BAD_METHODCALL TSRMLS_CC, "pq\\Connection already initialized");
652 } else {
653 php_pqconn_event_data_t *evdata = php_pqconn_event_data_init(obj TSRMLS_CC);
654 php_pqconn_resource_factory_data_t rfdata = {dsn_str, flags};
655
656 obj->intern = ecalloc(1, sizeof(*obj->intern));
657
658 obj->intern->default_auto_convert = PHP_PQRES_CONV_ALL;
659
660 zend_hash_init(&obj->intern->listeners, 0, NULL, (dtor_func_t) zend_hash_destroy, 0);
661 zend_hash_init(&obj->intern->converters, 0, NULL, ZVAL_PTR_DTOR, 0);
662 zend_hash_init(&obj->intern->eventhandlers, 0, NULL, (dtor_func_t) zend_hash_destroy, 0);
663
664 if (flags & PHP_PQCONN_PERSISTENT) {
665 php_persistent_handle_factory_t *phf = php_persistent_handle_concede(NULL, ZEND_STRL("pq\\Connection"), dsn_str, dsn_len, php_pqconn_wakeup, php_pqconn_retire TSRMLS_CC);
666 php_resource_factory_init(&obj->intern->factory, php_persistent_handle_get_resource_factory_ops(), phf, (void (*)(void*)) php_persistent_handle_abandon);
667 } else {
668 php_resource_factory_init(&obj->intern->factory, &php_pqconn_resource_factory_ops, NULL, NULL);
669 }
670
671 if (flags & PHP_PQCONN_ASYNC) {
672 obj->intern->poller = (int (*)(PGconn*)) PQconnectPoll;
673 }
674
675 obj->intern->conn = php_resource_factory_handle_ctor(&obj->intern->factory, &rfdata TSRMLS_CC);
676
677 PQsetInstanceData(obj->intern->conn, php_pqconn_event, evdata);
678 PQsetNoticeReceiver(obj->intern->conn, php_pqconn_notice_recv, evdata);
679
680 if (SUCCESS != php_pqconn_update_socket(getThis(), obj TSRMLS_CC)) {
681 throw_exce(EX_CONNECTION_FAILED TSRMLS_CC, "Connection failed (%s)", PHP_PQerrorMessage(obj->intern->conn));
682 }
683 }
684 }
685 }
686
687 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_reset, 0, 0, 0)
688 ZEND_END_ARG_INFO();
689 static PHP_METHOD(pqconn, reset) {
690 zend_error_handling zeh;
691 STATUS rv;
692
693 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
694 rv = zend_parse_parameters_none();
695 zend_restore_error_handling(&zeh TSRMLS_CC);
696
697 if (SUCCESS == rv) {
698 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
699
700 if (!obj->intern) {
701 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
702 } else {
703 PQreset(obj->intern->conn);
704
705 if (CONNECTION_OK != PQstatus(obj->intern->conn)) {
706 throw_exce(EX_CONNECTION_FAILED TSRMLS_CC, "Connection reset failed: (%s)", PHP_PQerrorMessage(obj->intern->conn));
707 }
708
709 php_pqconn_notify_listeners(obj TSRMLS_CC);
710 }
711 }
712 }
713
714 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_reset_async, 0, 0, 0)
715 ZEND_END_ARG_INFO();
716 static PHP_METHOD(pqconn, resetAsync) {
717 zend_error_handling zeh;
718 STATUS rv;
719
720 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
721 rv = zend_parse_parameters_none();
722 zend_restore_error_handling(&zeh TSRMLS_CC);
723
724 if (SUCCESS == rv) {
725 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
726
727 if (!obj->intern) {
728 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
729 } else {
730 if (!PQresetStart(obj->intern->conn)) {
731 throw_exce(EX_IO TSRMLS_CC, "Failed to start connection reset (%s)", PHP_PQerrorMessage(obj->intern->conn));
732 } else {
733 obj->intern->poller = (int (*)(PGconn*)) PQresetPoll;
734 }
735
736 php_pqconn_notify_listeners(obj TSRMLS_CC);
737 }
738 }
739 }
740
741 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_unlisten, 0, 0, 1)
742 ZEND_ARG_INFO(0, channel)
743 ZEND_END_ARG_INFO();
744 static PHP_METHOD(pqconn, unlisten)
745 {
746 zend_error_handling zeh;
747 char *channel_str;
748 int channel_len;
749 STATUS rv;
750
751 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
752 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &channel_str, &channel_len);
753 zend_restore_error_handling(&zeh TSRMLS_CC);
754
755 if (SUCCESS == rv) {
756 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
757
758 if (!obj->intern) {
759 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
760 } else if (SUCCESS == zend_hash_del(&obj->intern->listeners, channel_str, channel_len + 1)) {
761 PGresult *res = unlisten(obj->intern->conn, channel_str, channel_len);
762
763 if (res) {
764 php_pqres_success(res TSRMLS_CC);
765 PHP_PQclear(res);
766 }
767 }
768 }
769 }
770
771 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_unlisten_async, 0, 0, 1)
772 ZEND_ARG_INFO(0, channel)
773 ZEND_END_ARG_INFO();
774 static PHP_METHOD(pqconn, unlistenAsync) {
775 zend_error_handling zeh;
776 char *channel_str;
777 int channel_len;
778 STATUS rv;
779
780 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
781 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &channel_str, &channel_len);
782 zend_restore_error_handling(&zeh TSRMLS_CC);
783
784 if (SUCCESS == rv) {
785 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
786
787 if (!obj->intern) {
788 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
789 } else {
790 char *quoted_channel = PQescapeIdentifier(obj->intern->conn, channel_str, channel_len);
791
792 if (!quoted_channel) {
793 throw_exce(EX_ESCAPE TSRMLS_CC, "Failed to escape channel identifier (%s)", PHP_PQerrorMessage(obj->intern->conn));
794 } else {
795 smart_str cmd = {0};
796
797 smart_str_appends(&cmd, "UNLISTEN ");
798 smart_str_appends(&cmd, quoted_channel);
799 smart_str_0(&cmd);
800
801 if (!PQsendQuery(obj->intern->conn, cmd.c)) {
802 throw_exce(EX_IO TSRMLS_CC, "Failed to uninstall listener (%s)", PHP_PQerrorMessage(obj->intern->conn));
803 } else {
804 obj->intern->poller = PQconsumeInput;
805 zend_hash_del(&obj->intern->listeners, channel_str, channel_len + 1);
806 }
807
808 smart_str_free(&cmd);
809 PQfreemem(quoted_channel);
810 php_pqconn_notify_listeners(obj TSRMLS_CC);
811 }
812 }
813 }
814 }
815
816 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)
817 {
818 HashTable ht, *existing_listeners;
819
820 php_pq_callback_addref(listener);
821
822 if (SUCCESS == zend_hash_find(&obj->intern->listeners, channel_str, channel_len + 1, (void *) &existing_listeners)) {
823 zend_hash_next_index_insert(existing_listeners, (void *) listener, sizeof(*listener), NULL);
824 } else {
825 zend_hash_init(&ht, 1, NULL, (dtor_func_t) php_pq_callback_dtor, 0);
826 zend_hash_next_index_insert(&ht, (void *) listener, sizeof(*listener), NULL);
827 zend_hash_add(&obj->intern->listeners, channel_str, channel_len + 1, (void *) &ht, sizeof(HashTable), NULL);
828 }
829 }
830
831 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_listen, 0, 0, 2)
832 ZEND_ARG_INFO(0, channel)
833 ZEND_ARG_INFO(0, callable)
834 ZEND_END_ARG_INFO();
835 static PHP_METHOD(pqconn, listen) {
836 zend_error_handling zeh;
837 char *channel_str = NULL;
838 int channel_len = 0;
839 php_pq_callback_t listener = {{0}};
840 STATUS rv;
841
842 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
843 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sf", &channel_str, &channel_len, &listener.fci, &listener.fcc);
844 zend_restore_error_handling(&zeh TSRMLS_CC);
845
846 if (SUCCESS == rv) {
847 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
848
849 if (!obj->intern) {
850 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
851 } else {
852 char *quoted_channel = PQescapeIdentifier(obj->intern->conn, channel_str, channel_len);
853
854 if (!quoted_channel) {
855 throw_exce(EX_ESCAPE TSRMLS_CC, "Failed to escape channel identifier (%s)", PHP_PQerrorMessage(obj->intern->conn));
856 } else {
857 PGresult *res;
858 smart_str cmd = {0};
859
860 smart_str_appends(&cmd, "LISTEN ");
861 smart_str_appends(&cmd, quoted_channel);
862 smart_str_0(&cmd);
863
864 res = PQexec(obj->intern->conn, cmd.c);
865
866 smart_str_free(&cmd);
867 PQfreemem(quoted_channel);
868
869 if (!res) {
870 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to install listener (%s)", PHP_PQerrorMessage(obj->intern->conn));
871 } else {
872 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
873 obj->intern->poller = PQconsumeInput;
874 php_pqconn_add_listener(obj, channel_str, channel_len, &listener TSRMLS_CC);
875 }
876 PHP_PQclear(res);
877 }
878
879 php_pqconn_notify_listeners(obj TSRMLS_CC);
880 }
881 }
882 }
883 }
884
885 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_listen_async, 0, 0, 0)
886 ZEND_ARG_INFO(0, channel)
887 ZEND_ARG_INFO(0, callable)
888 ZEND_END_ARG_INFO();
889 static PHP_METHOD(pqconn, listenAsync) {
890 zend_error_handling zeh;
891 char *channel_str = NULL;
892 int channel_len = 0;
893 php_pq_callback_t listener = {{0}};
894 STATUS rv;
895
896 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
897 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sf", &channel_str, &channel_len, &listener.fci, &listener.fcc);
898 zend_restore_error_handling(&zeh TSRMLS_CC);
899
900 if (SUCCESS == rv) {
901 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
902
903 if (!obj->intern) {
904 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
905 } else {
906 char *quoted_channel = PQescapeIdentifier(obj->intern->conn, channel_str, channel_len);
907
908 if (!quoted_channel) {
909 throw_exce(EX_ESCAPE TSRMLS_CC, "Failed to escape channel identifier (%s)", PHP_PQerrorMessage(obj->intern->conn));
910 } else {
911 smart_str cmd = {0};
912
913 smart_str_appends(&cmd, "LISTEN ");
914 smart_str_appends(&cmd, quoted_channel);
915 smart_str_0(&cmd);
916
917 if (!PQsendQuery(obj->intern->conn, cmd.c)) {
918 throw_exce(EX_IO TSRMLS_CC, "Failed to install listener (%s)", PHP_PQerrorMessage(obj->intern->conn));
919 } else {
920 obj->intern->poller = PQconsumeInput;
921 php_pqconn_add_listener(obj, channel_str, channel_len, &listener TSRMLS_CC);
922 }
923
924 smart_str_free(&cmd);
925 PQfreemem(quoted_channel);
926 php_pqconn_notify_listeners(obj TSRMLS_CC);
927 }
928 }
929 }
930 }
931
932 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_notify, 0, 0, 2)
933 ZEND_ARG_INFO(0, channel)
934 ZEND_ARG_INFO(0, message)
935 ZEND_END_ARG_INFO();
936 static PHP_METHOD(pqconn, notify) {
937 zend_error_handling zeh;
938 char *channel_str, *message_str;
939 int channel_len, message_len;
940 STATUS rv;
941
942 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
943 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &channel_str, &channel_len, &message_str, &message_len);
944 zend_restore_error_handling(&zeh TSRMLS_CC);
945
946 if (SUCCESS == rv) {
947 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
948
949 if (!obj->intern) {
950 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
951 } else {
952 PGresult *res;
953 char *params[2] = {channel_str, message_str};
954
955 res = PQexecParams(obj->intern->conn, "select pg_notify($1, $2)", 2, NULL, (const char *const*) params, NULL, NULL, 0);
956
957 if (!res) {
958 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to notify listeners (%s)", PHP_PQerrorMessage(obj->intern->conn));
959 } else {
960 php_pqres_success(res TSRMLS_CC);
961 PHP_PQclear(res);
962 }
963
964 php_pqconn_notify_listeners(obj TSRMLS_CC);
965 }
966 }
967 }
968
969 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_notify_async, 0, 0, 2)
970 ZEND_ARG_INFO(0, channel)
971 ZEND_ARG_INFO(0, message)
972 ZEND_END_ARG_INFO();
973 static PHP_METHOD(pqconn, notifyAsync) {
974 zend_error_handling zeh;
975 char *channel_str, *message_str;
976 int channel_len, message_len;
977 STATUS rv;
978
979 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
980 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &channel_str, &channel_len, &message_str, &message_len);
981 zend_restore_error_handling(&zeh TSRMLS_CC);
982
983 if (SUCCESS == rv) {
984 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
985
986 if (!obj->intern) {
987 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
988 } else {
989 char *params[2] = {channel_str, message_str};
990
991 if (!PQsendQueryParams(obj->intern->conn, "select pg_notify($1, $2)", 2, NULL, (const char *const*) params, NULL, NULL, 0)) {
992 throw_exce(EX_IO TSRMLS_CC, "Failed to notify listeners (%s)", PHP_PQerrorMessage(obj->intern->conn));
993 } else {
994 obj->intern->poller = PQconsumeInput;
995 }
996
997 php_pqconn_notify_listeners(obj TSRMLS_CC);
998 }
999 }
1000 }
1001
1002 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_poll, 0, 0, 0)
1003 ZEND_END_ARG_INFO();
1004 static PHP_METHOD(pqconn, poll) {
1005 zend_error_handling zeh;
1006 STATUS rv;
1007
1008 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1009 rv = zend_parse_parameters_none();
1010 zend_restore_error_handling(&zeh TSRMLS_CC);
1011
1012 if (SUCCESS == rv) {
1013 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1014
1015 if (!obj->intern) {
1016 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1017 } else if (!obj->intern->poller) {
1018 throw_exce(EX_RUNTIME TSRMLS_CC, "No asynchronous operation active");
1019 } else {
1020 if (obj->intern->poller == PQconsumeInput) {
1021 RETVAL_LONG(obj->intern->poller(obj->intern->conn) * PGRES_POLLING_OK);
1022 } else {
1023 RETVAL_LONG(obj->intern->poller(obj->intern->conn));
1024 }
1025 php_pqconn_notify_listeners(obj TSRMLS_CC);
1026 }
1027 }
1028 }
1029
1030 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec, 0, 0, 1)
1031 ZEND_ARG_INFO(0, query)
1032 ZEND_END_ARG_INFO();
1033 static PHP_METHOD(pqconn, exec) {
1034 zend_error_handling zeh;
1035 char *query_str;
1036 int query_len;
1037 STATUS rv;
1038
1039 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1040 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &query_str, &query_len);
1041 zend_restore_error_handling(&zeh TSRMLS_CC);
1042
1043 if (SUCCESS == rv) {
1044 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1045
1046 if (!obj->intern) {
1047 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1048 } else {
1049 PGresult *res = PQexec(obj->intern->conn, query_str);
1050
1051 if (!res) {
1052 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
1053 } else if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
1054 php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), &return_value TSRMLS_CC);
1055 } else {
1056 PHP_PQclear(res);
1057 }
1058
1059 php_pqconn_notify_listeners(obj TSRMLS_CC);
1060 }
1061 }
1062 }
1063
1064 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_get_result, 0, 0, 0)
1065 ZEND_END_ARG_INFO();
1066 static PHP_METHOD(pqconn, getResult) {
1067 zend_error_handling zeh;
1068 STATUS rv;
1069
1070 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1071 rv = zend_parse_parameters_none();
1072 zend_restore_error_handling(&zeh TSRMLS_CC);
1073
1074 if (SUCCESS == rv) {
1075 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1076
1077 if (!obj->intern) {
1078 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1079 } else {
1080 PGresult *res = PQgetResult(obj->intern->conn);
1081
1082 if (!res) {
1083 RETVAL_NULL();
1084 } else {
1085 php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), &return_value TSRMLS_CC);
1086 }
1087
1088 php_pqconn_notify_listeners(obj TSRMLS_CC);
1089 }
1090 }
1091 }
1092
1093 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_async, 0, 0, 1)
1094 ZEND_ARG_INFO(0, query)
1095 ZEND_ARG_INFO(0, callable)
1096 ZEND_END_ARG_INFO();
1097 static PHP_METHOD(pqconn, execAsync) {
1098 zend_error_handling zeh;
1099 php_pq_callback_t resolver = {{0}};
1100 char *query_str;
1101 int query_len;
1102 STATUS rv;
1103
1104 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1105 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|f", &query_str, &query_len, &resolver.fci, &resolver.fcc);
1106 zend_restore_error_handling(&zeh TSRMLS_CC);
1107
1108 if (SUCCESS == rv) {
1109 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1110
1111 if (!obj->intern) {
1112 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1113 } else if (!PQsendQuery(obj->intern->conn, query_str)) {
1114 throw_exce(EX_IO TSRMLS_CC, "Failed to execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
1115 } else if (obj->intern->unbuffered && !PQsetSingleRowMode(obj->intern->conn)) {
1116 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn));
1117 } else {
1118 php_pq_callback_recurse(&obj->intern->onevent, &resolver TSRMLS_CC);
1119 obj->intern->poller = PQconsumeInput;
1120 php_pqconn_notify_listeners(obj TSRMLS_CC);
1121 }
1122 }
1123 }
1124
1125 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_params, 0, 0, 2)
1126 ZEND_ARG_INFO(0, query)
1127 ZEND_ARG_ARRAY_INFO(0, params, 0)
1128 ZEND_ARG_ARRAY_INFO(0, types, 1)
1129 ZEND_END_ARG_INFO();
1130 static PHP_METHOD(pqconn, execParams) {
1131 zend_error_handling zeh;
1132 char *query_str;
1133 int query_len;
1134 zval *zparams;
1135 zval *ztypes = NULL;
1136 STATUS rv;
1137
1138 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1139 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|a/!", &query_str, &query_len, &zparams, &ztypes);
1140 zend_restore_error_handling(&zeh TSRMLS_CC);
1141
1142 if (SUCCESS == rv) {
1143 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1144
1145 if (!obj->intern) {
1146 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1147 } else {
1148 PGresult *res;
1149 php_pq_params_t *params;
1150
1151 params = php_pq_params_init(&obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, Z_ARRVAL_P(zparams) TSRMLS_CC);
1152 res = PQexecParams(obj->intern->conn, query_str, params->param.count, params->type.oids, (const char *const*) params->param.strings, NULL, NULL, 0);
1153 php_pq_params_free(&params);
1154
1155 if (!res) {
1156 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
1157 } else {
1158 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
1159 php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), &return_value TSRMLS_CC);
1160 } else {
1161 PHP_PQclear(res);
1162 }
1163
1164 php_pqconn_notify_listeners(obj TSRMLS_CC);
1165 }
1166 }
1167 }
1168 }
1169
1170 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_params_async, 0, 0, 2)
1171 ZEND_ARG_INFO(0, query)
1172 ZEND_ARG_ARRAY_INFO(0, params, 0)
1173 ZEND_ARG_ARRAY_INFO(0, types, 1)
1174 ZEND_ARG_INFO(0, callable)
1175 ZEND_END_ARG_INFO();
1176 static PHP_METHOD(pqconn, execParamsAsync) {
1177 zend_error_handling zeh;
1178 php_pq_callback_t resolver = {{0}};
1179 char *query_str;
1180 int query_len;
1181 zval *zparams;
1182 zval *ztypes = NULL;
1183 STATUS rv;
1184
1185 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1186 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|a/!f", &query_str, &query_len, &zparams, &ztypes, &resolver.fci, &resolver.fcc);
1187 zend_restore_error_handling(&zeh TSRMLS_CC);
1188
1189 if (SUCCESS == rv) {
1190 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1191
1192 if (!obj->intern) {
1193 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1194 } else {
1195 int rc;
1196 php_pq_params_t *params;
1197
1198 params = php_pq_params_init(&obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, Z_ARRVAL_P(zparams) TSRMLS_CC);
1199 rc = PQsendQueryParams(obj->intern->conn, query_str, params->param.count, params->type.oids, (const char *const*) params->param.strings, NULL, NULL, 0);
1200 php_pq_params_free(&params);
1201
1202 if (!rc) {
1203 throw_exce(EX_IO TSRMLS_CC, "Failed to execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
1204 } else if (obj->intern->unbuffered && !PQsetSingleRowMode(obj->intern->conn)) {
1205 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn));
1206 } else {
1207 php_pq_callback_recurse(&obj->intern->onevent, &resolver TSRMLS_CC);
1208 obj->intern->poller = PQconsumeInput;
1209 php_pqconn_notify_listeners(obj TSRMLS_CC);
1210 }
1211 }
1212 }
1213 zend_restore_error_handling(&zeh TSRMLS_CC);
1214 }
1215
1216 STATUS php_pqconn_prepare(zval *object, php_pqconn_object_t *obj, const char *name, const char *query, php_pq_params_t *params TSRMLS_DC)
1217 {
1218 PGresult *res;
1219 STATUS rv;
1220
1221 if (!obj) {
1222 obj = zend_object_store_get_object(object TSRMLS_CC);
1223 }
1224
1225 res = PQprepare(obj->intern->conn, name, query, params->type.count, params->type.oids);
1226
1227 if (!res) {
1228 rv = FAILURE;
1229 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to prepare statement (%s)", PHP_PQerrorMessage(obj->intern->conn));
1230 } else {
1231 rv = php_pqres_success(res TSRMLS_CC);
1232 PHP_PQclear(res);
1233 php_pqconn_notify_listeners(obj TSRMLS_CC);
1234 }
1235
1236 return rv;
1237 }
1238
1239 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_prepare, 0, 0, 2)
1240 ZEND_ARG_INFO(0, name)
1241 ZEND_ARG_INFO(0, query)
1242 ZEND_ARG_ARRAY_INFO(0, types, 1)
1243 ZEND_END_ARG_INFO();
1244 static PHP_METHOD(pqconn, prepare) {
1245 zend_error_handling zeh;
1246 zval *ztypes = NULL;
1247 char *name_str, *query_str;
1248 int name_len, *query_len;
1249 STATUS rv;
1250
1251 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1252 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!", &name_str, &name_len, &query_str, &query_len, &ztypes);
1253 zend_restore_error_handling(&zeh TSRMLS_CC);
1254
1255 if (SUCCESS == rv) {
1256 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1257
1258 if (!obj->intern) {
1259 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1260 } else {
1261 php_pq_params_t *params = php_pq_params_init(&obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, NULL TSRMLS_CC);
1262
1263 if (SUCCESS != php_pqconn_prepare(getThis(), obj, name_str, query_str, params TSRMLS_CC)) {
1264 php_pq_params_free(&params);
1265 } else {
1266 php_pqstm_t *stm = ecalloc(1, sizeof(*stm));
1267
1268 php_pq_object_addref(obj TSRMLS_CC);
1269 stm->conn = obj;
1270 stm->name = estrdup(name_str);
1271 stm->params = params;
1272 ZEND_INIT_SYMTABLE(&stm->bound);
1273
1274 return_value->type = IS_OBJECT;
1275 return_value->value.obj = php_pqstm_create_object_ex(php_pqstm_class_entry, stm, NULL TSRMLS_CC);
1276 }
1277 }
1278 }
1279 }
1280
1281 STATUS php_pqconn_prepare_async(zval *object, php_pqconn_object_t *obj, const char *name, const char *query, php_pq_params_t *params TSRMLS_DC)
1282 {
1283 STATUS rv;
1284
1285 if (!obj) {
1286 obj = zend_object_store_get_object(object TSRMLS_CC);
1287 }
1288
1289 if (!PQsendPrepare(obj->intern->conn, name, query, params->type.count, params->type.oids)) {
1290 rv = FAILURE;
1291 throw_exce(EX_IO TSRMLS_CC, "Failed to prepare statement (%s)", PHP_PQerrorMessage(obj->intern->conn));
1292 } else if (obj->intern->unbuffered && !PQsetSingleRowMode(obj->intern->conn)) {
1293 rv = FAILURE;
1294 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn));
1295 } else {
1296 rv = SUCCESS;
1297 obj->intern->poller = PQconsumeInput;
1298 php_pqconn_notify_listeners(obj TSRMLS_CC);
1299 }
1300
1301 return rv;
1302 }
1303
1304 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_prepare_async, 0, 0, 2)
1305 ZEND_ARG_INFO(0, name)
1306 ZEND_ARG_INFO(0, query)
1307 ZEND_ARG_ARRAY_INFO(0, types, 1)
1308 ZEND_END_ARG_INFO();
1309 static PHP_METHOD(pqconn, prepareAsync) {
1310 zend_error_handling zeh;
1311 zval *ztypes = NULL;
1312 char *name_str, *query_str;
1313 int name_len, *query_len;
1314 STATUS rv;
1315
1316 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1317 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!", &name_str, &name_len, &query_str, &query_len, &ztypes);
1318 zend_restore_error_handling(&zeh TSRMLS_CC);
1319
1320 if (SUCCESS == rv) {
1321 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1322
1323 if (!obj->intern) {
1324 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1325 } else {
1326 php_pq_params_t *params = php_pq_params_init(&obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, NULL TSRMLS_CC);
1327
1328 if (SUCCESS != php_pqconn_prepare_async(getThis(), obj, name_str, query_str, params TSRMLS_CC)) {
1329 php_pq_params_free(&params);
1330 } else {
1331 php_pqstm_t *stm = ecalloc(1, sizeof(*stm));
1332
1333 php_pq_object_addref(obj TSRMLS_CC);
1334 stm->conn = obj;
1335 stm->name = estrdup(name_str);
1336 stm->params = params;
1337 ZEND_INIT_SYMTABLE(&stm->bound);
1338
1339 return_value->type = IS_OBJECT;
1340 return_value->value.obj = php_pqstm_create_object_ex(php_pqstm_class_entry, stm, NULL TSRMLS_CC);
1341 }
1342 }
1343 }
1344 }
1345
1346 static inline char *declare_str(const char *name_str, size_t name_len, unsigned flags, const char *query_str, size_t query_len)
1347 {
1348 size_t decl_len = name_len + query_len + sizeof("DECLARE BINARY INSENSITIVE NO SCROLL CURSOR WITHOUT HOLD FOR ");
1349 char *decl_str;
1350
1351 decl_str = emalloc(decl_len);
1352 decl_len = slprintf(decl_str, decl_len, "DECLARE %s %s %s %s CURSOR %s FOR %s",
1353 name_str,
1354 (flags & PHP_PQ_DECLARE_BINARY) ? "BINARY" : "",
1355 (flags & PHP_PQ_DECLARE_INSENSITIVE) ? "INSENSITIVE" : "",
1356 (flags & PHP_PQ_DECLARE_NO_SCROLL) ? "NO SCROLL" :
1357 (flags & PHP_PQ_DECLARE_SCROLL) ? "SCROLL" : "",
1358 (flags & PHP_PQ_DECLARE_WITH_HOLD) ? "WITH HOLD" : "",
1359 query_str
1360 );
1361 return decl_str;
1362 }
1363
1364 STATUS php_pqconn_declare(zval *object, php_pqconn_object_t *obj, const char *decl TSRMLS_DC)
1365 {
1366 PGresult *res;
1367 STATUS rv;
1368
1369 if (!obj) {
1370 obj = zend_object_store_get_object(object TSRMLS_CC);
1371 }
1372
1373 res = PQexec(obj->intern->conn, decl);
1374
1375 if (!res) {
1376 rv = FAILURE;
1377 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to declare cursor (%s)", PHP_PQerrorMessage(obj->intern->conn));
1378 } else {
1379 rv = php_pqres_success(res TSRMLS_CC);
1380 PHP_PQclear(res);
1381 php_pqconn_notify_listeners(obj TSRMLS_CC);
1382 }
1383
1384 return rv;
1385 }
1386
1387 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_declare, 0, 0, 3)
1388 ZEND_ARG_INFO(0, name)
1389 ZEND_ARG_INFO(0, flags)
1390 ZEND_ARG_INFO(0, query)
1391 ZEND_END_ARG_INFO();
1392 static PHP_METHOD(pqconn, declare) {
1393 zend_error_handling zeh;
1394 char *name_str, *query_str;
1395 int name_len, query_len;
1396 long flags;
1397 STATUS rv;
1398
1399 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1400 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sls", &name_str, &name_len, &flags, &query_str, &query_len);
1401 zend_restore_error_handling(&zeh TSRMLS_CC);
1402
1403 if (SUCCESS == rv) {
1404 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1405
1406 if (!obj->intern) {
1407 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1408 } else {
1409 char *decl = declare_str(name_str, name_len, flags, query_str, query_len);
1410
1411 if (SUCCESS != php_pqconn_declare(getThis(), obj, decl TSRMLS_CC)) {
1412 efree(decl);
1413 } else {
1414 php_pqcur_t *cur = ecalloc(1, sizeof(*cur));
1415
1416 php_pq_object_addref(obj TSRMLS_CC);
1417 cur->conn = obj;
1418 cur->open = 1;
1419 cur->name = estrdup(name_str);
1420 cur->decl = decl;
1421
1422 return_value->type = IS_OBJECT;
1423 return_value->value.obj = php_pqcur_create_object_ex(php_pqcur_class_entry, cur, NULL TSRMLS_CC);
1424 }
1425 }
1426 }
1427 }
1428
1429 STATUS php_pqconn_declare_async(zval *object, php_pqconn_object_t *obj, const char *decl TSRMLS_DC)
1430 {
1431 STATUS rv;
1432
1433 if (!obj) {
1434 obj = zend_object_store_get_object(object TSRMLS_CC);
1435 }
1436
1437 if (!PQsendQuery(obj->intern->conn, decl)) {
1438 rv = FAILURE;
1439 throw_exce(EX_IO TSRMLS_CC, "Failed to declare cursor (%s)", PHP_PQerrorMessage(obj->intern->conn));
1440 } else if (obj->intern->unbuffered && !PQsetSingleRowMode(obj->intern->conn)) {
1441 rv = FAILURE;
1442 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn));
1443 } else {
1444 rv = SUCCESS;
1445 obj->intern->poller = PQconsumeInput;
1446 php_pqconn_notify_listeners(obj TSRMLS_CC);
1447 }
1448
1449 return rv;
1450 }
1451
1452 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_declare_async, 0, 0, 2)
1453 ZEND_ARG_INFO(0, name)
1454 ZEND_ARG_INFO(0, flags)
1455 ZEND_ARG_INFO(0, query)
1456 ZEND_END_ARG_INFO();
1457 static PHP_METHOD(pqconn, declareAsync) {
1458 zend_error_handling zeh;
1459 char *name_str, *query_str;
1460 int name_len, query_len;
1461 long flags;
1462 STATUS rv;
1463
1464 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1465 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sls", &name_str, &name_len, &flags, &query_str, &query_len);
1466 zend_restore_error_handling(&zeh TSRMLS_CC);
1467
1468 if (SUCCESS == rv) {
1469 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1470
1471 if (!obj->intern) {
1472 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1473 } else {
1474 char *decl = declare_str(name_str, name_len, flags, query_str, query_len);
1475
1476 if (SUCCESS != php_pqconn_declare_async(getThis(), obj, decl TSRMLS_CC)) {
1477 efree(decl);
1478 } else {
1479 php_pqcur_t *cur = ecalloc(1, sizeof(*cur));
1480
1481 php_pq_object_addref(obj TSRMLS_CC);
1482 cur->conn = obj;
1483 cur->open = 1;
1484 cur->name = estrdup(name_str);
1485 cur->decl = decl;
1486
1487 return_value->type = IS_OBJECT;
1488 return_value->value.obj = php_pqcur_create_object_ex(php_pqcur_class_entry, cur, NULL TSRMLS_CC);
1489 }
1490 }
1491 }
1492 }
1493
1494 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_quote, 0, 0, 1)
1495 ZEND_ARG_INFO(0, string)
1496 ZEND_END_ARG_INFO();
1497 static PHP_METHOD(pqconn, quote) {
1498 char *str;
1499 int len;
1500
1501 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len)) {
1502 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1503
1504 if (!obj->intern) {
1505 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1506 } else {
1507 char *quoted = PQescapeLiteral(obj->intern->conn, str, len);
1508
1509 if (!quoted) {
1510 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to quote string (%s)", PHP_PQerrorMessage(obj->intern->conn));
1511 RETVAL_FALSE;
1512 } else {
1513 RETVAL_STRING(quoted, 1);
1514 PQfreemem(quoted);
1515 }
1516 }
1517 }
1518 }
1519
1520 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_quote_name, 0, 0, 1)
1521 ZEND_ARG_INFO(0, type)
1522 ZEND_END_ARG_INFO();
1523 static PHP_METHOD(pqconn, quoteName) {
1524 char *str;
1525 int len;
1526
1527 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len)) {
1528 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1529
1530 if (!obj->intern) {
1531 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1532 } else {
1533 char *quoted = PQescapeIdentifier(obj->intern->conn, str, len);
1534
1535 if (!quoted) {
1536 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to quote name (%s)", PHP_PQerrorMessage(obj->intern->conn));
1537 RETVAL_FALSE;
1538 } else {
1539 RETVAL_STRING(quoted, 1);
1540 PQfreemem(quoted);
1541 }
1542 }
1543 }
1544 }
1545
1546 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_escape_bytea, 0, 0, 1)
1547 ZEND_ARG_INFO(0, bytea)
1548 ZEND_END_ARG_INFO();
1549 static PHP_METHOD(pqconn, escapeBytea) {
1550 char *str;
1551 int len;
1552
1553 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len)) {
1554 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1555
1556 if (!obj->intern) {
1557 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1558 } else {
1559 size_t escaped_len;
1560 char *escaped_str = (char *) PQescapeByteaConn(obj->intern->conn, (unsigned char *) str, len, &escaped_len);
1561
1562 if (!escaped_str) {
1563 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to escape bytea (%s)", PHP_PQerrorMessage(obj->intern->conn));
1564 RETVAL_FALSE;
1565 } else {
1566 RETVAL_STRINGL(escaped_str, escaped_len - 1, 1);
1567 PQfreemem(escaped_str);
1568 }
1569 }
1570 }
1571 }
1572
1573 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_unescape_bytea, 0, 0, 1)
1574 ZEND_ARG_INFO(0, bytea)
1575 ZEND_END_ARG_INFO();
1576 static PHP_METHOD(pqconn, unescapeBytea) {
1577 char *str;
1578 int len;
1579
1580 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len)) {
1581 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1582
1583 if (!obj->intern) {
1584 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1585 } else {
1586 size_t unescaped_len;
1587 char *unescaped_str = (char *) PQunescapeBytea((unsigned char *)str, &unescaped_len);
1588
1589 if (!unescaped_str) {
1590 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to unescape bytea (%s)", PHP_PQerrorMessage(obj->intern->conn));
1591 RETVAL_FALSE;
1592 } else {
1593 RETVAL_STRINGL(unescaped_str, unescaped_len, 1);
1594 PQfreemem(unescaped_str);
1595 }
1596 }
1597 }
1598 }
1599
1600 STATUS php_pqconn_start_transaction(zval *zconn, php_pqconn_object_t *conn_obj, long isolation, zend_bool readonly, zend_bool deferrable TSRMLS_DC)
1601 {
1602 STATUS rv = FAILURE;
1603
1604 if (!conn_obj) {
1605 conn_obj = zend_object_store_get_object(zconn TSRMLS_CC);
1606 }
1607
1608 if (!conn_obj->intern) {
1609 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1610 } else {
1611 PGresult *res;
1612 smart_str cmd = {0};
1613 const char *il = isolation_level(&isolation);
1614
1615 smart_str_appends(&cmd, "START TRANSACTION ISOLATION LEVEL ");
1616 smart_str_appends(&cmd, il);
1617 smart_str_appends(&cmd, ", READ ");
1618 smart_str_appends(&cmd, readonly ? "ONLY" : "WRITE");
1619 smart_str_appends(&cmd, ",");
1620 smart_str_appends(&cmd, deferrable ? "" : " NOT");
1621 smart_str_appends(&cmd, " DEFERRABLE");
1622 smart_str_0(&cmd);
1623
1624 res = PQexec(conn_obj->intern->conn, cmd.c);
1625
1626 if (!res) {
1627 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to start transaction (%s)", PHP_PQerrorMessage(conn_obj->intern->conn));
1628 } else {
1629 rv = php_pqres_success(res TSRMLS_CC);
1630 PHP_PQclear(res);
1631 php_pqconn_notify_listeners(conn_obj TSRMLS_CC);
1632 }
1633
1634 smart_str_free(&cmd);
1635 }
1636
1637 return rv;
1638 }
1639
1640 STATUS php_pqconn_start_transaction_async(zval *zconn, php_pqconn_object_t *conn_obj, long isolation, zend_bool readonly, zend_bool deferrable TSRMLS_DC)
1641 {
1642 STATUS rv = FAILURE;
1643
1644 if (!conn_obj) {
1645 conn_obj = zend_object_store_get_object(zconn TSRMLS_CC);
1646 }
1647
1648 if (!conn_obj->intern) {
1649 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1650 } else {
1651 smart_str cmd = {0};
1652 const char *il = isolation_level(&isolation);
1653
1654 smart_str_appends(&cmd, "START TRANSACTION ISOLATION LEVEL ");
1655 smart_str_appends(&cmd, il);
1656 smart_str_appends(&cmd, ", READ ");
1657 smart_str_appends(&cmd, readonly ? "ONLY" : "WRITE");
1658 smart_str_appends(&cmd, ",");
1659 smart_str_appends(&cmd, deferrable ? "" : "NOT ");
1660 smart_str_appends(&cmd, " DEFERRABLE");
1661 smart_str_0(&cmd);
1662
1663 if (!PQsendQuery(conn_obj->intern->conn, cmd.c)) {
1664 throw_exce(EX_IO TSRMLS_CC, "Failed to start transaction (%s)", PHP_PQerrorMessage(conn_obj->intern->conn));
1665 } else {
1666 rv = SUCCESS;
1667 conn_obj->intern->poller = PQconsumeInput;
1668 php_pqconn_notify_listeners(conn_obj TSRMLS_CC);
1669 }
1670
1671 smart_str_free(&cmd);
1672 }
1673
1674 return rv;
1675 }
1676
1677 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_start_transaction, 0, 0, 0)
1678 ZEND_ARG_INFO(0, isolation)
1679 ZEND_ARG_INFO(0, readonly)
1680 ZEND_ARG_INFO(0, deferrable)
1681 ZEND_END_ARG_INFO();
1682 static PHP_METHOD(pqconn, startTransaction) {
1683 zend_error_handling zeh;
1684 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1685 long isolation = obj->intern ? obj->intern->default_txn_isolation : PHP_PQTXN_READ_COMMITTED;
1686 zend_bool readonly = obj->intern ? obj->intern->default_txn_readonly : 0;
1687 zend_bool deferrable = obj->intern ? obj->intern->default_txn_deferrable : 0;
1688 STATUS rv;
1689
1690 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1691 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lbb", &isolation, &readonly, &deferrable);
1692 zend_restore_error_handling(&zeh TSRMLS_CC);
1693
1694 if (SUCCESS == rv) {
1695 rv = php_pqconn_start_transaction(getThis(), obj, isolation, readonly, deferrable TSRMLS_CC);
1696
1697 if (SUCCESS == rv) {
1698 php_pqtxn_t *txn = ecalloc(1, sizeof(*txn));
1699
1700 php_pq_object_addref(obj TSRMLS_CC);
1701 txn->conn = obj;
1702 txn->open = 1;
1703 txn->isolation = isolation;
1704 txn->readonly = readonly;
1705 txn->deferrable = deferrable;
1706
1707 return_value->type = IS_OBJECT;
1708 return_value->value.obj = php_pqtxn_create_object_ex(php_pqtxn_class_entry, txn, NULL TSRMLS_CC);
1709 }
1710 }
1711 }
1712
1713 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_start_transaction_async, 0, 0, 0)
1714 ZEND_ARG_INFO(0, isolation)
1715 ZEND_ARG_INFO(0, readonly)
1716 ZEND_ARG_INFO(0, deferrable)
1717 ZEND_END_ARG_INFO();
1718 static PHP_METHOD(pqconn, startTransactionAsync) {
1719 zend_error_handling zeh;
1720 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1721 long isolation = obj->intern ? obj->intern->default_txn_isolation : PHP_PQTXN_READ_COMMITTED;
1722 zend_bool readonly = obj->intern ? obj->intern->default_txn_readonly : 0;
1723 zend_bool deferrable = obj->intern ? obj->intern->default_txn_deferrable : 0;
1724 STATUS rv;
1725
1726 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1727 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lbb", &isolation, &readonly, &deferrable);
1728 zend_restore_error_handling(&zeh TSRMLS_CC);
1729
1730 if (SUCCESS == rv) {
1731 rv = php_pqconn_start_transaction_async(getThis(), obj, isolation, readonly, deferrable TSRMLS_CC);
1732
1733 if (SUCCESS == rv) {
1734 php_pqtxn_t *txn = ecalloc(1, sizeof(*txn));
1735
1736 php_pq_object_addref(obj TSRMLS_CC);
1737 txn->conn = obj;
1738 txn->isolation = isolation;
1739 txn->readonly = readonly;
1740 txn->deferrable = deferrable;
1741
1742 return_value->type = IS_OBJECT;
1743 return_value->value.obj = php_pqtxn_create_object_ex(php_pqtxn_class_entry, txn, NULL TSRMLS_CC);
1744 }
1745 }
1746 }
1747
1748 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_trace, 0, 0, 0)
1749 ZEND_ARG_INFO(0, stdio_stream)
1750 ZEND_END_ARG_INFO();
1751 static PHP_METHOD(pqconn, trace) {
1752 zval *zstream = NULL;
1753
1754 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r!", &zstream)) {
1755 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1756
1757 if (!obj->intern) {
1758 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1759 } else {
1760 if (!zstream) {
1761 PQuntrace(obj->intern->conn);
1762 RETVAL_TRUE;
1763 } else {
1764 FILE *fp;
1765 php_stream *stream = NULL;
1766
1767 php_stream_from_zval(stream, &zstream);
1768
1769 if (SUCCESS != php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void *) &fp, REPORT_ERRORS)) {
1770 RETVAL_FALSE;
1771 } else {
1772 stream->flags |= PHP_STREAM_FLAG_NO_CLOSE;
1773 PQtrace(obj->intern->conn, fp);
1774 RETVAL_TRUE;
1775 }
1776 }
1777 }
1778 }
1779 }
1780
1781 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_off, 0, 0, 1)
1782 ZEND_ARG_INFO(0, type)
1783 ZEND_END_ARG_INFO();
1784 static PHP_METHOD(pqconn, off) {
1785 zend_error_handling zeh;
1786 char *type_str;
1787 int type_len;
1788 STATUS rv;
1789
1790 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1791 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &type_str, &type_len);
1792 zend_restore_error_handling(&zeh TSRMLS_CC);
1793
1794 if (SUCCESS == rv) {
1795 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1796
1797 if (!obj->intern) {
1798 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1799 } else {
1800 RETURN_BOOL(SUCCESS == zend_hash_del(&obj->intern->eventhandlers, type_str, type_len + 1));
1801 }
1802 }
1803 }
1804
1805 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_on, 0, 0, 2)
1806 ZEND_ARG_INFO(0, type)
1807 ZEND_ARG_INFO(0, callable)
1808 ZEND_END_ARG_INFO();
1809 static PHP_METHOD(pqconn, on) {
1810 zend_error_handling zeh;
1811 char *type_str;
1812 int type_len;
1813 php_pq_callback_t cb = {{0}};
1814 STATUS rv;
1815
1816 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1817 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sf", &type_str, &type_len, &cb.fci, &cb.fcc);
1818 zend_restore_error_handling(&zeh TSRMLS_CC);
1819
1820 if (SUCCESS == rv) {
1821 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1822
1823 if (!obj->intern) {
1824 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1825 } else {
1826 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1827
1828 RETVAL_LONG(php_pqconn_add_eventhandler(obj, type_str, type_len, &cb TSRMLS_CC));
1829 }
1830 }
1831 }
1832
1833 struct apply_set_converter_arg {
1834 HashTable *ht;
1835 zval **zconv;
1836 unsigned add:1;
1837 };
1838
1839 static int apply_set_converter(void *p, void *a TSRMLS_DC)
1840 {
1841 zval *tmp, **zoid = p;
1842 struct apply_set_converter_arg *arg = a;
1843
1844 tmp = *zoid;
1845 Z_ADDREF_P(tmp);
1846 convert_to_long_ex(&tmp);
1847 if (arg->add) {
1848 Z_ADDREF_PP(arg->zconv);
1849 zend_hash_index_update(arg->ht, Z_LVAL_P(tmp), arg->zconv, sizeof(zval *), NULL);
1850 } else {
1851 zend_hash_index_del(arg->ht, Z_LVAL_P(tmp));
1852 }
1853 zval_ptr_dtor(&tmp);
1854
1855 return ZEND_HASH_APPLY_KEEP;
1856 }
1857
1858 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_set_converter, 0, 0, 1)
1859 ZEND_ARG_OBJ_INFO(0, converter, pq\\Converter, 0)
1860 ZEND_END_ARG_INFO();
1861 static PHP_METHOD(pqconn, setConverter) {
1862 STATUS rv;
1863 zend_error_handling zeh;
1864 zval *zcnv;
1865
1866 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1867 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zcnv, php_pqconv_class_entry);
1868 zend_restore_error_handling(&zeh TSRMLS_CC);
1869
1870 if (SUCCESS == rv) {
1871 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1872
1873 if (!obj->intern) {
1874 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1875 } else {
1876 zval *tmp, *zoids = NULL;
1877 struct apply_set_converter_arg arg = {NULL};
1878
1879 zend_call_method_with_0_params(&zcnv, NULL, NULL, "converttypes", &zoids);
1880 tmp = zoids;
1881 Z_ADDREF_P(tmp);
1882 convert_to_array_ex(&tmp);
1883
1884 arg.ht = &obj->intern->converters;
1885 arg.zconv = &zcnv;
1886 arg.add = 1;
1887
1888 zend_hash_apply_with_argument(Z_ARRVAL_P(tmp), apply_set_converter, &arg TSRMLS_CC);
1889
1890 zval_ptr_dtor(&tmp);
1891 zval_ptr_dtor(&zoids);
1892 }
1893 }
1894 }
1895
1896 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_unset_converter, 0, 0, 1)
1897 ZEND_ARG_OBJ_INFO(0, converter, pq\\Converter, 0)
1898 ZEND_END_ARG_INFO();
1899 static PHP_METHOD(pqconn, unsetConverter) {
1900 STATUS rv;
1901 zend_error_handling zeh;
1902 zval *zcnv;
1903
1904 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1905 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zcnv, php_pqconv_class_entry);
1906 zend_restore_error_handling(&zeh TSRMLS_CC);
1907
1908 if (SUCCESS == rv) {
1909 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1910
1911 if (!obj->intern) {
1912 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1913 } else {
1914 zval *tmp, *zoids = NULL;
1915 struct apply_set_converter_arg arg = {NULL};
1916
1917 zend_call_method_with_0_params(&zcnv, NULL, NULL, "converttypes", &zoids);
1918 tmp = zoids;
1919 Z_ADDREF_P(tmp);
1920 convert_to_array_ex(&tmp);
1921
1922 arg.ht = &obj->intern->converters;
1923 arg.zconv = &zcnv;
1924 arg.add = 0;
1925
1926 zend_hash_apply_with_argument(Z_ARRVAL_P(tmp), apply_set_converter, &arg TSRMLS_CC);
1927
1928 zval_ptr_dtor(&tmp);
1929 zval_ptr_dtor(&zoids);
1930 }
1931 }
1932 }
1933
1934 static zend_function_entry php_pqconn_methods[] = {
1935 PHP_ME(pqconn, __construct, ai_pqconn_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
1936 PHP_ME(pqconn, reset, ai_pqconn_reset, ZEND_ACC_PUBLIC)
1937 PHP_ME(pqconn, resetAsync, ai_pqconn_reset_async, ZEND_ACC_PUBLIC)
1938 PHP_ME(pqconn, poll, ai_pqconn_poll, ZEND_ACC_PUBLIC)
1939 PHP_ME(pqconn, exec, ai_pqconn_exec, ZEND_ACC_PUBLIC)
1940 PHP_ME(pqconn, execAsync, ai_pqconn_exec_async, ZEND_ACC_PUBLIC)
1941 PHP_ME(pqconn, execParams, ai_pqconn_exec_params, ZEND_ACC_PUBLIC)
1942 PHP_ME(pqconn, execParamsAsync, ai_pqconn_exec_params_async, ZEND_ACC_PUBLIC)
1943 PHP_ME(pqconn, prepare, ai_pqconn_prepare, ZEND_ACC_PUBLIC)
1944 PHP_ME(pqconn, prepareAsync, ai_pqconn_prepare_async, ZEND_ACC_PUBLIC)
1945 PHP_ME(pqconn, declare, ai_pqconn_declare, ZEND_ACC_PUBLIC)
1946 PHP_ME(pqconn, declareAsync, ai_pqconn_declare_async, ZEND_ACC_PUBLIC)
1947 PHP_ME(pqconn, unlisten, ai_pqconn_unlisten, ZEND_ACC_PUBLIC)
1948 PHP_ME(pqconn, unlistenAsync, ai_pqconn_unlisten_async, ZEND_ACC_PUBLIC)
1949 PHP_ME(pqconn, listen, ai_pqconn_listen, ZEND_ACC_PUBLIC)
1950 PHP_ME(pqconn, listenAsync, ai_pqconn_listen_async, ZEND_ACC_PUBLIC)
1951 PHP_ME(pqconn, notify, ai_pqconn_notify, ZEND_ACC_PUBLIC)
1952 PHP_ME(pqconn, notifyAsync, ai_pqconn_notify_async, ZEND_ACC_PUBLIC)
1953 PHP_ME(pqconn, getResult, ai_pqconn_get_result, ZEND_ACC_PUBLIC)
1954 PHP_ME(pqconn, quote, ai_pqconn_quote, ZEND_ACC_PUBLIC)
1955 PHP_ME(pqconn, quoteName, ai_pqconn_quote_name, ZEND_ACC_PUBLIC)
1956 PHP_ME(pqconn, escapeBytea, ai_pqconn_escape_bytea, ZEND_ACC_PUBLIC)
1957 PHP_ME(pqconn, unescapeBytea, ai_pqconn_unescape_bytea, ZEND_ACC_PUBLIC)
1958 PHP_ME(pqconn, startTransaction, ai_pqconn_start_transaction, ZEND_ACC_PUBLIC)
1959 PHP_ME(pqconn, startTransactionAsync, ai_pqconn_start_transaction_async, ZEND_ACC_PUBLIC)
1960 PHP_ME(pqconn, trace, ai_pqconn_trace, ZEND_ACC_PUBLIC)
1961 PHP_ME(pqconn, off, ai_pqconn_off, ZEND_ACC_PUBLIC)
1962 PHP_ME(pqconn, on, ai_pqconn_on, ZEND_ACC_PUBLIC)
1963 PHP_ME(pqconn, setConverter, ai_pqconn_set_converter, ZEND_ACC_PUBLIC)
1964 PHP_ME(pqconn, unsetConverter, ai_pqconn_unset_converter, ZEND_ACC_PUBLIC)
1965 {0}
1966 };
1967
1968 PHP_MSHUTDOWN_FUNCTION(pqconn)
1969 {
1970 zend_hash_destroy(&php_pqconn_object_prophandlers);
1971 return SUCCESS;
1972 }
1973
1974 PHP_MINIT_FUNCTION(pqconn)
1975 {
1976 zend_class_entry ce = {0};
1977 php_pq_object_prophandler_t ph = {0};
1978
1979 INIT_NS_CLASS_ENTRY(ce, "pq", "Connection", php_pqconn_methods);
1980 php_pqconn_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
1981 php_pqconn_class_entry->create_object = php_pqconn_create_object;
1982
1983 memcpy(&php_pqconn_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1984 php_pqconn_object_handlers.read_property = php_pq_object_read_prop;
1985 php_pqconn_object_handlers.write_property = php_pq_object_write_prop;
1986 php_pqconn_object_handlers.clone_obj = NULL;
1987 php_pqconn_object_handlers.get_property_ptr_ptr = NULL;
1988 php_pqconn_object_handlers.get_gc = NULL;
1989 php_pqconn_object_handlers.get_properties = php_pq_object_properties;
1990 php_pqconn_object_handlers.get_debug_info = php_pq_object_debug_info;
1991
1992 zend_hash_init(&php_pqconn_object_prophandlers, 19, NULL, NULL, 1);
1993
1994 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("status"), CONNECTION_BAD, ZEND_ACC_PUBLIC TSRMLS_CC);
1995 ph.read = php_pqconn_object_read_status;
1996 zend_hash_add(&php_pqconn_object_prophandlers, "status", sizeof("status"), (void *) &ph, sizeof(ph), NULL);
1997
1998 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("transactionStatus"), PQTRANS_UNKNOWN, ZEND_ACC_PUBLIC TSRMLS_CC);
1999 ph.read = php_pqconn_object_read_transaction_status;
2000 zend_hash_add(&php_pqconn_object_prophandlers, "transactionStatus", sizeof("transactionStatus"), (void *) &ph, sizeof(ph), NULL);
2001
2002 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("socket"), ZEND_ACC_PUBLIC TSRMLS_CC);
2003 ph.read = NULL; /* forward to std prophandler */
2004 zend_hash_add(&php_pqconn_object_prophandlers, "socket", sizeof("socket"), (void *) &ph, sizeof(ph), NULL);
2005
2006 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC TSRMLS_CC);
2007 ph.read = php_pqconn_object_read_error_message;
2008 zend_hash_add(&php_pqconn_object_prophandlers, "errorMessage", sizeof("errorMessage"), (void *) &ph, sizeof(ph), NULL);
2009
2010 zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("busy"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
2011 ph.read = php_pqconn_object_read_busy;
2012 zend_hash_add(&php_pqconn_object_prophandlers, "busy", sizeof("busy"), (void *) &ph, sizeof(ph), NULL);
2013
2014 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("encoding"), ZEND_ACC_PUBLIC TSRMLS_CC);
2015 ph.read = php_pqconn_object_read_encoding;
2016 ph.write = php_pqconn_object_write_encoding;
2017 zend_hash_add(&php_pqconn_object_prophandlers, "encoding", sizeof("encoding"), (void *) &ph, sizeof(ph), NULL);
2018 ph.write = NULL;
2019
2020 zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("unbuffered"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
2021 ph.read = php_pqconn_object_read_unbuffered;
2022 ph.write = php_pqconn_object_write_unbuffered;
2023 zend_hash_add(&php_pqconn_object_prophandlers, "unbuffered", sizeof("unbuffered"), (void *) &ph, sizeof(ph), NULL);
2024 ph.write = NULL;
2025
2026 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("db"), ZEND_ACC_PUBLIC TSRMLS_CC);
2027 ph.read = php_pqconn_object_read_db;
2028 zend_hash_add(&php_pqconn_object_prophandlers, "db", sizeof("db"), (void *) &ph, sizeof(ph), NULL);
2029
2030 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("user"), ZEND_ACC_PUBLIC TSRMLS_CC);
2031 ph.read = php_pqconn_object_read_user;
2032 zend_hash_add(&php_pqconn_object_prophandlers, "user", sizeof("user"), (void *) &ph, sizeof(ph), NULL);
2033
2034 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("pass"), ZEND_ACC_PUBLIC TSRMLS_CC);
2035 ph.read = php_pqconn_object_read_pass;
2036 zend_hash_add(&php_pqconn_object_prophandlers, "pass", sizeof("pass"), (void *) &ph, sizeof(ph), NULL);
2037
2038 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("host"), ZEND_ACC_PUBLIC TSRMLS_CC);
2039 ph.read = php_pqconn_object_read_host;
2040 zend_hash_add(&php_pqconn_object_prophandlers, "host", sizeof("host"), (void *) &ph, sizeof(ph), NULL);
2041
2042 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("port"), ZEND_ACC_PUBLIC TSRMLS_CC);
2043 ph.read = php_pqconn_object_read_port;
2044 zend_hash_add(&php_pqconn_object_prophandlers, "port", sizeof("port"), (void *) &ph, sizeof(ph), NULL);
2045
2046 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("options"), ZEND_ACC_PUBLIC TSRMLS_CC);
2047 ph.read = php_pqconn_object_read_options;
2048 zend_hash_add(&php_pqconn_object_prophandlers, "options", sizeof("options"), (void *) &ph, sizeof(ph), NULL);
2049
2050 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("eventHandlers"), ZEND_ACC_PUBLIC TSRMLS_CC);
2051 ph.read = php_pqconn_object_read_event_handlers;
2052 zend_hash_add(&php_pqconn_object_prophandlers, "eventHandlers", sizeof("eventHandlers"), (void *) &ph, sizeof(ph), NULL);
2053
2054 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("defaultFetchType"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
2055 ph.read = php_pqconn_object_read_def_fetch_type;
2056 ph.write = php_pqconn_object_write_def_fetch_type;
2057 zend_hash_add(&php_pqconn_object_prophandlers, "defaultFetchType", sizeof("defaultFetchType"), (void *) &ph, sizeof(ph), NULL);
2058 ph.write = NULL;
2059
2060 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("defaultTransactionIsolation"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
2061 ph.read = php_pqconn_object_read_def_txn_isolation;
2062 ph.write = php_pqconn_object_write_def_txn_isolation;
2063 zend_hash_add(&php_pqconn_object_prophandlers, "defaultTransactionIsolation", sizeof("defaultTransactionIsolation"), (void *) &ph, sizeof(ph), NULL);
2064 ph.write = NULL;
2065
2066 zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("defaultTransactionReadonly"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
2067 ph.read = php_pqconn_object_read_def_txn_readonly;
2068 ph.write = php_pqconn_object_write_def_txn_readonly;
2069 zend_hash_add(&php_pqconn_object_prophandlers, "defaultTransactionReadonly", sizeof("defaultTransactionReadonly"), (void *) &ph, sizeof(ph), NULL);
2070 ph.write = NULL;
2071
2072 zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("defaultTransactionDeferrable"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
2073 ph.read = php_pqconn_object_read_def_txn_deferrable;
2074 ph.write = php_pqconn_object_write_def_txn_deferrable;
2075 zend_hash_add(&php_pqconn_object_prophandlers, "defaultTransactionDeferrable", sizeof("defaultTransactionDeferrable"), (void *) &ph, sizeof(ph), NULL);
2076 ph.write = NULL;
2077
2078 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("defaultAutoConvert"), PHP_PQRES_CONV_ALL, ZEND_ACC_PUBLIC TSRMLS_CC);
2079 ph.read = php_pqconn_object_read_def_auto_conv;
2080 ph.write = php_pqconn_object_write_def_auto_conv;
2081 zend_hash_add(&php_pqconn_object_prophandlers, "defaultAutoConvert", sizeof("defaultAutoConvert"), (void *) &ph, sizeof(ph), NULL);
2082 ph.write = NULL;
2083
2084 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("OK"), CONNECTION_OK TSRMLS_CC);
2085 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("BAD"), CONNECTION_BAD TSRMLS_CC);
2086 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("STARTED"), CONNECTION_STARTED TSRMLS_CC);
2087 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("MADE"), CONNECTION_MADE TSRMLS_CC);
2088 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("AWAITING_RESPONSE"), CONNECTION_AWAITING_RESPONSE TSRMLS_CC);
2089 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("AUTH_OK"), CONNECTION_AUTH_OK TSRMLS_CC);
2090 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("SSL_STARTUP"), CONNECTION_SSL_STARTUP TSRMLS_CC);
2091 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("SETENV"), CONNECTION_SETENV TSRMLS_CC);
2092
2093 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_IDLE"), PQTRANS_IDLE TSRMLS_CC);
2094 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_ACTIVE"), PQTRANS_ACTIVE TSRMLS_CC);
2095 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_INTRANS"), PQTRANS_INTRANS TSRMLS_CC);
2096 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_INERROR"), PQTRANS_INERROR TSRMLS_CC);
2097 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_UNKNOWN"), PQTRANS_UNKNOWN TSRMLS_CC);
2098
2099 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_FAILED"), PGRES_POLLING_FAILED TSRMLS_CC);
2100 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_READING"), PGRES_POLLING_READING TSRMLS_CC);
2101 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_WRITING"), PGRES_POLLING_WRITING TSRMLS_CC);
2102 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_OK"), PGRES_POLLING_OK TSRMLS_CC);
2103
2104 zend_declare_class_constant_stringl(php_pqconn_class_entry, ZEND_STRL("EVENT_NOTICE"), ZEND_STRL("notice") TSRMLS_CC);
2105 zend_declare_class_constant_stringl(php_pqconn_class_entry, ZEND_STRL("EVENT_RESULT"), ZEND_STRL("result") TSRMLS_CC);
2106 zend_declare_class_constant_stringl(php_pqconn_class_entry, ZEND_STRL("EVENT_RESET"), ZEND_STRL("reset") TSRMLS_CC);
2107
2108 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("ASYNC"), 0x1 TSRMLS_CC);
2109 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("PERSISTENT"), 0x2 TSRMLS_CC);
2110
2111 return SUCCESS;
2112 }
2113
2114 /*
2115 * Local variables:
2116 * tab-width: 4
2117 * c-basic-offset: 4
2118 * End:
2119 * vim600: noet sw=4 ts=4 fdm=marker
2120 * vim<600: noet sw=4 ts=4
2121 */