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