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