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