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