fix arginfo params
[m6w6/ext-pq] / src / php_pq.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: pq |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2013, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
16
17 #include <php.h>
18 #include <Zend/zend_interfaces.h>
19 #include <ext/standard/info.h>
20 #include <ext/spl/spl_array.h>
21
22 #include <libpq-events.h>
23
24 #include "php_pq.h"
25
26 typedef int STATUS; /* SUCCESS/FAILURE */
27
28 /*
29 ZEND_DECLARE_MODULE_GLOBALS(pq)
30 */
31
32 const zend_function_entry pq_functions[] = {
33 {0}
34 };
35
36 /* {{{ pq_module_entry
37 */
38 zend_module_entry pq_module_entry = {
39 STANDARD_MODULE_HEADER,
40 "pq",
41 pq_functions,
42 PHP_MINIT(pq),
43 PHP_MSHUTDOWN(pq),
44 NULL,/*PHP_RINIT(pq),*/
45 NULL,/*PHP_RSHUTDOWN(pq),*/
46 PHP_MINFO(pq),
47 PHP_PQ_EXT_VERSION,
48 STANDARD_MODULE_PROPERTIES
49 };
50 /* }}} */
51
52 #ifdef COMPILE_DL_PQ
53 ZEND_GET_MODULE(pq)
54 #endif
55
56 /* {{{ PHP_INI
57 */
58 /* Remove comments and fill if you need to have entries in php.ini
59 PHP_INI_BEGIN()
60 STD_PHP_INI_ENTRY("pq.global_value", "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_pq_globals, pq_globals)
61 STD_PHP_INI_ENTRY("pq.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_pq_globals, pq_globals)
62 PHP_INI_END()
63 */
64 /* }}} */
65
66 /* {{{ php_pq_init_globals
67 */
68 /* Uncomment this function if you have INI entries
69 static void php_pq_init_globals(zend_pq_globals *pq_globals)
70 {
71 pq_globals->global_value = 0;
72 pq_globals->global_string = NULL;
73 }
74 */
75 /* }}} */
76
77 static zend_class_entry *php_pqconn_class_entry;
78 static zend_class_entry *php_pqres_class_entry;
79 static zend_class_entry *php_pqstm_class_entry;
80
81 static zend_object_handlers php_pqconn_object_handlers;
82 static zend_object_handlers php_pqres_object_handlers;
83 static zend_object_handlers php_pqstm_object_handlers;
84
85 typedef struct php_pq_callback {
86 zend_fcall_info fci;
87 zend_fcall_info_cache fcc;
88 void *data;
89 } php_pq_callback_t;
90
91 typedef struct php_pqbase_object {
92 zend_object zo;
93 void *intern;
94 HashTable *prophandler;
95 } php_pqbase_object_t;
96
97 typedef struct php_pqconn_object {
98 zend_object zo;
99 PGconn *conn;
100 HashTable *prophandler;
101
102 int (*poller)(PGconn *);
103 HashTable listeners;
104 php_pq_callback_t onevent;
105 unsigned async:1;
106 } php_pqconn_object_t;
107
108 typedef struct php_pqconn_event_data {
109 php_pqconn_object_t *obj;
110 #ifdef ZTS
111 void ***ts;
112 #endif
113 } php_pqconn_event_data_t;
114
115 typedef enum php_pqres_fetch {
116 PHP_PQRES_FETCH_ARRAY,
117 PHP_PQRES_FETCH_ASSOC,
118 PHP_PQRES_FETCH_OBJECT
119 } php_pqres_fetch_t;
120
121 typedef struct php_pqres_iterator {
122 zend_object_iterator zi;
123 zval *current_val;
124 unsigned index;
125 php_pqres_fetch_t fetch_type;
126 } php_pqres_iterator_t;
127
128 typedef struct php_pqres_object {
129 zend_object zo;
130 PGresult *res;
131 HashTable *prophandler;
132
133 php_pqres_iterator_t *iter;
134 } php_pqres_object_t;
135
136 typedef struct php_pqstm_object {
137 zend_object zo;
138 char *name;
139 HashTable *prophandler;
140
141 zval *conn;
142 } php_pqstm_object_t;
143
144 static HashTable php_pqconn_object_prophandlers;
145 static HashTable php_pqres_object_prophandlers;
146 static HashTable php_pqstm_object_prophandlers;
147
148 typedef void (*php_pq_object_prophandler_func_t)(zval *object, void *o, zval *return_value TSRMLS_DC);
149
150 typedef struct php_pq_object_prophandler {
151 php_pq_object_prophandler_func_t read;
152 php_pq_object_prophandler_func_t write;
153 } php_pq_object_prophandler_t;
154
155 static zend_object_iterator_funcs php_pqres_iterator_funcs;
156
157 static zend_object_iterator *php_pqres_iterator_init(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
158 {
159 php_pqres_iterator_t *iter;
160 zval *prop, *zfetch_type;
161
162 iter = ecalloc(1, sizeof(*iter));
163 iter->zi.funcs = &php_pqres_iterator_funcs;
164 iter->zi.data = object;
165 Z_ADDREF_P(object);
166
167 zfetch_type = prop = zend_read_property(ce, object, ZEND_STRL("fetchType"), 0 TSRMLS_CC);
168 if (Z_TYPE_P(zfetch_type) != IS_LONG) {
169 convert_to_long_ex(&zfetch_type);
170 }
171 iter->fetch_type = Z_LVAL_P(zfetch_type);
172 if (zfetch_type != prop) {
173 zval_ptr_dtor(&zfetch_type);
174 }
175 if (Z_REFCOUNT_P(prop)) {
176 zval_ptr_dtor(&prop);
177 } else {
178 zval_dtor(prop);
179 FREE_ZVAL(prop);
180 }
181
182 return (zend_object_iterator *) iter;
183 }
184
185 static void php_pqres_iterator_dtor(zend_object_iterator *i TSRMLS_DC)
186 {
187 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
188
189 if (iter->current_val) {
190 zval_ptr_dtor(&iter->current_val);
191 iter->current_val = NULL;
192 }
193 zval_ptr_dtor((zval **) &iter->zi.data);
194 efree(iter);
195 }
196
197 static STATUS php_pqres_iterator_valid(zend_object_iterator *i TSRMLS_DC)
198 {
199 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
200 php_pqres_object_t *obj = zend_object_store_get_object(iter->zi.data TSRMLS_CC);
201
202 if (PQresultStatus(obj->res) != PGRES_TUPLES_OK) {
203 return FAILURE;
204 }
205 if (PQntuples(obj->res) <= iter->index) {
206 return FAILURE;
207 }
208
209 return SUCCESS;
210 }
211
212 static zval *php_pqres_row_to_zval(PGresult *res, unsigned row, php_pqres_fetch_t fetch_type TSRMLS_DC)
213 {
214 zval *data;
215 int c, cols;
216
217 MAKE_STD_ZVAL(data);
218 if (PHP_PQRES_FETCH_OBJECT == fetch_type) {
219 object_init(data);
220 } else {
221 array_init(data);
222 }
223
224 for (c = 0, cols = PQnfields(res); c < cols; ++c) {
225 if (PQgetisnull(res, row, c)) {
226 switch (fetch_type) {
227 case PHP_PQRES_FETCH_OBJECT:
228 add_property_null(data, PQfname(res, c));
229 break;
230
231 case PHP_PQRES_FETCH_ASSOC:
232 add_assoc_null(data, PQfname(res, c));
233 break;
234
235 case PHP_PQRES_FETCH_ARRAY:
236 add_index_null(data, c);
237 break;
238 }
239 } else {
240 char *val = PQgetvalue(res, row, c);
241 int len = PQgetlength(res, row, c);
242
243 switch (fetch_type) {
244 case PHP_PQRES_FETCH_OBJECT:
245 add_property_stringl(data, PQfname(res, c), val, len, 1);
246 break;
247
248 case PHP_PQRES_FETCH_ASSOC:
249 add_assoc_stringl(data, PQfname(res, c), val, len, 1);
250 break;
251
252 case PHP_PQRES_FETCH_ARRAY:
253 add_index_stringl(data, c, val, len ,1);
254 break;
255 }
256 }
257 }
258
259 return data;
260 }
261
262 static void php_pqres_iterator_current(zend_object_iterator *i, zval ***data_ptr TSRMLS_DC)
263 {
264 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
265 php_pqres_object_t *obj = zend_object_store_get_object(iter->zi.data TSRMLS_CC);
266
267 if (iter->current_val) {
268 zval_ptr_dtor(&iter->current_val);
269 }
270 iter->current_val = php_pqres_row_to_zval(obj->res, iter->index, iter->fetch_type TSRMLS_CC);
271 *data_ptr = &iter->current_val;
272 }
273
274 static int php_pqres_iterator_key(zend_object_iterator *i, char **key_str, uint *key_len, ulong *key_num TSRMLS_DC)
275 {
276 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
277
278 *key_num = (ulong) iter->index;
279
280 return HASH_KEY_IS_LONG;
281 }
282
283 static void php_pqres_iterator_next(zend_object_iterator *i TSRMLS_DC)
284 {
285 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
286
287 ++iter->index;
288 }
289
290 static void php_pqres_iterator_rewind(zend_object_iterator *i TSRMLS_DC)
291 {
292 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
293
294 iter->index = 0;
295 }
296
297 static zend_object_iterator_funcs php_pqres_iterator_funcs = {
298 php_pqres_iterator_dtor,
299 /* check for end of iteration (FAILURE or SUCCESS if data is valid) */
300 php_pqres_iterator_valid,
301 /* fetch the item data for the current element */
302 php_pqres_iterator_current,
303 /* fetch the key for the current element (return HASH_KEY_IS_STRING or HASH_KEY_IS_LONG) (optional, may be NULL) */
304 php_pqres_iterator_key,
305 /* step forwards to next element */
306 php_pqres_iterator_next,
307 /* rewind to start of data (optional, may be NULL) */
308 php_pqres_iterator_rewind,
309 /* invalidate current value/key (optional, may be NULL) */
310 NULL
311 };
312
313 static void php_pq_callback_dtor(php_pq_callback_t *cb) {
314 if (cb->fci.size > 0) {
315 zend_fcall_info_args_clear(&cb->fci, 1);
316 zval_ptr_dtor(&cb->fci.function_name);
317 if (cb->fci.object_ptr) {
318 zval_ptr_dtor(&cb->fci.object_ptr);
319 }
320 }
321 cb->fci.size = 0;
322 }
323
324 static void php_pq_callback_addref(php_pq_callback_t *cb)
325 {
326 Z_ADDREF_P(cb->fci.function_name);
327 if (cb->fci.object_ptr) {
328 Z_ADDREF_P(cb->fci.object_ptr);
329 }
330 }
331
332 static void php_pqconn_object_free(void *o TSRMLS_DC)
333 {
334 php_pqconn_object_t *obj = o;
335
336 if (obj->conn) {
337 PQfinish(obj->conn);
338 obj->conn = NULL;
339 }
340 if (obj->onevent.fci.size > 0) {
341 php_pq_callback_dtor(&obj->onevent);
342 }
343 zend_hash_destroy(&obj->listeners);
344 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
345 efree(obj);
346 }
347
348 static int php_pqconn_event(PGEventId id, void *e, void *data);
349
350 static void php_pqres_object_free(void *o TSRMLS_DC)
351 {
352 php_pqres_object_t *obj = o;
353
354 if (obj->res) {
355 zval *res = PQresultInstanceData(obj->res, php_pqconn_event);
356 if (res) {
357 PQresultSetInstanceData(obj->res, php_pqconn_event, NULL);
358 zval_ptr_dtor(&res);
359 } else {
360 PQclear(obj->res);
361 obj->res = NULL;
362 }
363 }
364 if (obj->iter) {
365 php_pqres_iterator_dtor((zend_object_iterator *) obj->iter TSRMLS_CC);
366 obj->iter = NULL;
367 }
368 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
369 efree(obj);
370 }
371
372 static void php_pqstm_object_free(void *o TSRMLS_DC)
373 {
374 php_pqstm_object_t *obj = o;
375
376 if (obj->name) {
377 efree(obj->name);
378 obj->name = NULL;
379 }
380 if (obj->conn) {
381 zval_ptr_dtor(&obj->conn);
382 obj->conn = NULL;
383 }
384 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
385 efree(obj);
386 }
387
388 static zend_object_value php_pqconn_create_object_ex(zend_class_entry *ce, PGconn *conn, php_pqconn_object_t **ptr TSRMLS_DC)
389 {
390 zend_object_value ov;
391 php_pqconn_object_t *o;
392
393 o = ecalloc(1, sizeof(*o));
394 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
395 object_properties_init((zend_object *) o, ce);
396 o->prophandler = &php_pqconn_object_prophandlers;
397
398 if (ptr) {
399 *ptr = o;
400 }
401
402 if (conn) {
403 o->conn = conn;
404 o->async = !PQisnonblocking(o->conn);
405 }
406
407 zend_hash_init(&o->listeners, 0, NULL, (dtor_func_t) zend_hash_destroy, 0);
408
409 ov.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqconn_object_free, NULL TSRMLS_CC);
410 ov.handlers = &php_pqconn_object_handlers;
411
412 return ov;
413 }
414
415 static zend_object_value php_pqres_create_object_ex(zend_class_entry *ce, PGresult *res, php_pqres_object_t **ptr TSRMLS_DC)
416 {
417 zend_object_value ov;
418 php_pqres_object_t *o;
419
420 o = ecalloc(1, sizeof(*o));
421 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
422 object_properties_init((zend_object *) o, ce);
423 o->prophandler = &php_pqres_object_prophandlers;
424
425 if (ptr) {
426 *ptr = o;
427 }
428
429 if (res) {
430 o->res = res;
431 }
432
433 ov.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqres_object_free, NULL TSRMLS_CC);
434 ov.handlers = &php_pqres_object_handlers;
435
436 return ov;
437 }
438
439 static zend_object_value php_pqstm_create_object_ex(zend_class_entry *ce, zval *conn, const char *name, php_pqstm_object_t **ptr TSRMLS_DC)
440 {
441 zend_object_value ov;
442 php_pqstm_object_t *o;
443
444 o = ecalloc(1, sizeof(*o));
445 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
446 object_properties_init((zend_object *) o, ce);
447 o->prophandler = &php_pqstm_object_prophandlers;
448
449 if (ptr) {
450 *ptr = o;
451 }
452
453 if (conn) {
454 Z_ADDREF_P(conn);
455 o->conn = conn;
456 }
457
458 if (name) {
459 o->name = estrdup(name);
460 }
461
462 ov.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqstm_object_free, NULL TSRMLS_CC);
463 ov.handlers = &php_pqstm_object_handlers;
464
465 return ov;
466 }
467
468 static zend_object_value php_pqconn_create_object(zend_class_entry *class_type TSRMLS_DC)
469 {
470 return php_pqconn_create_object_ex(class_type, NULL, NULL TSRMLS_CC);
471 }
472
473 static zend_object_value php_pqres_create_object(zend_class_entry *class_type TSRMLS_DC)
474 {
475 return php_pqres_create_object_ex(class_type, NULL, NULL TSRMLS_CC);
476 }
477
478 static zend_object_value php_pqstm_create_object(zend_class_entry *class_type TSRMLS_DC)
479 {
480 return php_pqstm_create_object_ex(class_type, NULL, NULL, NULL TSRMLS_CC);
481 }
482
483 static int apply_ph_to_debug(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
484 {
485 php_pq_object_prophandler_t *ph = p;
486 HashTable *ht = va_arg(argv, HashTable *);
487 zval **return_value, *object = va_arg(argv, zval *);
488 php_pqbase_object_t *obj = va_arg(argv, php_pqbase_object_t *);
489
490 if (SUCCESS == zend_hash_find(ht, key->arKey, key->nKeyLength, (void *) &return_value)) {
491 if (ph->read) {
492 MAKE_STD_ZVAL(*return_value);
493 ZVAL_NULL(*return_value);
494
495 ph->read(object, obj, *return_value TSRMLS_CC);
496 } else {
497 zval member;
498
499 INIT_PZVAL(&member);
500 ZVAL_STRINGL(&member, key->arKey, key->nKeyLength-1, 0);
501 *return_value = zend_get_std_object_handlers()->read_property(object, &member, BP_VAR_R, NULL TSRMLS_CC);
502 Z_ADDREF_PP(return_value);
503 }
504 }
505
506 return ZEND_HASH_APPLY_KEEP;
507 }
508
509 static int apply_pi_to_debug(void *p, void *arg TSRMLS_DC)
510 {
511 zend_property_info *pi = p;
512 HashTable *ht = arg;
513
514 zend_hash_add_empty_element(ht, pi->name, pi->name_length + 1);
515
516 return ZEND_HASH_APPLY_KEEP;
517 }
518
519 static HashTable *php_pq_object_debug_info(zval *object, int *temp TSRMLS_DC)
520 {
521 HashTable *ht;
522 php_pqbase_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
523
524 *temp = 1;
525 ALLOC_HASHTABLE(ht);
526 ZEND_INIT_SYMTABLE(ht);
527
528 zend_hash_apply_with_argument(&obj->zo.ce->properties_info, apply_pi_to_debug, ht TSRMLS_CC);
529 zend_hash_apply_with_arguments(obj->prophandler TSRMLS_CC, apply_ph_to_debug, 3, ht, object, obj);
530
531 return ht;
532 }
533 static void php_pqconn_object_read_status(zval *object, void *o, zval *return_value TSRMLS_DC)
534 {
535 php_pqconn_object_t *obj = o;
536
537 RETVAL_LONG(PQstatus(obj->conn));
538 }
539
540 static void php_pqconn_object_read_transaction_status(zval *object, void *o, zval *return_value TSRMLS_DC)
541 {
542 php_pqconn_object_t *obj = o;
543
544 RETVAL_LONG(PQtransactionStatus(obj->conn));
545 }
546
547 static void php_pqconn_object_read_error_message(zval *object, void *o, zval *return_value TSRMLS_DC)
548 {
549 php_pqconn_object_t *obj = o;
550 char *error = PQerrorMessage(obj->conn);
551
552 if (error) {
553 RETVAL_STRING(error, 1);
554 } else {
555 RETVAL_NULL();
556 }
557 }
558
559 static int apply_notify_listener(void *p, void *arg TSRMLS_DC)
560 {
561 php_pq_callback_t *listener = p;
562 PGnotify *nfy = arg;
563 zval *zpid, *zchannel, *zmessage;
564
565 MAKE_STD_ZVAL(zpid);
566 ZVAL_LONG(zpid, nfy->be_pid);
567 MAKE_STD_ZVAL(zchannel);
568 ZVAL_STRING(zchannel, nfy->relname, 1);
569 MAKE_STD_ZVAL(zmessage);
570 ZVAL_STRING(zmessage, nfy->extra, 1);
571
572 zend_fcall_info_argn(&listener->fci TSRMLS_CC, 3, &zchannel, &zmessage, &zpid);
573 zend_fcall_info_call(&listener->fci, &listener->fcc, NULL, NULL TSRMLS_CC);
574
575 zval_ptr_dtor(&zchannel);
576 zval_ptr_dtor(&zmessage);
577 zval_ptr_dtor(&zpid);
578
579 return ZEND_HASH_APPLY_KEEP;
580 }
581
582 static int apply_notify_listeners(void *p, void *arg TSRMLS_DC)
583 {
584 HashTable *listeners = p;
585
586 zend_hash_apply_with_argument(listeners, apply_notify_listener, arg TSRMLS_CC);
587
588 return ZEND_HASH_APPLY_KEEP;
589 }
590
591 static void php_pqconn_notify_listeners(zval *this_ptr, php_pqconn_object_t *obj TSRMLS_DC)
592 {
593 PGnotify *nfy;
594
595 if (!obj) {
596 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
597 }
598
599 while ((nfy = PQnotifies(obj->conn))) {
600 zend_hash_apply_with_argument(&obj->listeners, apply_notify_listeners, nfy TSRMLS_CC);
601 PQfreemem(nfy);
602 }
603 }
604
605 /* FIXME: extend to types->nspname->typname */
606 #define PHP_PQ_TYPES_QUERY \
607 "select t.oid, t.* " \
608 "from pg_type t join pg_namespace n on t.typnamespace=n.oid " \
609 "where typisdefined " \
610 "and typrelid=0 " \
611 "and nspname in ('public', 'pg_catalog')"
612 static void php_pqconn_object_read_types(zval *object, void *o, zval *return_value TSRMLS_DC)
613 {
614 php_pqconn_object_t *obj = o;
615 PGresult *res = PQexec(obj->conn, PHP_PQ_TYPES_QUERY);
616
617 php_pqconn_notify_listeners(object, obj TSRMLS_CC);
618
619 /* FIXME: cache that */
620 if (res) {
621 if (PGRES_TUPLES_OK == PQresultStatus(res)) {
622 int r, rows;
623 zval *byoid, *byname;
624
625 MAKE_STD_ZVAL(byoid);
626 MAKE_STD_ZVAL(byname);
627 object_init(byoid);
628 object_init(byname);
629 object_init(return_value);
630 for (r = 0, rows = PQntuples(res); r < rows; ++r) {
631 zval *row = php_pqres_row_to_zval(res, r, PHP_PQRES_FETCH_OBJECT TSRMLS_CC);
632
633 add_property_zval(byoid, PQgetvalue(res, r, 0), row);
634 add_property_zval(byname, PQgetvalue(res, r, 1), row);
635 zval_ptr_dtor(&row);
636 }
637
638 add_property_zval(return_value, "byOid", byoid);
639 add_property_zval(return_value, "byName", byname);
640 zval_ptr_dtor(&byoid);
641 zval_ptr_dtor(&byname);
642 } else {
643 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not fetch types: %s", PQresultErrorMessage(res));
644 }
645 PQclear(res);
646 } else {
647 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not fetch types: %s", PQerrorMessage(obj->conn));
648 }
649 }
650
651 static void php_pqconn_object_read_busy(zval *object, void *o, zval *return_value TSRMLS_DC)
652 {
653 php_pqconn_object_t *obj = o;
654
655 RETVAL_BOOL(PQisBusy(obj->conn));
656 }
657
658 static void php_pqres_object_read_status(zval *object, void *o, zval *return_value TSRMLS_DC)
659 {
660 php_pqres_object_t *obj = o;
661
662 RETVAL_LONG(PQresultStatus(obj->res));
663 }
664
665 static void php_pqres_object_read_error_message(zval *object, void *o, zval *return_value TSRMLS_DC)
666 {
667 php_pqres_object_t *obj = o;
668 char *error = PQresultErrorMessage(obj->res);
669
670 if (error) {
671 RETVAL_STRING(error, 1);
672 } else {
673 RETVAL_NULL();
674 }
675 }
676
677 static void php_pqres_object_read_num_rows(zval *object, void *o, zval *return_value TSRMLS_DC)
678 {
679 php_pqres_object_t *obj = o;
680
681 RETVAL_LONG(PQntuples(obj->res));
682 }
683
684 static void php_pqres_object_read_num_cols(zval *object, void *o, zval *return_value TSRMLS_DC)
685 {
686 php_pqres_object_t *obj = o;
687
688 RETVAL_LONG(PQnfields(obj->res));
689 }
690
691 static void php_pqres_object_read_affected_rows(zval *object, void *o, zval *return_value TSRMLS_DC)
692 {
693 php_pqres_object_t *obj = o;
694
695 RETVAL_LONG(atoi(PQcmdTuples(obj->res)));
696 }
697
698 static void php_pqres_object_read_fetch_type(zval *object, void *o, zval *return_value TSRMLS_DC)
699 {
700 php_pqres_object_t *obj = o;
701
702 if (obj->iter) {
703 RETVAL_LONG(obj->iter->fetch_type);
704 } else {
705 RETVAL_LONG(PHP_PQRES_FETCH_ARRAY);
706 }
707 }
708
709 static void php_pqres_object_write_fetch_type(zval *object, void *o, zval *value TSRMLS_DC)
710 {
711 php_pqres_object_t *obj = o;
712 zval *zfetch_type = value;
713
714 if (Z_TYPE_P(zfetch_type) != IS_LONG) {
715 convert_to_long_ex(&zfetch_type);
716 }
717
718 obj->iter->fetch_type = Z_LVAL_P(zfetch_type);
719
720 if (zfetch_type != value) {
721 zval_ptr_dtor(&zfetch_type);
722 }
723 }
724
725 static void php_pqstm_object_read_name(zval *object, void *o, zval *return_value TSRMLS_DC)
726 {
727 php_pqstm_object_t *obj = o;
728
729 RETVAL_STRING(obj->name, 1);
730 }
731
732 static void php_pqstm_object_read_connection(zval *object, void *o, zval *return_value TSRMLS_DC)
733 {
734 php_pqstm_object_t *obj = o;
735
736 RETVAL_ZVAL(obj->conn, 1, 0);
737 }
738
739 static zval *php_pqconn_object_read_prop(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
740 {
741 php_pqconn_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
742 php_pq_object_prophandler_t *handler;
743 zval *return_value;
744
745 if (!obj->conn) {
746 zend_error(E_WARNING, "Connection not initialized");
747 } else if ((SUCCESS == zend_hash_find(&php_pqconn_object_prophandlers, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void *) &handler)) && handler->read) {
748 if (type == BP_VAR_R) {
749 ALLOC_ZVAL(return_value);
750 Z_SET_REFCOUNT_P(return_value, 0);
751 Z_UNSET_ISREF_P(return_value);
752
753 handler->read(object, obj, return_value TSRMLS_CC);
754 } else {
755 zend_error(E_ERROR, "Cannot access pq\\Connection properties by reference or array key/index");
756 return_value = NULL;
757 }
758 } else {
759 return_value = zend_get_std_object_handlers()->read_property(object, member, type, key TSRMLS_CC);
760 }
761
762 return return_value;
763 }
764
765 static void php_pqconn_object_write_prop(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
766 {
767 php_pqconn_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
768 php_pq_object_prophandler_t *handler;
769
770 if (SUCCESS == zend_hash_find(&php_pqconn_object_prophandlers, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void *) &handler)) {
771 if (handler->write) {
772 handler->write(object, obj, value TSRMLS_CC);
773 }
774 } else {
775 zend_get_std_object_handlers()->write_property(object, member, value, key TSRMLS_CC);
776 }
777 }
778
779 static zval *php_pqres_object_read_prop(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
780 {
781 php_pqres_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
782 php_pq_object_prophandler_t *handler;
783 zval *return_value;
784
785 if (!obj->res) {
786 zend_error(E_WARNING, "Result not initialized");
787 } else if (SUCCESS == zend_hash_find(&php_pqres_object_prophandlers, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void *) &handler)) {
788 if (type == BP_VAR_R) {
789 ALLOC_ZVAL(return_value);
790 Z_SET_REFCOUNT_P(return_value, 0);
791 Z_UNSET_ISREF_P(return_value);
792
793 handler->read(object, obj, return_value TSRMLS_CC);
794 } else {
795 zend_error(E_ERROR, "Cannot access pq\\Result properties by reference or array key/index");
796 return_value = NULL;
797 }
798 } else {
799 return_value = zend_get_std_object_handlers()->read_property(object, member, type, key TSRMLS_CC);
800 }
801
802 return return_value;
803 }
804
805 static void php_pqres_object_write_prop(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
806 {
807 php_pqres_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
808 php_pq_object_prophandler_t *handler;
809
810 if (!obj->res) {
811 zend_error(E_WARNING, "Result not initialized");
812 } else if (SUCCESS == zend_hash_find(&php_pqres_object_prophandlers, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void *) &handler)) {
813 if (handler->write) {
814 /* ensure obj->iter is initialized, for e.g. write_fetch_type */
815 if (!obj->iter) {
816 obj->iter = (php_pqres_iterator_t *) php_pqres_iterator_init(Z_OBJCE_P(object), object, 0 TSRMLS_CC);
817 obj->iter->zi.funcs->rewind((zend_object_iterator *) obj->iter TSRMLS_CC);
818 }
819 handler->write(object, obj, value TSRMLS_CC);
820 }
821 } else {
822 zend_get_std_object_handlers()->write_property(object, member, value, key TSRMLS_CC);
823 }
824 }
825
826 static zval *php_pqstm_object_read_prop(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
827 {
828 php_pqstm_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
829 php_pq_object_prophandler_t *handler;
830 zval *return_value;
831
832 if (!obj->conn) {
833 zend_error(E_WARNING, "Statement not initialized");
834 } else if (SUCCESS == zend_hash_find(&php_pqstm_object_prophandlers, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void *) &handler)) {
835 if (type == BP_VAR_R) {
836 ALLOC_ZVAL(return_value);
837 Z_SET_REFCOUNT_P(return_value, 0);
838 Z_UNSET_ISREF_P(return_value);
839
840 handler->read(object, obj, return_value TSRMLS_CC);
841 } else {
842 zend_error(E_ERROR, "Cannot access pq\\Statement properties by reference or array key/index");
843 return_value = NULL;
844 }
845 } else {
846 return_value = zend_get_std_object_handlers()->read_property(object, member, type, key TSRMLS_CC);
847 }
848
849 return return_value;
850 }
851
852 static void php_pqstm_object_write_prop(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
853 {
854 php_pqstm_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
855 php_pq_object_prophandler_t *handler;
856
857 if (!obj->conn) {
858 zend_error(E_WARNING, "Result not initialized");
859 } else if (SUCCESS == zend_hash_find(&php_pqstm_object_prophandlers, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void *) &handler)) {
860 if (handler->write) {
861 handler->write(object, obj, value TSRMLS_CC);
862 }
863 } else {
864 zend_get_std_object_handlers()->write_property(object, member, value, key TSRMLS_CC);
865 }
866 }
867
868 static STATUS php_pqconn_update_socket(zval *this_ptr, php_pqconn_object_t *obj TSRMLS_DC)
869 {
870 zval *zsocket, zmember;
871 php_stream *stream;
872 STATUS retval;
873 int socket;
874
875 if (!obj) {
876 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
877 }
878
879 INIT_PZVAL(&zmember);
880 ZVAL_STRINGL(&zmember, "socket", sizeof("socket")-1, 0);
881 MAKE_STD_ZVAL(zsocket);
882
883 if ((CONNECTION_BAD != PQstatus(obj->conn))
884 && (-1 < (socket = PQsocket(obj->conn)))
885 && (stream = php_stream_fopen_from_fd(socket, "r+b", NULL))) {
886 php_stream_to_zval(stream, zsocket);
887 retval = SUCCESS;
888 } else {
889 ZVAL_NULL(zsocket);
890 retval = FAILURE;
891 }
892 zend_get_std_object_handlers()->write_property(getThis(), &zmember, zsocket, NULL TSRMLS_CC);
893 zval_ptr_dtor(&zsocket);
894
895 return retval;
896 }
897
898 #ifdef ZTS
899 # define TSRMLS_DF(d) TSRMLS_D = (d)->ts
900 # define TSRMLS_CF(d) (d)->ts = TSRMLS_C
901 #else
902 # define TSRMLS_DF(d)
903 # define TSRMLS_CF(d)
904 #endif
905
906 static void php_pqconn_event_register(PGEventRegister *event, php_pqconn_event_data_t *data)
907 {
908 PQsetInstanceData(event->conn, php_pqconn_event, data);
909 }
910 static void php_pqconn_event_conndestroy(PGEventConnDestroy *event, php_pqconn_event_data_t *data)
911 {
912 PQsetInstanceData(event->conn, php_pqconn_event, NULL);
913 efree(data);
914 }
915 static void php_pqconn_event_resultcreate(PGEventResultCreate *event, php_pqconn_event_data_t *data)
916 {
917 TSRMLS_DF(data);
918
919 if (data->obj->onevent.fci.size > 0) {
920 zval *res;
921
922 MAKE_STD_ZVAL(res);
923 res->type = IS_OBJECT;
924 res->value.obj = php_pqres_create_object_ex(php_pqres_class_entry, event->result, NULL TSRMLS_CC);
925
926 Z_ADDREF_P(res);
927 PQresultSetInstanceData(event->result, php_pqconn_event, res);
928
929 zend_fcall_info_argn(&data->obj->onevent.fci TSRMLS_CC, 1, &res);
930 zend_fcall_info_call(&data->obj->onevent.fci, &data->obj->onevent.fcc, NULL, NULL TSRMLS_CC);
931 zval_ptr_dtor(&res);
932 }
933 }
934
935 static int php_pqconn_event(PGEventId id, void *e, void *data)
936 {
937 switch (id) {
938 case PGEVT_REGISTER:
939 php_pqconn_event_register(e, data);
940 break;
941 case PGEVT_CONNDESTROY:
942 php_pqconn_event_conndestroy(e, data);
943 break;
944 case PGEVT_RESULTCREATE:
945 php_pqconn_event_resultcreate(e, data);
946 break;
947 default:
948 break;
949 }
950
951 return 1;
952 }
953
954 static php_pqconn_event_data_t *php_pqconn_event_data_init(php_pqconn_object_t *obj TSRMLS_DC)
955 {
956 php_pqconn_event_data_t *data = emalloc(sizeof(*data));
957
958 data->obj = obj;
959 TSRMLS_CF(data);
960
961 return data;
962 }
963
964 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_construct, 0, 0, 1)
965 ZEND_ARG_INFO(0, dsn)
966 ZEND_ARG_INFO(0, async)
967 ZEND_END_ARG_INFO();
968 static PHP_METHOD(pqconn, __construct) {
969 zend_error_handling zeh;
970 char *dsn_str;
971 int dsn_len;
972 zend_bool async = 0;
973
974 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
975 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &dsn_str, &dsn_len, &async)) {
976 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
977 php_pqconn_event_data_t *data = php_pqconn_event_data_init(obj TSRMLS_CC);
978
979 if (obj->conn) {
980 PQfinish(obj->conn);
981 }
982 if ((obj->async = async)) {
983 obj->conn = PQconnectStart(dsn_str);
984 obj->poller = (int (*)(PGconn*)) PQconnectPoll;
985 } else {
986 obj->conn = PQconnectdb(dsn_str);
987 }
988
989 PQregisterEventProc(obj->conn, php_pqconn_event, "ext-pq", data);
990 if (SUCCESS != php_pqconn_update_socket(getThis(), obj TSRMLS_CC)) {
991 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection failed: %s", PQerrorMessage(obj->conn));
992 }
993 }
994 zend_restore_error_handling(&zeh TSRMLS_CC);
995 }
996
997 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_reset, 0, 0, 0)
998 ZEND_END_ARG_INFO();
999 static PHP_METHOD(pqconn, reset) {
1000 if (SUCCESS == zend_parse_parameters_none()) {
1001 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1002
1003 if (obj->conn) {
1004 if (obj->async) {
1005 if (PQresetStart(obj->conn)) {
1006 obj->poller = (int (*)(PGconn*)) PQresetPoll;
1007 RETURN_TRUE;
1008 }
1009 } else {
1010 PQreset(obj->conn);
1011
1012 if (CONNECTION_OK == PQstatus(obj->conn)) {
1013 RETURN_TRUE;
1014 } else {
1015 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection reset failed: %s", PQerrorMessage(obj->conn));
1016 }
1017 }
1018 } else {
1019 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
1020 }
1021 RETURN_FALSE;
1022 }
1023 }
1024
1025 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)
1026 {
1027 HashTable ht, *existing_listeners;
1028
1029 php_pq_callback_addref(listener);
1030
1031 if (SUCCESS == zend_hash_find(&obj->listeners, channel_str, channel_len + 1, (void *) &existing_listeners)) {
1032 zend_hash_next_index_insert(existing_listeners, (void *) listener, sizeof(*listener), NULL);
1033 } else {
1034 zend_hash_init(&ht, 1, NULL, (dtor_func_t) php_pq_callback_dtor, 0);
1035 zend_hash_next_index_insert(&ht, (void *) listener, sizeof(*listener), NULL);
1036 zend_hash_add(&obj->listeners, channel_str, channel_len + 1, (void *) &ht, sizeof(HashTable), NULL);
1037 }
1038 }
1039
1040 static STATUS php_pqres_success(PGresult *res TSRMLS_DC)
1041 {
1042 switch (PQresultStatus(res)) {
1043 case PGRES_BAD_RESPONSE:
1044 case PGRES_NONFATAL_ERROR:
1045 case PGRES_FATAL_ERROR:
1046 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", PQresultErrorMessage(res));
1047 return FAILURE;
1048 default:
1049 return SUCCESS;
1050 }
1051 }
1052
1053 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_listen, 0, 0, 0)
1054 ZEND_ARG_INFO(0, channel)
1055 ZEND_ARG_INFO(0, callable)
1056 ZEND_END_ARG_INFO();
1057 static PHP_METHOD(pqconn, listen) {
1058 char *channel_str = NULL;
1059 int channel_len = 0;
1060 php_pq_callback_t listener;
1061
1062 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sf", &channel_str, &channel_len, &listener.fci, &listener.fcc)) {
1063 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1064
1065 obj->poller = PQconsumeInput;
1066
1067 if (obj->conn) {
1068 PGresult *res;
1069 char cmd[1024];
1070
1071 slprintf(cmd, sizeof(cmd), "LISTEN %s", channel_str);
1072 res = PQexec(obj->conn, cmd);
1073
1074 if (res) {
1075 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
1076 php_pqconn_add_listener(obj, channel_str, channel_len, &listener TSRMLS_CC);
1077 RETVAL_TRUE;
1078 } else {
1079 RETVAL_FALSE;
1080 }
1081 PQclear(res);
1082 } else {
1083 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not install listener: %s", PQerrorMessage(obj->conn));
1084 RETVAL_FALSE;
1085 }
1086
1087 php_pqconn_notify_listeners(getThis(), obj TSRMLS_CC);
1088
1089 } else {
1090 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
1091 RETVAL_FALSE;
1092 }
1093 }
1094 }
1095
1096 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_notify, 0, 0, 2)
1097 ZEND_ARG_INFO(0, channel)
1098 ZEND_ARG_INFO(0, message)
1099 ZEND_END_ARG_INFO();
1100 static PHP_METHOD(pqconn, notify) {
1101 char *channel_str, *message_str;
1102 int channel_len, message_len;
1103
1104 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &channel_str, &channel_len, &message_str, &message_len)) {
1105 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1106
1107 if (obj->conn) {
1108 PGresult *res;
1109 char *params[2] = {channel_str, message_str};
1110
1111 res = PQexecParams(obj->conn, "select pg_notify($1, $2)", 2, NULL, (const char *const*) params, NULL, NULL, 0);
1112
1113 if (res) {
1114 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
1115 RETVAL_TRUE;
1116 } else {
1117 RETVAL_FALSE;
1118 }
1119 PQclear(res);
1120 } else {
1121 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not notify listeners: %s", PQerrorMessage(obj->conn));
1122 RETVAL_FALSE;
1123 }
1124
1125 php_pqconn_notify_listeners(getThis(), obj TSRMLS_CC);
1126
1127 } else {
1128 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
1129 RETVAL_FALSE;
1130 }
1131 }
1132 }
1133
1134 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_poll, 0, 0, 0)
1135 ZEND_END_ARG_INFO();
1136 static PHP_METHOD(pqconn, poll) {
1137 if (SUCCESS == zend_parse_parameters_none()) {
1138 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1139
1140 if (obj->conn) {
1141 if (obj->poller) {
1142 if (obj->poller == PQconsumeInput) {
1143 RETVAL_LONG(obj->poller(obj->conn) * PGRES_POLLING_OK);
1144 php_pqconn_notify_listeners(getThis(), obj TSRMLS_CC);
1145 return;
1146 } else {
1147 RETURN_LONG(obj->poller(obj->conn));
1148 }
1149 } else {
1150 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No asynchronous operation active");
1151 }
1152 } else {
1153 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
1154 }
1155 RETURN_FALSE;
1156 }
1157 }
1158
1159 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec, 0, 0, 1)
1160 ZEND_ARG_INFO(0, query)
1161 ZEND_END_ARG_INFO();
1162 static PHP_METHOD(pqconn, exec) {
1163 zend_error_handling zeh;
1164 char *query_str;
1165 int query_len;
1166
1167 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
1168 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &query_str, &query_len)) {
1169 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1170
1171 if (obj->conn) {
1172 PGresult *res = PQexec(obj->conn, query_str);
1173
1174 php_pqconn_notify_listeners(getThis(), obj TSRMLS_CC);
1175
1176 if (res) {
1177 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
1178 return_value->type = IS_OBJECT;
1179 return_value->value.obj = php_pqres_create_object_ex(php_pqres_class_entry, res, NULL TSRMLS_CC);
1180 }
1181 } else {
1182 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute query: %s", PQerrorMessage(obj->conn));
1183 }
1184 } else {
1185 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
1186 }
1187 }
1188 zend_restore_error_handling(&zeh TSRMLS_CC);
1189 }
1190
1191 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_getResult, 0, 0, 0)
1192 ZEND_END_ARG_INFO();
1193 static PHP_METHOD(pqconn, getResult) {
1194 if (SUCCESS == zend_parse_parameters_none()) {
1195 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1196
1197 if (obj->conn) {
1198 PGresult *res = PQgetResult(obj->conn);
1199
1200 if (res) {
1201 return_value->type = IS_OBJECT;
1202 return_value->value.obj = php_pqres_create_object_ex(php_pqres_class_entry, res, NULL TSRMLS_CC);
1203 } else {
1204 RETVAL_NULL();
1205 }
1206 } else {
1207 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
1208 RETVAL_FALSE;
1209 }
1210 }
1211 }
1212
1213 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_async, 0, 0, 1)
1214 ZEND_ARG_INFO(0, query)
1215 ZEND_ARG_INFO(0, callable)
1216 ZEND_END_ARG_INFO();
1217 static PHP_METHOD(pqconn, execAsync) {
1218 zend_error_handling zeh;
1219 php_pq_callback_t resolver;
1220 char *query_str;
1221 int query_len;
1222
1223 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
1224 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|f", &query_str, &query_len, &resolver.fci, &resolver.fcc)) {
1225 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1226
1227 if (obj->conn) {
1228 php_pq_callback_dtor(&obj->onevent);
1229 if (resolver.fci.size > 0) {
1230 obj->onevent = resolver;
1231 php_pq_callback_addref(&obj->onevent);
1232 }
1233
1234 obj->poller = PQconsumeInput;
1235
1236 if (PQsendQuery(obj->conn, query_str)) {
1237 RETVAL_TRUE;
1238 } else {
1239 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute query: %s", PQerrorMessage(obj->conn));
1240 RETVAL_FALSE;
1241 }
1242 } else {
1243 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
1244 RETVAL_FALSE;
1245 }
1246 }
1247 zend_restore_error_handling(&zeh TSRMLS_CC);
1248 }
1249
1250 static int apply_to_oid(void *p, void *arg TSRMLS_DC)
1251 {
1252 Oid **types = arg;
1253 zval **ztype = p;
1254
1255 if (Z_TYPE_PP(ztype) != IS_LONG) {
1256 convert_to_long_ex(ztype);
1257 }
1258
1259 **types = Z_LVAL_PP(ztype);
1260 ++*types;
1261
1262 if (*ztype != *(zval **)p) {
1263 zval_ptr_dtor(ztype);
1264 }
1265 return ZEND_HASH_APPLY_KEEP;
1266 }
1267
1268 static int apply_to_param(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
1269 {
1270 char ***params;
1271 HashTable *zdtor;
1272 zval **zparam = p;
1273
1274 params = (char ***) va_arg(argv, char ***);
1275 zdtor = (HashTable *) va_arg(argv, HashTable *);
1276
1277 if (Z_TYPE_PP(zparam) == IS_NULL) {
1278 **params = NULL;
1279 ++*params;
1280 } else {
1281 if (Z_TYPE_PP(zparam) != IS_STRING) {
1282 convert_to_string_ex(zparam);
1283 }
1284
1285 **params = Z_STRVAL_PP(zparam);
1286 ++*params;
1287
1288 if (*zparam != *(zval **)p) {
1289 zend_hash_next_index_insert(zdtor, zparam, sizeof(zval *), NULL);
1290 }
1291 }
1292 return ZEND_HASH_APPLY_KEEP;
1293 }
1294
1295 static void php_pq_types_to_array(HashTable *ht, Oid **types TSRMLS_DC)
1296 {
1297 *types = NULL;
1298
1299 if (zend_hash_num_elements(ht)) {
1300 Oid *tmp;
1301
1302 *types = tmp = ecalloc(zend_hash_num_elements(ht) + 1, sizeof(Oid));
1303 zend_hash_apply_with_argument(ht, apply_to_oid, &tmp TSRMLS_CC);
1304 }
1305 }
1306
1307 static void php_pq_params_to_array(HashTable *ht, char ***params, int *count, HashTable *zdtor TSRMLS_DC)
1308 {
1309 *params = NULL;
1310
1311 if ((*count = zend_hash_num_elements(ht))) {
1312 char **tmp;
1313
1314 *params = tmp = ecalloc(*count, sizeof(char *));
1315 zend_hash_apply_with_arguments(ht TSRMLS_CC, apply_to_param, 2, &tmp, zdtor);
1316 }
1317 }
1318
1319 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_params, 0, 0, 2)
1320 ZEND_ARG_INFO(0, query)
1321 ZEND_ARG_ARRAY_INFO(0, params, 0)
1322 ZEND_ARG_ARRAY_INFO(0, types, 1)
1323 ZEND_END_ARG_INFO();
1324 static PHP_METHOD(pqconn, execParams) {
1325 zend_error_handling zeh;
1326 char *query_str;
1327 int query_len;
1328 zval *zparams;
1329 zval *ztypes = NULL;
1330
1331 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
1332 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|a/!", &query_str, &query_len, &zparams, &ztypes)) {
1333 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1334
1335 if (obj->conn) {
1336 PGresult *res;
1337 int count = 0;
1338 Oid *types = NULL;
1339 char **params = NULL;
1340 HashTable zdtor;
1341
1342 ZEND_INIT_SYMTABLE(&zdtor);
1343 php_pq_params_to_array(Z_ARRVAL_P(zparams), &params, &count, &zdtor TSRMLS_CC);
1344
1345 if (ztypes) {
1346 php_pq_types_to_array(Z_ARRVAL_P(ztypes), &types TSRMLS_CC);
1347 }
1348
1349 res = PQexecParams(obj->conn, query_str, count, types, (const char *const*) params, NULL, NULL, 0);
1350
1351 zend_hash_destroy(&zdtor);
1352 if (types) {
1353 efree(types);
1354 }
1355 if (params) {
1356 efree(params);
1357 }
1358
1359 php_pqconn_notify_listeners(getThis(), obj TSRMLS_CC);
1360
1361 if (res) {
1362 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
1363 return_value->type = IS_OBJECT;
1364 return_value->value.obj = php_pqres_create_object_ex(php_pqres_class_entry, res, NULL TSRMLS_CC);
1365 }
1366 } else {
1367 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute query: %s", PQerrorMessage(obj->conn));
1368 RETVAL_FALSE;
1369 }
1370 } else {
1371 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
1372 RETVAL_FALSE;
1373 }
1374 }
1375 zend_restore_error_handling(&zeh TSRMLS_CC);
1376 }
1377
1378 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_params_async, 0, 0, 2)
1379 ZEND_ARG_INFO(0, query)
1380 ZEND_ARG_ARRAY_INFO(0, params, 0)
1381 ZEND_ARG_ARRAY_INFO(0, types, 1)
1382 ZEND_ARG_INFO(0, callable)
1383 ZEND_END_ARG_INFO();
1384 static PHP_METHOD(pqconn, execParamsAsync) {
1385 zend_error_handling zeh;
1386 php_pq_callback_t resolver;
1387 char *query_str;
1388 int query_len;
1389 zval *zparams;
1390 zval *ztypes = NULL;
1391
1392 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
1393 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|a/!f", &query_str, &query_len, &zparams, &ztypes, &resolver.fci, &resolver.fcc)) {
1394 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1395
1396 if (obj->conn) {
1397 int count = 0;
1398 Oid *types = NULL;
1399 char **params = NULL;
1400 HashTable zdtor;
1401
1402 ZEND_INIT_SYMTABLE(&zdtor);
1403 php_pq_params_to_array(Z_ARRVAL_P(zparams), &params, &count, &zdtor TSRMLS_CC);
1404
1405 if (ztypes) {
1406 php_pq_types_to_array(Z_ARRVAL_P(ztypes), &types TSRMLS_CC);
1407 }
1408
1409 php_pq_callback_dtor(&obj->onevent);
1410 if (resolver.fci.size > 0) {
1411 obj->onevent = resolver;
1412 php_pq_callback_addref(&obj->onevent);
1413 }
1414
1415 obj->poller = PQconsumeInput;
1416
1417 if (PQsendQueryParams(obj->conn, query_str, count, types, (const char *const*) params, NULL, NULL, 0)) {
1418 RETVAL_TRUE;
1419 } else {
1420 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute query: %s", PQerrorMessage(obj->conn));
1421 RETVAL_FALSE;
1422 }
1423
1424 zend_hash_destroy(&zdtor);
1425 if (types) {
1426 efree(types);
1427 }
1428 if (params) {
1429 efree(params);
1430 }
1431
1432 php_pqconn_notify_listeners(getThis(), obj TSRMLS_CC);
1433
1434 } else {
1435 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
1436 RETVAL_FALSE;
1437 }
1438 }
1439 zend_restore_error_handling(&zeh TSRMLS_CC);
1440 }
1441
1442 static STATUS php_pqconn_prepare(PGconn *conn, const char *name, const char *query, HashTable *typest TSRMLS_DC)
1443 {
1444 Oid *types = NULL;
1445 int count = 0;
1446 PGresult *res;
1447 STATUS rv;
1448
1449 if (typest && (count = zend_hash_num_elements(typest))) {
1450 Oid *tmp;
1451
1452 tmp = types = ecalloc(count, sizeof(Oid));
1453 zend_hash_apply_with_argument(typest, apply_to_oid, &tmp TSRMLS_CC);
1454 }
1455
1456 res = PQprepare(conn, name, query, count, types);
1457
1458 if (types) {
1459 efree(types);
1460 }
1461
1462 if (res) {
1463 rv = php_pqres_success(res TSRMLS_CC);
1464 PQclear(res);
1465 } else {
1466 rv = FAILURE;
1467 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not prepare statement: %s", PQerrorMessage(conn));
1468 }
1469
1470 return rv;
1471 }
1472
1473 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_prepare, 0, 0, 2)
1474 ZEND_ARG_INFO(0, name)
1475 ZEND_ARG_INFO(0, query)
1476 ZEND_ARG_ARRAY_INFO(0, types, 1)
1477 ZEND_END_ARG_INFO();
1478 static PHP_METHOD(pqconn, prepare) {
1479 zend_error_handling zeh;
1480 zval *ztypes = NULL;
1481 char *name_str, *query_str;
1482 int name_len, *query_len;
1483
1484 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
1485 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!", &name_str, &name_len, &query_str, &query_len, &ztypes)) {
1486 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1487
1488 if (obj->conn) {
1489 if (SUCCESS == php_pqconn_prepare(obj->conn, name_str, query_str, ztypes ? Z_ARRVAL_P(ztypes) : NULL TSRMLS_CC)) {
1490 return_value->type = IS_OBJECT;
1491 return_value->value.obj = php_pqstm_create_object_ex(php_pqstm_class_entry, getThis(), name_str, NULL TSRMLS_CC);
1492 }
1493 php_pqconn_notify_listeners(getThis(), obj TSRMLS_CC);
1494 } else {
1495 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
1496 }
1497 }
1498 }
1499
1500 static zend_function_entry php_pqconn_methods[] = {
1501 PHP_ME(pqconn, __construct, ai_pqconn_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
1502 PHP_ME(pqconn, reset, ai_pqconn_reset, ZEND_ACC_PUBLIC)
1503 PHP_ME(pqconn, poll, ai_pqconn_poll, ZEND_ACC_PUBLIC)
1504 PHP_ME(pqconn, exec, ai_pqconn_exec, ZEND_ACC_PUBLIC)
1505 PHP_ME(pqconn, execParams, ai_pqconn_exec_params, ZEND_ACC_PUBLIC)
1506 PHP_ME(pqconn, prepare, ai_pqconn_prepare, ZEND_ACC_PUBLIC)
1507 PHP_ME(pqconn, listen, ai_pqconn_listen, ZEND_ACC_PUBLIC)
1508 PHP_ME(pqconn, notify, ai_pqconn_notify, ZEND_ACC_PUBLIC)
1509 PHP_ME(pqconn, getResult, ai_pqconn_getResult, ZEND_ACC_PUBLIC)
1510 PHP_ME(pqconn, execAsync, ai_pqconn_exec_async, ZEND_ACC_PUBLIC)
1511 PHP_ME(pqconn, execParamsAsync, ai_pqconn_exec_params_async, ZEND_ACC_PUBLIC)
1512 {0}
1513 };
1514
1515 static zval **php_pqres_iteration(zval *this_ptr, php_pqres_object_t *obj, php_pqres_fetch_t fetch_type TSRMLS_DC)
1516 {
1517 zval **row = NULL;
1518 php_pqres_fetch_t orig_fetch;
1519
1520 if (!obj) {
1521 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1522 }
1523
1524 if (!obj->iter) {
1525 obj->iter = (php_pqres_iterator_t *) php_pqres_iterator_init(Z_OBJCE_P(getThis()), getThis(), 0 TSRMLS_CC);
1526 obj->iter->zi.funcs->rewind((zend_object_iterator *) obj->iter TSRMLS_CC);
1527 }
1528 orig_fetch = obj->iter->fetch_type;
1529 obj->iter->fetch_type = fetch_type;
1530 if (SUCCESS == obj->iter->zi.funcs->valid((zend_object_iterator *) obj->iter TSRMLS_CC)) {
1531 obj->iter->zi.funcs->get_current_data((zend_object_iterator *) obj->iter, &row TSRMLS_CC);
1532 obj->iter->zi.funcs->move_forward((zend_object_iterator *) obj->iter TSRMLS_CC);
1533 }
1534 obj->iter->fetch_type = orig_fetch;
1535
1536 return row ? row : NULL;
1537 }
1538
1539 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_row, 0, 0, 0)
1540 ZEND_ARG_INFO(0, fetch_type)
1541 ZEND_END_ARG_INFO();
1542 static PHP_METHOD(pqres, fetchRow) {
1543 zend_error_handling zeh;
1544 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1545 long fetch_type = obj->iter ? obj->iter->fetch_type : PHP_PQRES_FETCH_ARRAY;
1546
1547 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
1548 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &fetch_type)) {
1549 zval **row = php_pqres_iteration(getThis(), obj, fetch_type TSRMLS_CC);
1550
1551 if (row) {
1552 RETVAL_ZVAL(*row, 1, 0);
1553 } else {
1554 RETVAL_FALSE;
1555 }
1556 }
1557 zend_restore_error_handling(&zeh TSRMLS_CC);
1558 }
1559
1560 static zval **column_at(zval *row, int col TSRMLS_DC)
1561 {
1562 zval **data = NULL;
1563 HashTable *ht = HASH_OF(row);
1564 int count = zend_hash_num_elements(ht);
1565
1566 if (col < count) {
1567 zend_hash_internal_pointer_reset(ht);
1568 while (col-- > 0) {
1569 zend_hash_move_forward(ht);
1570 }
1571 zend_hash_get_current_data(ht, (void *) &data);
1572 } else {
1573 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Column index %d does excess column count %d", col, count);
1574 }
1575 return data;
1576 }
1577
1578 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_col, 0, 0, 0)
1579 ZEND_ARG_INFO(0, col_num)
1580 ZEND_END_ARG_INFO();
1581 static PHP_METHOD(pqres, fetchCol) {
1582 zend_error_handling zeh;
1583 long fetch_col = 0;
1584
1585 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
1586 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &fetch_col)) {
1587 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1588 zval **row = php_pqres_iteration(getThis(), obj, obj->iter ? obj->iter->fetch_type : 0 TSRMLS_CC);
1589
1590 if (row) {
1591 zval **col = column_at(*row, fetch_col TSRMLS_CC);
1592
1593 if (col) {
1594 RETVAL_ZVAL(*col, 1, 0);
1595 } else {
1596 RETVAL_FALSE;
1597 }
1598 } else {
1599 RETVAL_FALSE;
1600 }
1601 }
1602 zend_restore_error_handling(&zeh TSRMLS_CC);
1603
1604 }
1605
1606 static zend_function_entry php_pqres_methods[] = {
1607 PHP_ME(pqres, fetchRow, ai_pqres_fetch_row, ZEND_ACC_PUBLIC)
1608 PHP_ME(pqres, fetchCol, ai_pqres_fetch_col, ZEND_ACC_PUBLIC)
1609 {0}
1610 };
1611
1612 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_construct, 0, 0, 3)
1613 ZEND_ARG_OBJ_INFO(0, Connection, pq\\Connection, 0)
1614 ZEND_ARG_INFO(0, name)
1615 ZEND_ARG_INFO(0, query)
1616 ZEND_ARG_ARRAY_INFO(0, types, 1)
1617 ZEND_END_ARG_INFO();
1618 static PHP_METHOD(pqstm, __construct) {
1619 zend_error_handling zeh;
1620 zval *zconn, *ztypes = NULL;
1621 char *name_str, *query_str;
1622 int name_len, *query_len;
1623
1624 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
1625 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oss|a/!", &zconn, php_pqconn_class_entry, &name_str, &name_len, &query_str, &query_len, &ztypes)) {
1626 php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1627 php_pqconn_object_t *conn_obj = zend_object_store_get_object(zconn TSRMLS_CC);
1628
1629 if (conn_obj->conn) {
1630 if (SUCCESS == php_pqconn_prepare(conn_obj->conn, name_str, query_str, ztypes ? Z_ARRVAL_P(ztypes) : NULL TSRMLS_CC)) {
1631 Z_ADDREF_P(zconn);
1632 obj->conn = zconn;
1633 obj->name = estrdup(name_str);
1634 }
1635 php_pqconn_notify_listeners(obj->conn, conn_obj TSRMLS_CC);
1636 } else {
1637 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
1638 }
1639 }
1640 }
1641
1642 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_exec, 0, 0, 0)
1643 ZEND_ARG_ARRAY_INFO(0, params, 1)
1644 ZEND_END_ARG_INFO();
1645 static PHP_METHOD(pqstm, exec) {
1646 zend_error_handling zeh;
1647 zval *zparams = NULL;
1648
1649 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
1650 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a/!", &zparams)) {
1651 php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1652
1653 if (obj->conn && obj->name) {
1654 php_pqconn_object_t *conn_obj = zend_object_store_get_object(obj->conn TSRMLS_CC);
1655
1656 if (conn_obj->conn) {
1657 int count = 0;
1658 char **params = NULL;
1659 HashTable zdtor;
1660 PGresult *res;
1661
1662 ZEND_INIT_SYMTABLE(&zdtor);
1663
1664 if (zparams && (count = zend_hash_num_elements(Z_ARRVAL_P(zparams)))) {
1665 char **tmp;
1666
1667 tmp = params = ecalloc(count, sizeof(char *));
1668 zend_hash_apply_with_arguments(Z_ARRVAL_P(zparams) TSRMLS_CC, apply_to_param, 2, &tmp, &zdtor);
1669 }
1670
1671 res = PQexecPrepared(conn_obj->conn, obj->name, count, (const char *const*) params, NULL, NULL, 0);
1672
1673 if (params) {
1674 efree(params);
1675 }
1676 zend_hash_destroy(&zdtor);
1677
1678 php_pqconn_notify_listeners(obj->conn, conn_obj TSRMLS_CC);
1679
1680 if (res) {
1681 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
1682 return_value->type = IS_OBJECT;
1683 return_value->value.obj = php_pqres_create_object_ex(php_pqres_class_entry, res, NULL TSRMLS_CC);
1684 }
1685 } else {
1686 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute statement: %s", PQerrorMessage(conn_obj->conn));
1687 }
1688 } else {
1689 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
1690 }
1691 } else {
1692 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Statement not initialized");
1693 }
1694 }
1695 zend_restore_error_handling(&zeh TSRMLS_CC);
1696 }
1697
1698 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_desc, 0, 0, 0)
1699 ZEND_END_ARG_INFO();
1700 static PHP_METHOD(pqstm, desc) {
1701 zend_error_handling zeh;
1702
1703 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
1704 if (SUCCESS == zend_parse_parameters_none()) {
1705 php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1706
1707 if (obj->conn && obj->name) {
1708 php_pqconn_object_t *conn_obj = zend_object_store_get_object(obj->conn TSRMLS_CC);
1709
1710 if (conn_obj->conn) {
1711 PGresult *res = PQdescribePrepared(conn_obj->conn, obj->name);
1712
1713 php_pqconn_notify_listeners(obj->conn, conn_obj TSRMLS_CC);
1714
1715 if (res) {
1716 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
1717 int p, params;
1718
1719 array_init(return_value);
1720 for (p = 0, params = PQnparams(res); p < params; ++p) {
1721 add_next_index_long(return_value, PQparamtype(res, p));
1722 }
1723 }
1724 } else {
1725 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not describe statement: %s", PQerrorMessage(conn_obj->conn));
1726 }
1727 } else {
1728 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
1729 }
1730 } else {
1731 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Statement not initialized");
1732 }
1733 }
1734 zend_restore_error_handling(&zeh TSRMLS_CC);
1735 }
1736
1737 static zend_function_entry php_pqstm_methods[] = {
1738 PHP_ME(pqstm, __construct, ai_pqstm_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
1739 PHP_ME(pqstm, exec, ai_pqstm_exec, ZEND_ACC_PUBLIC)
1740 PHP_ME(pqstm, desc, ai_pqstm_desc, ZEND_ACC_PUBLIC)
1741 {0}
1742 };
1743
1744 /* {{{ PHP_MINIT_FUNCTION
1745 */
1746 PHP_MINIT_FUNCTION(pq)
1747 {
1748 zend_class_entry ce = {0};
1749 php_pq_object_prophandler_t ph = {0};
1750
1751 zend_hash_init(&php_pqconn_object_prophandlers, 1, NULL, NULL, 1);
1752 INIT_NS_CLASS_ENTRY(ce, "pq", "Connection", php_pqconn_methods);
1753 php_pqconn_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
1754 php_pqconn_class_entry->create_object = php_pqconn_create_object;
1755 memcpy(&php_pqconn_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1756 php_pqconn_object_handlers.read_property = php_pqconn_object_read_prop;
1757 php_pqconn_object_handlers.write_property = php_pqconn_object_write_prop;
1758 php_pqconn_object_handlers.clone_obj = NULL;
1759 php_pqconn_object_handlers.get_property_ptr_ptr = NULL;
1760 php_pqconn_object_handlers.get_debug_info = php_pq_object_debug_info;
1761
1762 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("status"), CONNECTION_BAD, ZEND_ACC_PUBLIC TSRMLS_CC);
1763 ph.read = php_pqconn_object_read_status;
1764 zend_hash_add(&php_pqconn_object_prophandlers, "status", sizeof("status"), (void *) &ph, sizeof(ph), NULL);
1765
1766 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("transactionStatus"), PQTRANS_UNKNOWN, ZEND_ACC_PUBLIC TSRMLS_CC);
1767 ph.read = php_pqconn_object_read_transaction_status;
1768 zend_hash_add(&php_pqconn_object_prophandlers, "transactionStatus", sizeof("transactionStatus"), (void *) &ph, sizeof(ph), NULL);
1769
1770 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("socket"), ZEND_ACC_PUBLIC TSRMLS_CC);
1771 ph.read = NULL; /* forward to std prophandler */
1772 zend_hash_add(&php_pqconn_object_prophandlers, "socket", sizeof("socket"), (void *) &ph, sizeof(ph), NULL);
1773
1774 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC TSRMLS_CC);
1775 ph.read = php_pqconn_object_read_error_message;
1776 zend_hash_add(&php_pqconn_object_prophandlers, "errorMessage", sizeof("errorMessage"), (void *) &ph, sizeof(ph), NULL);
1777
1778 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("types"), ZEND_ACC_PUBLIC TSRMLS_CC);
1779 ph.read = php_pqconn_object_read_types;
1780 zend_hash_add(&php_pqconn_object_prophandlers, "types", sizeof("types"), (void *) &ph, sizeof(ph), NULL);
1781
1782 zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("busy"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
1783 ph.read = php_pqconn_object_read_busy;
1784 zend_hash_add(&php_pqconn_object_prophandlers, "busy", sizeof("busy"), (void *) &ph, sizeof(ph), NULL);
1785
1786 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("OK"), CONNECTION_OK TSRMLS_CC);
1787 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("BAD"), CONNECTION_BAD TSRMLS_CC);
1788 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("STARTED"), CONNECTION_STARTED TSRMLS_CC);
1789 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("MADE"), CONNECTION_MADE TSRMLS_CC);
1790 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("AWAITING_RESPONSE"), CONNECTION_AWAITING_RESPONSE TSRMLS_CC);
1791 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("AUTH_OK"), CONNECTION_AUTH_OK TSRMLS_CC);
1792 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("SSL_STARTUP"), CONNECTION_SSL_STARTUP TSRMLS_CC);
1793 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("SETENV"), CONNECTION_SETENV TSRMLS_CC);
1794
1795 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_IDLE"), PQTRANS_IDLE TSRMLS_CC);
1796 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_ACTIVE"), PQTRANS_ACTIVE TSRMLS_CC);
1797 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_INTRANS"), PQTRANS_INTRANS TSRMLS_CC);
1798 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_INERROR"), PQTRANS_INERROR TSRMLS_CC);
1799 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_UNKNOWN"), PQTRANS_UNKNOWN TSRMLS_CC);
1800
1801 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_FAILED"), PGRES_POLLING_FAILED TSRMLS_CC);
1802 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_READING"), PGRES_POLLING_READING TSRMLS_CC);
1803 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_WRITING"), PGRES_POLLING_WRITING TSRMLS_CC);
1804 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_OK"), PGRES_POLLING_OK TSRMLS_CC);
1805
1806 zend_hash_init(&php_pqres_object_prophandlers, 1, NULL, NULL, 1);
1807 memset(&ce, 0, sizeof(ce));
1808 INIT_NS_CLASS_ENTRY(ce, "pq", "Result", php_pqres_methods);
1809 php_pqres_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
1810 php_pqres_class_entry->create_object = php_pqres_create_object;
1811 php_pqres_class_entry->iterator_funcs.funcs = &php_pqres_iterator_funcs;
1812 php_pqres_class_entry->get_iterator = php_pqres_iterator_init;
1813
1814 memcpy(&php_pqres_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1815 php_pqres_object_handlers.read_property = php_pqres_object_read_prop;
1816 php_pqres_object_handlers.write_property = php_pqres_object_write_prop;
1817 php_pqres_object_handlers.clone_obj = NULL;
1818 php_pqres_object_handlers.get_property_ptr_ptr = NULL;
1819 php_pqres_object_handlers.get_debug_info = php_pq_object_debug_info;
1820
1821 zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("status"), ZEND_ACC_PUBLIC TSRMLS_CC);
1822 ph.read = php_pqres_object_read_status;
1823 zend_hash_add(&php_pqres_object_prophandlers, "status", sizeof("status"), (void *) &ph, sizeof(ph), NULL);
1824
1825 zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC TSRMLS_CC);
1826 ph.read = php_pqres_object_read_error_message;
1827 zend_hash_add(&php_pqres_object_prophandlers, "errorMessage", sizeof("errorMessage"), (void *) &ph, sizeof(ph), NULL);
1828
1829 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("numRows"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
1830 ph.read = php_pqres_object_read_num_rows;
1831 zend_hash_add(&php_pqres_object_prophandlers, "numRows", sizeof("numRows"), (void *) &ph, sizeof(ph), NULL);
1832
1833 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("numCols"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
1834 ph.read = php_pqres_object_read_num_cols;
1835 zend_hash_add(&php_pqres_object_prophandlers, "numCols", sizeof("numCols"), (void *) &ph, sizeof(ph), NULL);
1836
1837 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("affectedRows"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
1838 ph.read = php_pqres_object_read_affected_rows;
1839 zend_hash_add(&php_pqres_object_prophandlers, "affectedRows", sizeof("affectedRows"), (void *) &ph, sizeof(ph), NULL);
1840
1841 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("fetchType"), PHP_PQRES_FETCH_ARRAY, ZEND_ACC_PUBLIC TSRMLS_CC);
1842 ph.read = php_pqres_object_read_fetch_type;
1843 ph.write = php_pqres_object_write_fetch_type;
1844 zend_hash_add(&php_pqres_object_prophandlers, "fetchType", sizeof("fetchType"), (void *) &ph, sizeof(ph), NULL);
1845 ph.write = NULL;
1846
1847 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("EMPTY_QUERY"), PGRES_EMPTY_QUERY TSRMLS_CC);
1848 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COMMAND_OK"), PGRES_COMMAND_OK TSRMLS_CC);
1849 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("TUPLES_OK"), PGRES_TUPLES_OK TSRMLS_CC);
1850 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_OUT"), PGRES_COPY_OUT TSRMLS_CC);
1851 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_IN"), PGRES_COPY_IN TSRMLS_CC);
1852 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("BAD_RESPONSE"), PGRES_BAD_RESPONSE TSRMLS_CC);
1853 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("NONFATAL_ERROR"), PGRES_NONFATAL_ERROR TSRMLS_CC);
1854 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FATAL_ERROR"), PGRES_FATAL_ERROR TSRMLS_CC);
1855 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_BOTH"), PGRES_COPY_BOTH TSRMLS_CC);
1856 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("SINGLE_TUPLE"), PGRES_SINGLE_TUPLE TSRMLS_CC);
1857
1858 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_ARRAY"), PHP_PQRES_FETCH_ARRAY TSRMLS_CC);
1859 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_ASSOC"), PHP_PQRES_FETCH_ASSOC TSRMLS_CC);
1860 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_OBJECT"), PHP_PQRES_FETCH_OBJECT TSRMLS_CC);
1861
1862 zend_hash_init(&php_pqstm_object_prophandlers, 1, NULL, NULL, 1);
1863 memset(&ce, 0, sizeof(ce));
1864 INIT_NS_CLASS_ENTRY(ce, "pq", "Statement", php_pqstm_methods);
1865 php_pqstm_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
1866 php_pqstm_class_entry->create_object = php_pqstm_create_object;
1867
1868 memcpy(&php_pqstm_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1869 php_pqstm_object_handlers.read_property = php_pqstm_object_read_prop;
1870 php_pqstm_object_handlers.write_property = php_pqstm_object_write_prop;
1871 php_pqstm_object_handlers.clone_obj = NULL;
1872 php_pqstm_object_handlers.get_property_ptr_ptr = NULL;
1873 php_pqstm_object_handlers.get_debug_info = php_pq_object_debug_info;
1874
1875 zend_declare_property_null(php_pqstm_class_entry, ZEND_STRL("name"), ZEND_ACC_PUBLIC TSRMLS_CC);
1876 ph.read = php_pqstm_object_read_name;
1877 zend_hash_add(&php_pqstm_object_prophandlers, "name", sizeof("name"), (void *) &ph, sizeof(ph), NULL);
1878
1879 zend_declare_property_null(php_pqstm_class_entry, ZEND_STRL("connection"), ZEND_ACC_PUBLIC TSRMLS_CC);
1880 ph.read = php_pqstm_object_read_connection;
1881 zend_hash_add(&php_pqstm_object_prophandlers, "connection", sizeof("connection"), (void *) &ph, sizeof(ph), NULL);
1882
1883 /*
1884 REGISTER_INI_ENTRIES();
1885 */
1886 return SUCCESS;
1887 }
1888 /* }}} */
1889
1890 /* {{{ PHP_MSHUTDOWN_FUNCTION
1891 */
1892 PHP_MSHUTDOWN_FUNCTION(pq)
1893 {
1894 /* uncomment this line if you have INI entries
1895 UNREGISTER_INI_ENTRIES();
1896 */
1897 return SUCCESS;
1898 }
1899 /* }}} */
1900
1901 /* {{{ PHP_MINFO_FUNCTION
1902 */
1903 PHP_MINFO_FUNCTION(pq)
1904 {
1905 php_info_print_table_start();
1906 php_info_print_table_header(2, "pq support", "enabled");
1907 php_info_print_table_end();
1908
1909 /* Remove comments if you have entries in php.ini
1910 DISPLAY_INI_ENTRIES();
1911 */
1912 }
1913 /* }}} */
1914
1915
1916
1917 /*
1918 * Local variables:
1919 * tab-width: 4
1920 * c-basic-offset: 4
1921 * End:
1922 * vim600: noet sw=4 ts=4 fdm=marker
1923 * vim<600: noet sw=4 ts=4
1924 */