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