Merge branch 'master' of git.php.net:/pecl/database/pq
[m6w6/ext-pq] / src / php_pqres.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: pq |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2013, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
16
17 #include <php.h>
18
19 #include <ext/spl/spl_iterators.h>
20 #if HAVE_JSON
21 #include <ext/json/php_json.h>
22 #endif
23 #include <libpq-events.h>
24
25 #include "php_pq.h"
26 #include "php_pq_misc.h"
27 #include "php_pq_object.h"
28 #include "php_pqexc.h"
29 #include "php_pqres.h"
30 #undef PHP_PQ_TYPE
31 #include "php_pq_type.h"
32
33 zend_class_entry *php_pqres_class_entry;
34 static zend_object_handlers php_pqres_object_handlers;
35 static HashTable php_pqres_object_prophandlers;
36 static zend_object_iterator_funcs php_pqres_iterator_funcs;
37
38 static zend_object_iterator *php_pqres_iterator_init(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
39 {
40 php_pqres_iterator_t *iter;
41 zval *prop, *zfetch_type;
42
43 iter = ecalloc(1, sizeof(*iter));
44 iter->zi.funcs = &php_pqres_iterator_funcs;
45 iter->zi.data = object;
46 /* do not addref, because the iterator lives inside this object anyway */
47
48 zfetch_type = prop = zend_read_property(ce, object, ZEND_STRL("fetchType"), 0 TSRMLS_CC);
49 if (Z_TYPE_P(zfetch_type) != IS_LONG) {
50 convert_to_long_ex(&zfetch_type);
51 }
52 iter->fetch_type = Z_LVAL_P(zfetch_type);
53 if (zfetch_type != prop) {
54 zval_ptr_dtor(&zfetch_type);
55 }
56 if (Z_REFCOUNT_P(prop)) {
57 zval_ptr_dtor(&prop);
58 } else {
59 zval_dtor(prop);
60 FREE_ZVAL(prop);
61 }
62
63 return (zend_object_iterator *) iter;
64 }
65
66 static void php_pqres_iterator_dtor(zend_object_iterator *i TSRMLS_DC)
67 {
68 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
69
70 if (iter->current_val) {
71 zval_ptr_dtor(&iter->current_val);
72 iter->current_val = NULL;
73 }
74 efree(iter);
75 }
76
77 static STATUS php_pqres_iterator_valid(zend_object_iterator *i TSRMLS_DC)
78 {
79 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
80 php_pqres_object_t *obj = zend_object_store_get_object(iter->zi.data TSRMLS_CC);
81
82 switch (PQresultStatus(obj->intern->res)) {
83 case PGRES_TUPLES_OK:
84 #if HAVE_PGRES_SINGLE_TUPLE
85 case PGRES_SINGLE_TUPLE:
86 #endif
87 if (PQntuples(obj->intern->res) <= iter->index) {
88 return FAILURE;
89 }
90 break;
91 default:
92 return FAILURE;
93 }
94
95 return SUCCESS;
96 }
97
98 zval *php_pqres_typed_zval(php_pqres_t *res, char *val, size_t len, Oid typ TSRMLS_DC)
99 {
100 zval *zv, **zconv;
101
102 MAKE_STD_ZVAL(zv);
103
104 if (SUCCESS == zend_hash_index_find(&res->converters, typ, (void *) &zconv)) {
105 zval *ztype, *tmp = NULL;
106
107 MAKE_STD_ZVAL(ztype);
108 ZVAL_LONG(ztype, typ);
109 ZVAL_STRINGL(zv, val, len, 1);
110 zend_call_method_with_2_params(zconv, NULL, NULL, "convertfromstring", &tmp, zv, ztype);
111 zval_ptr_dtor(&ztype);
112
113 if (tmp) {
114 zval_ptr_dtor(&zv);
115 zv = tmp;
116 }
117
118 return zv;
119 }
120
121 switch (typ) {
122 case PHP_PQ_OID_BOOL:
123 if (!(res->auto_convert & PHP_PQRES_CONV_BOOL)) {
124 goto noconversion;
125 }
126 ZVAL_BOOL(zv, *val == 't');
127 break;
128 #if SIZEOF_LONG >= 8
129 case PHP_PQ_OID_INT8:
130 case PHP_PQ_OID_TID:
131 #endif
132 case PHP_PQ_OID_INT4:
133 case PHP_PQ_OID_INT2:
134 case PHP_PQ_OID_XID:
135 case PHP_PQ_OID_OID:
136 if (!(res->auto_convert & PHP_PQRES_CONV_INT)) {
137 goto noconversion;
138 }
139 ZVAL_LONG(zv, zend_atol(val, len));
140 break;
141
142 case PHP_PQ_OID_FLOAT4:
143 case PHP_PQ_OID_FLOAT8:
144 if (!(res->auto_convert & PHP_PQRES_CONV_FLOAT)) {
145 goto noconversion;
146 }
147 ZVAL_DOUBLE(zv, zend_strtod(val, NULL));
148 break;
149
150 case PHP_PQ_OID_DATE:
151 if (!(res->auto_convert & PHP_PQRES_CONV_DATETIME)) {
152 goto noconversion;
153 }
154 php_pqdt_from_string(val, len, "Y-m-d", zv TSRMLS_CC);
155 break;
156
157 case PHP_PQ_OID_ABSTIME:
158 if (!(res->auto_convert & PHP_PQRES_CONV_DATETIME)) {
159 goto noconversion;
160 }
161 php_pqdt_from_string(val, len, "Y-m-d H:i:s", zv TSRMLS_CC);
162 break;
163
164 case PHP_PQ_OID_TIMESTAMP:
165 if (!(res->auto_convert & PHP_PQRES_CONV_DATETIME)) {
166 goto noconversion;
167 }
168 php_pqdt_from_string(val, len, "Y-m-d H:i:s.u", zv TSRMLS_CC);
169 break;
170
171 case PHP_PQ_OID_TIMESTAMPTZ:
172 if (!(res->auto_convert & PHP_PQRES_CONV_DATETIME)) {
173 goto noconversion;
174 }
175 php_pqdt_from_string(val, len, "Y-m-d H:i:s.uO", zv TSRMLS_CC);
176 break;
177
178 #if HAVE_JSON && defined(PHP_PQ_OID_JSON)
179 # ifdef PHP_PQ_OID_JSONB
180 case PHP_PQ_OID_JSONB:
181 # endif
182 case PHP_PQ_OID_JSON:
183 if (!(res->auto_convert & PHP_PQRES_CONV_JSON)) {
184 goto noconversion;
185 }
186 php_json_decode_ex(zv, val, len, 0, 512 /* PHP_JSON_DEFAULT_DEPTH */ TSRMLS_CC);
187 break;
188 #endif
189
190 default:
191 if (!(res->auto_convert & PHP_PQRES_CONV_ARRAY)) {
192 goto noconversion;
193 }
194 if (PHP_PQ_TYPE_IS_ARRAY(typ) && (Z_ARRVAL_P(zv) = php_pq_parse_array(res, val, len, PHP_PQ_TYPE_OF_ARRAY(typ) TSRMLS_CC))) {
195 Z_TYPE_P(zv) = IS_ARRAY;
196 } else {
197 noconversion:
198 ZVAL_STRINGL(zv, val, len, 1);
199 }
200 break;
201 }
202
203 return zv;
204 }
205
206 static inline zval *php_pqres_get_col(php_pqres_t *r, unsigned row, unsigned col TSRMLS_DC)
207 {
208 zval *zv;
209
210 if (PQgetisnull(r->res, row, col)) {
211 MAKE_STD_ZVAL(zv);
212 ZVAL_NULL(zv);
213 } else {
214 zv = php_pqres_typed_zval(r, PQgetvalue(r->res, row, col), PQgetlength(r->res, row, col), PQftype(r->res, col) TSRMLS_CC);
215 }
216
217 return zv;
218 }
219
220 static inline void php_pqres_add_col_to_zval(php_pqres_t *r, unsigned row, unsigned col, php_pqres_fetch_t fetch_type, zval *data TSRMLS_DC)
221 {
222 if (PQgetisnull(r->res, row, col)) {
223 switch (fetch_type) {
224 case PHP_PQRES_FETCH_OBJECT:
225 add_property_null(data, PQfname(r->res, col));
226 break;
227
228 case PHP_PQRES_FETCH_ASSOC:
229 add_assoc_null(data, PQfname(r->res, col));
230 break;
231
232 case PHP_PQRES_FETCH_ARRAY:
233 add_index_null(data, col);
234 break;
235 }
236 } else {
237 zval *zv;
238
239 zv = php_pqres_typed_zval(r, PQgetvalue(r->res, row, col), PQgetlength(r->res, row, col), PQftype(r->res, col) TSRMLS_CC);
240
241 switch (fetch_type) {
242 case PHP_PQRES_FETCH_OBJECT:
243 add_property_zval(data, PQfname(r->res, col), zv);
244 zval_ptr_dtor(&zv);
245 break;
246
247 case PHP_PQRES_FETCH_ASSOC:
248 add_assoc_zval(data, PQfname(r->res, col), zv);
249 break;
250
251 case PHP_PQRES_FETCH_ARRAY:
252 add_index_zval(data, col, zv);
253 break;
254 }
255 }
256 }
257
258 zval *php_pqres_row_to_zval(PGresult *res, unsigned row, php_pqres_fetch_t fetch_type, zval **data_ptr TSRMLS_DC)
259 {
260 zval *data = NULL;
261 int c, cols;
262 php_pqres_object_t *res_obj = PQresultInstanceData(res, php_pqconn_event);
263
264 if (data_ptr) {
265 data = *data_ptr;
266 }
267 if (!data) {
268 MAKE_STD_ZVAL(data);
269 if (PHP_PQRES_FETCH_OBJECT == fetch_type) {
270 object_init(data);
271 } else {
272 array_init(data);
273 }
274 if (data_ptr) {
275 *data_ptr = data;
276 }
277 }
278
279 if (PQntuples(res) > row) {
280 for (c = 0, cols = PQnfields(res); c < cols; ++c) {
281 php_pqres_add_col_to_zval(res_obj->intern, row, c, fetch_type, data TSRMLS_CC);
282 }
283 }
284
285 return data;
286 }
287
288 static void php_pqres_iterator_current(zend_object_iterator *i, zval ***data_ptr TSRMLS_DC)
289 {
290 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
291 php_pqres_object_t *obj = zend_object_store_get_object(iter->zi.data TSRMLS_CC);
292
293 if (!iter->current_val) {
294 iter->current_val = php_pqres_row_to_zval(obj->intern->res, iter->index, iter->fetch_type, NULL TSRMLS_CC);
295 }
296 *data_ptr = &iter->current_val;
297 }
298
299 #if PHP_VERSION_ID >= 50500
300 static void php_pqres_iterator_key(zend_object_iterator *i, zval *key TSRMLS_DC)
301 {
302 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
303
304 ZVAL_LONG(key, iter->index);
305 }
306 #else
307 static int php_pqres_iterator_key(zend_object_iterator *i, char **key_str, uint *key_len, ulong *key_num TSRMLS_DC)
308 {
309 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
310
311 *key_num = (ulong) iter->index;
312
313 return HASH_KEY_IS_LONG;
314 }
315 #endif
316
317 static void php_pqres_iterator_invalidate(zend_object_iterator *i TSRMLS_DC)
318 {
319 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
320
321 if (iter->current_val) {
322 zval_ptr_dtor(&iter->current_val);
323 iter->current_val = NULL;
324 }
325 }
326
327 static void php_pqres_iterator_next(zend_object_iterator *i TSRMLS_DC)
328 {
329 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
330
331 php_pqres_iterator_invalidate(i TSRMLS_CC);
332 ++iter->index;
333 }
334
335 static void php_pqres_iterator_rewind(zend_object_iterator *i TSRMLS_DC)
336 {
337 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
338
339 php_pqres_iterator_invalidate(i TSRMLS_CC);
340 iter->index = 0;
341 }
342
343 static zend_object_iterator_funcs php_pqres_iterator_funcs = {
344 php_pqres_iterator_dtor,
345 /* check for end of iteration (FAILURE or SUCCESS if data is valid) */
346 php_pqres_iterator_valid,
347 /* fetch the item data for the current element */
348 php_pqres_iterator_current,
349 /* fetch the key for the current element (return HASH_KEY_IS_STRING or HASH_KEY_IS_LONG) (optional, may be NULL) */
350 php_pqres_iterator_key,
351 /* step forwards to next element */
352 php_pqres_iterator_next,
353 /* rewind to start of data (optional, may be NULL) */
354 php_pqres_iterator_rewind,
355 /* invalidate current value/key (optional, may be NULL) */
356 php_pqres_iterator_invalidate
357 };
358
359 static int php_pqres_count_elements(zval *object, long *count TSRMLS_DC)
360 {
361 php_pqres_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
362
363 if (!obj->intern) {
364 return FAILURE;
365 } else {
366 *count = (long) PQntuples(obj->intern->res);
367 return SUCCESS;
368 }
369 }
370
371 STATUS php_pqres_success(PGresult *res TSRMLS_DC)
372 {
373 zval *zexc;
374
375 switch (PQresultStatus(res)) {
376 case PGRES_BAD_RESPONSE:
377 case PGRES_NONFATAL_ERROR:
378 case PGRES_FATAL_ERROR:
379 zexc = throw_exce(EX_SQL TSRMLS_CC, "%s", PHP_PQresultErrorMessage(res));
380 zend_update_property_string(Z_OBJCE_P(zexc), zexc, ZEND_STRL("sqlstate"), PQresultErrorField(res, PG_DIAG_SQLSTATE) TSRMLS_CC);
381 return FAILURE;
382 default:
383 return SUCCESS;
384 }
385 }
386
387 void php_pqres_init_instance_data(PGresult *res, php_pqconn_object_t *conn_obj, php_pqres_object_t **ptr TSRMLS_DC)
388 {
389 php_pqres_object_t *obj;
390 php_pqres_t *r = ecalloc(1, sizeof(*r));
391
392 r->res = res;
393 zend_hash_init(&r->bound, 0, 0, ZVAL_PTR_DTOR, 0);
394 zend_hash_init(&r->converters, 0, 0, ZVAL_PTR_DTOR, 0);
395 zend_hash_copy(&r->converters, &conn_obj->intern->converters, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
396
397 r->auto_convert = conn_obj->intern->default_auto_convert;
398 r->default_fetch_type = conn_obj->intern->default_fetch_type;
399
400 php_pqres_create_object_ex(php_pqres_class_entry, r, &obj TSRMLS_CC);
401 PQresultSetInstanceData(res, php_pqconn_event, obj);
402
403 if (ptr) {
404 *ptr = obj;
405 }
406 }
407
408 static void php_pqres_object_free(void *o TSRMLS_DC)
409 {
410 php_pqres_object_t *obj = o;
411 #if DBG_GC
412 fprintf(stderr, "FREE res(#%d) %p\n", obj->zv.handle, obj);
413 #endif
414 if (obj->intern) {
415 if (obj->intern->res) {
416 PQresultSetInstanceData(obj->intern->res, php_pqconn_event, NULL);
417 PQclear(obj->intern->res);
418 obj->intern->res = NULL;
419 }
420
421 if (obj->intern->iter) {
422 php_pqres_iterator_dtor((zend_object_iterator *) obj->intern->iter TSRMLS_CC);
423 obj->intern->iter = NULL;
424 }
425
426 zend_hash_destroy(&obj->intern->bound);
427 zend_hash_destroy(&obj->intern->converters);
428
429 efree(obj->intern);
430 obj->intern = NULL;
431 }
432 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
433 efree(obj);
434 }
435
436 zend_object_value php_pqres_create_object_ex(zend_class_entry *ce, php_pqres_t *intern, php_pqres_object_t **ptr TSRMLS_DC)
437 {
438 php_pqres_object_t *o;
439
440 o = ecalloc(1, sizeof(*o));
441 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
442 object_properties_init((zend_object *) o, ce);
443 o->prophandler = &php_pqres_object_prophandlers;
444
445 if (ptr) {
446 *ptr = o;
447 }
448
449 if (intern) {
450 o->intern = intern;
451 }
452
453 o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqres_object_free, NULL TSRMLS_CC);
454 o->zv.handlers = &php_pqres_object_handlers;
455
456 return o->zv;
457 }
458
459 static zend_object_value php_pqres_create_object(zend_class_entry *class_type TSRMLS_DC)
460 {
461 return php_pqres_create_object_ex(class_type, NULL, NULL TSRMLS_CC);
462 }
463
464 static void php_pqres_object_read_status(zval *object, void *o, zval *return_value TSRMLS_DC)
465 {
466 php_pqres_object_t *obj = o;
467
468 RETVAL_LONG(PQresultStatus(obj->intern->res));
469 }
470
471 static void php_pqres_object_read_status_message(zval *object, void *o, zval *return_value TSRMLS_DC)
472 {
473 php_pqres_object_t *obj = o;
474
475 RETVAL_STRING(PQresStatus(PQresultStatus(obj->intern->res))+sizeof("PGRES"), 1);
476 }
477
478 static void php_pqres_object_read_error_message(zval *object, void *o, zval *return_value TSRMLS_DC)
479 {
480 php_pqres_object_t *obj = o;
481 char *error = PHP_PQresultErrorMessage(obj->intern->res);
482
483 if (error) {
484 RETVAL_STRING(error, 1);
485 } else {
486 RETVAL_NULL();
487 }
488 }
489
490 static void php_pqres_object_read_num_rows(zval *object, void *o, zval *return_value TSRMLS_DC)
491 {
492 php_pqres_object_t *obj = o;
493
494 RETVAL_LONG(PQntuples(obj->intern->res));
495 }
496
497 static void php_pqres_object_read_num_cols(zval *object, void *o, zval *return_value TSRMLS_DC)
498 {
499 php_pqres_object_t *obj = o;
500
501 RETVAL_LONG(PQnfields(obj->intern->res));
502 }
503
504 static void php_pqres_object_read_affected_rows(zval *object, void *o, zval *return_value TSRMLS_DC)
505 {
506 php_pqres_object_t *obj = o;
507
508 RETVAL_LONG(atoi(PQcmdTuples(obj->intern->res)));
509 }
510
511 static void php_pqres_object_read_fetch_type(zval *object, void *o, zval *return_value TSRMLS_DC)
512 {
513 php_pqres_object_t *obj = o;
514
515 if (obj->intern->iter) {
516 RETVAL_LONG(obj->intern->iter->fetch_type);
517 } else {
518 RETVAL_LONG(obj->intern->default_fetch_type);
519 }
520 }
521
522 static void php_pqres_object_write_fetch_type(zval *object, void *o, zval *value TSRMLS_DC)
523 {
524 php_pqres_object_t *obj = o;
525 zval *zfetch_type = value;
526
527 if (Z_TYPE_P(value) != IS_LONG) {
528 if (Z_REFCOUNT_P(value) > 1) {
529 zval *tmp;
530 MAKE_STD_ZVAL(tmp);
531 ZVAL_ZVAL(tmp, zfetch_type, 1, 0);
532 convert_to_long(tmp);
533 zfetch_type = tmp;
534 } else {
535 convert_to_long_ex(&zfetch_type);
536 }
537 }
538
539 if (!obj->intern->iter) {
540 obj->intern->iter = (php_pqres_iterator_t *) php_pqres_iterator_init(Z_OBJCE_P(object), object, 0 TSRMLS_CC);
541 obj->intern->iter->zi.funcs->rewind((zend_object_iterator *) obj->intern->iter TSRMLS_CC);
542 }
543 obj->intern->iter->fetch_type = Z_LVAL_P(zfetch_type);
544
545 if (zfetch_type != value) {
546 zval_ptr_dtor(&zfetch_type);
547 }
548 }
549
550 static void php_pqres_object_read_auto_conv(zval *object, void *o, zval *return_value TSRMLS_DC)
551 {
552 php_pqres_object_t *obj = o;
553
554 RETVAL_LONG(obj->intern->auto_convert);
555 }
556
557 static void php_pqres_object_write_auto_conv(zval *object, void *o, zval *value TSRMLS_DC)
558 {
559 php_pqres_object_t *obj = o;
560 zval *zauto_conv = value;
561
562 if (Z_TYPE_P(value) != IS_LONG) {
563 if (Z_REFCOUNT_P(value) > 1) {
564 zval *tmp;
565 MAKE_STD_ZVAL(tmp);
566 ZVAL_ZVAL(tmp, zauto_conv, 1, 0);
567 convert_to_long(tmp);
568 zauto_conv = tmp;
569 } else {
570 convert_to_long_ex(&zauto_conv);
571 }
572 }
573
574 obj->intern->auto_convert = Z_LVAL_P(zauto_conv);
575
576 if (zauto_conv != value) {
577 zval_ptr_dtor(&zauto_conv);
578 }
579 }
580
581 static STATUS php_pqres_iteration(zval *this_ptr, php_pqres_object_t *obj, php_pqres_fetch_t fetch_type, zval ***row TSRMLS_DC)
582 {
583 STATUS rv;
584 php_pqres_fetch_t orig_fetch;
585
586 if (!obj) {
587 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
588 }
589
590 if (obj->intern->iter) {
591 obj->intern->iter->zi.funcs->move_forward((zend_object_iterator *) obj->intern->iter TSRMLS_CC);
592 } else {
593 obj->intern->iter = (php_pqres_iterator_t *) php_pqres_iterator_init(Z_OBJCE_P(getThis()), getThis(), 0 TSRMLS_CC);
594 obj->intern->iter->zi.funcs->rewind((zend_object_iterator *) obj->intern->iter TSRMLS_CC);
595 }
596 orig_fetch = obj->intern->iter->fetch_type;
597 obj->intern->iter->fetch_type = fetch_type;
598 if (SUCCESS == (rv = obj->intern->iter->zi.funcs->valid((zend_object_iterator *) obj->intern->iter TSRMLS_CC))) {
599 obj->intern->iter->zi.funcs->get_current_data((zend_object_iterator *) obj->intern->iter, row TSRMLS_CC);
600 }
601 obj->intern->iter->fetch_type = orig_fetch;
602
603 return rv;
604 }
605
606 typedef struct php_pqres_col {
607 char *name;
608 int num;
609 } php_pqres_col_t;
610
611 static STATUS column_nn(php_pqres_object_t *obj, zval *zcol, php_pqres_col_t *col TSRMLS_DC)
612 {
613 long index = -1;
614 char *name = NULL;
615
616 if (!zcol) {
617 index = 0;
618 } else {
619 switch (Z_TYPE_P(zcol)) {
620 case IS_NULL:
621 index = 0;
622 break;
623
624 case IS_LONG:
625 index = Z_LVAL_P(zcol);
626 break;
627
628 default:
629 convert_to_string(zcol);
630 /* no break */
631
632 case IS_STRING:
633 if (!is_numeric_string(Z_STRVAL_P(zcol), Z_STRLEN_P(zcol), &index, NULL, 0)) {
634 name = Z_STRVAL_P(zcol);
635 }
636 break;
637 }
638 }
639
640 if (name) {
641 col->name = name;
642 col->num = PQfnumber(obj->intern->res, name);
643 } else {
644 col->name = PQfname(obj->intern->res, index);
645 col->num = index;
646 }
647
648 if (!col->name) {
649 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to find column at index %ld", index);
650 return FAILURE;
651 }
652 if (col->num == -1) {
653 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to find column with name '%s'", name);
654 return FAILURE;
655 }
656 return SUCCESS;
657 }
658
659 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_bind, 0, 0, 2)
660 ZEND_ARG_INFO(0, col)
661 ZEND_ARG_INFO(1, ref)
662 ZEND_END_ARG_INFO();
663 static PHP_METHOD(pqres, bind) {
664 zval *zcol, *zref;
665 zend_error_handling zeh;
666 STATUS rv;
667
668 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
669 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/z", &zcol, &zref);
670 zend_restore_error_handling(&zeh TSRMLS_CC);
671
672 if (SUCCESS == rv) {
673 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
674
675 if (!obj->intern) {
676 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized");
677 } else {
678 php_pqres_col_t col;
679
680 if (SUCCESS != column_nn(obj, zcol, &col TSRMLS_CC)) {
681 RETVAL_FALSE;
682 } else {
683 Z_ADDREF_P(zref);
684
685 if (SUCCESS != zend_hash_index_update(&obj->intern->bound, col.num, (void *) &zref, sizeof(zval *), NULL)) {
686 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to bind column %s@%d", col.name, col.num);
687 RETVAL_FALSE;
688 } else {
689 zend_hash_sort(&obj->intern->bound, zend_qsort, compare_index, 0 TSRMLS_CC);
690 RETVAL_TRUE;
691 }
692 }
693 }
694 }
695 }
696
697 static int apply_bound(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
698 {
699 zval **zvalue, **zbound = p;
700 zval **zrow = va_arg(argv, zval **);
701 STATUS *rv = va_arg(argv, STATUS *);
702
703 if (SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(zrow), key->h, (void *) &zvalue)) {
704 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to find column ad index %lu", key->h);
705 *rv = FAILURE;
706 return ZEND_HASH_APPLY_STOP;
707 } else {
708 zval_dtor(*zbound);
709 ZVAL_COPY_VALUE(*zbound, *zvalue);
710 ZVAL_NULL(*zvalue);
711 zval_ptr_dtor(zvalue);
712 Z_ADDREF_P(*zbound);
713 *zvalue = *zbound;
714 *rv = SUCCESS;
715 return ZEND_HASH_APPLY_KEEP;
716 }
717 }
718
719 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_bound, 0, 0, 0)
720 ZEND_END_ARG_INFO();
721 static PHP_METHOD(pqres, fetchBound) {
722 zend_error_handling zeh;
723 STATUS rv;
724
725 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
726 rv = zend_parse_parameters_none();
727 zend_restore_error_handling(&zeh TSRMLS_CC);
728
729 if (SUCCESS == rv) {
730 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
731
732 if (!obj->intern) {
733 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized");
734 } else {
735 zval **row = NULL;
736
737 if (SUCCESS == php_pqres_iteration(getThis(), obj, PHP_PQRES_FETCH_ARRAY, &row TSRMLS_CC) && row) {
738 zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh TSRMLS_CC);
739 zend_hash_apply_with_arguments(&obj->intern->bound TSRMLS_CC, apply_bound, 2, row, &rv);
740 zend_restore_error_handling(&zeh TSRMLS_CC);
741
742 if (SUCCESS != rv) {
743 zval_ptr_dtor(row);
744 } else {
745 RETVAL_ZVAL(*row, 1, 0);
746 }
747 }
748 }
749 }
750 }
751
752 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_row, 0, 0, 0)
753 ZEND_ARG_INFO(0, fetch_type)
754 ZEND_END_ARG_INFO();
755 static PHP_METHOD(pqres, fetchRow) {
756 zend_error_handling zeh;
757 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
758 long fetch_type = -1;
759 STATUS rv;
760
761 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
762 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &fetch_type);
763 zend_restore_error_handling(&zeh TSRMLS_CC);
764
765 if (SUCCESS == rv) {
766 if (!obj->intern) {
767 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized");
768 } else {
769 zval **row = NULL;
770
771 if (fetch_type == -1) {
772 fetch_type = obj->intern->iter ? obj->intern->iter->fetch_type : obj->intern->default_fetch_type;
773 }
774
775 zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh TSRMLS_CC);
776 php_pqres_iteration(getThis(), obj, fetch_type, &row TSRMLS_CC);
777 zend_restore_error_handling(&zeh TSRMLS_CC);
778
779 if (row) {
780 RETVAL_ZVAL(*row, 1, 0);
781 }
782 }
783 }
784 }
785
786 static zval **column_at(zval *row, int col TSRMLS_DC)
787 {
788 zval **data = NULL;
789 HashTable *ht = HASH_OF(row);
790 int count = zend_hash_num_elements(ht);
791
792 if (col >= count) {
793 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Column index %d exceeds column count %d", col, count);
794 } else {
795 zend_hash_internal_pointer_reset(ht);
796 while (col-- > 0) {
797 zend_hash_move_forward(ht);
798 }
799 zend_hash_get_current_data(ht, (void *) &data);
800 }
801 return data;
802 }
803
804 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_col, 0, 0, 1)
805 ZEND_ARG_INFO(1, ref)
806 ZEND_ARG_INFO(0, col)
807 ZEND_END_ARG_INFO();
808 static PHP_METHOD(pqres, fetchCol) {
809 zend_error_handling zeh;
810 zval *zcol = NULL, *zref;
811 STATUS rv;
812
813 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
814 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z/!", &zref, &zcol);
815 zend_restore_error_handling(&zeh TSRMLS_CC);
816
817 if (SUCCESS == rv) {
818 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
819
820 if (!obj->intern) {
821 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized");
822 } else {
823 zval **row = NULL;
824
825 zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh TSRMLS_CC);
826 php_pqres_iteration(getThis(), obj, obj->intern->iter ? obj->intern->iter->fetch_type : 0, &row TSRMLS_CC);
827 if (row) {
828 php_pqres_col_t col;
829
830 if (SUCCESS != column_nn(obj, zcol, &col TSRMLS_CC)) {
831 RETVAL_FALSE;
832 } else {
833 zval **zres = column_at(*row, col.num TSRMLS_CC);
834
835 if (!zres) {
836 RETVAL_FALSE;
837 } else {
838 zval_dtor(zref);
839 ZVAL_ZVAL(zref, *zres, 1, 0);
840 RETVAL_TRUE;
841 }
842 }
843 }
844 zend_restore_error_handling(&zeh TSRMLS_CC);
845 }
846 }
847 }
848
849 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_all_cols, 0, 0, 0)
850 ZEND_ARG_INFO(0, col)
851 ZEND_END_ARG_INFO();
852 static PHP_METHOD(pqres, fetchAllCols) {
853 zend_error_handling zeh;
854 zval *zcol = NULL;
855 STATUS rv;
856
857 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
858 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!", &zcol);
859 zend_restore_error_handling(&zeh TSRMLS_CC);
860
861 if (SUCCESS == rv) {
862 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
863
864 if (!obj->intern) {
865 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized");
866 } else {
867 php_pqres_col_t col;
868
869 zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh TSRMLS_CC);
870 if (SUCCESS == column_nn(obj, zcol, &col TSRMLS_CC)) {
871 int r, rows = PQntuples(obj->intern->res);
872
873 array_init(return_value);
874 for (r = 0; r < rows; ++r) {
875 add_next_index_zval(return_value, php_pqres_get_col(obj->intern, r, col.num TSRMLS_CC));
876 }
877 }
878 zend_restore_error_handling(&zeh TSRMLS_CC);
879 }
880 }
881 }
882
883 struct apply_to_col_arg {
884 php_pqres_object_t *obj;
885 php_pqres_col_t *cols;
886 STATUS status;
887 };
888
889 static int apply_to_col(void *p, void *a TSRMLS_DC)
890 {
891 zval **c = p;
892 struct apply_to_col_arg *arg = a;
893
894 if (SUCCESS != column_nn(arg->obj, *c, arg->cols TSRMLS_CC)) {
895 arg->status = FAILURE;
896 return ZEND_HASH_APPLY_STOP;
897 } else {
898 arg->status = SUCCESS;
899 ++arg->cols;
900 return ZEND_HASH_APPLY_KEEP;
901 }
902 }
903
904 static php_pqres_col_t *php_pqres_convert_to_cols(php_pqres_object_t *obj, HashTable *ht TSRMLS_DC)
905 {
906 struct apply_to_col_arg arg = {NULL};
907 php_pqres_col_t *tmp;
908
909 arg.obj = obj;
910 arg.cols = ecalloc(zend_hash_num_elements(ht), sizeof(*tmp));
911 tmp = arg.cols;
912 zend_hash_apply_with_argument(ht, apply_to_col, &arg TSRMLS_CC);
913
914 if (SUCCESS == arg.status) {
915 return tmp;
916 } else {
917 efree(tmp);
918 return NULL;
919 }
920 }
921
922 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_map, 0, 0, 0)
923 ZEND_ARG_INFO(0, keys)
924 ZEND_ARG_INFO(0, vals)
925 ZEND_ARG_INFO(0, fetch_type)
926 ZEND_END_ARG_INFO();
927 static PHP_METHOD(pqres, map) {
928 zend_error_handling zeh;
929 zval *zkeys = 0, *zvals = 0;
930 long fetch_type = -1;
931 STATUS rv;
932
933 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
934 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z/!z/!l", &zkeys, &zvals, &fetch_type);
935 zend_restore_error_handling(&zeh TSRMLS_CC);
936
937 if (SUCCESS == rv) {
938 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
939
940 if (!obj->intern) {
941 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized");
942 } else {
943 int ks = 0, vs = 0;
944 php_pqres_col_t def = {PQfname(obj->intern->res, 0), 0}, *keys = NULL, *vals = NULL;
945
946 if (zkeys) {
947 convert_to_array(zkeys);
948
949 if ((ks = zend_hash_num_elements(Z_ARRVAL_P(zkeys)))) {
950 keys = php_pqres_convert_to_cols(obj, Z_ARRVAL_P(zkeys) TSRMLS_CC);
951 } else {
952 ks = 1;
953 keys = &def;
954 }
955 } else {
956 ks = 1;
957 keys = &def;
958 }
959 if (zvals) {
960 convert_to_array(zvals);
961
962 if ((vs = zend_hash_num_elements(Z_ARRVAL_P(zvals)))) {
963 vals = php_pqres_convert_to_cols(obj, Z_ARRVAL_P(zvals) TSRMLS_CC);
964 }
965 }
966
967 if (fetch_type == -1) {
968 fetch_type = obj->intern->iter ? obj->intern->iter->fetch_type : obj->intern->default_fetch_type;
969 }
970
971 if (keys) {
972 int rows, r;
973 zval **cur;
974
975 switch (fetch_type) {
976 case PHP_PQRES_FETCH_ARRAY:
977 case PHP_PQRES_FETCH_ASSOC:
978 array_init(return_value);
979 break;
980 case PHP_PQRES_FETCH_OBJECT:
981 object_init(return_value);
982 break;
983 }
984 for (r = 0, rows = PQntuples(obj->intern->res); r < rows; ++r) {
985 int k, v;
986
987 cur = &return_value;
988 for (k = 0; k < ks; ++k) {
989 char *key = PQgetvalue(obj->intern->res, r, keys[k].num);
990 int len = PQgetlength(obj->intern->res, r, keys[k].num);
991
992 if (SUCCESS != zend_symtable_find(HASH_OF(*cur), key, len + 1, (void *) &cur)) {
993 zval *tmp;
994
995 MAKE_STD_ZVAL(tmp);
996 switch (fetch_type) {
997 case PHP_PQRES_FETCH_ARRAY:
998 case PHP_PQRES_FETCH_ASSOC:
999 array_init(tmp);
1000 break;
1001 case PHP_PQRES_FETCH_OBJECT:
1002 object_init(tmp);
1003 break;
1004 }
1005 if (SUCCESS != zend_symtable_update(HASH_OF(*cur), key, len + 1, (void *) &tmp, sizeof(zval *), (void *) &cur)) {
1006 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to create map");
1007 goto err;
1008 }
1009 }
1010 }
1011 if (vals && vs) {
1012 for (v = 0; v < vs; ++v) {
1013 char *val = PQgetvalue(obj->intern->res, r, vals[v].num);
1014 int len = PQgetlength(obj->intern->res, r, vals[v].num);
1015
1016 switch (fetch_type) {
1017 case PHP_PQRES_FETCH_ARRAY:
1018 add_index_stringl(*cur, vals[v].num, val, len, 1);
1019 break;
1020 case PHP_PQRES_FETCH_ASSOC:
1021 add_assoc_stringl(*cur, vals[v].name, val, len, 1);
1022 break;
1023 case PHP_PQRES_FETCH_OBJECT:
1024 add_property_stringl(*cur, vals[v].name, val, len, 1);
1025 break;
1026 }
1027 }
1028 } else {
1029 php_pqres_row_to_zval(obj->intern->res, r, fetch_type, cur TSRMLS_CC);
1030 }
1031 }
1032 }
1033
1034 err:
1035 if (keys && keys != &def) {
1036 efree(keys);
1037 }
1038 if (vals) {
1039 efree(vals);
1040 }
1041 }
1042 }
1043 }
1044
1045 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_all, 0, 0, 0)
1046 ZEND_ARG_INFO(0, fetch_type)
1047 ZEND_END_ARG_INFO();
1048 static PHP_METHOD(pqres, fetchAll) {
1049 zend_error_handling zeh;
1050 long fetch_type = -1;
1051 STATUS rv;
1052
1053 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1054 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &fetch_type);
1055 zend_restore_error_handling(&zeh TSRMLS_CC);
1056
1057 if (SUCCESS == rv) {
1058 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1059 if (!obj->intern) {
1060 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized");
1061 } else {
1062 int r, rows = PQntuples(obj->intern->res);
1063
1064 if (fetch_type == -1) {
1065 fetch_type = obj->intern->iter ? obj->intern->iter->fetch_type : obj->intern->default_fetch_type;
1066 }
1067
1068 array_init(return_value);
1069 for (r = 0; r < rows; ++r) {
1070 add_next_index_zval(return_value, php_pqres_row_to_zval(obj->intern->res, r, fetch_type, NULL TSRMLS_CC));
1071 }
1072 }
1073 }
1074 }
1075
1076 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_count, 0, 0, 0)
1077 ZEND_END_ARG_INFO();
1078 static PHP_METHOD(pqres, count) {
1079 zend_error_handling zeh;
1080 STATUS rv;
1081
1082 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1083 rv = zend_parse_parameters_none();
1084 zend_restore_error_handling(&zeh TSRMLS_CC);
1085
1086 if (SUCCESS == rv) {
1087 long count;
1088
1089 if (SUCCESS != php_pqres_count_elements(getThis(), &count TSRMLS_CC)) {
1090 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized");
1091 } else {
1092 RETVAL_LONG(count);
1093 }
1094 }
1095 }
1096
1097 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_desc, 0, 0, 0)
1098 ZEND_END_ARG_INFO();
1099 static PHP_METHOD(pqres, desc) {
1100 zend_error_handling zeh;
1101 STATUS rv;
1102
1103 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1104 rv = zend_parse_parameters_none();
1105 zend_restore_error_handling(&zeh TSRMLS_CC);
1106
1107 if (SUCCESS == rv) {
1108 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1109
1110 if (!obj->intern) {
1111 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized");
1112 } else {
1113 int p, params;
1114
1115 array_init(return_value);
1116 for (p = 0, params = PQnparams(obj->intern->res); p < params; ++p) {
1117 add_next_index_long(return_value, PQparamtype(obj->intern->res, p));
1118 }
1119 }
1120 }
1121 }
1122
1123 static zend_function_entry php_pqres_methods[] = {
1124 PHP_ME(pqres, bind, ai_pqres_bind, ZEND_ACC_PUBLIC)
1125 PHP_ME(pqres, fetchBound, ai_pqres_fetch_bound, ZEND_ACC_PUBLIC)
1126 PHP_ME(pqres, fetchRow, ai_pqres_fetch_row, ZEND_ACC_PUBLIC)
1127 PHP_ME(pqres, fetchCol, ai_pqres_fetch_col, ZEND_ACC_PUBLIC)
1128 PHP_ME(pqres, fetchAll, ai_pqres_fetch_all, ZEND_ACC_PUBLIC)
1129 PHP_ME(pqres, fetchAllCols, ai_pqres_fetch_all_cols, ZEND_ACC_PUBLIC)
1130 PHP_ME(pqres, count, ai_pqres_count, ZEND_ACC_PUBLIC)
1131 PHP_ME(pqres, map, ai_pqres_map, ZEND_ACC_PUBLIC)
1132 PHP_ME(pqres, desc, ai_pqres_desc, ZEND_ACC_PUBLIC)
1133 {0}
1134 };
1135
1136 PHP_MSHUTDOWN_FUNCTION(pqres)
1137 {
1138 zend_hash_destroy(&php_pqres_object_prophandlers);
1139 return SUCCESS;
1140 }
1141
1142 PHP_MINIT_FUNCTION(pqres)
1143 {
1144 zend_class_entry ce = {0};
1145 php_pq_object_prophandler_t ph = {0};
1146
1147 INIT_NS_CLASS_ENTRY(ce, "pq", "Result", php_pqres_methods);
1148 php_pqres_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
1149 php_pqres_class_entry->create_object = php_pqres_create_object;
1150 php_pqres_class_entry->iterator_funcs.funcs = &php_pqres_iterator_funcs;
1151 php_pqres_class_entry->get_iterator = php_pqres_iterator_init;
1152 zend_class_implements(php_pqres_class_entry TSRMLS_CC, 2, zend_ce_traversable, spl_ce_Countable);
1153
1154 memcpy(&php_pqres_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1155 php_pqres_object_handlers.read_property = php_pq_object_read_prop;
1156 php_pqres_object_handlers.write_property = php_pq_object_write_prop;
1157 php_pqres_object_handlers.clone_obj = NULL;
1158 php_pqres_object_handlers.get_property_ptr_ptr = NULL;
1159 php_pqres_object_handlers.get_gc = NULL;
1160 php_pqres_object_handlers.get_debug_info = php_pq_object_debug_info;
1161 php_pqres_object_handlers.get_properties = php_pq_object_properties;
1162 php_pqres_object_handlers.count_elements = php_pqres_count_elements;
1163
1164 zend_hash_init(&php_pqres_object_prophandlers, 8, NULL, NULL, 1);
1165
1166 zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("status"), ZEND_ACC_PUBLIC TSRMLS_CC);
1167 ph.read = php_pqres_object_read_status;
1168 zend_hash_add(&php_pqres_object_prophandlers, "status", sizeof("status"), (void *) &ph, sizeof(ph), NULL);
1169
1170 zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("statusMessage"), ZEND_ACC_PUBLIC TSRMLS_CC);
1171 ph.read = php_pqres_object_read_status_message;
1172 zend_hash_add(&php_pqres_object_prophandlers, "statusMessage", sizeof("statusMessage"), (void *) &ph, sizeof(ph), NULL);
1173
1174 zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC TSRMLS_CC);
1175 ph.read = php_pqres_object_read_error_message;
1176 zend_hash_add(&php_pqres_object_prophandlers, "errorMessage", sizeof("errorMessage"), (void *) &ph, sizeof(ph), NULL);
1177
1178 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("numRows"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
1179 ph.read = php_pqres_object_read_num_rows;
1180 zend_hash_add(&php_pqres_object_prophandlers, "numRows", sizeof("numRows"), (void *) &ph, sizeof(ph), NULL);
1181
1182 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("numCols"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
1183 ph.read = php_pqres_object_read_num_cols;
1184 zend_hash_add(&php_pqres_object_prophandlers, "numCols", sizeof("numCols"), (void *) &ph, sizeof(ph), NULL);
1185
1186 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("affectedRows"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
1187 ph.read = php_pqres_object_read_affected_rows;
1188 zend_hash_add(&php_pqres_object_prophandlers, "affectedRows", sizeof("affectedRows"), (void *) &ph, sizeof(ph), NULL);
1189
1190 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("fetchType"), PHP_PQRES_FETCH_ARRAY, ZEND_ACC_PUBLIC TSRMLS_CC);
1191 ph.read = php_pqres_object_read_fetch_type;
1192 ph.write = php_pqres_object_write_fetch_type;
1193 zend_hash_add(&php_pqres_object_prophandlers, "fetchType", sizeof("fetchType"), (void *) &ph, sizeof(ph), NULL);
1194 ph.write = NULL;
1195
1196 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("autoConvert"), PHP_PQRES_CONV_ALL, ZEND_ACC_PUBLIC TSRMLS_CC);
1197 ph.read = php_pqres_object_read_auto_conv;
1198 ph.write = php_pqres_object_write_auto_conv;
1199 zend_hash_add(&php_pqres_object_prophandlers, "autoConvert", sizeof("autoConvert"), (void *) &ph, sizeof(ph), NULL);
1200 ph.write = NULL;
1201
1202 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("EMPTY_QUERY"), PGRES_EMPTY_QUERY TSRMLS_CC);
1203 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COMMAND_OK"), PGRES_COMMAND_OK TSRMLS_CC);
1204 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("TUPLES_OK"), PGRES_TUPLES_OK TSRMLS_CC);
1205 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_OUT"), PGRES_COPY_OUT TSRMLS_CC);
1206 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_IN"), PGRES_COPY_IN TSRMLS_CC);
1207 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("BAD_RESPONSE"), PGRES_BAD_RESPONSE TSRMLS_CC);
1208 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("NONFATAL_ERROR"), PGRES_NONFATAL_ERROR TSRMLS_CC);
1209 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FATAL_ERROR"), PGRES_FATAL_ERROR TSRMLS_CC);
1210 #ifdef HAVE_PGRES_COPY_BOTH
1211 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_BOTH"), PGRES_COPY_BOTH TSRMLS_CC);
1212 #endif
1213 #if HAVE_PGRES_SINGLE_TUPLE
1214 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("SINGLE_TUPLE"), PGRES_SINGLE_TUPLE TSRMLS_CC);
1215 #endif
1216
1217 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_ARRAY"), PHP_PQRES_FETCH_ARRAY TSRMLS_CC);
1218 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_ASSOC"), PHP_PQRES_FETCH_ASSOC TSRMLS_CC);
1219 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_OBJECT"), PHP_PQRES_FETCH_OBJECT TSRMLS_CC);
1220
1221 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_BOOL"), PHP_PQRES_CONV_BOOL TSRMLS_CC);
1222 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_INT"), PHP_PQRES_CONV_INT TSRMLS_CC);
1223 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_FLOAT"), PHP_PQRES_CONV_FLOAT TSRMLS_CC);
1224 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_SCALAR"), PHP_PQRES_CONV_SCALAR TSRMLS_CC);
1225 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_ARRAY"), PHP_PQRES_CONV_ARRAY TSRMLS_CC);
1226 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_DATETIME"), PHP_PQRES_CONV_DATETIME TSRMLS_CC);
1227 #if HAVE_JSON
1228 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_JSON"), PHP_PQRES_CONV_JSON TSRMLS_CC);
1229 #endif
1230 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_ALL"), PHP_PQRES_CONV_ALL TSRMLS_CC);
1231
1232 return SUCCESS;
1233 }
1234
1235 /*
1236 * Local variables:
1237 * tab-width: 4
1238 * c-basic-offset: 4
1239 * End:
1240 * vim600: noet sw=4 ts=4 fdm=marker
1241 * vim<600: noet sw=4 ts=4
1242 */