prepare v2.2.3
[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, unsigned long 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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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 #if PHP_VERSION_ID >= 80000
518 zend_std_write_property(Z_OBJ_P(zobj), Z_STR(zmember), &zsocket, NULL);
519 #else
520 zend_std_write_property(zobj, &zmember, &zsocket, NULL);
521 #endif
522 zval_ptr_dtor(&zsocket);
523 zval_ptr_dtor(&zmember);
524
525 return retval;
526 }
527
528 static void *php_pqconn_resource_factory_ctor(void *data, void *init_arg)
529 {
530 php_pqconn_resource_factory_data_t *o = init_arg;
531 PGconn *conn = NULL;;
532
533 if (o->flags & PHP_PQCONN_ASYNC) {
534 conn = PQconnectStart(o->dsn);
535 } else {
536 conn = PQconnectdb(o->dsn);
537 }
538
539 if (conn) {
540 PQregisterEventProc(conn, php_pqconn_event, "ext-pq", NULL);
541 }
542
543 return conn;
544 }
545
546 static void php_pqconn_resource_factory_dtor(void *opaque, void *handle)
547 {
548 php_pqconn_event_data_t *evdata = PQinstanceData(handle, php_pqconn_event);
549
550 /* we don't care for anything, except free'ing evdata */
551 if (evdata) {
552 PQsetInstanceData(handle, php_pqconn_event, NULL);
553 memset(evdata, 0, sizeof(*evdata));
554 efree(evdata);
555 }
556
557 PQfinish(handle);
558 }
559
560 static php_resource_factory_ops_t php_pqconn_resource_factory_ops = {
561 php_pqconn_resource_factory_ctor,
562 NULL,
563 php_pqconn_resource_factory_dtor
564 };
565
566 php_resource_factory_ops_t *php_pqconn_get_resource_factory_ops(void)
567 {
568 return &php_pqconn_resource_factory_ops;
569 }
570
571 static void php_pqconn_wakeup(php_persistent_handle_factory_t *f, void **handle)
572 {
573 PGresult *res = PQexec(*handle, "");
574 php_pqres_clear(res);
575
576 if (CONNECTION_OK != PQstatus(*handle)) {
577 PQreset(*handle);
578 }
579 }
580
581 static inline PGresult *unlisten(PGconn *conn, const char *channel_str, size_t channel_len)
582 {
583 char *quoted_channel = PQescapeIdentifier(conn, channel_str, channel_len);
584 PGresult *res = NULL;
585
586 if (quoted_channel) {
587 smart_str cmd = {0};
588
589 smart_str_appends(&cmd, "UNLISTEN ");
590 smart_str_appends(&cmd, quoted_channel);
591 smart_str_0(&cmd);
592
593 res = PQexec(conn, smart_str_v(&cmd));
594
595 smart_str_free(&cmd);
596 PQfreemem(quoted_channel);
597 }
598
599 return res;
600 }
601
602 static int apply_unlisten(zval *p, int argc, va_list argv, zend_hash_key *key)
603 {
604 php_pqconn_object_t *obj = va_arg(argv, php_pqconn_object_t *);
605 PGresult *res = unlisten(obj->intern->conn, key->key->val, key->key->len);
606
607 if (res) {
608 php_pqres_clear(res);
609 }
610
611 return ZEND_HASH_APPLY_REMOVE;
612 }
613
614 static void php_pqconn_retire(php_persistent_handle_factory_t *f, void **handle)
615 {
616 php_pqconn_event_data_t *evdata = PQinstanceData(*handle, php_pqconn_event);
617 PGcancel *cancel;
618 PGresult *res;
619
620 /* go away */
621 PQsetInstanceData(*handle, php_pqconn_event, NULL);
622
623 /* ignore notices */
624 PQsetNoticeReceiver(*handle, php_pqconn_notice_ignore, NULL);
625
626 /* cancel async queries */
627 if (PQisBusy(*handle) && (cancel = PQgetCancel(*handle))) {
628 char err[256] = {0};
629
630 PQcancel(cancel, err, sizeof(err));
631 PQfreeCancel(cancel);
632 }
633 /* clean up async results */
634 while ((res = PQgetResult(*handle))) {
635 php_pqres_clear(res);
636 }
637
638 /* clean up transaction & session */
639 switch (PQtransactionStatus(*handle)) {
640 case PQTRANS_IDLE:
641 res = PQexec(*handle, "RESET ALL");
642 break;
643 default:
644 res = PQexec(*handle, "ROLLBACK; RESET ALL");
645 break;
646 }
647
648 if (res) {
649 php_pqres_clear(res);
650 }
651
652 if (evdata) {
653 /* clean up notify listeners */
654 zend_hash_apply_with_arguments(&evdata->obj->intern->listeners, apply_unlisten, 1, evdata->obj);
655
656 /* release instance data */
657 efree(evdata);
658 }
659 }
660
661 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_construct, 0, 0, 1)
662 ZEND_ARG_INFO(0, dsn)
663 ZEND_ARG_INFO(0, flags)
664 ZEND_END_ARG_INFO();
665 static PHP_METHOD(pqconn, __construct) {
666 zend_error_handling zeh;
667 char *dsn_str = "";
668 size_t dsn_len = 0;
669 zend_long flags = 0;
670 ZEND_RESULT_CODE rv;
671
672 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
673 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "|sl", &dsn_str, &dsn_len, &flags);
674 zend_restore_error_handling(&zeh);
675
676 if (SUCCESS == rv) {
677 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
678
679 if (obj->intern) {
680 throw_exce(EX_BAD_METHODCALL, "pq\\Connection already initialized");
681 } else {
682 php_pqconn_event_data_t *evdata = php_pqconn_event_data_init(obj);
683 php_pqconn_resource_factory_data_t rfdata = {dsn_str, flags};
684
685 obj->intern = ecalloc(1, sizeof(*obj->intern));
686
687 obj->intern->default_auto_convert = PHP_PQRES_CONV_ALL;
688
689 zend_hash_init(&obj->intern->listeners, 0, NULL, ZVAL_PTR_DTOR, 0);
690 zend_hash_init(&obj->intern->statements, 0, NULL, NULL, 0);
691 zend_hash_init(&obj->intern->converters, 0, NULL, ZVAL_PTR_DTOR, 0);
692 zend_hash_init(&obj->intern->eventhandlers, 0, NULL, ZVAL_PTR_DTOR, 0);
693
694 if (flags & PHP_PQCONN_PERSISTENT) {
695 zend_string *dsn = zend_string_init(dsn_str, dsn_len, 0);
696 php_persistent_handle_factory_t *phf = php_persistent_handle_concede(NULL, PHP_PQ_G->connection.name, dsn, php_pqconn_wakeup, php_pqconn_retire);
697 php_persistent_handle_resource_factory_init(&obj->intern->factory, phf);
698 zend_string_release(dsn);
699 } else {
700 php_resource_factory_init(&obj->intern->factory, &php_pqconn_resource_factory_ops, NULL, NULL);
701 }
702
703 if (flags & PHP_PQCONN_ASYNC) {
704 obj->intern->poller = (int (*)(PGconn*)) PQconnectPoll;
705 }
706
707 obj->intern->conn = php_resource_factory_handle_ctor(&obj->intern->factory, &rfdata);
708
709 PQsetInstanceData(obj->intern->conn, php_pqconn_event, evdata);
710 PQsetNoticeReceiver(obj->intern->conn, php_pqconn_notice_recv, evdata);
711
712 if (SUCCESS != php_pqconn_update_socket(getThis(), obj)) {
713 throw_exce(EX_CONNECTION_FAILED, "Connection failed (%s)", PHP_PQerrorMessage(obj->intern->conn));
714 }
715 }
716 }
717 }
718
719 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_reset, 0, 0, 0)
720 ZEND_END_ARG_INFO();
721 static PHP_METHOD(pqconn, reset) {
722 zend_error_handling zeh;
723 ZEND_RESULT_CODE rv;
724
725 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
726 rv = zend_parse_parameters_none();
727 zend_restore_error_handling(&zeh);
728
729 if (SUCCESS == rv) {
730 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
731
732 if (!obj->intern) {
733 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
734 } else {
735 PQreset(obj->intern->conn);
736
737 if (CONNECTION_OK != PQstatus(obj->intern->conn)) {
738 throw_exce(EX_CONNECTION_FAILED, "Connection reset failed: (%s)", PHP_PQerrorMessage(obj->intern->conn));
739 }
740
741 php_pqconn_notify_listeners(obj);
742 }
743 }
744 }
745
746 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_reset_async, 0, 0, 0)
747 ZEND_END_ARG_INFO();
748 static PHP_METHOD(pqconn, resetAsync) {
749 zend_error_handling zeh;
750 ZEND_RESULT_CODE rv;
751
752 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
753 rv = zend_parse_parameters_none();
754 zend_restore_error_handling(&zeh);
755
756 if (SUCCESS == rv) {
757 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
758
759 if (!obj->intern) {
760 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
761 } else {
762 if (!PQresetStart(obj->intern->conn)) {
763 throw_exce(EX_IO, "Failed to start connection reset (%s)", PHP_PQerrorMessage(obj->intern->conn));
764 } else {
765 obj->intern->poller = (int (*)(PGconn*)) PQresetPoll;
766 }
767
768 php_pqconn_notify_listeners(obj);
769 }
770 }
771 }
772
773 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_unlisten, 0, 0, 1)
774 ZEND_ARG_INFO(0, channel)
775 ZEND_END_ARG_INFO();
776 static PHP_METHOD(pqconn, unlisten)
777 {
778 zend_error_handling zeh;
779 char *channel_str;
780 size_t channel_len;
781 ZEND_RESULT_CODE rv;
782
783 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
784 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "s", &channel_str, &channel_len);
785 zend_restore_error_handling(&zeh);
786
787 if (SUCCESS == rv) {
788 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
789
790 if (!obj->intern) {
791 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
792 } else if (SUCCESS == zend_hash_str_del(&obj->intern->listeners, channel_str, channel_len)) {
793 PGresult *res = unlisten(obj->intern->conn, channel_str, channel_len);
794
795 if (res) {
796 php_pqres_success(res);
797 php_pqres_clear(res);
798 }
799 }
800 }
801 }
802
803 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_unlisten_async, 0, 0, 1)
804 ZEND_ARG_INFO(0, channel)
805 ZEND_END_ARG_INFO();
806 static PHP_METHOD(pqconn, unlistenAsync) {
807 zend_error_handling zeh;
808 char *channel_str;
809 size_t channel_len;
810 ZEND_RESULT_CODE rv;
811
812 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
813 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "s", &channel_str, &channel_len);
814 zend_restore_error_handling(&zeh);
815
816 if (SUCCESS == rv) {
817 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
818
819 if (!obj->intern) {
820 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
821 } else {
822 char *quoted_channel = PQescapeIdentifier(obj->intern->conn, channel_str, channel_len);
823
824 if (!quoted_channel) {
825 throw_exce(EX_ESCAPE, "Failed to escape channel identifier (%s)", PHP_PQerrorMessage(obj->intern->conn));
826 } else {
827 smart_str cmd = {0};
828
829 smart_str_appends(&cmd, "UNLISTEN ");
830 smart_str_appends(&cmd, quoted_channel);
831 smart_str_0(&cmd);
832
833 if (!PQsendQuery(obj->intern->conn, smart_str_v(&cmd))) {
834 throw_exce(EX_IO, "Failed to uninstall listener (%s)", PHP_PQerrorMessage(obj->intern->conn));
835 } else {
836 obj->intern->poller = PQconsumeInput;
837 zend_hash_str_del(&obj->intern->listeners, channel_str, channel_len);
838 }
839
840 smart_str_free(&cmd);
841 PQfreemem(quoted_channel);
842 php_pqconn_notify_listeners(obj);
843 }
844 }
845 }
846 }
847
848 static void php_pqconn_add_listener(php_pqconn_object_t *obj, const char *channel_str, size_t channel_len, php_pq_callback_t *listener)
849 {
850 zval *existing;
851
852 php_pq_callback_addref(listener);
853
854 if ((existing = zend_hash_str_find(&obj->intern->listeners, channel_str, channel_len))) {
855 zend_hash_next_index_insert_mem(Z_ARRVAL_P(existing), (void *) listener, sizeof(*listener));
856 } else {
857 zval tmp;
858 HashTable *ht;
859
860 ALLOC_HASHTABLE(ht);
861 zend_hash_init(ht, 0, NULL, php_pq_callback_hash_dtor, 0);
862 zend_hash_next_index_insert_mem(ht, (void *) listener, sizeof(*listener));
863
864 ZVAL_ARR(&tmp, ht);
865 zend_hash_str_add(&obj->intern->listeners, channel_str, channel_len, &tmp);
866 }
867 }
868
869 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_listen, 0, 0, 2)
870 ZEND_ARG_INFO(0, channel)
871 ZEND_ARG_INFO(0, callable)
872 ZEND_END_ARG_INFO();
873 static PHP_METHOD(pqconn, listen) {
874 zend_error_handling zeh;
875 char *channel_str = NULL;
876 size_t channel_len = 0;
877 php_pq_callback_t listener = PHP_PQ_CALLBACK_INIT;
878 ZEND_RESULT_CODE rv;
879
880 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
881 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "sf", &channel_str, &channel_len, &listener.fci, &listener.fcc);
882 zend_restore_error_handling(&zeh);
883
884 if (SUCCESS == rv) {
885 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
886
887 if (!obj->intern) {
888 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
889 } else {
890 char *quoted_channel = PQescapeIdentifier(obj->intern->conn, channel_str, channel_len);
891
892 if (!quoted_channel) {
893 throw_exce(EX_ESCAPE, "Failed to escape channel identifier (%s)", PHP_PQerrorMessage(obj->intern->conn));
894 } else {
895 PGresult *res;
896 smart_str cmd = {0};
897
898 smart_str_appends(&cmd, "LISTEN ");
899 smart_str_appends(&cmd, quoted_channel);
900 smart_str_0(&cmd);
901
902 res = php_pq_exec(obj->intern->conn, smart_str_v(&cmd));
903
904 smart_str_free(&cmd);
905 PQfreemem(quoted_channel);
906
907 if (!res) {
908 throw_exce(EX_RUNTIME, "Failed to install listener (%s)", PHP_PQerrorMessage(obj->intern->conn));
909 } else {
910 if (SUCCESS == php_pqres_success(res)) {
911 obj->intern->poller = PQconsumeInput;
912 php_pqconn_add_listener(obj, channel_str, channel_len, &listener);
913 }
914 php_pqres_clear(res);
915 }
916
917 php_pqconn_notify_listeners(obj);
918 }
919 }
920 }
921 }
922
923 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_listen_async, 0, 0, 0)
924 ZEND_ARG_INFO(0, channel)
925 ZEND_ARG_INFO(0, callable)
926 ZEND_END_ARG_INFO();
927 static PHP_METHOD(pqconn, listenAsync) {
928 zend_error_handling zeh;
929 char *channel_str = NULL;
930 size_t channel_len = 0;
931 php_pq_callback_t listener = PHP_PQ_CALLBACK_INIT;
932 ZEND_RESULT_CODE rv;
933
934 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
935 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "sf", &channel_str, &channel_len, &listener.fci, &listener.fcc);
936 zend_restore_error_handling(&zeh);
937
938 if (SUCCESS == rv) {
939 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
940
941 if (!obj->intern) {
942 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
943 } else {
944 char *quoted_channel = PQescapeIdentifier(obj->intern->conn, channel_str, channel_len);
945
946 if (!quoted_channel) {
947 throw_exce(EX_ESCAPE, "Failed to escape channel identifier (%s)", PHP_PQerrorMessage(obj->intern->conn));
948 } else {
949 smart_str cmd = {0};
950
951 smart_str_appends(&cmd, "LISTEN ");
952 smart_str_appends(&cmd, quoted_channel);
953 smart_str_0(&cmd);
954
955 if (!PQsendQuery(obj->intern->conn, smart_str_v(&cmd))) {
956 throw_exce(EX_IO, "Failed to install listener (%s)", PHP_PQerrorMessage(obj->intern->conn));
957 } else {
958 obj->intern->poller = PQconsumeInput;
959 php_pqconn_add_listener(obj, channel_str, channel_len, &listener);
960 }
961
962 smart_str_free(&cmd);
963 PQfreemem(quoted_channel);
964 php_pqconn_notify_listeners(obj);
965 }
966 }
967 }
968 }
969
970 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_notify, 0, 0, 2)
971 ZEND_ARG_INFO(0, channel)
972 ZEND_ARG_INFO(0, message)
973 ZEND_END_ARG_INFO();
974 static PHP_METHOD(pqconn, notify) {
975 zend_error_handling zeh;
976 char *channel_str, *message_str;
977 size_t channel_len, message_len;
978 ZEND_RESULT_CODE rv;
979
980 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
981 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &channel_str, &channel_len, &message_str, &message_len);
982 zend_restore_error_handling(&zeh);
983
984 if (SUCCESS == rv) {
985 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
986
987 if (!obj->intern) {
988 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
989 } else {
990 PGresult *res;
991 char *params[2] = {channel_str, message_str};
992
993 res = PQexecParams(obj->intern->conn, "select pg_notify($1, $2)", 2, NULL, (const char *const*) params, NULL, NULL, 0);
994
995 if (!res) {
996 throw_exce(EX_RUNTIME, "Failed to notify listeners (%s)", PHP_PQerrorMessage(obj->intern->conn));
997 } else {
998 php_pqres_success(res);
999 php_pqres_clear(res);
1000 }
1001
1002 php_pqconn_notify_listeners(obj);
1003 }
1004 }
1005 }
1006
1007 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_notify_async, 0, 0, 2)
1008 ZEND_ARG_INFO(0, channel)
1009 ZEND_ARG_INFO(0, message)
1010 ZEND_END_ARG_INFO();
1011 static PHP_METHOD(pqconn, notifyAsync) {
1012 zend_error_handling zeh;
1013 char *channel_str, *message_str;
1014 size_t channel_len, message_len;
1015 ZEND_RESULT_CODE rv;
1016
1017 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1018 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &channel_str, &channel_len, &message_str, &message_len);
1019 zend_restore_error_handling(&zeh);
1020
1021 if (SUCCESS == rv) {
1022 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1023
1024 if (!obj->intern) {
1025 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1026 } else {
1027 char *params[2] = {channel_str, message_str};
1028
1029 if (!PQsendQueryParams(obj->intern->conn, "select pg_notify($1, $2)", 2, NULL, (const char *const*) params, NULL, NULL, 0)) {
1030 throw_exce(EX_IO, "Failed to notify listeners (%s)", PHP_PQerrorMessage(obj->intern->conn));
1031 } else {
1032 obj->intern->poller = PQconsumeInput;
1033 }
1034
1035 php_pqconn_notify_listeners(obj);
1036 }
1037 }
1038 }
1039
1040 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_poll, 0, 0, 0)
1041 ZEND_END_ARG_INFO();
1042 static PHP_METHOD(pqconn, poll) {
1043 zend_error_handling zeh;
1044 ZEND_RESULT_CODE rv;
1045
1046 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1047 rv = zend_parse_parameters_none();
1048 zend_restore_error_handling(&zeh);
1049
1050 if (SUCCESS == rv) {
1051 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1052
1053 if (!obj->intern) {
1054 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1055 } else if (!obj->intern->poller) {
1056 throw_exce(EX_RUNTIME, "No asynchronous operation active");
1057 } else {
1058 if (obj->intern->poller == PQconsumeInput) {
1059 RETVAL_LONG(obj->intern->poller(obj->intern->conn) * PGRES_POLLING_OK);
1060 } else {
1061 RETVAL_LONG(obj->intern->poller(obj->intern->conn));
1062 }
1063 php_pqconn_notify_listeners(obj);
1064 }
1065 }
1066 }
1067
1068 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_flush, 0, 0, 0)
1069 ZEND_END_ARG_INFO();
1070 static PHP_METHOD(pqconn, flush) {
1071 zend_error_handling zeh;
1072 ZEND_RESULT_CODE rv;
1073
1074 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1075 rv = zend_parse_parameters_none();
1076 zend_restore_error_handling(&zeh);
1077
1078 if (SUCCESS == rv) {
1079 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1080
1081 if (!obj->intern) {
1082 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1083 } else if (!obj->intern->poller) {
1084 throw_exce(EX_RUNTIME, "No asynchronous operation active");
1085 } else {
1086 switch (PQflush(obj->intern->conn)) {
1087 case -1:
1088 default:
1089 throw_exce(EX_RUNTIME, "Failed to flush connection: %s", PHP_PQerrorMessage(obj->intern->conn));
1090 break;
1091 case 0:
1092 RETVAL_TRUE;
1093 break;
1094 case 1:
1095 RETVAL_FALSE;
1096 break;
1097 }
1098 }
1099 }
1100 }
1101
1102 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec, 0, 0, 1)
1103 ZEND_ARG_INFO(0, query)
1104 ZEND_END_ARG_INFO();
1105 static PHP_METHOD(pqconn, exec) {
1106 zend_error_handling zeh;
1107 char *query_str;
1108 size_t query_len;
1109 ZEND_RESULT_CODE rv;
1110
1111 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1112 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "s", &query_str, &query_len);
1113 zend_restore_error_handling(&zeh);
1114
1115 if (SUCCESS == rv) {
1116 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1117
1118 if (!obj->intern) {
1119 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1120 } else {
1121 PGresult *res = php_pq_exec(obj->intern->conn, query_str);
1122
1123 if (!res) {
1124 throw_exce(EX_RUNTIME, "Failed to execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
1125 } else if (SUCCESS == php_pqres_success(res)) {
1126 php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), return_value);
1127 } else {
1128 php_pqres_clear(res);
1129 }
1130
1131 php_pqconn_notify_listeners(obj);
1132 }
1133 }
1134 }
1135
1136 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_get_result, 0, 0, 0)
1137 ZEND_END_ARG_INFO();
1138 static PHP_METHOD(pqconn, getResult) {
1139 zend_error_handling zeh;
1140 ZEND_RESULT_CODE rv;
1141
1142 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1143 rv = zend_parse_parameters_none();
1144 zend_restore_error_handling(&zeh);
1145
1146 if (SUCCESS == rv) {
1147 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1148
1149 if (!obj->intern) {
1150 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1151 } else {
1152 PGresult *res = PQgetResult(obj->intern->conn);
1153 php_pq_object_t *res_obj;
1154
1155 if (res && (res_obj = PQresultInstanceData(res, php_pqconn_event))) {
1156 php_pq_object_to_zval_no_addref(res_obj, return_value);
1157 } else {
1158 RETVAL_NULL();
1159 }
1160
1161 php_pqconn_notify_listeners(obj);
1162 }
1163 }
1164 }
1165
1166 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_async, 0, 0, 1)
1167 ZEND_ARG_INFO(0, query)
1168 ZEND_ARG_INFO(0, callable)
1169 ZEND_END_ARG_INFO();
1170 static PHP_METHOD(pqconn, execAsync) {
1171 zend_error_handling zeh;
1172 php_pq_callback_t resolver = PHP_PQ_CALLBACK_INIT;
1173 char *query_str;
1174 size_t query_len;
1175 ZEND_RESULT_CODE rv;
1176
1177 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1178 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "s|f", &query_str, &query_len, &resolver.fci, &resolver.fcc);
1179 zend_restore_error_handling(&zeh);
1180
1181 if (SUCCESS == rv) {
1182 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1183
1184 if (!obj->intern) {
1185 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1186 } else if (!PQsendQuery(obj->intern->conn, query_str)) {
1187 throw_exce(EX_IO, "Failed to execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
1188 #if HAVE_PQSETSINGLEROWMODE
1189 } else if (obj->intern->unbuffered && !PQsetSingleRowMode(obj->intern->conn)) {
1190 throw_exce(EX_RUNTIME, "Failed to enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn));
1191 #endif
1192 } else {
1193 php_pq_callback_recurse(&obj->intern->onevent, &resolver);
1194 obj->intern->poller = PQconsumeInput;
1195 php_pqconn_notify_listeners(obj);
1196 }
1197 }
1198 }
1199
1200 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_params, 0, 0, 2)
1201 ZEND_ARG_INFO(0, query)
1202 ZEND_ARG_ARRAY_INFO(0, params, 0)
1203 ZEND_ARG_ARRAY_INFO(0, types, 1)
1204 ZEND_END_ARG_INFO();
1205 static PHP_METHOD(pqconn, execParams) {
1206 zend_error_handling zeh;
1207 char *query_str;
1208 size_t query_len;
1209 zval *zparams;
1210 zval *ztypes = NULL;
1211 ZEND_RESULT_CODE rv;
1212
1213 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1214 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "sa/|a/!", &query_str, &query_len, &zparams, &ztypes);
1215 zend_restore_error_handling(&zeh);
1216
1217 if (SUCCESS == rv) {
1218 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1219
1220 if (!obj->intern) {
1221 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1222 } else {
1223 PGresult *res;
1224 php_pq_params_t *params;
1225
1226 params = php_pq_params_init(&obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, Z_ARRVAL_P(zparams));
1227 res = PQexecParams(obj->intern->conn, query_str, params->param.count, params->type.oids, (const char *const*) params->param.strings, NULL, NULL, 0);
1228 php_pq_params_free(&params);
1229
1230 if (!res) {
1231 throw_exce(EX_RUNTIME, "Failed to execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
1232 } else {
1233 if (SUCCESS == php_pqres_success(res)) {
1234 php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), return_value);
1235 } else {
1236 php_pqres_clear(res);
1237 }
1238
1239 php_pqconn_notify_listeners(obj);
1240 }
1241 }
1242 }
1243 }
1244
1245 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_params_async, 0, 0, 2)
1246 ZEND_ARG_INFO(0, query)
1247 ZEND_ARG_ARRAY_INFO(0, params, 0)
1248 ZEND_ARG_ARRAY_INFO(0, types, 1)
1249 ZEND_ARG_INFO(0, callable)
1250 ZEND_END_ARG_INFO();
1251 static PHP_METHOD(pqconn, execParamsAsync) {
1252 zend_error_handling zeh;
1253 php_pq_callback_t resolver = PHP_PQ_CALLBACK_INIT;
1254 char *query_str;
1255 size_t query_len;
1256 zval *zparams;
1257 zval *ztypes = NULL;
1258 ZEND_RESULT_CODE rv;
1259
1260 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1261 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "sa/|a/!f", &query_str, &query_len, &zparams, &ztypes, &resolver.fci, &resolver.fcc);
1262 zend_restore_error_handling(&zeh);
1263
1264 if (SUCCESS == rv) {
1265 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1266
1267 if (!obj->intern) {
1268 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1269 } else {
1270 int rc;
1271 php_pq_params_t *params;
1272
1273 params = php_pq_params_init(&obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, Z_ARRVAL_P(zparams));
1274 rc = PQsendQueryParams(obj->intern->conn, query_str, params->param.count, params->type.oids, (const char *const*) params->param.strings, NULL, NULL, 0);
1275 php_pq_params_free(&params);
1276
1277 if (!rc) {
1278 throw_exce(EX_IO, "Failed to execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
1279 #if HAVE_PQSETSINGLEROWMODE
1280 } else if (obj->intern->unbuffered && !PQsetSingleRowMode(obj->intern->conn)) {
1281 throw_exce(EX_RUNTIME, "Failed to enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn));
1282 #endif
1283 } else {
1284 php_pq_callback_recurse(&obj->intern->onevent, &resolver);
1285 obj->intern->poller = PQconsumeInput;
1286 php_pqconn_notify_listeners(obj);
1287 }
1288 }
1289 }
1290 zend_restore_error_handling(&zeh);
1291 }
1292
1293 ZEND_RESULT_CODE php_pqconn_prepare(zval *object, php_pqconn_object_t *obj, const char *name, const char *query, php_pq_params_t *params)
1294 {
1295 PGresult *res;
1296 ZEND_RESULT_CODE rv;
1297
1298 if (!obj) {
1299 obj = PHP_PQ_OBJ(object, NULL);
1300 }
1301
1302 res = php_pq_prepare(obj->intern->conn, name, query, params->type.count, params->type.oids);
1303
1304 if (!res) {
1305 rv = FAILURE;
1306 throw_exce(EX_RUNTIME, "Failed to prepare statement (%s)", PHP_PQerrorMessage(obj->intern->conn));
1307 } else {
1308 rv = php_pqres_success(res);
1309 php_pqres_clear(res);
1310 php_pqconn_notify_listeners(obj);
1311 }
1312
1313 return rv;
1314 }
1315
1316 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_prepare, 0, 0, 2)
1317 ZEND_ARG_INFO(0, name)
1318 ZEND_ARG_INFO(0, query)
1319 ZEND_ARG_ARRAY_INFO(0, types, 1)
1320 ZEND_END_ARG_INFO();
1321 static PHP_METHOD(pqconn, prepare) {
1322 zend_error_handling zeh;
1323 zval *ztypes = NULL;
1324 char *name_str, *query_str;
1325 size_t name_len, *query_len;
1326 ZEND_RESULT_CODE rv;
1327
1328 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1329 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "ss|a/!", &name_str, &name_len, &query_str, &query_len, &ztypes);
1330 zend_restore_error_handling(&zeh);
1331
1332 if (SUCCESS == rv) {
1333 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1334
1335 if (!obj->intern) {
1336 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1337 } else {
1338 php_pq_params_t *params = php_pq_params_init(&obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, NULL);
1339
1340 if (SUCCESS != php_pqconn_prepare(getThis(), obj, name_str, query_str, params)) {
1341 php_pq_params_free(&params);
1342 } else {
1343 php_pqstm_t *stm = php_pqstm_init(obj, name_str, query_str, params);
1344
1345 RETVAL_OBJ(&php_pqstm_create_object_ex(php_pqstm_class_entry, stm)->zo);
1346 }
1347 }
1348 }
1349 }
1350
1351 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)
1352 {
1353 ZEND_RESULT_CODE rv;
1354
1355 if (!obj) {
1356 obj = PHP_PQ_OBJ(object, NULL);
1357 }
1358
1359 if (!PQsendPrepare(obj->intern->conn, name, query, params->type.count, params->type.oids)) {
1360 rv = FAILURE;
1361 throw_exce(EX_IO, "Failed to prepare statement (%s)", PHP_PQerrorMessage(obj->intern->conn));
1362 } else {
1363 rv = SUCCESS;
1364 obj->intern->poller = PQconsumeInput;
1365 php_pqconn_notify_listeners(obj);
1366 }
1367
1368 return rv;
1369 }
1370
1371 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_prepare_async, 0, 0, 2)
1372 ZEND_ARG_INFO(0, name)
1373 ZEND_ARG_INFO(0, query)
1374 ZEND_ARG_ARRAY_INFO(0, types, 1)
1375 ZEND_END_ARG_INFO();
1376 static PHP_METHOD(pqconn, prepareAsync) {
1377 zend_error_handling zeh;
1378 zval *ztypes = NULL;
1379 char *name_str, *query_str;
1380 size_t name_len, *query_len;
1381 ZEND_RESULT_CODE rv;
1382
1383 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1384 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "ss|a/!", &name_str, &name_len, &query_str, &query_len, &ztypes);
1385 zend_restore_error_handling(&zeh);
1386
1387 if (SUCCESS == rv) {
1388 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1389
1390 if (!obj->intern) {
1391 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1392 } else {
1393 php_pq_params_t *params = php_pq_params_init(&obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, NULL);
1394
1395 if (SUCCESS != php_pqconn_prepare_async(getThis(), obj, name_str, query_str, params)) {
1396 php_pq_params_free(&params);
1397 } else {
1398 php_pqstm_t *stm = php_pqstm_init(obj, name_str, query_str, params);
1399
1400 RETVAL_OBJ(&php_pqstm_create_object_ex(php_pqstm_class_entry, stm)->zo);
1401 }
1402 }
1403 }
1404 }
1405
1406 ZEND_RESULT_CODE php_pqconn_declare(zval *object, php_pqconn_object_t *obj, const char *decl)
1407 {
1408 PGresult *res;
1409 ZEND_RESULT_CODE rv;
1410
1411 if (!obj) {
1412 obj = PHP_PQ_OBJ(object, NULL);
1413 }
1414
1415 res = php_pq_exec(obj->intern->conn, decl);
1416
1417 if (!res) {
1418 rv = FAILURE;
1419 throw_exce(EX_RUNTIME, "Failed to declare cursor (%s)", PHP_PQerrorMessage(obj->intern->conn));
1420 } else {
1421 rv = php_pqres_success(res);
1422 php_pqres_clear(res);
1423 php_pqconn_notify_listeners(obj);
1424 }
1425
1426 return rv;
1427 }
1428
1429 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_declare, 0, 0, 3)
1430 ZEND_ARG_INFO(0, name)
1431 ZEND_ARG_INFO(0, flags)
1432 ZEND_ARG_INFO(0, query)
1433 ZEND_END_ARG_INFO();
1434 static PHP_METHOD(pqconn, declare) {
1435 zend_error_handling zeh;
1436 char *name_str, *query_str;
1437 size_t name_len, query_len;
1438 zend_long flags;
1439 ZEND_RESULT_CODE rv;
1440
1441 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1442 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "sls", &name_str, &name_len, &flags, &query_str, &query_len);
1443 zend_restore_error_handling(&zeh);
1444
1445 if (SUCCESS == rv) {
1446 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1447
1448 if (!obj->intern) {
1449 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1450 } else {
1451 int query_offset;
1452 char *decl = php_pqcur_declare_str(name_str, name_len, flags, query_str, query_len, &query_offset);
1453
1454 if (SUCCESS != php_pqconn_declare(getThis(), obj, decl)) {
1455 efree(decl);
1456 } else {
1457 php_pqcur_t *cur = php_pqcur_init(obj, name_str, decl, query_offset, flags);
1458
1459 RETVAL_OBJ(&php_pqcur_create_object_ex(php_pqcur_class_entry, cur)->zo);
1460 }
1461 }
1462 }
1463 }
1464
1465 ZEND_RESULT_CODE php_pqconn_declare_async(zval *object, php_pqconn_object_t *obj, const char *decl)
1466 {
1467 ZEND_RESULT_CODE rv;
1468
1469 if (!obj) {
1470 obj = PHP_PQ_OBJ(object, NULL);
1471 }
1472
1473 if (!PQsendQuery(obj->intern->conn, decl)) {
1474 rv = FAILURE;
1475 throw_exce(EX_IO, "Failed to declare cursor (%s)", PHP_PQerrorMessage(obj->intern->conn));
1476 } else {
1477 rv = SUCCESS;
1478 obj->intern->poller = PQconsumeInput;
1479 php_pqconn_notify_listeners(obj);
1480 }
1481
1482 return rv;
1483 }
1484
1485 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_declare_async, 0, 0, 2)
1486 ZEND_ARG_INFO(0, name)
1487 ZEND_ARG_INFO(0, flags)
1488 ZEND_ARG_INFO(0, query)
1489 ZEND_END_ARG_INFO();
1490 static PHP_METHOD(pqconn, declareAsync) {
1491 zend_error_handling zeh;
1492 char *name_str, *query_str;
1493 size_t name_len, query_len;
1494 zend_long flags;
1495 ZEND_RESULT_CODE rv;
1496
1497 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1498 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "sls", &name_str, &name_len, &flags, &query_str, &query_len);
1499 zend_restore_error_handling(&zeh);
1500
1501 if (SUCCESS == rv) {
1502 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1503
1504 if (!obj->intern) {
1505 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1506 } else {
1507 int query_offset;
1508 char *decl = php_pqcur_declare_str(name_str, name_len, flags, query_str, query_len, &query_offset);
1509
1510 if (SUCCESS != php_pqconn_declare_async(getThis(), obj, decl)) {
1511 efree(decl);
1512 } else {
1513 php_pqcur_t *cur = php_pqcur_init(obj, name_str, decl, query_offset, flags);
1514
1515 RETVAL_OBJ(&php_pqcur_create_object_ex(php_pqcur_class_entry, cur)->zo);
1516 }
1517 }
1518 }
1519 }
1520
1521 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_quote, 0, 0, 1)
1522 ZEND_ARG_INFO(0, string)
1523 ZEND_END_ARG_INFO();
1524 static PHP_METHOD(pqconn, quote) {
1525 char *str;
1526 size_t len;
1527
1528 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &len)) {
1529 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1530
1531 if (!obj->intern) {
1532 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1533 } else {
1534 char *quoted = PQescapeLiteral(obj->intern->conn, str, len);
1535
1536 if (!quoted) {
1537 php_error_docref(NULL, E_WARNING, "Failed to quote string (%s)", PHP_PQerrorMessage(obj->intern->conn));
1538 RETVAL_FALSE;
1539 } else {
1540 RETVAL_STRING(quoted);
1541 PQfreemem(quoted);
1542 }
1543 }
1544 }
1545 }
1546
1547 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_quote_name, 0, 0, 1)
1548 ZEND_ARG_INFO(0, type)
1549 ZEND_END_ARG_INFO();
1550 static PHP_METHOD(pqconn, quoteName) {
1551 char *str;
1552 size_t len;
1553
1554 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &len)) {
1555 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1556
1557 if (!obj->intern) {
1558 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1559 } else {
1560 char *quoted = PQescapeIdentifier(obj->intern->conn, str, len);
1561
1562 if (!quoted) {
1563 php_error_docref(NULL, E_WARNING, "Failed to quote name (%s)", PHP_PQerrorMessage(obj->intern->conn));
1564 RETVAL_FALSE;
1565 } else {
1566 RETVAL_STRING(quoted);
1567 PQfreemem(quoted);
1568 }
1569 }
1570 }
1571 }
1572
1573 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_escape_bytea, 0, 0, 1)
1574 ZEND_ARG_INFO(0, bytea)
1575 ZEND_END_ARG_INFO();
1576 static PHP_METHOD(pqconn, escapeBytea) {
1577 char *str;
1578 size_t len;
1579
1580 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &len)) {
1581 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1582
1583 if (!obj->intern) {
1584 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1585 } else {
1586 size_t escaped_len;
1587 char *escaped_str = (char *) PQescapeByteaConn(obj->intern->conn, (unsigned char *) str, len, &escaped_len);
1588
1589 if (!escaped_str) {
1590 php_error_docref(NULL, E_WARNING, "Failed to escape bytea (%s)", PHP_PQerrorMessage(obj->intern->conn));
1591 RETVAL_FALSE;
1592 } else {
1593 RETVAL_STRINGL(escaped_str, escaped_len - 1);
1594 PQfreemem(escaped_str);
1595 }
1596 }
1597 }
1598 }
1599
1600 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_unescape_bytea, 0, 0, 1)
1601 ZEND_ARG_INFO(0, bytea)
1602 ZEND_END_ARG_INFO();
1603 static PHP_METHOD(pqconn, unescapeBytea) {
1604 char *str;
1605 size_t len;
1606
1607 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &len)) {
1608 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1609
1610 if (!obj->intern) {
1611 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1612 } else {
1613 size_t unescaped_len;
1614 char *unescaped_str = (char *) PQunescapeBytea((unsigned char *)str, &unescaped_len);
1615
1616 if (!unescaped_str) {
1617 php_error_docref(NULL, E_WARNING, "Failed to unescape bytea (%s)", PHP_PQerrorMessage(obj->intern->conn));
1618 RETVAL_FALSE;
1619 } else {
1620 RETVAL_STRINGL(unescaped_str, unescaped_len);
1621 PQfreemem(unescaped_str);
1622 }
1623 }
1624 }
1625 }
1626
1627 ZEND_RESULT_CODE php_pqconn_start_transaction(zval *zconn, php_pqconn_object_t *conn_obj, long isolation, zend_bool readonly, zend_bool deferrable)
1628 {
1629 ZEND_RESULT_CODE rv = FAILURE;
1630
1631 if (!conn_obj) {
1632 conn_obj = PHP_PQ_OBJ(zconn, NULL);
1633 }
1634
1635 if (!conn_obj->intern) {
1636 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1637 } else {
1638 PGresult *res;
1639 smart_str cmd = {0};
1640 const char *il = php_pq_isolation_level(&isolation);
1641
1642 smart_str_appends(&cmd, "START TRANSACTION ISOLATION LEVEL ");
1643 smart_str_appends(&cmd, il);
1644 smart_str_appends(&cmd, ", READ ");
1645 smart_str_appends(&cmd, readonly ? "ONLY" : "WRITE");
1646 smart_str_appends(&cmd, ",");
1647 smart_str_appends(&cmd, deferrable ? "" : " NOT");
1648 smart_str_appends(&cmd, " DEFERRABLE");
1649 smart_str_0(&cmd);
1650
1651 res = php_pq_exec(conn_obj->intern->conn, smart_str_v(&cmd));
1652
1653 if (!res) {
1654 throw_exce(EX_RUNTIME, "Failed to start transaction (%s)", PHP_PQerrorMessage(conn_obj->intern->conn));
1655 } else {
1656 rv = php_pqres_success(res);
1657 php_pqres_clear(res);
1658 php_pqconn_notify_listeners(conn_obj);
1659 }
1660
1661 smart_str_free(&cmd);
1662 }
1663
1664 return rv;
1665 }
1666
1667 ZEND_RESULT_CODE php_pqconn_start_transaction_async(zval *zconn, php_pqconn_object_t *conn_obj, long isolation, zend_bool readonly, zend_bool deferrable)
1668 {
1669 ZEND_RESULT_CODE rv = FAILURE;
1670
1671 if (!conn_obj) {
1672 conn_obj = PHP_PQ_OBJ(zconn, NULL);
1673 }
1674
1675 if (!conn_obj->intern) {
1676 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1677 } else {
1678 smart_str cmd = {0};
1679 const char *il = php_pq_isolation_level(&isolation);
1680
1681 smart_str_appends(&cmd, "START TRANSACTION ISOLATION LEVEL ");
1682 smart_str_appends(&cmd, il);
1683 smart_str_appends(&cmd, ", READ ");
1684 smart_str_appends(&cmd, readonly ? "ONLY" : "WRITE");
1685 smart_str_appends(&cmd, ",");
1686 smart_str_appends(&cmd, deferrable ? "" : "NOT ");
1687 smart_str_appends(&cmd, " DEFERRABLE");
1688 smart_str_0(&cmd);
1689
1690 if (!PQsendQuery(conn_obj->intern->conn, smart_str_v(&cmd))) {
1691 throw_exce(EX_IO, "Failed to start transaction (%s)", PHP_PQerrorMessage(conn_obj->intern->conn));
1692 } else {
1693 rv = SUCCESS;
1694 conn_obj->intern->poller = PQconsumeInput;
1695 php_pqconn_notify_listeners(conn_obj);
1696 }
1697
1698 smart_str_free(&cmd);
1699 }
1700
1701 return rv;
1702 }
1703
1704 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_start_transaction, 0, 0, 0)
1705 ZEND_ARG_INFO(0, isolation)
1706 ZEND_ARG_INFO(0, readonly)
1707 ZEND_ARG_INFO(0, deferrable)
1708 ZEND_END_ARG_INFO();
1709 static PHP_METHOD(pqconn, startTransaction) {
1710 zend_error_handling zeh;
1711 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1712 zend_long isolation = obj->intern ? obj->intern->default_txn_isolation : PHP_PQTXN_READ_COMMITTED;
1713 zend_bool readonly = obj->intern ? obj->intern->default_txn_readonly : 0;
1714 zend_bool deferrable = obj->intern ? obj->intern->default_txn_deferrable : 0;
1715 ZEND_RESULT_CODE rv;
1716
1717 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1718 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "|lbb", &isolation, &readonly, &deferrable);
1719 zend_restore_error_handling(&zeh);
1720
1721 if (SUCCESS == rv) {
1722 rv = php_pqconn_start_transaction(getThis(), obj, isolation, readonly, deferrable);
1723
1724 if (SUCCESS == rv) {
1725 php_pqtxn_t *txn = ecalloc(1, sizeof(*txn));
1726
1727 php_pq_object_addref(obj);
1728 txn->conn = obj;
1729 txn->open = 1;
1730 txn->isolation = isolation;
1731 txn->readonly = readonly;
1732 txn->deferrable = deferrable;
1733
1734 RETVAL_OBJ(&php_pqtxn_create_object_ex(php_pqtxn_class_entry, txn)->zo);
1735 }
1736 }
1737 }
1738
1739 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_start_transaction_async, 0, 0, 0)
1740 ZEND_ARG_INFO(0, isolation)
1741 ZEND_ARG_INFO(0, readonly)
1742 ZEND_ARG_INFO(0, deferrable)
1743 ZEND_END_ARG_INFO();
1744 static PHP_METHOD(pqconn, startTransactionAsync) {
1745 zend_error_handling zeh;
1746 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1747 zend_long isolation = obj->intern ? obj->intern->default_txn_isolation : PHP_PQTXN_READ_COMMITTED;
1748 zend_bool readonly = obj->intern ? obj->intern->default_txn_readonly : 0;
1749 zend_bool deferrable = obj->intern ? obj->intern->default_txn_deferrable : 0;
1750 ZEND_RESULT_CODE rv;
1751
1752 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1753 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "|lbb", &isolation, &readonly, &deferrable);
1754 zend_restore_error_handling(&zeh);
1755
1756 if (SUCCESS == rv) {
1757 rv = php_pqconn_start_transaction_async(getThis(), obj, isolation, readonly, deferrable);
1758
1759 if (SUCCESS == rv) {
1760 php_pqtxn_t *txn = ecalloc(1, sizeof(*txn));
1761
1762 php_pq_object_addref(obj);
1763 txn->conn = obj;
1764 txn->open = 1;
1765 txn->isolation = isolation;
1766 txn->readonly = readonly;
1767 txn->deferrable = deferrable;
1768
1769 RETVAL_OBJ(&php_pqtxn_create_object_ex(php_pqtxn_class_entry, txn)->zo);
1770 }
1771 }
1772 }
1773
1774 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_trace, 0, 0, 0)
1775 ZEND_ARG_INFO(0, stdio_stream)
1776 ZEND_END_ARG_INFO();
1777 static PHP_METHOD(pqconn, trace) {
1778 zval *zstream = NULL;
1779
1780 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|r!", &zstream)) {
1781 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1782
1783 if (!obj->intern) {
1784 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1785 } else {
1786 if (!zstream) {
1787 PQuntrace(obj->intern->conn);
1788 RETVAL_TRUE;
1789 } else {
1790 FILE *fp;
1791 php_stream *stream = NULL;
1792
1793 php_stream_from_zval(stream, zstream);
1794
1795 if (SUCCESS != php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void *) &fp, REPORT_ERRORS)) {
1796 RETVAL_FALSE;
1797 } else {
1798 stream->flags |= PHP_STREAM_FLAG_NO_CLOSE;
1799 PQtrace(obj->intern->conn, fp);
1800 RETVAL_TRUE;
1801 }
1802 }
1803 }
1804 }
1805 }
1806
1807 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_off, 0, 0, 1)
1808 ZEND_ARG_INFO(0, type)
1809 ZEND_END_ARG_INFO();
1810 static PHP_METHOD(pqconn, off) {
1811 zend_error_handling zeh;
1812 zend_string *type;
1813 ZEND_RESULT_CODE rv;
1814
1815 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1816 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "S", &type);
1817 zend_restore_error_handling(&zeh);
1818
1819 if (SUCCESS == rv) {
1820 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1821
1822 if (!obj->intern) {
1823 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1824 } else {
1825 RETURN_BOOL(SUCCESS == zend_hash_del(&obj->intern->eventhandlers, type));
1826 }
1827 }
1828 }
1829
1830 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_on, 0, 0, 2)
1831 ZEND_ARG_INFO(0, type)
1832 ZEND_ARG_INFO(0, callable)
1833 ZEND_END_ARG_INFO();
1834 static PHP_METHOD(pqconn, on) {
1835 zend_error_handling zeh;
1836 char *type_str;
1837 size_t type_len;
1838 php_pq_callback_t cb = PHP_PQ_CALLBACK_INIT;
1839 ZEND_RESULT_CODE rv;
1840
1841 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1842 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "sf", &type_str, &type_len, &cb.fci, &cb.fcc);
1843 zend_restore_error_handling(&zeh);
1844
1845 if (SUCCESS == rv) {
1846 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1847
1848 if (!obj->intern) {
1849 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1850 } else {
1851 RETVAL_LONG(php_pqconn_add_eventhandler(obj, type_str, type_len, &cb));
1852 }
1853 }
1854 }
1855
1856 struct apply_set_converter_arg {
1857 HashTable *ht;
1858 zval *zconv;
1859 unsigned add:1;
1860 };
1861
1862 static int apply_set_converter(zval *zoid, void *a)
1863 {
1864 zend_long oid = zval_get_long(zoid);
1865 struct apply_set_converter_arg *arg = a;
1866
1867 if (arg->add) {
1868 Z_ADDREF_P(arg->zconv);
1869 zend_hash_index_update(arg->ht, oid, arg->zconv);
1870 } else {
1871 zend_hash_index_del(arg->ht, oid);
1872 }
1873
1874 return ZEND_HASH_APPLY_KEEP;
1875 }
1876
1877 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_set_converter, 0, 0, 1)
1878 ZEND_ARG_OBJ_INFO(0, converter, pq\\Converter, 0)
1879 ZEND_END_ARG_INFO();
1880 static PHP_METHOD(pqconn, setConverter) {
1881 ZEND_RESULT_CODE rv;
1882 zend_error_handling zeh;
1883 zval *zcnv;
1884
1885 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1886 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "O", &zcnv, php_pqconv_class_entry);
1887 zend_restore_error_handling(&zeh);
1888
1889 if (SUCCESS == rv) {
1890 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1891
1892 if (!obj->intern) {
1893 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1894 } else {
1895 zval tmp, zoids;
1896 struct apply_set_converter_arg arg = {NULL};
1897
1898 ZVAL_NULL(&zoids);
1899 php_pq_call_method(zcnv, "converttypes", 0, &zoids);
1900 ZVAL_DUP(&tmp, &zoids);
1901 convert_to_array(&tmp);
1902
1903 arg.ht = &obj->intern->converters;
1904 arg.zconv = zcnv;
1905 arg.add = 1;
1906
1907 zend_hash_apply_with_argument(Z_ARRVAL(tmp), apply_set_converter, &arg);
1908
1909 zval_ptr_dtor(&tmp);
1910 zval_ptr_dtor(&zoids);
1911 }
1912 }
1913 }
1914
1915 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_unset_converter, 0, 0, 1)
1916 ZEND_ARG_OBJ_INFO(0, converter, pq\\Converter, 0)
1917 ZEND_END_ARG_INFO();
1918 static PHP_METHOD(pqconn, unsetConverter) {
1919 ZEND_RESULT_CODE rv;
1920 zend_error_handling zeh;
1921 zval *zcnv;
1922
1923 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1924 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "O", &zcnv, php_pqconv_class_entry);
1925 zend_restore_error_handling(&zeh);
1926
1927 if (SUCCESS == rv) {
1928 php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1929
1930 if (!obj->intern) {
1931 throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
1932 } else {
1933 zval tmp, zoids;
1934 struct apply_set_converter_arg arg = {NULL};
1935
1936 ZVAL_NULL(&zoids);
1937 php_pq_call_method(zcnv, "converttypes", 0, &zoids);
1938 ZVAL_DUP(&tmp, &zoids);
1939 convert_to_array(&tmp);
1940
1941 arg.ht = &obj->intern->converters;
1942 arg.zconv = zcnv;
1943 arg.add = 0;
1944
1945 zend_hash_apply_with_argument(Z_ARRVAL(tmp), apply_set_converter, &arg);
1946
1947 zval_ptr_dtor(&tmp);
1948 zval_ptr_dtor(&zoids);
1949 }
1950 }
1951 }
1952
1953 static zend_function_entry php_pqconn_methods[] = {
1954 PHP_ME(pqconn, __construct, ai_pqconn_construct, ZEND_ACC_PUBLIC)
1955 PHP_ME(pqconn, reset, ai_pqconn_reset, ZEND_ACC_PUBLIC)
1956 PHP_ME(pqconn, resetAsync, ai_pqconn_reset_async, ZEND_ACC_PUBLIC)
1957 PHP_ME(pqconn, poll, ai_pqconn_poll, ZEND_ACC_PUBLIC)
1958 PHP_ME(pqconn, flush, ai_pqconn_flush, ZEND_ACC_PUBLIC)
1959 PHP_ME(pqconn, exec, ai_pqconn_exec, ZEND_ACC_PUBLIC)
1960 PHP_ME(pqconn, execAsync, ai_pqconn_exec_async, ZEND_ACC_PUBLIC)
1961 PHP_ME(pqconn, execParams, ai_pqconn_exec_params, ZEND_ACC_PUBLIC)
1962 PHP_ME(pqconn, execParamsAsync, ai_pqconn_exec_params_async, ZEND_ACC_PUBLIC)
1963 PHP_ME(pqconn, prepare, ai_pqconn_prepare, ZEND_ACC_PUBLIC)
1964 PHP_ME(pqconn, prepareAsync, ai_pqconn_prepare_async, ZEND_ACC_PUBLIC)
1965 PHP_ME(pqconn, declare, ai_pqconn_declare, ZEND_ACC_PUBLIC)
1966 PHP_ME(pqconn, declareAsync, ai_pqconn_declare_async, ZEND_ACC_PUBLIC)
1967 PHP_ME(pqconn, unlisten, ai_pqconn_unlisten, ZEND_ACC_PUBLIC)
1968 PHP_ME(pqconn, unlistenAsync, ai_pqconn_unlisten_async, ZEND_ACC_PUBLIC)
1969 PHP_ME(pqconn, listen, ai_pqconn_listen, ZEND_ACC_PUBLIC)
1970 PHP_ME(pqconn, listenAsync, ai_pqconn_listen_async, ZEND_ACC_PUBLIC)
1971 PHP_ME(pqconn, notify, ai_pqconn_notify, ZEND_ACC_PUBLIC)
1972 PHP_ME(pqconn, notifyAsync, ai_pqconn_notify_async, ZEND_ACC_PUBLIC)
1973 PHP_ME(pqconn, getResult, ai_pqconn_get_result, ZEND_ACC_PUBLIC)
1974 PHP_ME(pqconn, quote, ai_pqconn_quote, ZEND_ACC_PUBLIC)
1975 PHP_ME(pqconn, quoteName, ai_pqconn_quote_name, ZEND_ACC_PUBLIC)
1976 PHP_ME(pqconn, escapeBytea, ai_pqconn_escape_bytea, ZEND_ACC_PUBLIC)
1977 PHP_ME(pqconn, unescapeBytea, ai_pqconn_unescape_bytea, ZEND_ACC_PUBLIC)
1978 PHP_ME(pqconn, startTransaction, ai_pqconn_start_transaction, ZEND_ACC_PUBLIC)
1979 PHP_ME(pqconn, startTransactionAsync, ai_pqconn_start_transaction_async, ZEND_ACC_PUBLIC)
1980 PHP_ME(pqconn, trace, ai_pqconn_trace, ZEND_ACC_PUBLIC)
1981 PHP_ME(pqconn, off, ai_pqconn_off, ZEND_ACC_PUBLIC)
1982 PHP_ME(pqconn, on, ai_pqconn_on, ZEND_ACC_PUBLIC)
1983 PHP_ME(pqconn, setConverter, ai_pqconn_set_converter, ZEND_ACC_PUBLIC)
1984 PHP_ME(pqconn, unsetConverter, ai_pqconn_unset_converter, ZEND_ACC_PUBLIC)
1985 {0}
1986 };
1987
1988 PHP_MSHUTDOWN_FUNCTION(pqconn)
1989 {
1990 php_persistent_handle_cleanup(PHP_PQ_G->connection.name, NULL);
1991 zend_string_release(PHP_PQ_G->connection.name);
1992 zend_hash_destroy(&php_pqconn_object_prophandlers);
1993 return SUCCESS;
1994 }
1995
1996 PHP_MINIT_FUNCTION(pqconn)
1997 {
1998 zend_class_entry ce = {0};
1999 php_pq_object_prophandler_t ph = {0};
2000
2001 INIT_NS_CLASS_ENTRY(ce, "pq", "Connection", php_pqconn_methods);
2002 php_pqconn_class_entry = zend_register_internal_class_ex(&ce, NULL);
2003 php_pqconn_class_entry->create_object = php_pqconn_create_object;
2004
2005 memcpy(&php_pqconn_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
2006 php_pqconn_object_handlers.offset = XtOffsetOf(php_pqconn_object_t, zo);
2007 php_pqconn_object_handlers.free_obj = php_pqconn_object_free;
2008 php_pqconn_object_handlers.read_property = php_pq_object_read_prop;
2009 php_pqconn_object_handlers.write_property = php_pq_object_write_prop;
2010 php_pqconn_object_handlers.clone_obj = NULL;
2011 php_pqconn_object_handlers.get_property_ptr_ptr = php_pq_object_get_prop_ptr_null;
2012 php_pqconn_object_handlers.get_gc = php_pq_object_get_gc;
2013 php_pqconn_object_handlers.get_properties = php_pq_object_properties;
2014 php_pqconn_object_handlers.get_debug_info = php_pq_object_debug_info;
2015
2016 zend_hash_init(&php_pqconn_object_prophandlers, 23, NULL, php_pq_object_prophandler_dtor, 1);
2017
2018 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("status"), CONNECTION_BAD, ZEND_ACC_PUBLIC);
2019 ph.read = php_pqconn_object_read_status;
2020 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "status", sizeof("status")-1, (void *) &ph, sizeof(ph));
2021
2022 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("transactionStatus"), PQTRANS_UNKNOWN, ZEND_ACC_PUBLIC);
2023 ph.read = php_pqconn_object_read_transaction_status;
2024 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "transactionStatus", sizeof("transactionStatus")-1, (void *) &ph, sizeof(ph));
2025
2026 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("socket"), ZEND_ACC_PUBLIC);
2027 ph.read = NULL; /* forward to std prophandler */
2028 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "socket", sizeof("socket")-1, (void *) &ph, sizeof(ph));
2029
2030 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC);
2031 ph.read = php_pqconn_object_read_error_message;
2032 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "errorMessage", sizeof("errorMessage")-1, (void *) &ph, sizeof(ph));
2033
2034 zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("busy"), 0, ZEND_ACC_PUBLIC);
2035 ph.read = php_pqconn_object_read_busy;
2036 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "busy", sizeof("busy")-1, (void *) &ph, sizeof(ph));
2037
2038 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("encoding"), ZEND_ACC_PUBLIC);
2039 ph.read = php_pqconn_object_read_encoding;
2040 ph.write = php_pqconn_object_write_encoding;
2041 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "encoding", sizeof("encoding")-1, (void *) &ph, sizeof(ph));
2042 ph.write = NULL;
2043
2044 zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("unbuffered"), 0, ZEND_ACC_PUBLIC);
2045 ph.read = php_pqconn_object_read_unbuffered;
2046 ph.write = php_pqconn_object_write_unbuffered;
2047 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "unbuffered", sizeof("unbuffered")-1, (void *) &ph, sizeof(ph));
2048 ph.write = NULL;
2049
2050 zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("nonblocking"), 0, ZEND_ACC_PUBLIC);
2051 ph.read = php_pqconn_object_read_nonblocking;
2052 ph.write = php_pqconn_object_write_nonblocking;
2053 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "nonblocking", sizeof("nonblocking")-1, (void *) &ph, sizeof(ph));
2054 ph.write = NULL;
2055
2056 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("db"), ZEND_ACC_PUBLIC);
2057 ph.read = php_pqconn_object_read_db;
2058 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "db", sizeof("db")-1, (void *) &ph, sizeof(ph));
2059
2060 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("user"), ZEND_ACC_PUBLIC);
2061 ph.read = php_pqconn_object_read_user;
2062 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "user", sizeof("user")-1, (void *) &ph, sizeof(ph));
2063
2064 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("pass"), ZEND_ACC_PUBLIC);
2065 ph.read = php_pqconn_object_read_pass;
2066 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "pass", sizeof("pass")-1, (void *) &ph, sizeof(ph));
2067
2068 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("host"), ZEND_ACC_PUBLIC);
2069 ph.read = php_pqconn_object_read_host;
2070 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "host", sizeof("host")-1, (void *) &ph, sizeof(ph));
2071
2072 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("port"), ZEND_ACC_PUBLIC);
2073 ph.read = php_pqconn_object_read_port;
2074 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "port", sizeof("port")-1, (void *) &ph, sizeof(ph));
2075
2076 #if HAVE_PQCONNINFO
2077 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("params"), ZEND_ACC_PUBLIC);
2078 ph.read = php_pqconn_object_read_params;
2079 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "params", sizeof("params")-1, (void *) &ph, sizeof(ph));
2080 #endif
2081
2082 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("options"), ZEND_ACC_PUBLIC);
2083 ph.read = php_pqconn_object_read_options;
2084 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "options", sizeof("options")-1, (void *) &ph, sizeof(ph));
2085
2086 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("eventHandlers"), ZEND_ACC_PUBLIC);
2087 ph.read = php_pqconn_object_read_event_handlers;
2088 ph.gc = php_pqconn_object_gc_event_handlers;
2089 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "eventHandlers", sizeof("eventHandlers")-1, (void *) &ph, sizeof(ph));
2090 ph.gc = NULL;
2091
2092 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("listeners"), ZEND_ACC_PUBLIC);
2093 ph.read = php_pqconn_object_read_listeners;
2094 ph.gc = php_pqconn_object_gc_listeners;
2095 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "listeners", sizeof("listeners")-1, (void *) &ph, sizeof(ph));
2096 ph.gc = NULL;
2097
2098 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("converters"), ZEND_ACC_PUBLIC);
2099 ph.read = php_pqconn_object_read_converters;
2100 ph.gc = php_pqconn_object_gc_converters;
2101 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "converters", sizeof("converters")-1, (void *) &ph, sizeof(ph));
2102 ph.gc = NULL;
2103
2104 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("defaultFetchType"), 0, ZEND_ACC_PUBLIC);
2105 ph.read = php_pqconn_object_read_def_fetch_type;
2106 ph.write = php_pqconn_object_write_def_fetch_type;
2107 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "defaultFetchType", sizeof("defaultFetchType")-1, (void *) &ph, sizeof(ph));
2108 ph.write = NULL;
2109
2110 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("defaultTransactionIsolation"), 0, ZEND_ACC_PUBLIC);
2111 ph.read = php_pqconn_object_read_def_txn_isolation;
2112 ph.write = php_pqconn_object_write_def_txn_isolation;
2113 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "defaultTransactionIsolation", sizeof("defaultTransactionIsolation")-1, (void *) &ph, sizeof(ph));
2114 ph.write = NULL;
2115
2116 zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("defaultTransactionReadonly"), 0, ZEND_ACC_PUBLIC);
2117 ph.read = php_pqconn_object_read_def_txn_readonly;
2118 ph.write = php_pqconn_object_write_def_txn_readonly;
2119 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "defaultTransactionReadonly", sizeof("defaultTransactionReadonly")-1, (void *) &ph, sizeof(ph));
2120 ph.write = NULL;
2121
2122 zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("defaultTransactionDeferrable"), 0, ZEND_ACC_PUBLIC);
2123 ph.read = php_pqconn_object_read_def_txn_deferrable;
2124 ph.write = php_pqconn_object_write_def_txn_deferrable;
2125 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "defaultTransactionDeferrable", sizeof("defaultTransactionDeferrable")-1, (void *) &ph, sizeof(ph));
2126 ph.write = NULL;
2127
2128 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("defaultAutoConvert"), PHP_PQRES_CONV_ALL, ZEND_ACC_PUBLIC);
2129 ph.read = php_pqconn_object_read_def_auto_conv;
2130 ph.write = php_pqconn_object_write_def_auto_conv;
2131 zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "defaultAutoConvert", sizeof("defaultAutoConvert")-1, (void *) &ph, sizeof(ph));
2132 ph.write = NULL;
2133
2134 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("OK"), CONNECTION_OK);
2135 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("BAD"), CONNECTION_BAD);
2136 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("STARTED"), CONNECTION_STARTED);
2137 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("MADE"), CONNECTION_MADE);
2138 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("AWAITING_RESPONSE"), CONNECTION_AWAITING_RESPONSE);
2139 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("AUTH_OK"), CONNECTION_AUTH_OK);
2140 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("SSL_STARTUP"), CONNECTION_SSL_STARTUP);
2141 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("SETENV"), CONNECTION_SETENV);
2142 #ifdef HAVE_CONNECTION_CHECK_WRITABLE
2143 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("CHECK_WRITABLE"), CONNECTION_CHECK_WRITABLE);
2144 #endif
2145 #ifdef HAVE_CONNECTION_CONSUME
2146 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("CONSUME"), CONNECTION_CONSUME);
2147 #endif
2148 #ifdef HAVE_CONNECTION_GSS_STARTUP
2149 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("GSS_STARTUP"), CONNECTION_GSS_STARTUP);
2150 #endif
2151
2152 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_IDLE"), PQTRANS_IDLE);
2153 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_ACTIVE"), PQTRANS_ACTIVE);
2154 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_INTRANS"), PQTRANS_INTRANS);
2155 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_INERROR"), PQTRANS_INERROR);
2156 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_UNKNOWN"), PQTRANS_UNKNOWN);
2157
2158 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_FAILED"), PGRES_POLLING_FAILED);
2159 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_READING"), PGRES_POLLING_READING);
2160 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_WRITING"), PGRES_POLLING_WRITING);
2161 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_OK"), PGRES_POLLING_OK);
2162
2163 zend_declare_class_constant_stringl(php_pqconn_class_entry, ZEND_STRL("EVENT_NOTICE"), ZEND_STRL("notice"));
2164 zend_declare_class_constant_stringl(php_pqconn_class_entry, ZEND_STRL("EVENT_RESULT"), ZEND_STRL("result"));
2165 zend_declare_class_constant_stringl(php_pqconn_class_entry, ZEND_STRL("EVENT_RESET"), ZEND_STRL("reset"));
2166
2167 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("ASYNC"), 0x1);
2168 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("PERSISTENT"), 0x2);
2169
2170 PHP_PQ_G->connection.name = zend_string_init(ZEND_STRL("pq\\Connection"), 1);
2171
2172 return php_persistent_handle_provide(PHP_PQ_G->connection.name, php_pqconn_get_resource_factory_ops(), NULL, NULL);
2173 }
2174
2175 /*
2176 * Local variables:
2177 * tab-width: 4
2178 * c-basic-offset: 4
2179 * End:
2180 * vim600: noet sw=4 ts=4 fdm=marker
2181 * vim<600: noet sw=4 ts=4
2182 */