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