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