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