fix build with subdir
[m6w6/ext-pq] / src / php_pq.c
1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2012 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Author: |
16 +----------------------------------------------------------------------+
17 */
18
19 /* $Id$ */
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #include <php.h>
26 #include <Zend/zend_interfaces.h>
27 #include <ext/standard/info.h>
28 #include <ext/spl/spl_array.h>
29
30 #include <libpq-events.h>
31
32 #include "php_pq.h"
33
34 typedef int STATUS; /* SUCCESS/FAILURE */
35
36 /*
37 ZEND_DECLARE_MODULE_GLOBALS(pq)
38 */
39
40 const zend_function_entry pq_functions[] = {
41 {0}
42 };
43
44 /* {{{ pq_module_entry
45 */
46 zend_module_entry pq_module_entry = {
47 STANDARD_MODULE_HEADER,
48 "pq",
49 pq_functions,
50 PHP_MINIT(pq),
51 PHP_MSHUTDOWN(pq),
52 NULL,/*PHP_RINIT(pq),*/
53 NULL,/*PHP_RSHUTDOWN(pq),*/
54 PHP_MINFO(pq),
55 PHP_PQ_EXT_VERSION,
56 STANDARD_MODULE_PROPERTIES
57 };
58 /* }}} */
59
60 #ifdef COMPILE_DL_PQ
61 ZEND_GET_MODULE(pq)
62 #endif
63
64 /* {{{ PHP_INI
65 */
66 /* Remove comments and fill if you need to have entries in php.ini
67 PHP_INI_BEGIN()
68 STD_PHP_INI_ENTRY("pq.global_value", "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_pq_globals, pq_globals)
69 STD_PHP_INI_ENTRY("pq.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_pq_globals, pq_globals)
70 PHP_INI_END()
71 */
72 /* }}} */
73
74 /* {{{ php_pq_init_globals
75 */
76 /* Uncomment this function if you have INI entries
77 static void php_pq_init_globals(zend_pq_globals *pq_globals)
78 {
79 pq_globals->global_value = 0;
80 pq_globals->global_string = NULL;
81 }
82 */
83 /* }}} */
84
85 static zend_class_entry *php_pqconn_class_entry;
86 static zend_class_entry *php_pqres_class_entry;
87 static zend_class_entry *php_pqstm_class_entry;
88
89 static zend_object_handlers php_pqconn_object_handlers;
90 static zend_object_handlers php_pqres_object_handlers;
91 static zend_object_handlers php_pqstm_object_handlers;
92
93 typedef struct php_pqconn_object {
94 zend_object zo;
95 PGconn *conn;
96 int (*poller)(PGconn *);
97 unsigned blocking:1;
98 } php_pqconn_object_t;
99
100 typedef enum php_pqres_fetch {
101 PHP_PQRES_FETCH_ARRAY,
102 PHP_PQRES_FETCH_ASSOC,
103 PHP_PQRES_FETCH_OBJECT
104 } php_pqres_fetch_t;
105
106 typedef struct php_pqres_iterator {
107 zend_object_iterator zi;
108 zval *current_val;
109 unsigned index;
110 php_pqres_fetch_t fetch_type;
111 } php_pqres_iterator_t;
112
113 typedef struct php_pqres_object {
114 zend_object zo;
115 PGresult *res;
116 php_pqres_iterator_t *iter;
117 } php_pqres_object_t;
118
119 typedef struct php_pqstm_intern {
120 char *name;
121 zval *conn;
122 } php_pqstm_intern_t;
123
124 typedef struct php_pqstm_object {
125 zend_object zo;
126 char *name;
127 zval *conn;
128 } php_pqstm_object_t;
129
130 static zend_object_iterator_funcs php_pqres_iterator_funcs;
131
132 static zend_object_iterator *php_pqres_iterator_init(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
133 {
134 php_pqres_iterator_t *iter;
135 zval *prop, *zfetch_type;
136
137 iter = ecalloc(1, sizeof(*iter));
138 iter->zi.funcs = &php_pqres_iterator_funcs;
139 iter->zi.data = object;
140 Z_ADDREF_P(object);
141
142 zfetch_type = prop = zend_read_property(ce, object, ZEND_STRL("fetchType"), 0 TSRMLS_CC);
143 if (Z_TYPE_P(zfetch_type) != IS_LONG) {
144 convert_to_long_ex(&zfetch_type);
145 }
146 iter->fetch_type = Z_LVAL_P(zfetch_type);
147 if (zfetch_type != prop) {
148 zval_ptr_dtor(&zfetch_type);
149 }
150 if (Z_REFCOUNT_P(prop)) {
151 zval_ptr_dtor(&prop);
152 } else {
153 zval_dtor(prop);
154 FREE_ZVAL(prop);
155 }
156
157 return (zend_object_iterator *) iter;
158 }
159
160 static void php_pqres_iterator_dtor(zend_object_iterator *i TSRMLS_DC)
161 {
162 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
163
164 if (iter->current_val) {
165 zval_ptr_dtor(&iter->current_val);
166 iter->current_val = NULL;
167 }
168 zval_ptr_dtor((zval **) &iter->zi.data);
169 efree(iter);
170 }
171
172 static STATUS php_pqres_iterator_valid(zend_object_iterator *i TSRMLS_DC)
173 {
174 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
175 php_pqres_object_t *obj = zend_object_store_get_object(iter->zi.data TSRMLS_CC);
176
177 if (PQresultStatus(obj->res) != PGRES_TUPLES_OK) {
178 return FAILURE;
179 }
180 if (PQntuples(obj->res) <= iter->index) {
181 return FAILURE;
182 }
183
184 return SUCCESS;
185 }
186
187 static zval *php_pqres_row_to_zval(PGresult *res, unsigned row, php_pqres_fetch_t fetch_type TSRMLS_DC)
188 {
189 zval *data;
190 int c, cols;
191
192 MAKE_STD_ZVAL(data);
193 if (PHP_PQRES_FETCH_OBJECT == fetch_type) {
194 object_init(data);
195 } else {
196 array_init(data);
197 }
198
199 for (c = 0, cols = PQnfields(res); c < cols; ++c) {
200 if (PQgetisnull(res, row, c)) {
201 switch (fetch_type) {
202 case PHP_PQRES_FETCH_OBJECT:
203 add_property_null(data, PQfname(res, c));
204 break;
205
206 case PHP_PQRES_FETCH_ASSOC:
207 add_assoc_null(data, PQfname(res, c));
208 break;
209
210 case PHP_PQRES_FETCH_ARRAY:
211 add_index_null(data, c);
212 break;
213 }
214 } else {
215 char *val = PQgetvalue(res, row, c);
216 int len = PQgetlength(res, row, c);
217
218 switch (fetch_type) {
219 case PHP_PQRES_FETCH_OBJECT:
220 add_property_stringl(data, PQfname(res, c), val, len, 1);
221 break;
222
223 case PHP_PQRES_FETCH_ASSOC:
224 add_assoc_stringl(data, PQfname(res, c), val, len, 1);
225 break;
226
227 case PHP_PQRES_FETCH_ARRAY:
228 add_index_stringl(data, c, val, len ,1);
229 break;
230 }
231 }
232 }
233
234 return data;
235 }
236
237 static void php_pqres_iterator_current(zend_object_iterator *i, zval ***data_ptr TSRMLS_DC)
238 {
239 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
240 php_pqres_object_t *obj = zend_object_store_get_object(iter->zi.data TSRMLS_CC);
241
242 if (iter->current_val) {
243 zval_ptr_dtor(&iter->current_val);
244 }
245 iter->current_val = php_pqres_row_to_zval(obj->res, iter->index, iter->fetch_type TSRMLS_CC);
246 *data_ptr = &iter->current_val;
247 }
248
249 static int php_pqres_iterator_key(zend_object_iterator *i, char **key_str, uint *key_len, ulong *key_num TSRMLS_DC)
250 {
251 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
252
253 *key_num = (ulong) iter->index;
254
255 return HASH_KEY_IS_LONG;
256 }
257
258 static void php_pqres_iterator_next(zend_object_iterator *i TSRMLS_DC)
259 {
260 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
261
262 ++iter->index;
263 }
264
265 static void php_pqres_iterator_rewind(zend_object_iterator *i TSRMLS_DC)
266 {
267 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
268
269 iter->index = 0;
270 }
271
272 static zend_object_iterator_funcs php_pqres_iterator_funcs = {
273 php_pqres_iterator_dtor,
274 /* check for end of iteration (FAILURE or SUCCESS if data is valid) */
275 php_pqres_iterator_valid,
276 /* fetch the item data for the current element */
277 php_pqres_iterator_current,
278 /* fetch the key for the current element (return HASH_KEY_IS_STRING or HASH_KEY_IS_LONG) (optional, may be NULL) */
279 php_pqres_iterator_key,
280 /* step forwards to next element */
281 php_pqres_iterator_next,
282 /* rewind to start of data (optional, may be NULL) */
283 php_pqres_iterator_rewind,
284 /* invalidate current value/key (optional, may be NULL) */
285 NULL
286 };
287
288 static void php_pqconn_object_free(void *o TSRMLS_DC)
289 {
290 php_pqconn_object_t *obj = o;
291
292 if (obj->conn) {
293 PQfinish(obj->conn);
294 obj->conn = NULL;
295 }
296 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
297 efree(obj);
298 }
299
300 static void php_pqres_object_free(void *o TSRMLS_DC)
301 {
302 php_pqres_object_t *obj = o;
303
304 if (obj->res) {
305 PQclear(obj->res);
306 obj->res = NULL;
307 }
308 if (obj->iter) {
309 php_pqres_iterator_dtor((zend_object_iterator *) obj->iter TSRMLS_CC);
310 obj->iter = NULL;
311 }
312 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
313 efree(obj);
314 }
315
316 static void php_pqstm_object_free(void *o TSRMLS_DC)
317 {
318 php_pqstm_object_t *obj = o;
319
320 if (obj->name) {
321 efree(obj->name);
322 obj->name = NULL;
323 }
324 if (obj->conn) {
325 zval_ptr_dtor(&obj->conn);
326 obj->conn = NULL;
327 }
328 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
329 efree(obj);
330 }
331
332 static zend_object_value php_pqconn_create_object_ex(zend_class_entry *ce, PGconn *conn, php_pqconn_object_t **ptr TSRMLS_DC)
333 {
334 zend_object_value ov;
335 php_pqconn_object_t *o;
336
337 o = ecalloc(1, sizeof(*o));
338 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
339 object_properties_init((zend_object *) o, ce);
340
341 if (ptr) {
342 *ptr = o;
343 }
344
345 if (conn) {
346 o->conn = conn;
347 o->blocking = !PQisnonblocking(o->conn);
348 }
349
350 ov.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqconn_object_free, NULL TSRMLS_CC);
351 ov.handlers = &php_pqconn_object_handlers;
352
353 return ov;
354 }
355
356 static zend_object_value php_pqres_create_object_ex(zend_class_entry *ce, PGresult *res, php_pqres_object_t **ptr TSRMLS_DC)
357 {
358 zend_object_value ov;
359 php_pqres_object_t *o;
360
361 o = ecalloc(1, sizeof(*o));
362 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
363 object_properties_init((zend_object *) o, ce);
364
365 if (ptr) {
366 *ptr = o;
367 }
368
369 if (res) {
370 o->res = res;
371 }
372
373 ov.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqres_object_free, NULL TSRMLS_CC);
374 ov.handlers = &php_pqres_object_handlers;
375
376 return ov;
377 }
378
379 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)
380 {
381 zend_object_value ov;
382 php_pqstm_object_t *o;
383
384 o = ecalloc(1, sizeof(*o));
385 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
386 object_properties_init((zend_object *) o, ce);
387
388 if (ptr) {
389 *ptr = o;
390 }
391
392 if (conn) {
393 Z_ADDREF_P(conn);
394 o->conn = conn;
395 }
396
397 if (name) {
398 o->name = estrdup(name);
399 }
400
401 ov.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqstm_object_free, NULL TSRMLS_CC);
402 ov.handlers = &php_pqstm_object_handlers;
403
404 return ov;
405 }
406
407 static zend_object_value php_pqconn_create_object(zend_class_entry *class_type TSRMLS_DC)
408 {
409 return php_pqconn_create_object_ex(class_type, NULL, NULL TSRMLS_CC);
410 }
411
412 static zend_object_value php_pqres_create_object(zend_class_entry *class_type TSRMLS_DC)
413 {
414 return php_pqres_create_object_ex(class_type, NULL, NULL TSRMLS_CC);
415 }
416
417 static zend_object_value php_pqstm_create_object(zend_class_entry *class_type TSRMLS_DC)
418 {
419 return php_pqstm_create_object_ex(class_type, NULL, NULL, NULL TSRMLS_CC);
420 }
421
422 static HashTable php_pqconn_object_prophandlers;
423 static HashTable php_pqres_object_prophandlers;
424 static HashTable php_pqstm_object_prophandlers;
425
426 typedef void (*php_pq_object_prophandler_func_t)(void *o, zval *return_value TSRMLS_DC);
427
428 typedef struct php_pq_object_prophandler {
429 php_pq_object_prophandler_func_t read;
430 php_pq_object_prophandler_func_t write;
431 } php_pq_object_prophandler_t;
432
433 static void php_pqconn_object_read_status(void *o, zval *return_value TSRMLS_DC)
434 {
435 php_pqconn_object_t *obj = o;
436
437 RETVAL_LONG(PQstatus(obj->conn));
438 }
439
440 static void php_pqconn_object_read_transaction_status(void *o, zval *return_value TSRMLS_DC)
441 {
442 php_pqconn_object_t *obj = o;
443
444 RETVAL_LONG(PQtransactionStatus(obj->conn));
445 }
446
447 static void php_pqconn_object_read_socket(void *o, zval *return_value TSRMLS_DC)
448 {
449 php_pqconn_object_t *obj = o;
450 php_stream *stream;
451 int socket = PQsocket(obj->conn);
452
453 if ((stream = php_stream_fopen_from_fd(socket, "r+b", NULL))) {
454 php_stream_to_zval(stream, return_value);
455 } else {
456 RETVAL_NULL();
457 }
458 }
459
460 static void php_pqconn_object_read_error_message(void *o, zval *return_value TSRMLS_DC)
461 {
462 php_pqconn_object_t *obj = o;
463 char *error = PQerrorMessage(obj->conn);
464
465 if (error) {
466 RETVAL_STRING(error, 1);
467 } else {
468 RETVAL_NULL();
469 }
470 }
471
472 /* FIXME: extend to types->nspname->typname */
473 #define PHP_PQ_TYPES_QUERY \
474 "select t.oid, t.* " \
475 "from pg_type t join pg_namespace n on t.typnamespace=n.oid " \
476 "where typisdefined " \
477 "and typrelid=0 " \
478 "and nspname in ('public', 'pg_catalog')"
479 static void php_pqconn_object_read_types(void *o, zval *return_value TSRMLS_DC)
480 {
481 php_pqconn_object_t *obj = o;
482 PGresult *res = PQexec(obj->conn, PHP_PQ_TYPES_QUERY);
483
484 /* FIXME: cache that */
485 if (res) {
486 if (PGRES_TUPLES_OK == PQresultStatus(res)) {
487 int r, rows;
488 zval *byoid, *byname;
489
490 MAKE_STD_ZVAL(byoid);
491 MAKE_STD_ZVAL(byname);
492 object_init(byoid);
493 object_init(byname);
494 object_init(return_value);
495 for (r = 0, rows = PQntuples(res); r < rows; ++r) {
496 zval *row = php_pqres_row_to_zval(res, r, PHP_PQRES_FETCH_OBJECT TSRMLS_CC);
497
498 add_property_zval(byoid, PQgetvalue(res, r, 0), row);
499 add_property_zval(byname, PQgetvalue(res, r, 1), row);
500 zval_ptr_dtor(&row);
501 }
502
503 add_property_zval(return_value, "byOid", byoid);
504 add_property_zval(return_value, "byName", byname);
505 zval_ptr_dtor(&byoid);
506 zval_ptr_dtor(&byname);
507 } else {
508 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not fetch types: %s", PQresultErrorMessage(res));
509 }
510 PQclear(res);
511 } else {
512 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not fetch types: %s", PQerrorMessage(obj->conn));
513 }
514 }
515
516 static void php_pqres_object_read_status(void *o, zval *return_value TSRMLS_DC)
517 {
518 php_pqres_object_t *obj = o;
519
520 RETVAL_LONG(PQresultStatus(obj->res));
521 }
522
523 static void php_pqres_object_read_error_message(void *o, zval *return_value TSRMLS_DC)
524 {
525 php_pqres_object_t *obj = o;
526 char *error = PQresultErrorMessage(obj->res);
527
528 if (error) {
529 RETVAL_STRING(error, 1);
530 } else {
531 RETVAL_NULL();
532 }
533 }
534
535 static void php_pqres_object_read_num_rows(void *o, zval *return_value TSRMLS_DC)
536 {
537 php_pqres_object_t *obj = o;
538
539 RETVAL_LONG(PQntuples(obj->res));
540 }
541
542 static void php_pqres_object_read_num_cols(void *o, zval *return_value TSRMLS_DC)
543 {
544 php_pqres_object_t *obj = o;
545
546 RETVAL_LONG(PQnfields(obj->res));
547 }
548
549 static void php_pqres_object_read_affected_rows(void *o, zval *return_value TSRMLS_DC)
550 {
551 php_pqres_object_t *obj = o;
552
553 RETVAL_LONG(atoi(PQcmdTuples(obj->res)));
554 }
555
556 static void php_pqres_object_read_fetch_type(void *o, zval *return_value TSRMLS_DC)
557 {
558 php_pqres_object_t *obj = o;
559
560 if (obj->iter) {
561 RETVAL_LONG(obj->iter->fetch_type);
562 } else {
563 RETVAL_LONG(PHP_PQRES_FETCH_ARRAY);
564 }
565 }
566
567 static void php_pqres_object_write_fetch_type(void *o, zval *value TSRMLS_DC)
568 {
569 php_pqres_object_t *obj = o;
570 zval *zfetch_type = value;
571
572 if (Z_TYPE_P(zfetch_type) != IS_LONG) {
573 convert_to_long_ex(&zfetch_type);
574 }
575
576 obj->iter->fetch_type = Z_LVAL_P(zfetch_type);
577
578 if (zfetch_type != value) {
579 zval_ptr_dtor(&zfetch_type);
580 }
581 }
582
583 static void php_pqstm_object_read_name(void *o, zval *return_value TSRMLS_DC)
584 {
585 php_pqstm_object_t *obj = o;
586
587 RETVAL_STRING(obj->name, 1);
588 }
589
590 static void php_pqstm_object_read_connection(void *o, zval *return_value TSRMLS_DC)
591 {
592 php_pqstm_object_t *obj = o;
593
594 RETVAL_ZVAL(obj->conn, 1, 0);
595 }
596
597 static zval *php_pqconn_object_read_prop(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
598 {
599 php_pqconn_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
600 php_pq_object_prophandler_t *handler;
601 zval *return_value;
602
603 if (!obj->conn) {
604 zend_error(E_WARNING, "Connection not initialized");
605 } else if (SUCCESS == zend_hash_find(&php_pqconn_object_prophandlers, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void *) &handler)) {
606 if (type == BP_VAR_R) {
607 ALLOC_ZVAL(return_value);
608 Z_SET_REFCOUNT_P(return_value, 0);
609 Z_UNSET_ISREF_P(return_value);
610
611 handler->read(obj, return_value TSRMLS_CC);
612 } else {
613 zend_error(E_ERROR, "Cannot access pq\\Connection properties by reference or array key/index");
614 return_value = NULL;
615 }
616 } else {
617 return_value = zend_get_std_object_handlers()->read_property(object, member, type, key TSRMLS_CC);
618 }
619
620 return return_value;
621 }
622
623 static void php_pqconn_object_write_prop(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
624 {
625 php_pqconn_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
626 php_pq_object_prophandler_t *handler;
627
628 if (SUCCESS == zend_hash_find(&php_pqconn_object_prophandlers, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void *) &handler)) {
629 if (handler->write) {
630 handler->write(obj, value TSRMLS_CC);
631 }
632 } else {
633 zend_get_std_object_handlers()->write_property(object, member, value, key TSRMLS_CC);
634 }
635 }
636
637 static zval *php_pqres_object_read_prop(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
638 {
639 php_pqres_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
640 php_pq_object_prophandler_t *handler;
641 zval *return_value;
642
643 if (!obj->res) {
644 zend_error(E_WARNING, "Result not initialized");
645 } else if (SUCCESS == zend_hash_find(&php_pqres_object_prophandlers, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void *) &handler)) {
646 if (type == BP_VAR_R) {
647 ALLOC_ZVAL(return_value);
648 Z_SET_REFCOUNT_P(return_value, 0);
649 Z_UNSET_ISREF_P(return_value);
650
651 handler->read(obj, return_value TSRMLS_CC);
652 } else {
653 zend_error(E_ERROR, "Cannot access pq\\Result properties by reference or array key/index");
654 return_value = NULL;
655 }
656 } else {
657 return_value = zend_get_std_object_handlers()->read_property(object, member, type, key TSRMLS_CC);
658 }
659
660 return return_value;
661 }
662
663 static void php_pqres_object_write_prop(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
664 {
665 php_pqres_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
666 php_pq_object_prophandler_t *handler;
667
668 if (!obj->res) {
669 zend_error(E_WARNING, "Result not initialized");
670 } else if (SUCCESS == zend_hash_find(&php_pqres_object_prophandlers, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void *) &handler)) {
671 if (handler->write) {
672 /* ensure obj->iter is initialized, for e.g. write_fetch_type */
673 if (!obj->iter) {
674 obj->iter = (php_pqres_iterator_t *) php_pqres_iterator_init(Z_OBJCE_P(object), object, 0 TSRMLS_CC);
675 obj->iter->zi.funcs->rewind((zend_object_iterator *) obj->iter TSRMLS_CC);
676 }
677 handler->write(obj, value TSRMLS_CC);
678 }
679 } else {
680 zend_get_std_object_handlers()->write_property(object, member, value, key TSRMLS_CC);
681 }
682 }
683
684 static zval *php_pqstm_object_read_prop(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
685 {
686 php_pqstm_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
687 php_pq_object_prophandler_t *handler;
688 zval *return_value;
689
690 if (!obj->conn) {
691 zend_error(E_WARNING, "Statement not initialized");
692 } else if (SUCCESS == zend_hash_find(&php_pqstm_object_prophandlers, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void *) &handler)) {
693 if (type == BP_VAR_R) {
694 ALLOC_ZVAL(return_value);
695 Z_SET_REFCOUNT_P(return_value, 0);
696 Z_UNSET_ISREF_P(return_value);
697
698 handler->read(obj, return_value TSRMLS_CC);
699 } else {
700 zend_error(E_ERROR, "Cannot access pq\\Statement properties by reference or array key/index");
701 return_value = NULL;
702 }
703 } else {
704 return_value = zend_get_std_object_handlers()->read_property(object, member, type, key TSRMLS_CC);
705 }
706
707 return return_value;
708 }
709
710 static void php_pqstm_object_write_prop(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
711 {
712 php_pqstm_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
713 php_pq_object_prophandler_t *handler;
714
715 if (!obj->conn) {
716 zend_error(E_WARNING, "Result not initialized");
717 } else if (SUCCESS == zend_hash_find(&php_pqstm_object_prophandlers, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void *) &handler)) {
718 if (handler->write) {
719 handler->write(obj, value TSRMLS_CC);
720 }
721 } else {
722 zend_get_std_object_handlers()->write_property(object, member, value, key TSRMLS_CC);
723 }
724 }
725
726 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_construct, 0, 0, 1)
727 ZEND_ARG_INFO(0, dsn)
728 ZEND_ARG_INFO(0, block)
729 ZEND_END_ARG_INFO();
730 static PHP_METHOD(pqconn, __construct) {
731 zend_error_handling zeh;
732 char *dsn_str;
733 int dsn_len;
734 zend_bool block = 1;
735
736 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
737 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &dsn_str, &dsn_len, &block)) {
738 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
739
740 if (obj->conn) {
741 PQfinish(obj->conn);
742 }
743 if ((obj->blocking = block)) {
744 obj->conn = PQconnectdb(dsn_str);
745 } else {
746 obj->conn = PQconnectStart(dsn_str);
747 obj->poller = (int (*)(PGconn*)) PQconnectPoll;
748 }
749
750 if (CONNECTION_BAD == PQstatus(obj->conn)) {
751 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection failed: %s", PQerrorMessage(obj->conn));
752 }
753 }
754 zend_restore_error_handling(&zeh TSRMLS_CC);
755 }
756
757 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_reset, 0, 0, 0)
758 ZEND_END_ARG_INFO();
759 static PHP_METHOD(pqconn, reset) {
760 if (SUCCESS == zend_parse_parameters_none()) {
761 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
762
763 if (obj->conn) {
764 if (obj->blocking) {
765 PQreset(obj->conn);
766 RETURN_TRUE; /* probably ;) */
767 } if (PQresetStart(obj->conn)) {
768 obj->poller = (int (*)(PGconn*)) PQresetPoll;
769 RETURN_TRUE;
770 }
771 } else {
772 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
773 }
774 RETURN_FALSE;
775 }
776 }
777
778 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_poll, 0, 0, 0)
779 ZEND_END_ARG_INFO();
780 static PHP_METHOD(pqconn, poll) {
781 if (SUCCESS == zend_parse_parameters_none()) {
782 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
783
784 if (obj->conn) {
785 if (obj->poller) {
786 RETURN_LONG(obj->poller(obj->conn));
787 } else {
788 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No asynchronous operation active");
789 }
790 } else {
791 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
792 }
793 RETURN_FALSE;
794 }
795 }
796
797 static STATUS php_pqres_success(PGresult *res TSRMLS_DC)
798 {
799 switch (PQresultStatus(res)) {
800 case PGRES_BAD_RESPONSE:
801 case PGRES_NONFATAL_ERROR:
802 case PGRES_FATAL_ERROR:
803 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: %s", PQresStatus(PQresultStatus(res)), PQresultErrorMessage(res));
804 return FAILURE;
805 default:
806 return SUCCESS;
807 }
808 }
809
810 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec, 0, 0, 1)
811 ZEND_ARG_INFO(0, query)
812 ZEND_END_ARG_INFO();
813 static PHP_METHOD(pqconn, exec) {
814 zend_error_handling zeh;
815 char *query_str;
816 int query_len;
817
818 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
819 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &query_str, &query_len)) {
820 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
821
822 if (obj->conn) {
823 PGresult *res = PQexec(obj->conn, query_str);
824
825 if (res) {
826 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
827 return_value->type = IS_OBJECT;
828 return_value->value.obj = php_pqres_create_object_ex(php_pqres_class_entry, res, NULL TSRMLS_CC);
829 }
830 } else {
831 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute query: %s", PQerrorMessage(obj->conn));
832 }
833 } else {
834 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
835 }
836 }
837 zend_restore_error_handling(&zeh TSRMLS_CC);
838 }
839
840 static int apply_to_oid(void *p, void *arg TSRMLS_DC)
841 {
842 Oid **types = arg;
843 zval **ztype = p;
844
845 if (Z_TYPE_PP(ztype) != IS_LONG) {
846 convert_to_long_ex(ztype);
847 }
848
849 **types = Z_LVAL_PP(ztype);
850 ++*types;
851
852 if (*ztype != *(zval **)p) {
853 zval_ptr_dtor(ztype);
854 }
855 return ZEND_HASH_APPLY_KEEP;
856 }
857
858 static int apply_to_param(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
859 {
860 char ***params;
861 HashTable *zdtor;
862 zval **zparam = p;
863
864 params = (char ***) va_arg(argv, char ***);
865 zdtor = (HashTable *) va_arg(argv, HashTable *);
866
867 if (Z_TYPE_PP(zparam) == IS_NULL) {
868 **params = NULL;
869 ++*params;
870 } else {
871 if (Z_TYPE_PP(zparam) != IS_STRING) {
872 convert_to_string_ex(zparam);
873 }
874
875 **params = Z_STRVAL_PP(zparam);
876 ++*params;
877
878 if (*zparam != *(zval **)p) {
879 zend_hash_next_index_insert(zdtor, zparam, sizeof(zval *), NULL);
880 }
881 }
882 return ZEND_HASH_APPLY_KEEP;
883 }
884
885 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_params, 0, 0, 2)
886 ZEND_ARG_INFO(0, query)
887 ZEND_ARG_ARRAY_INFO(0, params, 0)
888 ZEND_ARG_ARRAY_INFO(0, types, 1)
889 ZEND_END_ARG_INFO();
890 static PHP_METHOD(pqconn, execParams) {
891 zend_error_handling zeh;
892 char *query_str;
893 int query_len;
894 zval *zparams;
895 zval *ztypes = NULL;
896
897 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
898 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa/|a/!", &query_str, &query_len, &zparams, &ztypes)) {
899 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
900
901 if (obj->conn) {
902 PGresult *res;
903 int count = 0;
904 Oid *types = NULL;
905 char **params = NULL;
906 HashTable zdtor;
907
908 ZEND_INIT_SYMTABLE(&zdtor);
909
910 if (ztypes && zend_hash_num_elements(Z_ARRVAL_P(ztypes))) {
911 Oid *tmp;
912
913 tmp = types = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(ztypes)), sizeof(Oid));
914 zend_hash_apply_with_argument(Z_ARRVAL_P(ztypes), apply_to_oid, &tmp TSRMLS_CC);
915 }
916 if ((count = zend_hash_num_elements(Z_ARRVAL_P(zparams)))) {
917 char **tmp;
918
919 tmp = params = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(zparams)), sizeof(char *));
920 zend_hash_apply_with_arguments(Z_ARRVAL_P(zparams) TSRMLS_CC, apply_to_param, 2, &tmp, &zdtor);
921 }
922
923 res = PQexecParams(obj->conn, query_str, count, types, (const char *const*) params, NULL, NULL, 0);
924
925 zend_hash_destroy(&zdtor);
926 if (types) {
927 efree(types);
928 }
929 if (params) {
930 efree(params);
931 }
932
933 if (res) {
934 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
935 return_value->type = IS_OBJECT;
936 return_value->value.obj = php_pqres_create_object_ex(php_pqres_class_entry, res, NULL TSRMLS_CC);
937 }
938 } else {
939 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute query: %s", PQerrorMessage(obj->conn));
940 }
941 } else {
942 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
943 }
944 }
945 zend_restore_error_handling(&zeh TSRMLS_CC);
946 }
947
948 static STATUS php_pqconn_prepare(PGconn *conn, const char *name, const char *query, HashTable *typest TSRMLS_DC)
949 {
950 Oid *types = NULL;
951 int count = 0;
952 PGresult *res;
953
954 if (typest && (count = zend_hash_num_elements(typest))) {
955 Oid *tmp;
956
957 tmp = types = ecalloc(count, sizeof(Oid));
958 zend_hash_apply_with_argument(typest, apply_to_oid, &tmp TSRMLS_CC);
959 }
960
961 res = PQprepare(conn, name, query, count, types);
962
963 if (types) {
964 efree(types);
965 }
966
967 if (res) {
968 if (PGRES_COMMAND_OK == PQresultStatus(res)) {
969 return SUCCESS;
970 } else {
971 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not prepare statement: %s", PQresultErrorMessage(res));
972 }
973 PQclear(res);
974 } else {
975 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not prepare statement: %s", PQerrorMessage(conn));
976 }
977 return FAILURE;
978 }
979
980 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_prepare, 0, 0, 2)
981 ZEND_ARG_INFO(0, "name")
982 ZEND_ARG_INFO(0, "query")
983 ZEND_ARG_ARRAY_INFO(0, "types", 1)
984 ZEND_END_ARG_INFO();
985 static PHP_METHOD(pqconn, prepare) {
986 zend_error_handling zeh;
987 zval *ztypes = NULL;
988 char *name_str, *query_str;
989 int name_len, *query_len;
990
991 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
992 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!", &name_str, &name_len, &query_str, &query_len, &ztypes)) {
993 php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
994
995 if (obj->conn) {
996 if (SUCCESS == php_pqconn_prepare(obj->conn, name_str, query_str, ztypes ? Z_ARRVAL_P(ztypes) : NULL TSRMLS_CC)) {
997 return_value->type = IS_OBJECT;
998 return_value->value.obj = php_pqstm_create_object_ex(php_pqstm_class_entry, getThis(), name_str, NULL TSRMLS_CC);
999 }
1000 } else {
1001 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
1002 }
1003 }
1004 }
1005
1006 static zend_function_entry php_pqconn_methods[] = {
1007 PHP_ME(pqconn, __construct, ai_pqconn_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
1008 PHP_ME(pqconn, reset, ai_pqconn_reset, ZEND_ACC_PUBLIC)
1009 PHP_ME(pqconn, poll, ai_pqconn_poll, ZEND_ACC_PUBLIC)
1010 PHP_ME(pqconn, exec, ai_pqconn_exec, ZEND_ACC_PUBLIC)
1011 PHP_ME(pqconn, execParams, ai_pqconn_exec_params, ZEND_ACC_PUBLIC)
1012 PHP_ME(pqconn, prepare, ai_pqconn_prepare, ZEND_ACC_PUBLIC)
1013 {0}
1014 };
1015
1016 static zval **php_pqres_iteration(zval *this_ptr, php_pqres_object_t *obj, php_pqres_fetch_t fetch_type TSRMLS_DC)
1017 {
1018 zval **row = NULL;
1019 php_pqres_fetch_t orig_fetch;
1020
1021 if (!obj) {
1022 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1023 }
1024
1025 if (!obj->iter) {
1026 obj->iter = (php_pqres_iterator_t *) php_pqres_iterator_init(Z_OBJCE_P(getThis()), getThis(), 0 TSRMLS_CC);
1027 obj->iter->zi.funcs->rewind((zend_object_iterator *) obj->iter TSRMLS_CC);
1028 }
1029 orig_fetch = obj->iter->fetch_type;
1030 obj->iter->fetch_type = fetch_type;
1031 if (SUCCESS == obj->iter->zi.funcs->valid((zend_object_iterator *) obj->iter TSRMLS_CC)) {
1032 obj->iter->zi.funcs->get_current_data((zend_object_iterator *) obj->iter, &row TSRMLS_CC);
1033 obj->iter->zi.funcs->move_forward((zend_object_iterator *) obj->iter TSRMLS_CC);
1034 }
1035 obj->iter->fetch_type = orig_fetch;
1036
1037 return row ? row : NULL;
1038 }
1039
1040 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_row, 0, 0, 0)
1041 ZEND_ARG_INFO(0, fetch_type)
1042 ZEND_END_ARG_INFO();
1043 static PHP_METHOD(pqres, fetchRow) {
1044 zend_error_handling zeh;
1045 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1046 long fetch_type = obj->iter ? obj->iter->fetch_type : PHP_PQRES_FETCH_ARRAY;
1047
1048 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
1049 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &fetch_type)) {
1050 zval **row = php_pqres_iteration(getThis(), obj, fetch_type TSRMLS_CC);
1051
1052 if (row) {
1053 RETVAL_ZVAL(*row, 1, 0);
1054 } else {
1055 RETVAL_FALSE;
1056 }
1057 }
1058 zend_restore_error_handling(&zeh TSRMLS_CC);
1059 }
1060
1061 static zval **column_at(zval *row, int col TSRMLS_DC)
1062 {
1063 zval **data = NULL;
1064 HashTable *ht = HASH_OF(row);
1065 int count = zend_hash_num_elements(ht);
1066
1067 if (col < count) {
1068 zend_hash_internal_pointer_reset(ht);
1069 while (col-- > 0) {
1070 zend_hash_move_forward(ht);
1071 }
1072 zend_hash_get_current_data(ht, (void *) &data);
1073 } else {
1074 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Column index %d does excess column count %d", col, count);
1075 }
1076 return data;
1077 }
1078
1079 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_col, 0, 0, 0)
1080 ZEND_ARG_INFO(0, col_num)
1081 ZEND_END_ARG_INFO();
1082 static PHP_METHOD(pqres, fetchCol) {
1083 zend_error_handling zeh;
1084 long fetch_col = 0;
1085
1086 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
1087 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &fetch_col)) {
1088 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1089 zval **row = php_pqres_iteration(getThis(), obj, obj->iter ? obj->iter->fetch_type : 0 TSRMLS_CC);
1090
1091 if (row) {
1092 zval **col = column_at(*row, fetch_col TSRMLS_CC);
1093
1094 if (col) {
1095 RETVAL_ZVAL(*col, 1, 0);
1096 } else {
1097 RETVAL_FALSE;
1098 }
1099 } else {
1100 RETVAL_FALSE;
1101 }
1102 }
1103 zend_restore_error_handling(&zeh TSRMLS_CC);
1104
1105 }
1106
1107 static zend_function_entry php_pqres_methods[] = {
1108 PHP_ME(pqres, fetchRow, ai_pqres_fetch_row, ZEND_ACC_PUBLIC)
1109 PHP_ME(pqres, fetchCol, ai_pqres_fetch_col, ZEND_ACC_PUBLIC)
1110 {0}
1111 };
1112
1113 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_construct, 0, 0, 3)
1114 ZEND_ARG_OBJ_INFO(0, "Connection", "pq\\Connection", 0)
1115 ZEND_ARG_INFO(0, "name")
1116 ZEND_ARG_INFO(0, "query")
1117 ZEND_ARG_ARRAY_INFO(0, "types", 1)
1118 ZEND_END_ARG_INFO();
1119 static PHP_METHOD(pqstm, __construct) {
1120 zend_error_handling zeh;
1121 zval *zconn, *ztypes = NULL;
1122 char *name_str, *query_str;
1123 int name_len, *query_len;
1124
1125 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
1126 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)) {
1127 php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1128 php_pqconn_object_t *conn_obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1129
1130 if (conn_obj->conn) {
1131 if (SUCCESS == php_pqconn_prepare(conn_obj->conn, name_str, query_str, ztypes ? Z_ARRVAL_P(ztypes) : NULL TSRMLS_CC)) {
1132 Z_ADDREF_P(zconn);
1133 obj->conn = zconn;
1134 obj->name = estrdup(name_str);
1135 }
1136 } else {
1137 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
1138 }
1139 }
1140 }
1141
1142 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_exec, 0, 0, 0)
1143 ZEND_ARG_ARRAY_INFO(0, "params", 1)
1144 ZEND_END_ARG_INFO();
1145 static PHP_METHOD(pqstm, exec) {
1146 zend_error_handling zeh;
1147 zval *zparams = NULL;
1148
1149 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
1150 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a/!", &zparams)) {
1151 php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1152
1153 if (obj->conn && obj->name) {
1154 php_pqconn_object_t *conn_obj = zend_object_store_get_object(obj->conn TSRMLS_CC);
1155
1156 if (conn_obj->conn) {
1157 int count = 0;
1158 char **params = NULL;
1159 HashTable zdtor;
1160 PGresult *res;
1161
1162 ZEND_INIT_SYMTABLE(&zdtor);
1163
1164 if (zparams && (count = zend_hash_num_elements(Z_ARRVAL_P(zparams)))) {
1165 char **tmp;
1166
1167 tmp = params = ecalloc(count, sizeof(char *));
1168 zend_hash_apply_with_arguments(Z_ARRVAL_P(zparams) TSRMLS_CC, apply_to_param, 2, &tmp, &zdtor);
1169 }
1170
1171 res = PQexecPrepared(conn_obj->conn, obj->name, count, (const char *const*) params, NULL, NULL, 0);
1172
1173 if (params) {
1174 efree(params);
1175 }
1176 zend_hash_destroy(&zdtor);
1177
1178 if (res) {
1179 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
1180 return_value->type = IS_OBJECT;
1181 return_value->value.obj = php_pqres_create_object_ex(php_pqres_class_entry, res, NULL TSRMLS_CC);
1182 }
1183 } else {
1184 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute statement: %s", PQerrorMessage(conn_obj->conn));
1185 }
1186 } else {
1187 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
1188 }
1189 } else {
1190 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Statement not initialized");
1191 }
1192 }
1193 zend_restore_error_handling(&zeh TSRMLS_CC);
1194 }
1195
1196 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_desc, 0, 0, 0)
1197 ZEND_END_ARG_INFO();
1198 static PHP_METHOD(pqstm, desc) {
1199 zend_error_handling zeh;
1200
1201 zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
1202 if (SUCCESS == zend_parse_parameters_none()) {
1203 php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1204
1205 if (obj->conn && obj->name) {
1206 php_pqconn_object_t *conn_obj = zend_object_store_get_object(obj->conn TSRMLS_CC);
1207
1208 if (conn_obj->conn) {
1209 PGresult *res = PQdescribePrepared(conn_obj->conn, obj->name);
1210
1211 if (res) {
1212 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
1213 int p, params;
1214
1215 array_init(return_value);
1216 for (p = 0, params = PQnparams(res); p < params; ++p) {
1217 add_next_index_long(return_value, PQparamtype(res, p));
1218 }
1219 }
1220 } else {
1221 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not describe statement: %s", PQerrorMessage(conn_obj->conn));
1222 }
1223 } else {
1224 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
1225 }
1226 } else {
1227 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Statement not initialized");
1228 }
1229 }
1230 zend_restore_error_handling(&zeh TSRMLS_CC);
1231 }
1232
1233 static zend_function_entry php_pqstm_methods[] = {
1234 PHP_ME(pqstm, __construct, ai_pqstm_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
1235 PHP_ME(pqstm, exec, ai_pqstm_exec, ZEND_ACC_PUBLIC)
1236 PHP_ME(pqstm, desc, ai_pqstm_desc, ZEND_ACC_PUBLIC)
1237 {0}
1238 };
1239
1240 /* {{{ PHP_MINIT_FUNCTION
1241 */
1242 PHP_MINIT_FUNCTION(pq)
1243 {
1244 zend_class_entry ce = {0};
1245 php_pq_object_prophandler_t ph = {0};
1246
1247 zend_hash_init(&php_pqconn_object_prophandlers, 1, NULL, NULL, 1);
1248 INIT_NS_CLASS_ENTRY(ce, "pq", "Connection", php_pqconn_methods);
1249 php_pqconn_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
1250 php_pqconn_class_entry->create_object = php_pqconn_create_object;
1251 memcpy(&php_pqconn_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1252 php_pqconn_object_handlers.read_property = php_pqconn_object_read_prop;
1253 php_pqconn_object_handlers.write_property = php_pqconn_object_write_prop;
1254
1255 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("status"), CONNECTION_BAD, ZEND_ACC_PUBLIC TSRMLS_CC);
1256 ph.read = php_pqconn_object_read_status;
1257 zend_hash_add(&php_pqconn_object_prophandlers, "status", sizeof("status"), (void *) &ph, sizeof(ph), NULL);
1258
1259 zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("transactionStatus"), PQTRANS_UNKNOWN, ZEND_ACC_PUBLIC TSRMLS_CC);
1260 ph.read = php_pqconn_object_read_transaction_status;
1261 zend_hash_add(&php_pqconn_object_prophandlers, "transactionStatus", sizeof("transactionStatus"), (void *) &ph, sizeof(ph), NULL);
1262
1263 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("socket"), ZEND_ACC_PUBLIC TSRMLS_CC);
1264 ph.read = php_pqconn_object_read_socket;
1265 zend_hash_add(&php_pqconn_object_prophandlers, "socket", sizeof("socket"), (void *) &ph, sizeof(ph), NULL);
1266
1267 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC TSRMLS_CC);
1268 ph.read = php_pqconn_object_read_error_message;
1269 zend_hash_add(&php_pqconn_object_prophandlers, "errorMessage", sizeof("errorMessage"), (void *) &ph, sizeof(ph), NULL);
1270
1271 zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("types"), ZEND_ACC_PUBLIC TSRMLS_CC);
1272 ph.read = php_pqconn_object_read_types;
1273 zend_hash_add(&php_pqconn_object_prophandlers, "types", sizeof("types"), (void *) &ph, sizeof(ph), NULL);
1274
1275 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("OK"), CONNECTION_OK TSRMLS_CC);
1276 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("BAD"), CONNECTION_BAD TSRMLS_CC);
1277 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("STARTED"), CONNECTION_STARTED TSRMLS_CC);
1278 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("MADE"), CONNECTION_MADE TSRMLS_CC);
1279 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("AWAITING_RESPONSE"), CONNECTION_AWAITING_RESPONSE TSRMLS_CC);
1280 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("AUTH_OK"), CONNECTION_AUTH_OK TSRMLS_CC);
1281 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("SSL_STARTUP"), CONNECTION_SSL_STARTUP TSRMLS_CC);
1282 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("SETENV"), CONNECTION_SETENV TSRMLS_CC);
1283
1284 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_IDLE"), PQTRANS_IDLE TSRMLS_CC);
1285 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_ACTIVE"), PQTRANS_ACTIVE TSRMLS_CC);
1286 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_INTRANS"), PQTRANS_INTRANS TSRMLS_CC);
1287 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_INERROR"), PQTRANS_INERROR TSRMLS_CC);
1288 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_UNKNOWN"), PQTRANS_UNKNOWN TSRMLS_CC);
1289
1290 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_FAILED"), PGRES_POLLING_FAILED TSRMLS_CC);
1291 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_READING"), PGRES_POLLING_READING TSRMLS_CC);
1292 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_WRITING"), PGRES_POLLING_WRITING TSRMLS_CC);
1293 zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("POLLING_OK"), PGRES_POLLING_OK TSRMLS_CC);
1294
1295 zend_hash_init(&php_pqres_object_prophandlers, 1, NULL, NULL, 1);
1296 memset(&ce, 0, sizeof(ce));
1297 INIT_NS_CLASS_ENTRY(ce, "pq", "Result", php_pqres_methods);
1298 php_pqres_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
1299 php_pqres_class_entry->create_object = php_pqres_create_object;
1300 php_pqres_class_entry->iterator_funcs.funcs = &php_pqres_iterator_funcs;
1301 php_pqres_class_entry->get_iterator = php_pqres_iterator_init;
1302
1303 memcpy(&php_pqres_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1304 php_pqres_object_handlers.read_property = php_pqres_object_read_prop;
1305 php_pqres_object_handlers.write_property = php_pqres_object_write_prop;
1306
1307 zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("status"), ZEND_ACC_PUBLIC TSRMLS_CC);
1308 ph.read = php_pqres_object_read_status;
1309 zend_hash_add(&php_pqres_object_prophandlers, "status", sizeof("status"), (void *) &ph, sizeof(ph), NULL);
1310
1311 zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC TSRMLS_CC);
1312 ph.read = php_pqres_object_read_error_message;
1313 zend_hash_add(&php_pqres_object_prophandlers, "errorMessage", sizeof("errorMessage"), (void *) &ph, sizeof(ph), NULL);
1314
1315 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("numRows"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
1316 ph.read = php_pqres_object_read_num_rows;
1317 zend_hash_add(&php_pqres_object_prophandlers, "numRows", sizeof("numRows"), (void *) &ph, sizeof(ph), NULL);
1318
1319 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("numCols"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
1320 ph.read = php_pqres_object_read_num_cols;
1321 zend_hash_add(&php_pqres_object_prophandlers, "numCols", sizeof("numCols"), (void *) &ph, sizeof(ph), NULL);
1322
1323 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("affectedRows"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
1324 ph.read = php_pqres_object_read_affected_rows;
1325 zend_hash_add(&php_pqres_object_prophandlers, "affectedRows", sizeof("affectedRows"), (void *) &ph, sizeof(ph), NULL);
1326
1327 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("fetchType"), PHP_PQRES_FETCH_ARRAY, ZEND_ACC_PUBLIC TSRMLS_CC);
1328 ph.read = php_pqres_object_read_fetch_type;
1329 ph.write = php_pqres_object_write_fetch_type;
1330 zend_hash_add(&php_pqres_object_prophandlers, "fetchType", sizeof("fetchType"), (void *) &ph, sizeof(ph), NULL);
1331 ph.write = NULL;
1332
1333 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("EMPTY_QUERY"), PGRES_EMPTY_QUERY TSRMLS_CC);
1334 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COMMAND_OK"), PGRES_COMMAND_OK TSRMLS_CC);
1335 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("TUPLES_OK"), PGRES_TUPLES_OK TSRMLS_CC);
1336 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_OUT"), PGRES_COPY_OUT TSRMLS_CC);
1337 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_IN"), PGRES_COPY_IN TSRMLS_CC);
1338 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("BAD_RESPONSE"), PGRES_BAD_RESPONSE TSRMLS_CC);
1339 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("NONFATAL_ERROR"), PGRES_NONFATAL_ERROR TSRMLS_CC);
1340 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FATAL_ERROR"), PGRES_FATAL_ERROR TSRMLS_CC);
1341 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_BOTH"), PGRES_COPY_BOTH TSRMLS_CC);
1342 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("SINGLE_TUPLE"), PGRES_SINGLE_TUPLE TSRMLS_CC);
1343
1344 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_ARRAY"), PHP_PQRES_FETCH_ARRAY TSRMLS_CC);
1345 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_ASSOC"), PHP_PQRES_FETCH_ASSOC TSRMLS_CC);
1346 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_OBJECT"), PHP_PQRES_FETCH_OBJECT TSRMLS_CC);
1347
1348 zend_hash_init(&php_pqstm_object_prophandlers, 1, NULL, NULL, 1);
1349 memset(&ce, 0, sizeof(ce));
1350 INIT_NS_CLASS_ENTRY(ce, "pq", "Statement", php_pqstm_methods);
1351 php_pqstm_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
1352 php_pqstm_class_entry->create_object = php_pqstm_create_object;
1353
1354 memcpy(&php_pqstm_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1355 php_pqstm_object_handlers.read_property = php_pqstm_object_read_prop;
1356 php_pqstm_object_handlers.write_property = php_pqstm_object_write_prop;
1357
1358 zend_declare_property_null(php_pqstm_class_entry, ZEND_STRL("name"), ZEND_ACC_PUBLIC TSRMLS_CC);
1359 ph.read = php_pqstm_object_read_name;
1360 zend_hash_add(&php_pqstm_object_prophandlers, "name", sizeof("name"), (void *) &ph, sizeof(ph), NULL);
1361
1362 zend_declare_property_null(php_pqstm_class_entry, ZEND_STRL("connection"), ZEND_ACC_PUBLIC TSRMLS_CC);
1363 ph.read = php_pqstm_object_read_connection;
1364 zend_hash_add(&php_pqstm_object_prophandlers, "connection", sizeof("connection"), (void *) &ph, sizeof(ph), NULL);
1365
1366 /*
1367 REGISTER_INI_ENTRIES();
1368 */
1369 return SUCCESS;
1370 }
1371 /* }}} */
1372
1373 /* {{{ PHP_MSHUTDOWN_FUNCTION
1374 */
1375 PHP_MSHUTDOWN_FUNCTION(pq)
1376 {
1377 /* uncomment this line if you have INI entries
1378 UNREGISTER_INI_ENTRIES();
1379 */
1380 return SUCCESS;
1381 }
1382 /* }}} */
1383
1384 /* {{{ PHP_MINFO_FUNCTION
1385 */
1386 PHP_MINFO_FUNCTION(pq)
1387 {
1388 php_info_print_table_start();
1389 php_info_print_table_header(2, "pq support", "enabled");
1390 php_info_print_table_end();
1391
1392 /* Remove comments if you have entries in php.ini
1393 DISPLAY_INI_ENTRIES();
1394 */
1395 }
1396 /* }}} */
1397
1398
1399
1400 /*
1401 * Local variables:
1402 * tab-width: 4
1403 * c-basic-offset: 4
1404 * End:
1405 * vim600: noet sw=4 ts=4 fdm=marker
1406 * vim<600: noet sw=4 ts=4
1407 */