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