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