Fix releases link
[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 php_pq_object_t *res_obj;
1150
1151 if (res && (res_obj = PQresultInstanceData(res, php_pqconn_event))) {
1152 php_pq_object_to_zval_no_addref(res_obj, return_value);
1153 } else {
1154 RETVAL_NULL();
1155 }
1156
1157 php_pqconn_notify_listeners(obj);
1158 }
1159 }
1160 }
1161
1162 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_async, 0, 0, 1)
1163 ZEND_ARG_INFO(0, query)
1164 ZEND_ARG_INFO(0, callable)
1165 ZEND_END_ARG_INFO();
1166 static PHP_METHOD(pqconn, execAsync) {
1167 zend_error_handling zeh;
1168 php_pq_callback_t resolver = {{0}};
1169 char *query_str;
1170 size_t query_len;
1171 ZEND_RESULT_CODE rv;
1172
1173 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1174 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "s|f", &query_str, &query_len, &resolver.fci, &resolver.fcc);
1175 zend_restore_error_handling(&zeh);
1176
1177 if (SUCCESS == rv) {
1178 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1179
1180 if (!obj->intern) {
1181 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1182 } else if (!PQsendQuery(obj->intern->conn, query_str)) {
1183 throw_exce(EX_IO, "Failed to execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
1184 #if HAVE_PQSETSINGLEROWMODE
1185 } else if (obj->intern->unbuffered && !PQsetSingleRowMode(obj->intern->conn)) {
1186 throw_exce(EX_RUNTIME, "Failed to enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn));
1187 #endif
1188 } else {
1189 php_pq_callback_recurse(&obj->intern->onevent, &resolver);
1190 obj->intern->poller = PQconsumeInput;
1191 php_pqconn_notify_listeners(obj);
1192 }
1193 }
1194 }
1195
1196 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_params, 0, 0, 2)
1197 ZEND_ARG_INFO(0, query)
1198 ZEND_ARG_ARRAY_INFO(0, params, 0)
1199 ZEND_ARG_ARRAY_INFO(0, types, 1)
1200 ZEND_END_ARG_INFO();
1201 static PHP_METHOD(pqconn, execParams) {
1202 zend_error_handling zeh;
1203 char *query_str;
1204 size_t query_len;
1205 zval *zparams;
1206 zval *ztypes = NULL;
1207 ZEND_RESULT_CODE rv;
1208
1209 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1210 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "sa/|a/!", &query_str, &query_len, &zparams, &ztypes);
1211 zend_restore_error_handling(&zeh);
1212
1213 if (SUCCESS == rv) {
1214 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1215
1216 if (!obj->intern) {
1217 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1218 } else {
1219 PGresult *res;
1220 php_pq_params_t *params;
1221
1222 params = php_pq_params_init(&obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, Z_ARRVAL_P(zparams));
1223 res = PQexecParams(obj->intern->conn, query_str, params->param.count, params->type.oids, (const char *const*) params->param.strings, NULL, NULL, 0);
1224 php_pq_params_free(&params);
1225
1226 if (!res) {
1227 throw_exce(EX_RUNTIME, "Failed to execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
1228 } else {
1229 if (SUCCESS == php_pqres_success(res)) {
1230 php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), return_value);
1231 } else {
1232 php_pqres_clear(res);
1233 }
1234
1235 php_pqconn_notify_listeners(obj);
1236 }
1237 }
1238 }
1239 }
1240
1241 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_params_async, 0, 0, 2)
1242 ZEND_ARG_INFO(0, query)
1243 ZEND_ARG_ARRAY_INFO(0, params, 0)
1244 ZEND_ARG_ARRAY_INFO(0, types, 1)
1245 ZEND_ARG_INFO(0, callable)
1246 ZEND_END_ARG_INFO();
1247 static PHP_METHOD(pqconn, execParamsAsync) {
1248 zend_error_handling zeh;
1249 php_pq_callback_t resolver = {{0}};
1250 char *query_str;
1251 size_t query_len;
1252 zval *zparams;
1253 zval *ztypes = NULL;
1254 ZEND_RESULT_CODE rv;
1255
1256 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1257 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "sa/|a/!f", &query_str, &query_len, &zparams, &ztypes, &resolver.fci, &resolver.fcc);
1258 zend_restore_error_handling(&zeh);
1259
1260 if (SUCCESS == rv) {
1261 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1262
1263 if (!obj->intern) {
1264 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1265 } else {
1266 int rc;
1267 php_pq_params_t *params;
1268
1269 params = php_pq_params_init(&obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, Z_ARRVAL_P(zparams));
1270 rc = PQsendQueryParams(obj->intern->conn, query_str, params->param.count, params->type.oids, (const char *const*) params->param.strings, NULL, NULL, 0);
1271 php_pq_params_free(&params);
1272
1273 if (!rc) {
1274 throw_exce(EX_IO, "Failed to execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
1275 #if HAVE_PQSETSINGLEROWMODE
1276 } else if (obj->intern->unbuffered && !PQsetSingleRowMode(obj->intern->conn)) {
1277 throw_exce(EX_RUNTIME, "Failed to enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn));
1278 #endif
1279 } else {
1280 php_pq_callback_recurse(&obj->intern->onevent, &resolver);
1281 obj->intern->poller = PQconsumeInput;
1282 php_pqconn_notify_listeners(obj);
1283 }
1284 }
1285 }
1286 zend_restore_error_handling(&zeh);
1287 }
1288
1289 ZEND_RESULT_CODE php_pqconn_prepare(zval *object, php_pqconn_object_t *obj, const char *name, const char *query, php_pq_params_t *params)
1290 {
1291 PGresult *res;
1292 ZEND_RESULT_CODE rv;
1293
1294 if (!obj) {
1295 obj = PHP_PQ_OBJ(object, NULL);
1296 }
1297
1298 res = php_pq_prepare(obj->intern->conn, name, query, params->type.count, params->type.oids);
1299
1300 if (!res) {
1301 rv = FAILURE;
1302 throw_exce(EX_RUNTIME, "Failed to prepare statement (%s)", PHP_PQerrorMessage(obj->intern->conn));
1303 } else {
1304 rv = php_pqres_success(res);
1305 php_pqres_clear(res);
1306 php_pqconn_notify_listeners(obj);
1307 }
1308
1309 return rv;
1310 }
1311
1312 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_prepare, 0, 0, 2)
1313 ZEND_ARG_INFO(0, name)
1314 ZEND_ARG_INFO(0, query)
1315 ZEND_ARG_ARRAY_INFO(0, types, 1)
1316 ZEND_END_ARG_INFO();
1317 static PHP_METHOD(pqconn, prepare) {
1318 zend_error_handling zeh;
1319 zval *ztypes = NULL;
1320 char *name_str, *query_str;
1321 size_t name_len, *query_len;
1322 ZEND_RESULT_CODE rv;
1323
1324 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1325 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "ss|a/!", &name_str, &name_len, &query_str, &query_len, &ztypes);
1326 zend_restore_error_handling(&zeh);
1327
1328 if (SUCCESS == rv) {
1329 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1330
1331 if (!obj->intern) {
1332 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1333 } else {
1334 php_pq_params_t *params = php_pq_params_init(&obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, NULL);
1335
1336 if (SUCCESS != php_pqconn_prepare(getThis(), obj, name_str, query_str, params)) {
1337 php_pq_params_free(&params);
1338 } else {
1339 php_pqstm_t *stm = php_pqstm_init(obj, name_str, query_str, params);
1340
1341 RETVAL_OBJ(&php_pqstm_create_object_ex(php_pqstm_class_entry, stm)->zo);
1342 }
1343 }
1344 }
1345 }
1346
1347 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)
1348 {
1349 ZEND_RESULT_CODE rv;
1350
1351 if (!obj) {
1352 obj = PHP_PQ_OBJ(object, NULL);
1353 }
1354
1355 if (!PQsendPrepare(obj->intern->conn, name, query, params->type.count, params->type.oids)) {
1356 rv = FAILURE;
1357 throw_exce(EX_IO, "Failed to prepare statement (%s)", PHP_PQerrorMessage(obj->intern->conn));
1358 } else {
1359 rv = SUCCESS;
1360 obj->intern->poller = PQconsumeInput;
1361 php_pqconn_notify_listeners(obj);
1362 }
1363
1364 return rv;
1365 }
1366
1367 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_prepare_async, 0, 0, 2)
1368 ZEND_ARG_INFO(0, name)
1369 ZEND_ARG_INFO(0, query)
1370 ZEND_ARG_ARRAY_INFO(0, types, 1)
1371 ZEND_END_ARG_INFO();
1372 static PHP_METHOD(pqconn, prepareAsync) {
1373 zend_error_handling zeh;
1374 zval *ztypes = NULL;
1375 char *name_str, *query_str;
1376 size_t name_len, *query_len;
1377 ZEND_RESULT_CODE rv;
1378
1379 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1380 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "ss|a/!", &name_str, &name_len, &query_str, &query_len, &ztypes);
1381 zend_restore_error_handling(&zeh);
1382
1383 if (SUCCESS == rv) {
1384 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1385
1386 if (!obj->intern) {
1387 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1388 } else {
1389 php_pq_params_t *params = php_pq_params_init(&obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, NULL);
1390
1391 if (SUCCESS != php_pqconn_prepare_async(getThis(), obj, name_str, query_str, params)) {
1392 php_pq_params_free(&params);
1393 } else {
1394 php_pqstm_t *stm = php_pqstm_init(obj, name_str, query_str, params);
1395
1396 RETVAL_OBJ(&php_pqstm_create_object_ex(php_pqstm_class_entry, stm)->zo);
1397 }
1398 }
1399 }
1400 }
1401
1402 ZEND_RESULT_CODE php_pqconn_declare(zval *object, php_pqconn_object_t *obj, const char *decl)
1403 {
1404 PGresult *res;
1405 ZEND_RESULT_CODE rv;
1406
1407 if (!obj) {
1408 obj = PHP_PQ_OBJ(object, NULL);
1409 }
1410
1411 res = php_pq_exec(obj->intern->conn, decl);
1412
1413 if (!res) {
1414 rv = FAILURE;
1415 throw_exce(EX_RUNTIME, "Failed to declare cursor (%s)", PHP_PQerrorMessage(obj->intern->conn));
1416 } else {
1417 rv = php_pqres_success(res);
1418 php_pqres_clear(res);
1419 php_pqconn_notify_listeners(obj);
1420 }
1421
1422 return rv;
1423 }
1424
1425 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_declare, 0, 0, 3)
1426 ZEND_ARG_INFO(0, name)
1427 ZEND_ARG_INFO(0, flags)
1428 ZEND_ARG_INFO(0, query)
1429 ZEND_END_ARG_INFO();
1430 static PHP_METHOD(pqconn, declare) {
1431 zend_error_handling zeh;
1432 char *name_str, *query_str;
1433 size_t name_len, query_len;
1434 zend_long flags;
1435 ZEND_RESULT_CODE rv;
1436
1437 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1438 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "sls", &name_str, &name_len, &flags, &query_str, &query_len);
1439 zend_restore_error_handling(&zeh);
1440
1441 if (SUCCESS == rv) {
1442 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1443
1444 if (!obj->intern) {
1445 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1446 } else {
1447 int query_offset;
1448 char *decl = php_pqcur_declare_str(name_str, name_len, flags, query_str, query_len, &query_offset);
1449
1450 if (SUCCESS != php_pqconn_declare(getThis(), obj, decl)) {
1451 efree(decl);
1452 } else {
1453 php_pqcur_t *cur = php_pqcur_init(obj, name_str, decl, query_offset, flags);
1454
1455 RETVAL_OBJ(&php_pqcur_create_object_ex(php_pqcur_class_entry, cur)->zo);
1456 }
1457 }
1458 }
1459 }
1460
1461 ZEND_RESULT_CODE php_pqconn_declare_async(zval *object, php_pqconn_object_t *obj, const char *decl)
1462 {
1463 ZEND_RESULT_CODE rv;
1464
1465 if (!obj) {
1466 obj = PHP_PQ_OBJ(object, NULL);
1467 }
1468
1469 if (!PQsendQuery(obj->intern->conn, decl)) {
1470 rv = FAILURE;
1471 throw_exce(EX_IO, "Failed to declare cursor (%s)", PHP_PQerrorMessage(obj->intern->conn));
1472 } else {
1473 rv = SUCCESS;
1474 obj->intern->poller = PQconsumeInput;
1475 php_pqconn_notify_listeners(obj);
1476 }
1477
1478 return rv;
1479 }
1480
1481 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_declare_async, 0, 0, 2)
1482 ZEND_ARG_INFO(0, name)
1483 ZEND_ARG_INFO(0, flags)
1484 ZEND_ARG_INFO(0, query)
1485 ZEND_END_ARG_INFO();
1486 static PHP_METHOD(pqconn, declareAsync) {
1487 zend_error_handling zeh;
1488 char *name_str, *query_str;
1489 size_t name_len, query_len;
1490 zend_long flags;
1491 ZEND_RESULT_CODE rv;
1492
1493 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1494 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "sls", &name_str, &name_len, &flags, &query_str, &query_len);
1495 zend_restore_error_handling(&zeh);
1496
1497 if (SUCCESS == rv) {
1498 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1499
1500 if (!obj->intern) {
1501 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1502 } else {
1503 int query_offset;
1504 char *decl = php_pqcur_declare_str(name_str, name_len, flags, query_str, query_len, &query_offset);
1505
1506 if (SUCCESS != php_pqconn_declare_async(getThis(), obj, decl)) {
1507 efree(decl);
1508 } else {
1509 php_pqcur_t *cur = php_pqcur_init(obj, name_str, decl, query_offset, flags);
1510
1511 RETVAL_OBJ(&php_pqcur_create_object_ex(php_pqcur_class_entry, cur)->zo);
1512 }
1513 }
1514 }
1515 }
1516
1517 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_quote, 0, 0, 1)
1518 ZEND_ARG_INFO(0, string)
1519 ZEND_END_ARG_INFO();
1520 static PHP_METHOD(pqconn, quote) {
1521 char *str;
1522 size_t len;
1523
1524 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &len)) {
1525 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1526
1527 if (!obj->intern) {
1528 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1529 } else {
1530 char *quoted = PQescapeLiteral(obj->intern->conn, str, len);
1531
1532 if (!quoted) {
1533 php_error_docref(NULL, E_WARNING, "Failed to quote string (%s)", PHP_PQerrorMessage(obj->intern->conn));
1534 RETVAL_FALSE;
1535 } else {
1536 RETVAL_STRING(quoted);
1537 PQfreemem(quoted);
1538 }
1539 }
1540 }
1541 }
1542
1543 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_quote_name, 0, 0, 1)
1544 ZEND_ARG_INFO(0, type)
1545 ZEND_END_ARG_INFO();
1546 static PHP_METHOD(pqconn, quoteName) {
1547 char *str;
1548 size_t len;
1549
1550 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &len)) {
1551 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1552
1553 if (!obj->intern) {
1554 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1555 } else {
1556 char *quoted = PQescapeIdentifier(obj->intern->conn, str, len);
1557
1558 if (!quoted) {
1559 php_error_docref(NULL, E_WARNING, "Failed to quote name (%s)", PHP_PQerrorMessage(obj->intern->conn));
1560 RETVAL_FALSE;
1561 } else {
1562 RETVAL_STRING(quoted);
1563 PQfreemem(quoted);
1564 }
1565 }
1566 }
1567 }
1568
1569 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_escape_bytea, 0, 0, 1)
1570 ZEND_ARG_INFO(0, bytea)
1571 ZEND_END_ARG_INFO();
1572 static PHP_METHOD(pqconn, escapeBytea) {
1573 char *str;
1574 size_t len;
1575
1576 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &len)) {
1577 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1578
1579 if (!obj->intern) {
1580 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1581 } else {
1582 size_t escaped_len;
1583 char *escaped_str = (char *) PQescapeByteaConn(obj->intern->conn, (unsigned char *) str, len, &escaped_len);
1584
1585 if (!escaped_str) {
1586 php_error_docref(NULL, E_WARNING, "Failed to escape bytea (%s)", PHP_PQerrorMessage(obj->intern->conn));
1587 RETVAL_FALSE;
1588 } else {
1589 RETVAL_STRINGL(escaped_str, escaped_len - 1);
1590 PQfreemem(escaped_str);
1591 }
1592 }
1593 }
1594 }
1595
1596 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_unescape_bytea, 0, 0, 1)
1597 ZEND_ARG_INFO(0, bytea)
1598 ZEND_END_ARG_INFO();
1599 static PHP_METHOD(pqconn, unescapeBytea) {
1600 char *str;
1601 size_t len;
1602
1603 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &len)) {
1604 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1605
1606 if (!obj->intern) {
1607 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1608 } else {
1609 size_t unescaped_len;
1610 char *unescaped_str = (char *) PQunescapeBytea((unsigned char *)str, &unescaped_len);
1611
1612 if (!unescaped_str) {
1613 php_error_docref(NULL, E_WARNING, "Failed to unescape bytea (%s)", PHP_PQerrorMessage(obj->intern->conn));
1614 RETVAL_FALSE;
1615 } else {
1616 RETVAL_STRINGL(unescaped_str, unescaped_len);
1617 PQfreemem(unescaped_str);
1618 }
1619 }
1620 }
1621 }
1622
1623 ZEND_RESULT_CODE php_pqconn_start_transaction(zval *zconn, php_pqconn_object_t *conn_obj, long isolation, zend_bool readonly, zend_bool deferrable)
1624 {
1625 ZEND_RESULT_CODE rv = FAILURE;
1626
1627 if (!conn_obj) {
1628 conn_obj = PHP_PQ_OBJ(zconn, NULL);
1629 }
1630
1631 if (!conn_obj->intern) {
1632 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1633 } else {
1634 PGresult *res;
1635 smart_str cmd = {0};
1636 const char *il = php_pq_isolation_level(&isolation);
1637
1638 smart_str_appends(&cmd, "START TRANSACTION ISOLATION LEVEL ");
1639 smart_str_appends(&cmd, il);
1640 smart_str_appends(&cmd, ", READ ");
1641 smart_str_appends(&cmd, readonly ? "ONLY" : "WRITE");
1642 smart_str_appends(&cmd, ",");
1643 smart_str_appends(&cmd, deferrable ? "" : " NOT");
1644 smart_str_appends(&cmd, " DEFERRABLE");
1645 smart_str_0(&cmd);
1646
1647 res = php_pq_exec(conn_obj->intern->conn, smart_str_v(&cmd));
1648
1649 if (!res) {
1650 throw_exce(EX_RUNTIME, "Failed to start transaction (%s)", PHP_PQerrorMessage(conn_obj->intern->conn));
1651 } else {
1652 rv = php_pqres_success(res);
1653 php_pqres_clear(res);
1654 php_pqconn_notify_listeners(conn_obj);
1655 }
1656
1657 smart_str_free(&cmd);
1658 }
1659
1660 return rv;
1661 }
1662
1663 ZEND_RESULT_CODE php_pqconn_start_transaction_async(zval *zconn, php_pqconn_object_t *conn_obj, long isolation, zend_bool readonly, zend_bool deferrable)
1664 {
1665 ZEND_RESULT_CODE rv = FAILURE;
1666
1667 if (!conn_obj) {
1668 conn_obj = PHP_PQ_OBJ(zconn, NULL);
1669 }
1670
1671 if (!conn_obj->intern) {
1672 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1673 } else {
1674 smart_str cmd = {0};
1675 const char *il = php_pq_isolation_level(&isolation);
1676
1677 smart_str_appends(&cmd, "START TRANSACTION ISOLATION LEVEL ");
1678 smart_str_appends(&cmd, il);
1679 smart_str_appends(&cmd, ", READ ");
1680 smart_str_appends(&cmd, readonly ? "ONLY" : "WRITE");
1681 smart_str_appends(&cmd, ",");
1682 smart_str_appends(&cmd, deferrable ? "" : "NOT ");
1683 smart_str_appends(&cmd, " DEFERRABLE");
1684 smart_str_0(&cmd);
1685
1686 if (!PQsendQuery(conn_obj->intern->conn, smart_str_v(&cmd))) {
1687 throw_exce(EX_IO, "Failed to start transaction (%s)", PHP_PQerrorMessage(conn_obj->intern->conn));
1688 } else {
1689 rv = SUCCESS;
1690 conn_obj->intern->poller = PQconsumeInput;
1691 php_pqconn_notify_listeners(conn_obj);
1692 }
1693
1694 smart_str_free(&cmd);
1695 }
1696
1697 return rv;
1698 }
1699
1700 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_start_transaction, 0, 0, 0)
1701 ZEND_ARG_INFO(0, isolation)
1702 ZEND_ARG_INFO(0, readonly)
1703 ZEND_ARG_INFO(0, deferrable)
1704 ZEND_END_ARG_INFO();
1705 static PHP_METHOD(pqconn, startTransaction) {
1706 zend_error_handling zeh;
1707 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1708 zend_long isolation = obj->intern ? obj->intern->default_txn_isolation : PHP_PQTXN_READ_COMMITTED;
1709 zend_bool readonly = obj->intern ? obj->intern->default_txn_readonly : 0;
1710 zend_bool deferrable = obj->intern ? obj->intern->default_txn_deferrable : 0;
1711 ZEND_RESULT_CODE rv;
1712
1713 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1714 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "|lbb", &isolation, &readonly, &deferrable);
1715 zend_restore_error_handling(&zeh);
1716
1717 if (SUCCESS == rv) {
1718 rv = php_pqconn_start_transaction(getThis(), obj, isolation, readonly, deferrable);
1719
1720 if (SUCCESS == rv) {
1721 php_pqtxn_t *txn = ecalloc(1, sizeof(*txn));
1722
1723 php_pq_object_addref(obj);
1724 txn->conn = obj;
1725 txn->open = 1;
1726 txn->isolation = isolation;
1727 txn->readonly = readonly;
1728 txn->deferrable = deferrable;
1729
1730 RETVAL_OBJ(&php_pqtxn_create_object_ex(php_pqtxn_class_entry, txn)->zo);
1731 }
1732 }
1733 }
1734
1735 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_start_transaction_async, 0, 0, 0)
1736 ZEND_ARG_INFO(0, isolation)
1737 ZEND_ARG_INFO(0, readonly)
1738 ZEND_ARG_INFO(0, deferrable)
1739 ZEND_END_ARG_INFO();
1740 static PHP_METHOD(pqconn, startTransactionAsync) {
1741 zend_error_handling zeh;
1742 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1743 zend_long isolation = obj->intern ? obj->intern->default_txn_isolation : PHP_PQTXN_READ_COMMITTED;
1744 zend_bool readonly = obj->intern ? obj->intern->default_txn_readonly : 0;
1745 zend_bool deferrable = obj->intern ? obj->intern->default_txn_deferrable : 0;
1746 ZEND_RESULT_CODE rv;
1747
1748 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1749 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "|lbb", &isolation, &readonly, &deferrable);
1750 zend_restore_error_handling(&zeh);
1751
1752 if (SUCCESS == rv) {
1753 rv = php_pqconn_start_transaction_async(getThis(), obj, isolation, readonly, deferrable);
1754
1755 if (SUCCESS == rv) {
1756 php_pqtxn_t *txn = ecalloc(1, sizeof(*txn));
1757
1758 php_pq_object_addref(obj);
1759 txn->conn = obj;
1760 txn->open = 1;
1761 txn->isolation = isolation;
1762 txn->readonly = readonly;
1763 txn->deferrable = deferrable;
1764
1765 RETVAL_OBJ(&php_pqtxn_create_object_ex(php_pqtxn_class_entry, txn)->zo);
1766 }
1767 }
1768 }
1769
1770 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_trace, 0, 0, 0)
1771 ZEND_ARG_INFO(0, stdio_stream)
1772 ZEND_END_ARG_INFO();
1773 static PHP_METHOD(pqconn, trace) {
1774 zval *zstream = NULL;
1775
1776 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|r!", &zstream)) {
1777 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1778
1779 if (!obj->intern) {
1780 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1781 } else {
1782 if (!zstream) {
1783 PQuntrace(obj->intern->conn);
1784 RETVAL_TRUE;
1785 } else {
1786 FILE *fp;
1787 php_stream *stream = NULL;
1788
1789 php_stream_from_zval(stream, zstream);
1790
1791 if (SUCCESS != php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void *) &fp, REPORT_ERRORS)) {
1792 RETVAL_FALSE;
1793 } else {
1794 stream->flags |= PHP_STREAM_FLAG_NO_CLOSE;
1795 PQtrace(obj->intern->conn, fp);
1796 RETVAL_TRUE;
1797 }
1798 }
1799 }
1800 }
1801 }
1802
1803 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_off, 0, 0, 1)
1804 ZEND_ARG_INFO(0, type)
1805 ZEND_END_ARG_INFO();
1806 static PHP_METHOD(pqconn, off) {
1807 zend_error_handling zeh;
1808 zend_string *type;
1809 ZEND_RESULT_CODE rv;
1810
1811 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1812 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "S", &type);
1813 zend_restore_error_handling(&zeh);
1814
1815 if (SUCCESS == rv) {
1816 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1817
1818 if (!obj->intern) {
1819 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1820 } else {
1821 RETURN_BOOL(SUCCESS == zend_hash_del(&obj->intern->eventhandlers, type));
1822 }
1823 }
1824 }
1825
1826 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_on, 0, 0, 2)
1827 ZEND_ARG_INFO(0, type)
1828 ZEND_ARG_INFO(0, callable)
1829 ZEND_END_ARG_INFO();
1830 static PHP_METHOD(pqconn, on) {
1831 zend_error_handling zeh;
1832 char *type_str;
1833 size_t type_len;
1834 php_pq_callback_t cb = {{0}};
1835 ZEND_RESULT_CODE rv;
1836
1837 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1838 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "sf", &type_str, &type_len, &cb.fci, &cb.fcc);
1839 zend_restore_error_handling(&zeh);
1840
1841 if (SUCCESS == rv) {
1842 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1843
1844 if (!obj->intern) {
1845 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1846 } else {
1847 RETVAL_LONG(php_pqconn_add_eventhandler(obj, type_str, type_len, &cb));
1848 }
1849 }
1850 }
1851
1852 struct apply_set_converter_arg {
1853 HashTable *ht;
1854 zval *zconv;
1855 unsigned add:1;
1856 };
1857
1858 static int apply_set_converter(zval *zoid, void *a)
1859 {
1860 zend_long oid = zval_get_long(zoid);
1861 struct apply_set_converter_arg *arg = a;
1862
1863 if (arg->add) {
1864 Z_ADDREF_P(arg->zconv);
1865 zend_hash_index_update(arg->ht, oid, arg->zconv);
1866 } else {
1867 zend_hash_index_del(arg->ht, oid);
1868 }
1869
1870 return ZEND_HASH_APPLY_KEEP;
1871 }
1872
1873 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_set_converter, 0, 0, 1)
1874 ZEND_ARG_OBJ_INFO(0, converter, pq\\Converter, 0)
1875 ZEND_END_ARG_INFO();
1876 static PHP_METHOD(pqconn, setConverter) {
1877 ZEND_RESULT_CODE rv;
1878 zend_error_handling zeh;
1879 zval *zcnv;
1880
1881 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1882 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "O", &zcnv, php_pqconv_class_entry);
1883 zend_restore_error_handling(&zeh);
1884
1885 if (SUCCESS == rv) {
1886 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1887
1888 if (!obj->intern) {
1889 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1890 } else {
1891 zval tmp, zoids;
1892 struct apply_set_converter_arg arg = {NULL};
1893
1894 ZVAL_NULL(&zoids);
1895 zend_call_method_with_0_params(zcnv, NULL, NULL, "converttypes", &zoids);
1896 ZVAL_DUP(&tmp, &zoids);
1897 convert_to_array(&tmp);
1898
1899 arg.ht = &obj->intern->converters;
1900 arg.zconv = zcnv;
1901 arg.add = 1;
1902
1903 zend_hash_apply_with_argument(Z_ARRVAL(tmp), apply_set_converter, &arg);
1904
1905 zval_ptr_dtor(&tmp);
1906 zval_ptr_dtor(&zoids);
1907 }
1908 }
1909 }
1910
1911 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_unset_converter, 0, 0, 1)
1912 ZEND_ARG_OBJ_INFO(0, converter, pq\\Converter, 0)
1913 ZEND_END_ARG_INFO();
1914 static PHP_METHOD(pqconn, unsetConverter) {
1915 ZEND_RESULT_CODE rv;
1916 zend_error_handling zeh;
1917 zval *zcnv;
1918
1919 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1920 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "O", &zcnv, php_pqconv_class_entry);
1921 zend_restore_error_handling(&zeh);
1922
1923 if (SUCCESS == rv) {
1924 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1925
1926 if (!obj->intern) {
1927 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1928 } else {
1929 zval tmp, zoids;
1930 struct apply_set_converter_arg arg = {NULL};
1931
1932 ZVAL_NULL(&zoids);
1933 zend_call_method_with_0_params(zcnv, NULL, NULL, "converttypes", &zoids);
1934 ZVAL_DUP(&tmp, &zoids);
1935 convert_to_array(&tmp);
1936
1937 arg.ht = &obj->intern->converters;
1938 arg.zconv = zcnv;
1939 arg.add = 0;
1940
1941 zend_hash_apply_with_argument(Z_ARRVAL(tmp), apply_set_converter, &arg);
1942
1943 zval_ptr_dtor(&tmp);
1944 zval_ptr_dtor(&zoids);
1945 }
1946 }
1947 }
1948
1949 static zend_function_entry php_pqconn_methods[] = {
1950 PHP_ME(pqconn, __construct, ai_pqconn_construct, ZEND_ACC_PUBLIC)
1951 PHP_ME(pqconn, reset, ai_pqconn_reset, ZEND_ACC_PUBLIC)
1952 PHP_ME(pqconn, resetAsync, ai_pqconn_reset_async, ZEND_ACC_PUBLIC)
1953 PHP_ME(pqconn, poll, ai_pqconn_poll, ZEND_ACC_PUBLIC)
1954 PHP_ME(pqconn, flush, ai_pqconn_flush, ZEND_ACC_PUBLIC)
1955 PHP_ME(pqconn, exec, ai_pqconn_exec, ZEND_ACC_PUBLIC)
1956 PHP_ME(pqconn, execAsync, ai_pqconn_exec_async, ZEND_ACC_PUBLIC)
1957 PHP_ME(pqconn, execParams, ai_pqconn_exec_params, ZEND_ACC_PUBLIC)
1958 PHP_ME(pqconn, execParamsAsync, ai_pqconn_exec_params_async, ZEND_ACC_PUBLIC)
1959 PHP_ME(pqconn, prepare, ai_pqconn_prepare, ZEND_ACC_PUBLIC)
1960 PHP_ME(pqconn, prepareAsync, ai_pqconn_prepare_async, ZEND_ACC_PUBLIC)
1961 PHP_ME(pqconn, declare, ai_pqconn_declare, ZEND_ACC_PUBLIC)
1962 PHP_ME(pqconn, declareAsync, ai_pqconn_declare_async, ZEND_ACC_PUBLIC)
1963 PHP_ME(pqconn, unlisten, ai_pqconn_unlisten, ZEND_ACC_PUBLIC)
1964 PHP_ME(pqconn, unlistenAsync, ai_pqconn_unlisten_async, ZEND_ACC_PUBLIC)
1965 PHP_ME(pqconn, listen, ai_pqconn_listen, ZEND_ACC_PUBLIC)
1966 PHP_ME(pqconn, listenAsync, ai_pqconn_listen_async, ZEND_ACC_PUBLIC)
1967 PHP_ME(pqconn, notify, ai_pqconn_notify, ZEND_ACC_PUBLIC)
1968 PHP_ME(pqconn, notifyAsync, ai_pqconn_notify_async, ZEND_ACC_PUBLIC)
1969 PHP_ME(pqconn, getResult, ai_pqconn_get_result, ZEND_ACC_PUBLIC)
1970 PHP_ME(pqconn, quote, ai_pqconn_quote, ZEND_ACC_PUBLIC)
1971 PHP_ME(pqconn, quoteName, ai_pqconn_quote_name, ZEND_ACC_PUBLIC)
1972 PHP_ME(pqconn, escapeBytea, ai_pqconn_escape_bytea, ZEND_ACC_PUBLIC)
1973 PHP_ME(pqconn, unescapeBytea, ai_pqconn_unescape_bytea, ZEND_ACC_PUBLIC)
1974 PHP_ME(pqconn, startTransaction, ai_pqconn_start_transaction, ZEND_ACC_PUBLIC)
1975 PHP_ME(pqconn, startTransactionAsync, ai_pqconn_start_transaction_async, ZEND_ACC_PUBLIC)
1976 PHP_ME(pqconn, trace, ai_pqconn_trace, ZEND_ACC_PUBLIC)
1977 PHP_ME(pqconn, off, ai_pqconn_off, ZEND_ACC_PUBLIC)
1978 PHP_ME(pqconn, on, ai_pqconn_on, ZEND_ACC_PUBLIC)
1979 PHP_ME(pqconn, setConverter, ai_pqconn_set_converter, ZEND_ACC_PUBLIC)
1980 PHP_ME(pqconn, unsetConverter, ai_pqconn_unset_converter, ZEND_ACC_PUBLIC)
1981 {0}
1982 };
1983
1984 PHP_MSHUTDOWN_FUNCTION(pqconn)
1985 {
1986 php_persistent_handle_cleanup(PHP_PQ_G->connection.name, NULL);
1987 zend_string_release(PHP_PQ_G->connection.name);
1988 zend_hash_destroy(&php_pqconn_object_prophandlers);
1989 return SUCCESS;
1990 }
1991
1992 PHP_MINIT_FUNCTION(pqconn)
1993 {
1994 zend_class_entry ce = {0};
1995 php_pq_object_prophandler_t ph = {0};
1996
1997 INIT_NS_CLASS_ENTRY(ce, "pq", "Connection", php_pqconn_methods);
1998 php_pqconn_class_entry = zend_register_internal_class_ex(&ce, NULL);
1999 php_pqconn_class_entry->create_object = php_pqconn_create_object;
2000
2001 memcpy(&php_pqconn_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
2002 php_pqconn_object_handlers.offset = XtOffsetOf(php_pqconn_object_t, zo);
2003 php_pqconn_object_handlers.free_obj = php_pqconn_object_free;
2004 php_pqconn_object_handlers.read_property = php_pq_object_read_prop;
2005 php_pqconn_object_handlers.write_property = php_pq_object_write_prop;
2006 php_pqconn_object_handlers.clone_obj = NULL;
2007 php_pqconn_object_handlers.get_property_ptr_ptr = NULL;
2008 php_pqconn_object_handlers.get_gc = php_pq_object_get_gc;
2009 php_pqconn_object_handlers.get_properties = php_pq_object_properties;
2010 php_pqconn_object_handlers.get_debug_info = php_pq_object_debug_info;
2011
2012 zend_hash_init(&php_pqconn_object_prophandlers, 23, NULL, php_pq_object_prophandler_dtor, 1);
2013
2014 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("status"), CONNECTION_BAD, ZEND_ACC_PUBLIC);
2015 ph.read = php_pqconn_object_read_status;
2016 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "status", sizeof("status")-1, (void *) &ph, sizeof(ph));
2017
2018 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("transactionStatus"), PQTRANS_UNKNOWN, ZEND_ACC_PUBLIC);
2019 ph.read = php_pqconn_object_read_transaction_status;
2020 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "transactionStatus", sizeof("transactionStatus")-1, (void *) &ph, sizeof(ph));
2021
2022 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("socket"), ZEND_ACC_PUBLIC);
2023 ph.read = NULL; /* forward to std prophandler */
2024 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "socket", sizeof("socket")-1, (void *) &ph, sizeof(ph));
2025
2026 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC);
2027 ph.read = php_pqconn_object_read_error_message;
2028 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "errorMessage", sizeof("errorMessage")-1, (void *) &ph, sizeof(ph));
2029
2030 zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("busy"), 0, ZEND_ACC_PUBLIC);
2031 ph.read = php_pqconn_object_read_busy;
2032 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "busy", sizeof("busy")-1, (void *) &ph, sizeof(ph));
2033
2034 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("encoding"), ZEND_ACC_PUBLIC);
2035 ph.read = php_pqconn_object_read_encoding;
2036 ph.write = php_pqconn_object_write_encoding;
2037 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "encoding", sizeof("encoding")-1, (void *) &ph, sizeof(ph));
2038 ph.write = NULL;
2039
2040 zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("unbuffered"), 0, ZEND_ACC_PUBLIC);
2041 ph.read = php_pqconn_object_read_unbuffered;
2042 ph.write = php_pqconn_object_write_unbuffered;
2043 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "unbuffered", sizeof("unbuffered")-1, (void *) &ph, sizeof(ph));
2044 ph.write = NULL;
2045
2046 zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("nonblocking"), 0, ZEND_ACC_PUBLIC);
2047 ph.read = php_pqconn_object_read_nonblocking;
2048 ph.write = php_pqconn_object_write_nonblocking;
2049 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "nonblocking", sizeof("nonblocking")-1, (void *) &ph, sizeof(ph));
2050 ph.write = NULL;
2051
2052 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("db"), ZEND_ACC_PUBLIC);
2053 ph.read = php_pqconn_object_read_db;
2054 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "db", sizeof("db")-1, (void *) &ph, sizeof(ph));
2055
2056 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("user"), ZEND_ACC_PUBLIC);
2057 ph.read = php_pqconn_object_read_user;
2058 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "user", sizeof("user")-1, (void *) &ph, sizeof(ph));
2059
2060 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("pass"), ZEND_ACC_PUBLIC);
2061 ph.read = php_pqconn_object_read_pass;
2062 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "pass", sizeof("pass")-1, (void *) &ph, sizeof(ph));
2063
2064 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("host"), ZEND_ACC_PUBLIC);
2065 ph.read = php_pqconn_object_read_host;
2066 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "host", sizeof("host")-1, (void *) &ph, sizeof(ph));
2067
2068 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("port"), ZEND_ACC_PUBLIC);
2069 ph.read = php_pqconn_object_read_port;
2070 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "port", sizeof("port")-1, (void *) &ph, sizeof(ph));
2071
2072 #if HAVE_PQCONNINFO
2073 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("params"), ZEND_ACC_PUBLIC);
2074 ph.read = php_pqconn_object_read_params;
2075 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "params", sizeof("params")-1, (void *) &ph, sizeof(ph));
2076 #endif
2077
2078 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("options"), ZEND_ACC_PUBLIC);
2079 ph.read = php_pqconn_object_read_options;
2080 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "options", sizeof("options")-1, (void *) &ph, sizeof(ph));
2081
2082 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("eventHandlers"), ZEND_ACC_PUBLIC);
2083 ph.read = php_pqconn_object_read_event_handlers;
2084 ph.gc = php_pqconn_object_gc_event_handlers;
2085 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "eventHandlers", sizeof("eventHandlers")-1, (void *) &ph, sizeof(ph));
2086 ph.gc = NULL;
2087
2088 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("listeners"), ZEND_ACC_PUBLIC);
2089 ph.read = php_pqconn_object_read_listeners;
2090 ph.gc = php_pqconn_object_gc_listeners;
2091 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "listeners", sizeof("listeners")-1, (void *) &ph, sizeof(ph));
2092 ph.gc = NULL;
2093
2094 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("converters"), ZEND_ACC_PUBLIC);
2095 ph.read = php_pqconn_object_read_converters;
2096 ph.gc = php_pqconn_object_gc_converters;
2097 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "converters", sizeof("converters")-1, (void *) &ph, sizeof(ph));
2098 ph.gc = NULL;
2099
2100 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("defaultFetchType"), 0, ZEND_ACC_PUBLIC);
2101 ph.read = php_pqconn_object_read_def_fetch_type;
2102 ph.write = php_pqconn_object_write_def_fetch_type;
2103 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "defaultFetchType", sizeof("defaultFetchType")-1, (void *) &ph, sizeof(ph));
2104 ph.write = NULL;
2105
2106 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("defaultTransactionIsolation"), 0, ZEND_ACC_PUBLIC);
2107 ph.read = php_pqconn_object_read_def_txn_isolation;
2108 ph.write = php_pqconn_object_write_def_txn_isolation;
2109 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "defaultTransactionIsolation", sizeof("defaultTransactionIsolation")-1, (void *) &ph, sizeof(ph));
2110 ph.write = NULL;
2111
2112 zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("defaultTransactionReadonly"), 0, ZEND_ACC_PUBLIC);
2113 ph.read = php_pqconn_object_read_def_txn_readonly;
2114 ph.write = php_pqconn_object_write_def_txn_readonly;
2115 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "defaultTransactionReadonly", sizeof("defaultTransactionReadonly")-1, (void *) &ph, sizeof(ph));
2116 ph.write = NULL;
2117
2118 zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("defaultTransactionDeferrable"), 0, ZEND_ACC_PUBLIC);
2119 ph.read = php_pqconn_object_read_def_txn_deferrable;
2120 ph.write = php_pqconn_object_write_def_txn_deferrable;
2121 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "defaultTransactionDeferrable", sizeof("defaultTransactionDeferrable")-1, (void *) &ph, sizeof(ph));
2122 ph.write = NULL;
2123
2124 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("defaultAutoConvert"), PHP_PQRES_CONV_ALL, ZEND_ACC_PUBLIC);
2125 ph.read = php_pqconn_object_read_def_auto_conv;
2126 ph.write = php_pqconn_object_write_def_auto_conv;
2127 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "defaultAutoConvert", sizeof("defaultAutoConvert")-1, (void *) &ph, sizeof(ph));
2128 ph.write = NULL;
2129
2130 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("OK"), CONNECTION_OK);
2131 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("BAD"), CONNECTION_BAD);
2132 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("STARTED"), CONNECTION_STARTED);
2133 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("MADE"), CONNECTION_MADE);
2134 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("AWAITING_RESPONSE"), CONNECTION_AWAITING_RESPONSE);
2135 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("AUTH_OK"), CONNECTION_AUTH_OK);
2136 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("SSL_STARTUP"), CONNECTION_SSL_STARTUP);
2137 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("SETENV"), CONNECTION_SETENV);
2138
2139 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_IDLE"), PQTRANS_IDLE);
2140 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_ACTIVE"), PQTRANS_ACTIVE);
2141 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_INTRANS"), PQTRANS_INTRANS);
2142 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_INERROR"), PQTRANS_INERROR);
2143 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_UNKNOWN"), PQTRANS_UNKNOWN);
2144
2145 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_FAILED"), PGRES_POLLING_FAILED);
2146 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_READING"), PGRES_POLLING_READING);
2147 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_WRITING"), PGRES_POLLING_WRITING);
2148 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_OK"), PGRES_POLLING_OK);
2149
2150 zend_declare_class_constant_stringl(php_pqconn_class_entry, ZEND_STRL("EVENT_NOTICE"), ZEND_STRL("notice"));
2151 zend_declare_class_constant_stringl(php_pqconn_class_entry, ZEND_STRL("EVENT_RESULT"), ZEND_STRL("result"));
2152 zend_declare_class_constant_stringl(php_pqconn_class_entry, ZEND_STRL("EVENT_RESET"), ZEND_STRL("reset"));
2153
2154 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("ASYNC"), 0x1);
2155 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("PERSISTENT"), 0x2);
2156
2157 PHP_PQ_G->connection.name = zend_string_init(ZEND_STRL("pq\\Connection"), 1);
2158
2159 return php_persistent_handle_provide(PHP_PQ_G->connection.name, php_pqconn_get_resource_factory_ops(), NULL, NULL);
2160 }
2161
2162 /*
2163 * Local variables:
2164 * tab-width: 4
2165 * c-basic-offset: 4
2166 * End:
2167 * vim600: noet sw=4 ts=4 fdm=marker
2168 * vim<600: noet sw=4 ts=4
2169 */