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