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