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