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