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