test Statement::bind()
[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
19 #define SMART_STR_PREALLOC 256
20 #include <ext/standard/php_smart_str.h>
21
22 #include <libpq-events.h>
23 #include <fnmatch.h>
24
25 #include "php_pq.h"
26 #include "php_pq_misc.h"
27 #include "php_pq_object.h"
28 #include "php_pqexc.h"
29 #include "php_pqconn.h"
30 #include "php_pqconn_event.h"
31 #include "php_pqres.h"
32 #include "php_pqstm.h"
33 #include "php_pqtxn.h"
34
35 zend_class_entry *php_pqconn_class_entry;
36 static zend_object_handlers php_pqconn_object_handlers;
37 static HashTable php_pqconn_object_prophandlers;
38
39 /*
40 static void php_pqconn_del_eventhandler(php_pqconn_object_t *obj, const char *type_str, size_t type_len, ulong id TSRMLS_DC)
41 {
42 zval **evhs;
43
44 if (SUCCESS == zend_hash_find(&obj->intern->eventhandlers, type_str, type_len + 1, (void *) &evhs)) {
45 zend_hash_index_del(Z_ARRVAL_PP(evhs), id);
46 }
47 }
48 */
49
50 static ulong php_pqconn_add_eventhandler(php_pqconn_object_t *obj, const char *type_str, size_t type_len, php_pq_callback_t *cb TSRMLS_DC)
51 {
52 ulong h;
53 HashTable *evhs;
54
55 if (SUCCESS != zend_hash_find(&obj->intern->eventhandlers, type_str, type_len + 1, (void *) &evhs)) {
56 HashTable evh;
57
58 zend_hash_init(&evh, 1, NULL, (dtor_func_t) php_pq_callback_dtor, 0);
59 zend_hash_add(&obj->intern->eventhandlers, type_str, type_len + 1, (void *) &evh, sizeof(evh), (void *) &evhs);
60 }
61
62 php_pq_callback_addref(cb);
63 h = zend_hash_next_free_element(evhs);
64 zend_hash_index_update(evhs, h, (void *) cb, sizeof(*cb), NULL);
65
66 return h;
67 }
68
69 static void php_pqconn_object_free(void *o TSRMLS_DC)
70 {
71 php_pqconn_object_t *obj = o;
72 #if DBG_GC
73 fprintf(stderr, "FREE conn(#%d) %p\n", obj->zv.handle, obj);
74 #endif
75 if (obj->intern) {
76 php_resource_factory_handle_dtor(&obj->intern->factory, obj->intern->conn TSRMLS_CC);
77 php_resource_factory_dtor(&obj->intern->factory);
78 php_pq_callback_dtor(&obj->intern->onevent);
79 zend_hash_destroy(&obj->intern->listeners);
80 zend_hash_destroy(&obj->intern->converters);
81 zend_hash_destroy(&obj->intern->eventhandlers);
82 efree(obj->intern);
83 obj->intern = NULL;
84 }
85 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
86 efree(obj);
87 }
88
89
90 zend_object_value php_pqconn_create_object_ex(zend_class_entry *ce, php_pqconn_t *intern, php_pqconn_object_t **ptr TSRMLS_DC)
91 {
92 php_pqconn_object_t *o;
93
94 o = ecalloc(1, sizeof(*o));
95 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
96 object_properties_init((zend_object *) o, ce);
97 o->prophandler = &php_pqconn_object_prophandlers;
98
99 if (ptr) {
100 *ptr = o;
101 }
102
103 if (intern) {
104 o->intern = intern;
105 }
106
107 o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqconn_object_free, NULL TSRMLS_CC);
108 o->zv.handlers = &php_pqconn_object_handlers;
109
110 return o->zv;
111 }
112
113 static zend_object_value php_pqconn_create_object(zend_class_entry *class_type TSRMLS_DC)
114 {
115 return php_pqconn_create_object_ex(class_type, NULL, NULL TSRMLS_CC);
116 }
117
118 static void php_pqconn_object_read_status(zval *object, void *o, zval *return_value TSRMLS_DC)
119 {
120 php_pqconn_object_t *obj = o;
121
122 RETVAL_LONG(PQstatus(obj->intern->conn));
123 }
124
125 static void php_pqconn_object_read_transaction_status(zval *object, void *o, zval *return_value TSRMLS_DC)
126 {
127 php_pqconn_object_t *obj = o;
128
129 RETVAL_LONG(PQtransactionStatus(obj->intern->conn));
130 }
131
132 static void php_pqconn_object_read_error_message(zval *object, void *o, zval *return_value TSRMLS_DC)
133 {
134 php_pqconn_object_t *obj = o;
135 char *error = PHP_PQerrorMessage(obj->intern->conn);
136
137 if (error) {
138 RETVAL_STRING(error, 1);
139 } else {
140 RETVAL_NULL();
141 }
142 }
143
144 static int apply_notify_listener(void *p, void *arg TSRMLS_DC)
145 {
146 php_pq_callback_t *listener = p;
147 PGnotify *nfy = arg;
148 zval *zpid, *zchannel, *zmessage;
149
150 MAKE_STD_ZVAL(zpid);
151 ZVAL_LONG(zpid, nfy->be_pid);
152 MAKE_STD_ZVAL(zchannel);
153 ZVAL_STRING(zchannel, nfy->relname, 1);
154 MAKE_STD_ZVAL(zmessage);
155 ZVAL_STRING(zmessage, nfy->extra, 1);
156
157 zend_fcall_info_argn(&listener->fci TSRMLS_CC, 3, &zchannel, &zmessage, &zpid);
158 zend_fcall_info_call(&listener->fci, &listener->fcc, NULL, NULL TSRMLS_CC);
159
160 zval_ptr_dtor(&zchannel);
161 zval_ptr_dtor(&zmessage);
162 zval_ptr_dtor(&zpid);
163
164 return ZEND_HASH_APPLY_KEEP;
165 }
166
167 static int apply_notify_listeners(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
168 {
169 HashTable *listeners = p;
170 PGnotify *nfy = va_arg(argv, PGnotify *);
171
172 if (0 == fnmatch(key->arKey, nfy->relname, 0)) {
173 zend_hash_apply_with_argument(listeners, apply_notify_listener, nfy TSRMLS_CC);
174 }
175
176 return ZEND_HASH_APPLY_KEEP;
177 }
178
179 void php_pqconn_notify_listeners(php_pqconn_object_t *obj TSRMLS_DC)
180 {
181 PGnotify *nfy;
182
183 while ((nfy = PQnotifies(obj->intern->conn))) {
184 zend_hash_apply_with_arguments(&obj->intern->listeners TSRMLS_CC, apply_notify_listeners, 1, nfy);
185 PQfreemem(nfy);
186 }
187 }
188
189 static void php_pqconn_object_read_busy(zval *object, void *o, zval *return_value TSRMLS_DC)
190 {
191 php_pqconn_object_t *obj = o;
192
193 RETVAL_BOOL(PQisBusy(obj->intern->conn));
194 }
195
196 static void php_pqconn_object_read_encoding(zval *object, void *o, zval *return_value TSRMLS_DC)
197 {
198 php_pqconn_object_t *obj = o;
199
200 RETVAL_STRING(pg_encoding_to_char(PQclientEncoding(obj->intern->conn)), 1);
201 }
202
203 static void php_pqconn_object_write_encoding(zval *object, void *o, zval *value TSRMLS_DC)
204 {
205 php_pqconn_object_t *obj = o;
206 zval *zenc = value;
207
208 if (Z_TYPE_P(value) != IS_STRING) {
209 if (Z_REFCOUNT_P(value) > 1) {
210 zval *tmp;
211 MAKE_STD_ZVAL(tmp);
212 ZVAL_ZVAL(tmp, zenc, 1, 0);
213 convert_to_string(tmp);
214 zenc = tmp;
215 } else {
216 convert_to_string_ex(&zenc);
217 }
218 }
219
220 if (0 > PQsetClientEncoding(obj->intern->conn, Z_STRVAL_P(zenc))) {
221 zend_error(E_NOTICE, "Unrecognized encoding '%s'", Z_STRVAL_P(zenc));
222 }
223
224 if (zenc != value) {
225 zval_ptr_dtor(&zenc);
226 }
227 }
228
229 static void php_pqconn_object_read_unbuffered(zval *object, void *o, zval *return_value TSRMLS_DC)
230 {
231 php_pqconn_object_t *obj = o;
232
233 RETVAL_BOOL(obj->intern->unbuffered);
234 }
235
236 static void php_pqconn_object_write_unbuffered(zval *object, void *o, zval *value TSRMLS_DC)
237 {
238 php_pqconn_object_t *obj = o;
239
240 obj->intern->unbuffered = zend_is_true(value);
241 }
242
243 static void php_pqconn_object_read_db(zval *object, void *o, zval *return_value TSRMLS_DC)
244 {
245 php_pqconn_object_t *obj = o;
246 char *db = PQdb(obj->intern->conn);
247
248 if (db) {
249 RETVAL_STRING(db, 1);
250 } else {
251 RETVAL_EMPTY_STRING();
252 }
253 }
254
255 static void php_pqconn_object_read_user(zval *object, void *o, zval *return_value TSRMLS_DC)
256 {
257 php_pqconn_object_t *obj = o;
258 char *user = PQuser(obj->intern->conn);
259
260 if (user) {
261 RETVAL_STRING(user, 1);
262 } else {
263 RETVAL_EMPTY_STRING();
264 }
265 }
266
267 static void php_pqconn_object_read_pass(zval *object, void *o, zval *return_value TSRMLS_DC)
268 {
269 php_pqconn_object_t *obj = o;
270 char *pass = PQpass(obj->intern->conn);
271
272 if (pass) {
273 RETVAL_STRING(pass, 1);
274 } else {
275 RETVAL_EMPTY_STRING();
276 }
277 }
278
279 static void php_pqconn_object_read_host(zval *object, void *o, zval *return_value TSRMLS_DC)
280 {
281 php_pqconn_object_t *obj = o;
282 char *host = PQhost(obj->intern->conn);
283
284 if (host) {
285 RETVAL_STRING(host, 1);
286 } else {
287 RETVAL_EMPTY_STRING();
288 }
289 }
290
291 static void php_pqconn_object_read_port(zval *object, void *o, zval *return_value TSRMLS_DC)
292 {
293 php_pqconn_object_t *obj = o;
294 char *port = PQport(obj->intern->conn);
295
296 if (port) {
297 RETVAL_STRING(port, 1);
298 } else {
299 RETVAL_EMPTY_STRING();
300 }
301 }
302
303 static void php_pqconn_object_read_options(zval *object, void *o, zval *return_value TSRMLS_DC)
304 {
305 php_pqconn_object_t *obj = o;
306 char *options = PQoptions(obj->intern->conn);
307
308 if (options) {
309 RETVAL_STRING(options, 1);
310 } else {
311 RETVAL_EMPTY_STRING();
312 }
313 }
314
315 static int apply_read_event_handler_ex(void *p, void *arg TSRMLS_DC)
316 {
317 HashTable *rv = arg;
318 zval *zcb = php_pq_callback_to_zval(p);
319
320 zend_hash_next_index_insert(rv, &zcb, sizeof(zval *), NULL);
321
322 return ZEND_HASH_APPLY_KEEP;
323 }
324
325 static int apply_read_event_handlers(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
326 {
327 HashTable *evhs = p, *rv = va_arg(argv, HashTable *);
328 zval *entry, **entry_ptr;
329
330 MAKE_STD_ZVAL(entry);
331 array_init_size(entry, zend_hash_num_elements(evhs));
332
333 if (key->nKeyLength) {
334 zend_hash_add(rv, key->arKey, key->nKeyLength, &entry, sizeof(zval *), (void *) &entry_ptr);
335 } else {
336 zend_hash_index_update(rv, key->h, &entry, sizeof(zval *), (void *) &entry_ptr);
337 }
338
339 zend_hash_apply_with_argument(evhs, apply_read_event_handler_ex, Z_ARRVAL_PP(entry_ptr) TSRMLS_CC);
340
341 return ZEND_HASH_APPLY_KEEP;
342 }
343 static void php_pqconn_object_read_event_handlers(zval *object, void *o, zval *return_value TSRMLS_DC)
344 {
345 php_pqconn_object_t *obj = o;
346
347 array_init(return_value);
348 zend_hash_apply_with_arguments(&obj->intern->eventhandlers TSRMLS_CC, apply_read_event_handlers, 1, Z_ARRVAL_P(return_value) TSRMLS_CC);
349 }
350
351 static STATUS php_pqconn_update_socket(zval *this_ptr, php_pqconn_object_t *obj TSRMLS_DC)
352 {
353 zval *zsocket, zmember;
354 php_stream *stream;
355 STATUS retval;
356 int socket;
357
358 if (!obj) {
359 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
360 }
361
362 INIT_PZVAL(&zmember);
363 ZVAL_STRINGL(&zmember, "socket", sizeof("socket")-1, 0);
364 MAKE_STD_ZVAL(zsocket);
365
366 if ((CONNECTION_BAD != PQstatus(obj->intern->conn))
367 && (-1 < (socket = PQsocket(obj->intern->conn)))
368 && (stream = php_stream_fopen_from_fd(socket, "r+b", NULL))) {
369 stream->flags |= PHP_STREAM_FLAG_NO_CLOSE;
370 php_stream_to_zval(stream, zsocket);
371 retval = SUCCESS;
372 } else {
373 ZVAL_NULL(zsocket);
374 retval = FAILURE;
375 }
376 zend_get_std_object_handlers()->write_property(getThis(), &zmember, zsocket, NULL TSRMLS_CC);
377 zval_ptr_dtor(&zsocket);
378
379 return retval;
380 }
381
382 static void *php_pqconn_resource_factory_ctor(void *data, void *init_arg TSRMLS_DC)
383 {
384 php_pqconn_resource_factory_data_t *o = init_arg;
385 PGconn *conn = NULL;;
386
387 if (o->flags & PHP_PQCONN_ASYNC) {
388 conn = PQconnectStart(o->dsn);
389 } else {
390 conn = PQconnectdb(o->dsn);
391 }
392
393 if (conn) {
394 PQregisterEventProc(conn, php_pqconn_event, "ext-pq", NULL);
395 }
396
397 return conn;
398 }
399
400 static void php_pqconn_resource_factory_dtor(void *opaque, void *handle TSRMLS_DC)
401 {
402 php_pqconn_event_data_t *evdata = PQinstanceData(handle, php_pqconn_event);
403
404 /* we don't care for anything, except free'ing evdata */
405 if (evdata) {
406 PQsetInstanceData(handle, php_pqconn_event, NULL);
407 memset(evdata, 0, sizeof(*evdata));
408 efree(evdata);
409 }
410
411 PQfinish(handle);
412 }
413
414 static php_resource_factory_ops_t php_pqconn_resource_factory_ops = {
415 php_pqconn_resource_factory_ctor,
416 NULL,
417 php_pqconn_resource_factory_dtor
418 };
419
420 php_resource_factory_ops_t *php_pqconn_get_resource_factory_ops(void)
421 {
422 return &php_pqconn_resource_factory_ops;
423 }
424
425 static void php_pqconn_wakeup(php_persistent_handle_factory_t *f, void **handle TSRMLS_DC)
426 {
427 // FIXME: ping server
428 }
429
430 static int apply_unlisten(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
431 {
432 php_pqconn_object_t *obj = va_arg(argv, php_pqconn_object_t *);
433 char *quoted_channel = PQescapeIdentifier(obj->intern->conn, key->arKey, key->nKeyLength - 1);
434
435 if (quoted_channel) {
436 PGresult *res;
437 char *cmd;
438
439 spprintf(&cmd, 0, "UNLISTEN %s", quoted_channel);
440 if ((res = PQexec(obj->intern->conn, cmd))) {
441 PHP_PQclear(res);
442 }
443
444 efree(cmd);
445 PQfreemem(quoted_channel);
446 }
447
448 return ZEND_HASH_APPLY_REMOVE;
449 }
450
451 static void php_pqconn_retire(php_persistent_handle_factory_t *f, void **handle TSRMLS_DC)
452 {
453 php_pqconn_event_data_t *evdata = PQinstanceData(*handle, php_pqconn_event);
454 PGcancel *cancel;
455 PGresult *res;
456
457 /* go away */
458 PQsetInstanceData(*handle, php_pqconn_event, NULL);
459
460 /* ignore notices */
461 PQsetNoticeReceiver(*handle, php_pqconn_notice_ignore, NULL);
462
463 /* cancel async queries */
464 if (PQisBusy(*handle) && (cancel = PQgetCancel(*handle))) {
465 char err[256] = {0};
466
467 PQcancel(cancel, err, sizeof(err));
468 PQfreeCancel(cancel);
469 }
470 /* clean up async results */
471 while ((res = PQgetResult(*handle))) {
472 PHP_PQclear(res);
473 }
474
475 /* clean up transaction & session */
476 switch (PQtransactionStatus(*handle)) {
477 case PQTRANS_IDLE:
478 res = PQexec(*handle, "RESET ALL");
479 break;
480 default:
481 res = PQexec(*handle, "ROLLBACK; RESET ALL");
482 break;
483 }
484
485 if (res) {
486 PHP_PQclear(res);
487 }
488
489 if (evdata) {
490 /* clean up notify listeners */
491 zend_hash_apply_with_arguments(&evdata->obj->intern->listeners TSRMLS_CC, apply_unlisten, 1, evdata->obj);
492
493 /* release instance data */
494 memset(evdata, 0, sizeof(*evdata));
495 efree(evdata);
496 }
497 }
498
499 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_construct, 0, 0, 1)
500 ZEND_ARG_INFO(0, dsn)
501 ZEND_ARG_INFO(0, async)
502 ZEND_END_ARG_INFO();
503 static PHP_METHOD(pqconn, __construct) {
504 zend_error_handling zeh;
505 char *dsn_str = "";
506 int dsn_len = 0;
507 long flags = 0;
508 STATUS rv;
509
510 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
511 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sl", &dsn_str, &dsn_len, &flags);
512 zend_restore_error_handling(&zeh TSRMLS_CC);
513
514 if (SUCCESS == rv) {
515 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
516
517 if (obj->intern) {
518 throw_exce(EX_BAD_METHODCALL TSRMLS_CC, "pq\\Connection already initialized");
519 } else {
520 php_pqconn_event_data_t *evdata = php_pqconn_event_data_init(obj TSRMLS_CC);
521 php_pqconn_resource_factory_data_t rfdata = {dsn_str, flags};
522
523 obj->intern = ecalloc(1, sizeof(*obj->intern));
524
525 zend_hash_init(&obj->intern->listeners, 0, NULL, (dtor_func_t) zend_hash_destroy, 0);
526 zend_hash_init(&obj->intern->converters, 0, NULL, ZVAL_PTR_DTOR, 0);
527 zend_hash_init(&obj->intern->eventhandlers, 0, NULL, (dtor_func_t) zend_hash_destroy, 0);
528
529 if (flags & PHP_PQCONN_PERSISTENT) {
530 php_persistent_handle_factory_t *phf = php_persistent_handle_concede(NULL, ZEND_STRL("pq\\Connection"), dsn_str, dsn_len, php_pqconn_wakeup, php_pqconn_retire TSRMLS_CC);
531 php_resource_factory_init(&obj->intern->factory, php_persistent_handle_get_resource_factory_ops(), phf, (void (*)(void*)) php_persistent_handle_abandon);
532 } else {
533 php_resource_factory_init(&obj->intern->factory, &php_pqconn_resource_factory_ops, NULL, NULL);
534 }
535
536 if (flags & PHP_PQCONN_ASYNC) {
537 obj->intern->poller = (int (*)(PGconn*)) PQconnectPoll;
538 }
539
540 obj->intern->conn = php_resource_factory_handle_ctor(&obj->intern->factory, &rfdata TSRMLS_CC);
541
542 PQsetInstanceData(obj->intern->conn, php_pqconn_event, evdata);
543 PQsetNoticeReceiver(obj->intern->conn, php_pqconn_notice_recv, evdata);
544
545 if (SUCCESS != php_pqconn_update_socket(getThis(), obj TSRMLS_CC)) {
546 throw_exce(EX_CONNECTION_FAILED TSRMLS_CC, "Connection failed (%s)", PHP_PQerrorMessage(obj->intern->conn));
547 }
548 }
549 }
550 }
551
552 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_reset, 0, 0, 0)
553 ZEND_END_ARG_INFO();
554 static PHP_METHOD(pqconn, reset) {
555 zend_error_handling zeh;
556 STATUS rv;
557
558 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
559 rv = zend_parse_parameters_none();
560 zend_restore_error_handling(&zeh TSRMLS_CC);
561
562 if (SUCCESS == rv) {
563 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
564
565 if (!obj->intern) {
566 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
567 } else {
568 PQreset(obj->intern->conn);
569
570 if (CONNECTION_OK != PQstatus(obj->intern->conn)) {
571 throw_exce(EX_CONNECTION_FAILED TSRMLS_CC, "Connection reset failed: (%s)", PHP_PQerrorMessage(obj->intern->conn));
572 }
573
574 php_pqconn_notify_listeners(obj TSRMLS_CC);
575 }
576 }
577 }
578
579 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_reset_async, 0, 0, 0)
580 ZEND_END_ARG_INFO();
581 static PHP_METHOD(pqconn, resetAsync) {
582 zend_error_handling zeh;
583 STATUS rv;
584
585 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
586 rv = zend_parse_parameters_none();
587 zend_restore_error_handling(&zeh TSRMLS_CC);
588
589 if (SUCCESS == rv) {
590 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
591
592 if (!obj->intern) {
593 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
594 } else {
595 if (!PQresetStart(obj->intern->conn)) {
596 throw_exce(EX_IO TSRMLS_CC, "Failed to start connection reset (%s)", PHP_PQerrorMessage(obj->intern->conn));
597 } else {
598 obj->intern->poller = (int (*)(PGconn*)) PQresetPoll;
599 }
600
601 php_pqconn_notify_listeners(obj TSRMLS_CC);
602 }
603 }
604 }
605
606 static void php_pqconn_add_listener(php_pqconn_object_t *obj, const char *channel_str, size_t channel_len, php_pq_callback_t *listener TSRMLS_DC)
607 {
608 HashTable ht, *existing_listeners;
609
610 php_pq_callback_addref(listener);
611
612 if (SUCCESS == zend_hash_find(&obj->intern->listeners, channel_str, channel_len + 1, (void *) &existing_listeners)) {
613 zend_hash_next_index_insert(existing_listeners, (void *) listener, sizeof(*listener), NULL);
614 } else {
615 zend_hash_init(&ht, 1, NULL, (dtor_func_t) php_pq_callback_dtor, 0);
616 zend_hash_next_index_insert(&ht, (void *) listener, sizeof(*listener), NULL);
617 zend_hash_add(&obj->intern->listeners, channel_str, channel_len + 1, (void *) &ht, sizeof(HashTable), NULL);
618 }
619 }
620
621 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_listen, 0, 0, 0)
622 ZEND_ARG_INFO(0, channel)
623 ZEND_ARG_INFO(0, callable)
624 ZEND_END_ARG_INFO();
625 static PHP_METHOD(pqconn, listen) {
626 zend_error_handling zeh;
627 char *channel_str = NULL;
628 int channel_len = 0;
629 php_pq_callback_t listener;
630 STATUS rv;
631
632 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
633 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sf", &channel_str, &channel_len, &listener.fci, &listener.fcc);
634 zend_restore_error_handling(&zeh TSRMLS_CC);
635
636 if (SUCCESS == rv) {
637 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
638
639 if (!obj->intern) {
640 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
641 } else {
642 char *quoted_channel = PQescapeIdentifier(obj->intern->conn, channel_str, channel_len);
643
644 if (!quoted_channel) {
645 throw_exce(EX_ESCAPE TSRMLS_CC, "Failed to escape channel identifier (%s)", PHP_PQerrorMessage(obj->intern->conn));
646 } else {
647 PGresult *res;
648 smart_str cmd = {0};
649
650 smart_str_appends(&cmd, "LISTEN ");
651 smart_str_appends(&cmd, quoted_channel);
652 smart_str_0(&cmd);
653
654 res = PQexec(obj->intern->conn, cmd.c);
655
656 smart_str_free(&cmd);
657 PQfreemem(quoted_channel);
658
659 if (!res) {
660 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to install listener (%s)", PHP_PQerrorMessage(obj->intern->conn));
661 } else {
662 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
663 obj->intern->poller = PQconsumeInput;
664 php_pqconn_add_listener(obj, channel_str, channel_len, &listener TSRMLS_CC);
665 }
666 PHP_PQclear(res);
667 }
668
669 php_pqconn_notify_listeners(obj TSRMLS_CC);
670 }
671 }
672 }
673 }
674
675 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_listen_async, 0, 0, 0)
676 ZEND_ARG_INFO(0, channel)
677 ZEND_ARG_INFO(0, callable)
678 ZEND_END_ARG_INFO();
679 static PHP_METHOD(pqconn, listenAsync) {
680 zend_error_handling zeh;
681 char *channel_str = NULL;
682 int channel_len = 0;
683 php_pq_callback_t listener;
684 STATUS rv;
685
686 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
687 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sf", &channel_str, &channel_len, &listener.fci, &listener.fcc);
688 zend_restore_error_handling(&zeh TSRMLS_CC);
689
690 if (SUCCESS == rv) {
691 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
692
693 if (!obj->intern) {
694 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
695 } else {
696 char *quoted_channel = PQescapeIdentifier(obj->intern->conn, channel_str, channel_len);
697
698 if (!quoted_channel) {
699 throw_exce(EX_ESCAPE TSRMLS_CC, "Failed to escape channel identifier (%s)", PHP_PQerrorMessage(obj->intern->conn));
700 } else {
701 smart_str cmd = {0};
702
703 smart_str_appends(&cmd, "LISTEN ");
704 smart_str_appends(&cmd, quoted_channel);
705 smart_str_0(&cmd);
706
707 if (!PQsendQuery(obj->intern->conn, cmd.c)) {
708 throw_exce(EX_IO TSRMLS_CC, "Failed to install listener (%s)", PHP_PQerrorMessage(obj->intern->conn));
709 } else {
710 obj->intern->poller = PQconsumeInput;
711 php_pqconn_add_listener(obj, channel_str, channel_len, &listener TSRMLS_CC);
712 }
713
714 smart_str_free(&cmd);
715 PQfreemem(quoted_channel);
716 php_pqconn_notify_listeners(obj TSRMLS_CC);
717 }
718 }
719 }
720 }
721
722 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_notify, 0, 0, 2)
723 ZEND_ARG_INFO(0, channel)
724 ZEND_ARG_INFO(0, message)
725 ZEND_END_ARG_INFO();
726 static PHP_METHOD(pqconn, notify) {
727 zend_error_handling zeh;
728 char *channel_str, *message_str;
729 int channel_len, message_len;
730 STATUS rv;
731
732 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
733 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &channel_str, &channel_len, &message_str, &message_len);
734 zend_restore_error_handling(&zeh TSRMLS_CC);
735
736 if (SUCCESS == rv) {
737 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
738
739 if (!obj->intern) {
740 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
741 } else {
742 PGresult *res;
743 char *params[2] = {channel_str, message_str};
744
745 res = PQexecParams(obj->intern->conn, "select pg_notify($1, $2)", 2, NULL, (const char *const*) params, NULL, NULL, 0);
746
747 if (!res) {
748 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to notify listeners (%s)", PHP_PQerrorMessage(obj->intern->conn));
749 } else {
750 php_pqres_success(res TSRMLS_CC);
751 PHP_PQclear(res);
752 }
753
754 php_pqconn_notify_listeners(obj TSRMLS_CC);
755 }
756 }
757 }
758
759 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_notify_async, 0, 0, 2)
760 ZEND_ARG_INFO(0, channel)
761 ZEND_ARG_INFO(0, message)
762 ZEND_END_ARG_INFO();
763 static PHP_METHOD(pqconn, notifyAsync) {
764 zend_error_handling zeh;
765 char *channel_str, *message_str;
766 int channel_len, message_len;
767 STATUS rv;
768
769 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
770 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &channel_str, &channel_len, &message_str, &message_len);
771 zend_restore_error_handling(&zeh TSRMLS_CC);
772
773 if (SUCCESS == rv) {
774 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
775
776 if (!obj->intern) {
777 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
778 } else {
779 char *params[2] = {channel_str, message_str};
780
781 if (!PQsendQueryParams(obj->intern->conn, "select pg_notify($1, $2)", 2, NULL, (const char *const*) params, NULL, NULL, 0)) {
782 throw_exce(EX_IO TSRMLS_CC, "Failed to notify listeners (%s)", PHP_PQerrorMessage(obj->intern->conn));
783 } else {
784 obj->intern->poller = PQconsumeInput;
785 }
786
787 php_pqconn_notify_listeners(obj TSRMLS_CC);
788 }
789 }
790 }
791
792 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_poll, 0, 0, 0)
793 ZEND_END_ARG_INFO();
794 static PHP_METHOD(pqconn, poll) {
795 zend_error_handling zeh;
796 STATUS rv;
797
798 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
799 rv = zend_parse_parameters_none();
800 zend_restore_error_handling(&zeh TSRMLS_CC);
801
802 if (SUCCESS == rv) {
803 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
804
805 if (!obj->intern) {
806 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
807 } else if (!obj->intern->poller) {
808 throw_exce(EX_RUNTIME TSRMLS_CC, "No asynchronous operation active");
809 } else {
810 if (obj->intern->poller == PQconsumeInput) {
811 RETVAL_LONG(obj->intern->poller(obj->intern->conn) * PGRES_POLLING_OK);
812 } else {
813 RETVAL_LONG(obj->intern->poller(obj->intern->conn));
814 }
815 php_pqconn_notify_listeners(obj TSRMLS_CC);
816 }
817 }
818 }
819
820 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec, 0, 0, 1)
821 ZEND_ARG_INFO(0, query)
822 ZEND_END_ARG_INFO();
823 static PHP_METHOD(pqconn, exec) {
824 zend_error_handling zeh;
825 char *query_str;
826 int query_len;
827 STATUS rv;
828
829 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
830 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &query_str, &query_len);
831 zend_restore_error_handling(&zeh TSRMLS_CC);
832
833 if (SUCCESS == rv) {
834 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
835
836 if (!obj->intern) {
837 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
838 } else {
839 PGresult *res = PQexec(obj->intern->conn, query_str);
840
841 if (!res) {
842 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
843 } else if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
844 php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), &return_value TSRMLS_CC);
845 } else {
846 PHP_PQclear(res);
847 }
848
849 php_pqconn_notify_listeners(obj TSRMLS_CC);
850 }
851 }
852 }
853
854 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_get_result, 0, 0, 0)
855 ZEND_END_ARG_INFO();
856 static PHP_METHOD(pqconn, getResult) {
857 zend_error_handling zeh;
858 STATUS rv;
859
860 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
861 rv = zend_parse_parameters_none();
862 zend_restore_error_handling(&zeh TSRMLS_CC);
863
864 if (SUCCESS == rv) {
865 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
866
867 if (!obj->intern) {
868 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
869 } else {
870 PGresult *res = PQgetResult(obj->intern->conn);
871
872 if (!res) {
873 RETVAL_NULL();
874 } else {
875 php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), &return_value TSRMLS_CC);
876 }
877
878 php_pqconn_notify_listeners(obj TSRMLS_CC);
879 }
880 }
881 }
882
883 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_async, 0, 0, 1)
884 ZEND_ARG_INFO(0, query)
885 ZEND_ARG_INFO(0, callable)
886 ZEND_END_ARG_INFO();
887 static PHP_METHOD(pqconn, execAsync) {
888 zend_error_handling zeh;
889 php_pq_callback_t resolver = {{0}};
890 char *query_str;
891 int query_len;
892 STATUS rv;
893
894 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
895 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|f", &query_str, &query_len, &resolver.fci, &resolver.fcc);
896 zend_restore_error_handling(&zeh TSRMLS_CC);
897
898 if (SUCCESS == rv) {
899 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
900
901 if (!obj->intern) {
902 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
903 } else if (!PQsendQuery(obj->intern->conn, query_str)) {
904 throw_exce(EX_IO TSRMLS_CC, "Failed to execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
905 } else if (obj->intern->unbuffered && !PQsetSingleRowMode(obj->intern->conn)) {
906 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn));
907 } else {
908 obj->intern->poller = PQconsumeInput;
909 php_pq_callback_dtor(&obj->intern->onevent);
910 if (resolver.fci.size > 0) {
911 obj->intern->onevent = resolver;
912 php_pq_callback_addref(&obj->intern->onevent);
913 }
914 php_pqconn_notify_listeners(obj TSRMLS_CC);
915 }
916 }
917 }
918
919 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_params, 0, 0, 2)
920 ZEND_ARG_INFO(0, query)
921 ZEND_ARG_ARRAY_INFO(0, params, 0)
922 ZEND_ARG_ARRAY_INFO(0, types, 1)
923 ZEND_END_ARG_INFO();
924 static PHP_METHOD(pqconn, execParams) {
925 zend_error_handling zeh;
926 char *query_str;
927 int query_len;
928 zval *zparams;
929 zval *ztypes = NULL;
930 STATUS rv;
931
932 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
933 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|a/!", &query_str, &query_len, &zparams, &ztypes);
934 zend_restore_error_handling(&zeh TSRMLS_CC);
935
936 if (SUCCESS == rv) {
937 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
938
939 if (!obj->intern) {
940 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
941 } else {
942 PGresult *res;
943 php_pq_params_t *params;
944
945 params = php_pq_params_init(&obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, Z_ARRVAL_P(zparams) TSRMLS_CC);
946 res = PQexecParams(obj->intern->conn, query_str, params->param.count, params->type.oids, (const char *const*) params->param.strings, NULL, NULL, 0);
947 php_pq_params_free(&params);
948
949 if (!res) {
950 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
951 } else {
952 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
953 php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), &return_value TSRMLS_CC);
954 } else {
955 PHP_PQclear(res);
956 }
957
958 php_pqconn_notify_listeners(obj TSRMLS_CC);
959 }
960 }
961 }
962 }
963
964 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_params_async, 0, 0, 2)
965 ZEND_ARG_INFO(0, query)
966 ZEND_ARG_ARRAY_INFO(0, params, 0)
967 ZEND_ARG_ARRAY_INFO(0, types, 1)
968 ZEND_ARG_INFO(0, callable)
969 ZEND_END_ARG_INFO();
970 static PHP_METHOD(pqconn, execParamsAsync) {
971 zend_error_handling zeh;
972 php_pq_callback_t resolver = {{0}};
973 char *query_str;
974 int query_len;
975 zval *zparams;
976 zval *ztypes = NULL;
977 STATUS rv;
978
979 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
980 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|a/!f", &query_str, &query_len, &zparams, &ztypes, &resolver.fci, &resolver.fcc);
981 zend_restore_error_handling(&zeh TSRMLS_CC);
982
983 if (SUCCESS == rv) {
984 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
985
986 if (!obj->intern) {
987 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
988 } else {
989 int rc;
990 php_pq_params_t *params;
991
992 params = php_pq_params_init(&obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, Z_ARRVAL_P(zparams) TSRMLS_CC);
993 rc = PQsendQueryParams(obj->intern->conn, query_str, params->param.count, params->type.oids, (const char *const*) params->param.strings, NULL, NULL, 0);
994 php_pq_params_free(&params);
995
996 if (!rc) {
997 throw_exce(EX_IO TSRMLS_CC, "Failed to execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
998 } else if (obj->intern->unbuffered && !PQsetSingleRowMode(obj->intern->conn)) {
999 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn));
1000 } else {
1001 obj->intern->poller = PQconsumeInput;
1002 php_pq_callback_dtor(&obj->intern->onevent);
1003 if (resolver.fci.size > 0) {
1004 obj->intern->onevent = resolver;
1005 php_pq_callback_addref(&obj->intern->onevent);
1006 }
1007 php_pqconn_notify_listeners(obj TSRMLS_CC);
1008 }
1009 }
1010 }
1011 zend_restore_error_handling(&zeh TSRMLS_CC);
1012 }
1013
1014 STATUS php_pqconn_prepare(zval *object, php_pqconn_object_t *obj, const char *name, const char *query, php_pq_params_t *params TSRMLS_DC)
1015 {
1016 PGresult *res;
1017 STATUS rv;
1018
1019 if (!obj) {
1020 obj = zend_object_store_get_object(object TSRMLS_CC);
1021 }
1022
1023 res = PQprepare(obj->intern->conn, name, query, params->type.count, params->type.oids);
1024
1025 if (!res) {
1026 rv = FAILURE;
1027 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to prepare statement (%s)", PHP_PQerrorMessage(obj->intern->conn));
1028 } else {
1029 rv = php_pqres_success(res TSRMLS_CC);
1030 PHP_PQclear(res);
1031 php_pqconn_notify_listeners(obj TSRMLS_CC);
1032 }
1033
1034 return rv;
1035 }
1036
1037 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_prepare, 0, 0, 2)
1038 ZEND_ARG_INFO(0, type)
1039 ZEND_ARG_INFO(0, query)
1040 ZEND_ARG_ARRAY_INFO(0, types, 1)
1041 ZEND_END_ARG_INFO();
1042 static PHP_METHOD(pqconn, prepare) {
1043 zend_error_handling zeh;
1044 zval *ztypes = NULL;
1045 char *name_str, *query_str;
1046 int name_len, *query_len;
1047 STATUS rv;
1048
1049 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1050 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!", &name_str, &name_len, &query_str, &query_len, &ztypes);
1051 zend_restore_error_handling(&zeh TSRMLS_CC);
1052
1053 if (SUCCESS == rv) {
1054 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1055
1056 if (!obj->intern) {
1057 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1058 } else {
1059 php_pq_params_t *params = php_pq_params_init(&obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, NULL TSRMLS_CC);
1060
1061 if (SUCCESS != php_pqconn_prepare(getThis(), obj, name_str, query_str, params TSRMLS_CC)) {
1062 php_pq_params_free(&params);
1063 } else {
1064 php_pqstm_t *stm = ecalloc(1, sizeof(*stm));
1065
1066 php_pq_object_addref(obj TSRMLS_CC);
1067 stm->conn = obj;
1068 stm->name = estrdup(name_str);
1069 stm->params = params;
1070 ZEND_INIT_SYMTABLE(&stm->bound);
1071
1072 return_value->type = IS_OBJECT;
1073 return_value->value.obj = php_pqstm_create_object_ex(php_pqstm_class_entry, stm, NULL TSRMLS_CC);
1074 }
1075 }
1076 }
1077 }
1078
1079 STATUS php_pqconn_prepare_async(zval *object, php_pqconn_object_t *obj, const char *name, const char *query, php_pq_params_t *params TSRMLS_DC)
1080 {
1081 STATUS rv;
1082
1083 if (!obj) {
1084 obj = zend_object_store_get_object(object TSRMLS_CC);
1085 }
1086
1087 if (!PQsendPrepare(obj->intern->conn, name, query, params->type.count, params->type.oids)) {
1088 rv = FAILURE;
1089 throw_exce(EX_IO TSRMLS_CC, "Failed to prepare statement (%s)", PHP_PQerrorMessage(obj->intern->conn));
1090 } else if (obj->intern->unbuffered && !PQsetSingleRowMode(obj->intern->conn)) {
1091 rv = FAILURE;
1092 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn));
1093 } else {
1094 rv = SUCCESS;
1095 obj->intern->poller = PQconsumeInput;
1096 php_pqconn_notify_listeners(obj TSRMLS_CC);
1097 }
1098
1099 return rv;
1100 }
1101
1102 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_prepare_async, 0, 0, 2)
1103 ZEND_ARG_INFO(0, type)
1104 ZEND_ARG_INFO(0, query)
1105 ZEND_ARG_ARRAY_INFO(0, types, 1)
1106 ZEND_END_ARG_INFO();
1107 static PHP_METHOD(pqconn, prepareAsync) {
1108 zend_error_handling zeh;
1109 zval *ztypes = NULL;
1110 char *name_str, *query_str;
1111 int name_len, *query_len;
1112 STATUS rv;
1113
1114 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1115 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!", &name_str, &name_len, &query_str, &query_len, &ztypes);
1116 zend_restore_error_handling(&zeh TSRMLS_CC);
1117
1118 if (SUCCESS == rv) {
1119 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1120
1121 if (!obj->intern) {
1122 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1123 } else {
1124 php_pq_params_t *params = php_pq_params_init(&obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, NULL TSRMLS_CC);
1125
1126 if (SUCCESS != php_pqconn_prepare_async(getThis(), obj, name_str, query_str, params TSRMLS_CC)) {
1127 php_pq_params_free(&params);
1128 } else {
1129 php_pqstm_t *stm = ecalloc(1, sizeof(*stm));
1130
1131 php_pq_object_addref(obj TSRMLS_CC);
1132 stm->conn = obj;
1133 stm->name = estrdup(name_str);
1134 stm->params = params;
1135 ZEND_INIT_SYMTABLE(&stm->bound);
1136
1137 return_value->type = IS_OBJECT;
1138 return_value->value.obj = php_pqstm_create_object_ex(php_pqstm_class_entry, stm, NULL TSRMLS_CC);
1139 }
1140 }
1141 }
1142 }
1143
1144 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_quote, 0, 0, 1)
1145 ZEND_ARG_INFO(0, string)
1146 ZEND_END_ARG_INFO();
1147 static PHP_METHOD(pqconn, quote) {
1148 char *str;
1149 int len;
1150
1151 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len)) {
1152 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1153
1154 if (!obj->intern) {
1155 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1156 } else {
1157 char *quoted = PQescapeLiteral(obj->intern->conn, str, len);
1158
1159 if (!quoted) {
1160 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to quote string (%s)", PHP_PQerrorMessage(obj->intern->conn));
1161 RETVAL_FALSE;
1162 } else {
1163 RETVAL_STRING(quoted, 1);
1164 PQfreemem(quoted);
1165 }
1166 }
1167 }
1168 }
1169
1170 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_quote_name, 0, 0, 1)
1171 ZEND_ARG_INFO(0, type)
1172 ZEND_END_ARG_INFO();
1173 static PHP_METHOD(pqconn, quoteName) {
1174 char *str;
1175 int len;
1176
1177 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len)) {
1178 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1179
1180 if (!obj->intern) {
1181 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1182 } else {
1183 char *quoted = PQescapeIdentifier(obj->intern->conn, str, len);
1184
1185 if (!quoted) {
1186 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to quote name (%s)", PHP_PQerrorMessage(obj->intern->conn));
1187 RETVAL_FALSE;
1188 } else {
1189 RETVAL_STRING(quoted, 1);
1190 PQfreemem(quoted);
1191 }
1192 }
1193 }
1194 }
1195
1196 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_escape_bytea, 0, 0, 1)
1197 ZEND_ARG_INFO(0, bytea)
1198 ZEND_END_ARG_INFO();
1199 static PHP_METHOD(pqconn, escapeBytea) {
1200 char *str;
1201 int len;
1202
1203 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len)) {
1204 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1205
1206 if (!obj->intern) {
1207 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1208 } else {
1209 size_t escaped_len;
1210 char *escaped_str = (char *) PQescapeByteaConn(obj->intern->conn, (unsigned char *) str, len, &escaped_len);
1211
1212 if (!escaped_str) {
1213 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to escape bytea (%s)", PHP_PQerrorMessage(obj->intern->conn));
1214 RETVAL_FALSE;
1215 } else {
1216 RETVAL_STRINGL(escaped_str, escaped_len - 1, 1);
1217 PQfreemem(escaped_str);
1218 }
1219 }
1220 }
1221 }
1222
1223 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_unescape_bytea, 0, 0, 1)
1224 ZEND_ARG_INFO(0, bytea)
1225 ZEND_END_ARG_INFO();
1226 static PHP_METHOD(pqconn, unescapeBytea) {
1227 char *str;
1228 int len;
1229
1230 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len)) {
1231 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1232
1233 if (!obj->intern) {
1234 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1235 } else {
1236 size_t unescaped_len;
1237 char *unescaped_str = (char *) PQunescapeBytea((unsigned char *)str, &unescaped_len);
1238
1239 if (!unescaped_str) {
1240 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to unescape bytea (%s)", PHP_PQerrorMessage(obj->intern->conn));
1241 RETVAL_FALSE;
1242 } else {
1243 RETVAL_STRINGL(unescaped_str, unescaped_len, 1);
1244 PQfreemem(unescaped_str);
1245 }
1246 }
1247 }
1248 }
1249
1250 STATUS php_pqconn_start_transaction(zval *zconn, php_pqconn_object_t *conn_obj, long isolation, zend_bool readonly, zend_bool deferrable TSRMLS_DC)
1251 {
1252 STATUS rv = FAILURE;
1253
1254 if (!conn_obj) {
1255 conn_obj = zend_object_store_get_object(zconn TSRMLS_CC);
1256 }
1257
1258 if (!conn_obj->intern) {
1259 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1260 } else {
1261 PGresult *res;
1262 smart_str cmd = {0};
1263 const char *il = isolation_level(&isolation);
1264
1265 smart_str_appends(&cmd, "START TRANSACTION ISOLATION LEVEL ");
1266 smart_str_appends(&cmd, il);
1267 smart_str_appends(&cmd, ", READ ");
1268 smart_str_appends(&cmd, readonly ? "ONLY" : "WRITE");
1269 smart_str_appends(&cmd, ",");
1270 smart_str_appends(&cmd, deferrable ? "" : " NOT");
1271 smart_str_appends(&cmd, " DEFERRABLE");
1272 smart_str_0(&cmd);
1273
1274 res = PQexec(conn_obj->intern->conn, cmd.c);
1275
1276 if (!res) {
1277 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to start transaction (%s)", PHP_PQerrorMessage(conn_obj->intern->conn));
1278 } else {
1279 rv = php_pqres_success(res TSRMLS_CC);
1280 PHP_PQclear(res);
1281 php_pqconn_notify_listeners(conn_obj TSRMLS_CC);
1282 }
1283
1284 smart_str_free(&cmd);
1285 }
1286
1287 return rv;
1288 }
1289
1290 STATUS php_pqconn_start_transaction_async(zval *zconn, php_pqconn_object_t *conn_obj, long isolation, zend_bool readonly, zend_bool deferrable TSRMLS_DC)
1291 {
1292 STATUS rv = FAILURE;
1293
1294 if (!conn_obj) {
1295 conn_obj = zend_object_store_get_object(zconn TSRMLS_CC);
1296 }
1297
1298 if (!conn_obj->intern) {
1299 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1300 } else {
1301 smart_str cmd = {0};
1302 const char *il = isolation_level(&isolation);
1303
1304 smart_str_appends(&cmd, "START TRANSACTION ISOLATION LEVEL ");
1305 smart_str_appends(&cmd, il);
1306 smart_str_appends(&cmd, ", READ ");
1307 smart_str_appends(&cmd, readonly ? "ONLY" : "WRITE");
1308 smart_str_appends(&cmd, ",");
1309 smart_str_appends(&cmd, deferrable ? "" : "NOT ");
1310 smart_str_appends(&cmd, " DEFERRABLE");
1311 smart_str_0(&cmd);
1312
1313 if (!PQsendQuery(conn_obj->intern->conn, cmd.c)) {
1314 throw_exce(EX_IO TSRMLS_CC, "Failed to start transaction (%s)", PHP_PQerrorMessage(conn_obj->intern->conn));
1315 } else {
1316 rv = SUCCESS;
1317 conn_obj->intern->poller = PQconsumeInput;
1318 php_pqconn_notify_listeners(conn_obj TSRMLS_CC);
1319 }
1320
1321 smart_str_free(&cmd);
1322 }
1323
1324 return rv;
1325 }
1326
1327 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_start_transaction, 0, 0, 0)
1328 ZEND_ARG_INFO(0, isolation)
1329 ZEND_ARG_INFO(0, readonly)
1330 ZEND_ARG_INFO(0, deferrable)
1331 ZEND_END_ARG_INFO();
1332 static PHP_METHOD(pqconn, startTransaction) {
1333 zend_error_handling zeh;
1334 long isolation = PHP_PQTXN_READ_COMMITTED;
1335 zend_bool readonly = 0, deferrable = 0;
1336 STATUS rv;
1337
1338 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1339 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lbb", &isolation, &readonly, &deferrable);
1340 zend_restore_error_handling(&zeh TSRMLS_CC);
1341
1342 if (SUCCESS == rv) {
1343 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1344
1345 rv = php_pqconn_start_transaction(getThis(), obj, isolation, readonly, deferrable TSRMLS_CC);
1346
1347 if (SUCCESS == rv) {
1348 php_pqtxn_t *txn = ecalloc(1, sizeof(*txn));
1349
1350 php_pq_object_addref(obj TSRMLS_CC);
1351 txn->conn = obj;
1352 txn->open = 1;
1353 txn->isolation = isolation;
1354 txn->readonly = readonly;
1355 txn->deferrable = deferrable;
1356
1357 return_value->type = IS_OBJECT;
1358 return_value->value.obj = php_pqtxn_create_object_ex(php_pqtxn_class_entry, txn, NULL TSRMLS_CC);
1359 }
1360 }
1361 }
1362
1363 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_start_transaction_async, 0, 0, 0)
1364 ZEND_ARG_INFO(0, isolation)
1365 ZEND_ARG_INFO(0, readonly)
1366 ZEND_ARG_INFO(0, deferrable)
1367 ZEND_END_ARG_INFO();
1368 static PHP_METHOD(pqconn, startTransactionAsync) {
1369 zend_error_handling zeh;
1370 long isolation = PHP_PQTXN_READ_COMMITTED;
1371 zend_bool readonly = 0, deferrable = 0;
1372 STATUS rv;
1373
1374 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1375 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lbb", &isolation, &readonly, &deferrable);
1376 zend_restore_error_handling(&zeh TSRMLS_CC);
1377 if (SUCCESS == rv) {
1378 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1379
1380 rv = php_pqconn_start_transaction_async(getThis(), obj, isolation, readonly, deferrable TSRMLS_CC);
1381
1382 if (SUCCESS == rv) {
1383 php_pqtxn_t *txn = ecalloc(1, sizeof(*txn));
1384
1385 php_pq_object_addref(obj TSRMLS_CC);
1386 txn->conn = obj;
1387 txn->isolation = isolation;
1388 txn->readonly = readonly;
1389 txn->deferrable = deferrable;
1390
1391 return_value->type = IS_OBJECT;
1392 return_value->value.obj = php_pqtxn_create_object_ex(php_pqtxn_class_entry, txn, NULL TSRMLS_CC);
1393 }
1394 }
1395 }
1396
1397 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_trace, 0, 0, 0)
1398 ZEND_ARG_INFO(0, stdio_stream)
1399 ZEND_END_ARG_INFO();
1400 static PHP_METHOD(pqconn, trace) {
1401 zval *zstream = NULL;
1402
1403 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r!", &zstream)) {
1404 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1405
1406 if (!obj->intern) {
1407 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1408 } else {
1409 if (!zstream) {
1410 PQuntrace(obj->intern->conn);
1411 RETVAL_TRUE;
1412 } else {
1413 FILE *fp;
1414 php_stream *stream = NULL;
1415
1416 php_stream_from_zval(stream, &zstream);
1417
1418 if (SUCCESS != php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void *) &fp, REPORT_ERRORS)) {
1419 RETVAL_FALSE;
1420 } else {
1421 stream->flags |= PHP_STREAM_FLAG_NO_CLOSE;
1422 PQtrace(obj->intern->conn, fp);
1423 RETVAL_TRUE;
1424 }
1425 }
1426 }
1427 }
1428 }
1429
1430 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_on, 0, 0, 2)
1431 ZEND_ARG_INFO(0, type)
1432 ZEND_ARG_INFO(0, callable)
1433 ZEND_END_ARG_INFO();
1434 static PHP_METHOD(pqconn, on) {
1435 zend_error_handling zeh;
1436 char *type_str;
1437 int type_len;
1438 php_pq_callback_t cb;
1439 STATUS rv;
1440
1441 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1442 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sf", &type_str, &type_len, &cb.fci, &cb.fcc);
1443 zend_restore_error_handling(&zeh TSRMLS_CC);
1444
1445 if (SUCCESS == rv) {
1446 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1447
1448 if (!obj->intern) {
1449 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1450 } else {
1451 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1452
1453 RETVAL_LONG(php_pqconn_add_eventhandler(obj, type_str, type_len, &cb TSRMLS_CC));
1454 }
1455 }
1456 }
1457
1458 static int apply_set_converter(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
1459 {
1460 zval *tmp, **zoid = p, **zcnv = va_arg(argv, zval **);
1461 HashTable *converters = va_arg(argv, HashTable *);
1462
1463 tmp = *zoid;
1464 convert_to_long_ex(&tmp);
1465 Z_ADDREF_PP(zcnv);
1466 zend_hash_index_update(converters, Z_LVAL_P(tmp), zcnv, sizeof(zval *), NULL);
1467 if (tmp != *zoid) {
1468 zval_ptr_dtor(&tmp);
1469 }
1470
1471 return ZEND_HASH_APPLY_KEEP;
1472 }
1473
1474 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_set_converter, 0, 0, 1)
1475 ZEND_ARG_OBJ_INFO(0, converter, pq\\ConverterInterface, 0)
1476 ZEND_END_ARG_INFO();
1477 static PHP_METHOD(pqconn, setConverter) {
1478 STATUS rv;
1479 zend_error_handling zeh;
1480 zval *zcnv;
1481
1482 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1483 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zcnv, php_pqconv_class_entry);
1484 zend_restore_error_handling(&zeh TSRMLS_CC);
1485
1486 if (SUCCESS == rv) {
1487 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1488
1489 if (!obj->intern) {
1490 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
1491 } else {
1492 zval *tmp, *zoids = NULL;
1493
1494 zend_call_method_with_0_params(&zcnv, NULL, NULL, "converttypes", &zoids);
1495 tmp = zoids;
1496 convert_to_array_ex(&zoids);
1497 zend_hash_apply_with_arguments(Z_ARRVAL_P(zoids) TSRMLS_CC, apply_set_converter, 2, &zcnv, &obj->intern->converters);
1498 if (tmp != zoids) {
1499 zval_ptr_dtor(&tmp);
1500 }
1501 zval_ptr_dtor(&zoids);
1502 }
1503 }
1504 }
1505
1506 static zend_function_entry php_pqconn_methods[] = {
1507 PHP_ME(pqconn, __construct, ai_pqconn_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
1508 PHP_ME(pqconn, reset, ai_pqconn_reset, ZEND_ACC_PUBLIC)
1509 PHP_ME(pqconn, resetAsync, ai_pqconn_reset_async, ZEND_ACC_PUBLIC)
1510 PHP_ME(pqconn, poll, ai_pqconn_poll, ZEND_ACC_PUBLIC)
1511 PHP_ME(pqconn, exec, ai_pqconn_exec, ZEND_ACC_PUBLIC)
1512 PHP_ME(pqconn, execAsync, ai_pqconn_exec_async, ZEND_ACC_PUBLIC)
1513 PHP_ME(pqconn, execParams, ai_pqconn_exec_params, ZEND_ACC_PUBLIC)
1514 PHP_ME(pqconn, execParamsAsync, ai_pqconn_exec_params_async, ZEND_ACC_PUBLIC)
1515 PHP_ME(pqconn, prepare, ai_pqconn_prepare, ZEND_ACC_PUBLIC)
1516 PHP_ME(pqconn, prepareAsync, ai_pqconn_prepare_async, ZEND_ACC_PUBLIC)
1517 PHP_ME(pqconn, listen, ai_pqconn_listen, ZEND_ACC_PUBLIC)
1518 PHP_ME(pqconn, listenAsync, ai_pqconn_listen_async, ZEND_ACC_PUBLIC)
1519 PHP_ME(pqconn, notify, ai_pqconn_notify, ZEND_ACC_PUBLIC)
1520 PHP_ME(pqconn, notifyAsync, ai_pqconn_notify_async, ZEND_ACC_PUBLIC)
1521 PHP_ME(pqconn, getResult, ai_pqconn_get_result, ZEND_ACC_PUBLIC)
1522 PHP_ME(pqconn, quote, ai_pqconn_quote, ZEND_ACC_PUBLIC)
1523 PHP_ME(pqconn, quoteName, ai_pqconn_quote_name, ZEND_ACC_PUBLIC)
1524 PHP_ME(pqconn, escapeBytea, ai_pqconn_escape_bytea, ZEND_ACC_PUBLIC)
1525 PHP_ME(pqconn, unescapeBytea, ai_pqconn_unescape_bytea, ZEND_ACC_PUBLIC)
1526 PHP_ME(pqconn, startTransaction, ai_pqconn_start_transaction, ZEND_ACC_PUBLIC)
1527 PHP_ME(pqconn, startTransactionAsync, ai_pqconn_start_transaction_async, ZEND_ACC_PUBLIC)
1528 PHP_ME(pqconn, trace, ai_pqconn_trace, ZEND_ACC_PUBLIC)
1529 PHP_ME(pqconn, on, ai_pqconn_on, ZEND_ACC_PUBLIC)
1530 PHP_ME(pqconn, setConverter, ai_pqconn_set_converter, ZEND_ACC_PUBLIC)
1531 {0}
1532 };
1533
1534 PHP_MSHUTDOWN_FUNCTION(pqconn)
1535 {
1536 zend_hash_destroy(&php_pqconn_object_prophandlers);
1537 return SUCCESS;
1538 }
1539
1540 PHP_MINIT_FUNCTION(pqconn)
1541 {
1542 zend_class_entry ce = {0};
1543 php_pq_object_prophandler_t ph = {0};
1544
1545 INIT_NS_CLASS_ENTRY(ce, "pq", "Connection", php_pqconn_methods);
1546 php_pqconn_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
1547 php_pqconn_class_entry->create_object = php_pqconn_create_object;
1548
1549 memcpy(&php_pqconn_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1550 php_pqconn_object_handlers.read_property = php_pq_object_read_prop;
1551 php_pqconn_object_handlers.write_property = php_pq_object_write_prop;
1552 php_pqconn_object_handlers.clone_obj = NULL;
1553 php_pqconn_object_handlers.get_property_ptr_ptr = NULL;
1554 php_pqconn_object_handlers.get_gc = NULL;
1555 php_pqconn_object_handlers.get_properties = php_pq_object_properties;
1556 php_pqconn_object_handlers.get_debug_info = php_pq_object_debug_info;
1557
1558 zend_hash_init(&php_pqconn_object_prophandlers, 14, NULL, NULL, 1);
1559
1560 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("status"), CONNECTION_BAD, ZEND_ACC_PUBLIC TSRMLS_CC);
1561 ph.read = php_pqconn_object_read_status;
1562 zend_hash_add(&php_pqconn_object_prophandlers, "status", sizeof("status"), (void *) &ph, sizeof(ph), NULL);
1563
1564 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("transactionStatus"), PQTRANS_UNKNOWN, ZEND_ACC_PUBLIC TSRMLS_CC);
1565 ph.read = php_pqconn_object_read_transaction_status;
1566 zend_hash_add(&php_pqconn_object_prophandlers, "transactionStatus", sizeof("transactionStatus"), (void *) &ph, sizeof(ph), NULL);
1567
1568 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("socket"), ZEND_ACC_PUBLIC TSRMLS_CC);
1569 ph.read = NULL; /* forward to std prophandler */
1570 zend_hash_add(&php_pqconn_object_prophandlers, "socket", sizeof("socket"), (void *) &ph, sizeof(ph), NULL);
1571
1572 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC TSRMLS_CC);
1573 ph.read = php_pqconn_object_read_error_message;
1574 zend_hash_add(&php_pqconn_object_prophandlers, "errorMessage", sizeof("errorMessage"), (void *) &ph, sizeof(ph), NULL);
1575
1576 zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("busy"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
1577 ph.read = php_pqconn_object_read_busy;
1578 zend_hash_add(&php_pqconn_object_prophandlers, "busy", sizeof("busy"), (void *) &ph, sizeof(ph), NULL);
1579
1580 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("encoding"), ZEND_ACC_PUBLIC TSRMLS_CC);
1581 ph.read = php_pqconn_object_read_encoding;
1582 ph.write = php_pqconn_object_write_encoding;
1583 zend_hash_add(&php_pqconn_object_prophandlers, "encoding", sizeof("encoding"), (void *) &ph, sizeof(ph), NULL);
1584 ph.write = NULL;
1585
1586 zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("unbuffered"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
1587 ph.read = php_pqconn_object_read_unbuffered;
1588 ph.write = php_pqconn_object_write_unbuffered;
1589 zend_hash_add(&php_pqconn_object_prophandlers, "unbuffered", sizeof("unbuffered"), (void *) &ph, sizeof(ph), NULL);
1590 ph.write = NULL;
1591
1592 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("db"), ZEND_ACC_PUBLIC TSRMLS_CC);
1593 ph.read = php_pqconn_object_read_db;
1594 zend_hash_add(&php_pqconn_object_prophandlers, "db", sizeof("db"), (void *) &ph, sizeof(ph), NULL);
1595
1596 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("user"), ZEND_ACC_PUBLIC TSRMLS_CC);
1597 ph.read = php_pqconn_object_read_user;
1598 zend_hash_add(&php_pqconn_object_prophandlers, "user", sizeof("user"), (void *) &ph, sizeof(ph), NULL);
1599
1600 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("pass"), ZEND_ACC_PUBLIC TSRMLS_CC);
1601 ph.read = php_pqconn_object_read_pass;
1602 zend_hash_add(&php_pqconn_object_prophandlers, "pass", sizeof("pass"), (void *) &ph, sizeof(ph), NULL);
1603
1604 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("host"), ZEND_ACC_PUBLIC TSRMLS_CC);
1605 ph.read = php_pqconn_object_read_host;
1606 zend_hash_add(&php_pqconn_object_prophandlers, "host", sizeof("host"), (void *) &ph, sizeof(ph), NULL);
1607
1608 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("port"), ZEND_ACC_PUBLIC TSRMLS_CC);
1609 ph.read = php_pqconn_object_read_port;
1610 zend_hash_add(&php_pqconn_object_prophandlers, "port", sizeof("port"), (void *) &ph, sizeof(ph), NULL);
1611
1612 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("options"), ZEND_ACC_PUBLIC TSRMLS_CC);
1613 ph.read = php_pqconn_object_read_options;
1614 zend_hash_add(&php_pqconn_object_prophandlers, "options", sizeof("options"), (void *) &ph, sizeof(ph), NULL);
1615
1616 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("eventHandlers"), ZEND_ACC_PUBLIC TSRMLS_CC);
1617 ph.read = php_pqconn_object_read_event_handlers;
1618 zend_hash_add(&php_pqconn_object_prophandlers, "eventHandlers", sizeof("eventHandlers"), (void *) &ph, sizeof(ph), NULL);
1619
1620 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("OK"), CONNECTION_OK TSRMLS_CC);
1621 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("BAD"), CONNECTION_BAD TSRMLS_CC);
1622 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("STARTED"), CONNECTION_STARTED TSRMLS_CC);
1623 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("MADE"), CONNECTION_MADE TSRMLS_CC);
1624 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("AWAITING_RESPONSE"), CONNECTION_AWAITING_RESPONSE TSRMLS_CC);
1625 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("AUTH_OK"), CONNECTION_AUTH_OK TSRMLS_CC);
1626 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("SSL_STARTUP"), CONNECTION_SSL_STARTUP TSRMLS_CC);
1627 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("SETENV"), CONNECTION_SETENV TSRMLS_CC);
1628
1629 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_IDLE"), PQTRANS_IDLE TSRMLS_CC);
1630 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_ACTIVE"), PQTRANS_ACTIVE TSRMLS_CC);
1631 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_INTRANS"), PQTRANS_INTRANS TSRMLS_CC);
1632 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_INERROR"), PQTRANS_INERROR TSRMLS_CC);
1633 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_UNKNOWN"), PQTRANS_UNKNOWN TSRMLS_CC);
1634
1635 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_FAILED"), PGRES_POLLING_FAILED TSRMLS_CC);
1636 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_READING"), PGRES_POLLING_READING TSRMLS_CC);
1637 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_WRITING"), PGRES_POLLING_WRITING TSRMLS_CC);
1638 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_OK"), PGRES_POLLING_OK TSRMLS_CC);
1639
1640 zend_declare_class_constant_stringl(php_pqconn_class_entry, ZEND_STRL("EVENT_NOTICE"), ZEND_STRL("notice") TSRMLS_CC);
1641 zend_declare_class_constant_stringl(php_pqconn_class_entry, ZEND_STRL("EVENT_RESULT"), ZEND_STRL("result") TSRMLS_CC);
1642 zend_declare_class_constant_stringl(php_pqconn_class_entry, ZEND_STRL("EVENT_RESET"), ZEND_STRL("reset") TSRMLS_CC);
1643
1644 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("ASYNC"), 0x1 TSRMLS_CC);
1645 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("PERSISTENT"), 0x2 TSRMLS_CC);
1646
1647 return SUCCESS;
1648 }
1649
1650 /*
1651 * Local variables:
1652 * tab-width: 4
1653 * c-basic-offset: 4
1654 * End:
1655 * vim600: noet sw=4 ts=4 fdm=marker
1656 * vim<600: noet sw=4 ts=4
1657 */