Added pq\Result::$diag, listing PQresultErrorField details
[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 {PG_DIAG_SEVERITY, "severity"},
523 {PG_DIAG_SQLSTATE, "sqlstate"},
524 {PG_DIAG_MESSAGE_PRIMARY, "message_primary"},
525 {PG_DIAG_MESSAGE_DETAIL, "message_detail"},
526 {PG_DIAG_MESSAGE_HINT, "message_hint"},
527 {PG_DIAG_STATEMENT_POSITION,"statement_position"},
528 {PG_DIAG_INTERNAL_POSITION, "internal_position"},
529 {PG_DIAG_INTERNAL_QUERY, "internal_query"},
530 {PG_DIAG_CONTEXT, "context"},
531 {PG_DIAG_SCHEMA_NAME, "schema_name"},
532 {PG_DIAG_TABLE_NAME, "table_name"},
533 {PG_DIAG_COLUMN_NAME, "column_name"},
534 {PG_DIAG_DATATYPE_NAME, "datatype_name"},
535 {PG_DIAG_CONSTRAINT_NAME, "constraint_name"},
536 {PG_DIAG_SOURCE_FILE, "source_file"},
537 {PG_DIAG_SOURCE_LINE, "source_line"},
538 {PG_DIAG_SOURCE_FUNCTION, "source_function"}
539 };
540
541 array_init_size(return_value, 32);
542 for (i = 0; i < sizeof(diag)/sizeof(diag[0]); ++i) {
543 char *value = PQresultErrorField(obj->intern->res, diag[i].code);
544
545 if (value) {
546 add_assoc_string(return_value, diag[i].name, value, 1);
547 } else {
548 add_assoc_null(return_value, diag[i].name);
549 }
550 }
551 }
552
553 static void php_pqres_object_read_num_rows(zval *object, void *o, zval *return_value TSRMLS_DC)
554 {
555 php_pqres_object_t *obj = o;
556
557 RETVAL_LONG(PQntuples(obj->intern->res));
558 }
559
560 static void php_pqres_object_read_num_cols(zval *object, void *o, zval *return_value TSRMLS_DC)
561 {
562 php_pqres_object_t *obj = o;
563
564 RETVAL_LONG(PQnfields(obj->intern->res));
565 }
566
567 static void php_pqres_object_read_affected_rows(zval *object, void *o, zval *return_value TSRMLS_DC)
568 {
569 php_pqres_object_t *obj = o;
570
571 RETVAL_LONG(atoi(PQcmdTuples(obj->intern->res)));
572 }
573
574 static void php_pqres_object_read_fetch_type(zval *object, void *o, zval *return_value TSRMLS_DC)
575 {
576 php_pqres_object_t *obj = o;
577
578 RETVAL_LONG(php_pqres_fetch_type(obj->intern));
579 }
580
581 static void php_pqres_object_write_fetch_type(zval *object, void *o, zval *value TSRMLS_DC)
582 {
583 php_pqres_object_t *obj = o;
584 zval *zfetch_type = value;
585
586 if (Z_TYPE_P(value) != IS_LONG) {
587 if (Z_REFCOUNT_P(value) > 1) {
588 zval *tmp;
589 MAKE_STD_ZVAL(tmp);
590 ZVAL_ZVAL(tmp, zfetch_type, 1, 0);
591 convert_to_long(tmp);
592 zfetch_type = tmp;
593 } else {
594 convert_to_long_ex(&zfetch_type);
595 }
596 }
597
598 if (!obj->intern->iter) {
599 obj->intern->iter = (php_pqres_iterator_t *) php_pqres_iterator_init(Z_OBJCE_P(object), object, 0 TSRMLS_CC);
600 obj->intern->iter->zi.funcs->rewind((zend_object_iterator *) obj->intern->iter TSRMLS_CC);
601 }
602 obj->intern->iter->fetch_type = Z_LVAL_P(zfetch_type);
603
604 if (zfetch_type != value) {
605 zval_ptr_dtor(&zfetch_type);
606 }
607 }
608
609 static void php_pqres_object_read_auto_conv(zval *object, void *o, zval *return_value TSRMLS_DC)
610 {
611 php_pqres_object_t *obj = o;
612
613 RETVAL_LONG(obj->intern->auto_convert);
614 }
615
616 static void php_pqres_object_write_auto_conv(zval *object, void *o, zval *value TSRMLS_DC)
617 {
618 php_pqres_object_t *obj = o;
619 zval *zauto_conv = value;
620
621 if (Z_TYPE_P(value) != IS_LONG) {
622 if (Z_REFCOUNT_P(value) > 1) {
623 zval *tmp;
624 MAKE_STD_ZVAL(tmp);
625 ZVAL_ZVAL(tmp, zauto_conv, 1, 0);
626 convert_to_long(tmp);
627 zauto_conv = tmp;
628 } else {
629 convert_to_long_ex(&zauto_conv);
630 }
631 }
632
633 obj->intern->auto_convert = Z_LVAL_P(zauto_conv);
634
635 if (zauto_conv != value) {
636 zval_ptr_dtor(&zauto_conv);
637 }
638 }
639
640 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)
641 {
642 ZEND_RESULT_CODE rv;
643 php_pqres_fetch_t orig_fetch;
644
645 if (!obj) {
646 obj = zend_object_store_get_object(getThis() TSRMLS_CC);
647 }
648
649 if (obj->intern->iter) {
650 obj->intern->iter->zi.funcs->move_forward((zend_object_iterator *) obj->intern->iter TSRMLS_CC);
651 } else {
652 obj->intern->iter = (php_pqres_iterator_t *) php_pqres_iterator_init(Z_OBJCE_P(getThis()), getThis(), 0 TSRMLS_CC);
653 obj->intern->iter->zi.funcs->rewind((zend_object_iterator *) obj->intern->iter TSRMLS_CC);
654 }
655 orig_fetch = obj->intern->iter->fetch_type;
656 obj->intern->iter->fetch_type = fetch_type;
657 if (SUCCESS == (rv = obj->intern->iter->zi.funcs->valid((zend_object_iterator *) obj->intern->iter TSRMLS_CC))) {
658 obj->intern->iter->zi.funcs->get_current_data((zend_object_iterator *) obj->intern->iter, row TSRMLS_CC);
659 }
660 obj->intern->iter->fetch_type = orig_fetch;
661
662 return rv;
663 }
664
665 typedef struct php_pqres_col {
666 char *name;
667 int num;
668 } php_pqres_col_t;
669
670 static ZEND_RESULT_CODE column_nn(php_pqres_object_t *obj, zval *zcol, php_pqres_col_t *col TSRMLS_DC)
671 {
672 long index = -1;
673 char *name = NULL;
674
675 if (!zcol) {
676 index = 0;
677 } else {
678 switch (Z_TYPE_P(zcol)) {
679 case IS_NULL:
680 index = 0;
681 break;
682
683 case IS_LONG:
684 index = Z_LVAL_P(zcol);
685 break;
686
687 default:
688 convert_to_string(zcol);
689 /* no break */
690
691 case IS_STRING:
692 if (!is_numeric_string(Z_STRVAL_P(zcol), Z_STRLEN_P(zcol), &index, NULL, 0)) {
693 name = Z_STRVAL_P(zcol);
694 }
695 break;
696 }
697 }
698
699 if (name) {
700 col->name = name;
701 col->num = PQfnumber(obj->intern->res, name);
702 } else {
703 col->name = PQfname(obj->intern->res, index);
704 col->num = index;
705 }
706
707 if (!col->name) {
708 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to find column at index %ld", index);
709 return FAILURE;
710 }
711 if (col->num == -1) {
712 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to find column with name '%s'", name);
713 return FAILURE;
714 }
715 return SUCCESS;
716 }
717
718 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_bind, 0, 0, 2)
719 ZEND_ARG_INFO(0, col)
720 ZEND_ARG_INFO(1, ref)
721 ZEND_END_ARG_INFO();
722 static PHP_METHOD(pqres, bind) {
723 zval *zcol, *zref;
724 zend_error_handling zeh;
725 ZEND_RESULT_CODE rv;
726
727 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
728 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/z", &zcol, &zref);
729 zend_restore_error_handling(&zeh TSRMLS_CC);
730
731 if (SUCCESS == rv) {
732 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
733
734 if (!obj->intern) {
735 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized");
736 } else {
737 php_pqres_col_t col;
738
739 if (SUCCESS != column_nn(obj, zcol, &col TSRMLS_CC)) {
740 RETVAL_FALSE;
741 } else {
742 Z_ADDREF_P(zref);
743
744 if (SUCCESS != zend_hash_index_update(&obj->intern->bound, col.num, (void *) &zref, sizeof(zval *), NULL)) {
745 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to bind column %s@%d", col.name, col.num);
746 RETVAL_FALSE;
747 } else {
748 zend_hash_sort(&obj->intern->bound, zend_qsort, php_pq_compare_index, 0 TSRMLS_CC);
749 RETVAL_TRUE;
750 }
751 }
752 }
753 }
754 }
755
756 static int apply_bound(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
757 {
758 zval **zvalue, **zbound = p;
759 zval **zrow = va_arg(argv, zval **);
760 ZEND_RESULT_CODE *rv = va_arg(argv, ZEND_RESULT_CODE *);
761
762 if (SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(zrow), key->h, (void *) &zvalue)) {
763 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to find column ad index %lu", key->h);
764 *rv = FAILURE;
765 return ZEND_HASH_APPLY_STOP;
766 } else {
767 zval_dtor(*zbound);
768 ZVAL_COPY_VALUE(*zbound, *zvalue);
769 ZVAL_NULL(*zvalue);
770 zval_ptr_dtor(zvalue);
771 Z_ADDREF_P(*zbound);
772 *zvalue = *zbound;
773 *rv = SUCCESS;
774 return ZEND_HASH_APPLY_KEEP;
775 }
776 }
777
778 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_bound, 0, 0, 0)
779 ZEND_END_ARG_INFO();
780 static PHP_METHOD(pqres, fetchBound) {
781 zend_error_handling zeh;
782 ZEND_RESULT_CODE rv;
783
784 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
785 rv = zend_parse_parameters_none();
786 zend_restore_error_handling(&zeh TSRMLS_CC);
787
788 if (SUCCESS == rv) {
789 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
790
791 if (!obj->intern) {
792 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized");
793 } else {
794 zval **row = NULL;
795
796 if (SUCCESS == php_pqres_iteration(getThis(), obj, PHP_PQRES_FETCH_ARRAY, &row TSRMLS_CC) && row) {
797 zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh TSRMLS_CC);
798 zend_hash_apply_with_arguments(&obj->intern->bound TSRMLS_CC, apply_bound, 2, row, &rv);
799 zend_restore_error_handling(&zeh TSRMLS_CC);
800
801 if (SUCCESS != rv) {
802 zval_ptr_dtor(row);
803 } else {
804 RETVAL_ZVAL(*row, 1, 0);
805 }
806 }
807 }
808 }
809 }
810
811 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_row, 0, 0, 0)
812 ZEND_ARG_INFO(0, fetch_type)
813 ZEND_END_ARG_INFO();
814 static PHP_METHOD(pqres, fetchRow) {
815 zend_error_handling zeh;
816 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
817 long fetch_type = -1;
818 ZEND_RESULT_CODE rv;
819
820 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
821 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &fetch_type);
822 zend_restore_error_handling(&zeh TSRMLS_CC);
823
824 if (SUCCESS == rv) {
825 if (!obj->intern) {
826 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized");
827 } else {
828 zval **row = NULL;
829
830 if (fetch_type == -1) {
831 fetch_type = php_pqres_fetch_type(obj->intern);
832 }
833
834 zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh TSRMLS_CC);
835 php_pqres_iteration(getThis(), obj, fetch_type, &row TSRMLS_CC);
836 zend_restore_error_handling(&zeh TSRMLS_CC);
837
838 if (row) {
839 RETVAL_ZVAL(*row, 1, 0);
840 }
841 }
842 }
843 }
844
845 static zval **column_at(zval *row, int col TSRMLS_DC)
846 {
847 zval **data = NULL;
848 HashTable *ht = HASH_OF(row);
849 int count = zend_hash_num_elements(ht);
850
851 if (col >= count) {
852 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Column index %d exceeds column count %d", col, count);
853 } else {
854 zend_hash_internal_pointer_reset(ht);
855 while (col-- > 0) {
856 zend_hash_move_forward(ht);
857 }
858 zend_hash_get_current_data(ht, (void *) &data);
859 }
860 return data;
861 }
862
863 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_col, 0, 0, 1)
864 ZEND_ARG_INFO(1, ref)
865 ZEND_ARG_INFO(0, col)
866 ZEND_END_ARG_INFO();
867 static PHP_METHOD(pqres, fetchCol) {
868 zend_error_handling zeh;
869 zval *zcol = NULL, *zref;
870 ZEND_RESULT_CODE rv;
871
872 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
873 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z/!", &zref, &zcol);
874 zend_restore_error_handling(&zeh TSRMLS_CC);
875
876 if (SUCCESS == rv) {
877 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
878
879 if (!obj->intern) {
880 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized");
881 } else {
882 zval **row = NULL;
883
884 zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh TSRMLS_CC);
885 php_pqres_iteration(getThis(), obj, php_pqres_fetch_type(obj->intern), &row TSRMLS_CC);
886 if (row) {
887 php_pqres_col_t col;
888
889 if (SUCCESS != column_nn(obj, zcol, &col TSRMLS_CC)) {
890 RETVAL_FALSE;
891 } else {
892 zval **zres = column_at(*row, col.num TSRMLS_CC);
893
894 if (!zres) {
895 RETVAL_FALSE;
896 } else {
897 zval_dtor(zref);
898 ZVAL_ZVAL(zref, *zres, 1, 0);
899 RETVAL_TRUE;
900 }
901 }
902 }
903 zend_restore_error_handling(&zeh TSRMLS_CC);
904 }
905 }
906 }
907
908 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_all_cols, 0, 0, 0)
909 ZEND_ARG_INFO(0, col)
910 ZEND_END_ARG_INFO();
911 static PHP_METHOD(pqres, fetchAllCols) {
912 zend_error_handling zeh;
913 zval *zcol = NULL;
914 ZEND_RESULT_CODE rv;
915
916 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
917 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!", &zcol);
918 zend_restore_error_handling(&zeh TSRMLS_CC);
919
920 if (SUCCESS == rv) {
921 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
922
923 if (!obj->intern) {
924 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized");
925 } else {
926 php_pqres_col_t col;
927
928 zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh TSRMLS_CC);
929 if (SUCCESS == column_nn(obj, zcol, &col TSRMLS_CC)) {
930 int r, rows = PQntuples(obj->intern->res);
931
932 array_init(return_value);
933 for (r = 0; r < rows; ++r) {
934 add_next_index_zval(return_value, php_pqres_get_col(obj->intern, r, col.num TSRMLS_CC));
935 }
936 }
937 zend_restore_error_handling(&zeh TSRMLS_CC);
938 }
939 }
940 }
941
942 struct apply_to_col_arg {
943 php_pqres_object_t *obj;
944 php_pqres_col_t *cols;
945 ZEND_RESULT_CODE status;
946 };
947
948 static int apply_to_col(void *p, void *a TSRMLS_DC)
949 {
950 zval **c = p;
951 struct apply_to_col_arg *arg = a;
952
953 if (SUCCESS != column_nn(arg->obj, *c, arg->cols TSRMLS_CC)) {
954 arg->status = FAILURE;
955 return ZEND_HASH_APPLY_STOP;
956 } else {
957 arg->status = SUCCESS;
958 ++arg->cols;
959 return ZEND_HASH_APPLY_KEEP;
960 }
961 }
962
963 static php_pqres_col_t *php_pqres_convert_to_cols(php_pqres_object_t *obj, HashTable *ht TSRMLS_DC)
964 {
965 struct apply_to_col_arg arg = {NULL};
966 php_pqres_col_t *tmp;
967
968 arg.obj = obj;
969 arg.cols = ecalloc(zend_hash_num_elements(ht), sizeof(*tmp));
970 tmp = arg.cols;
971 zend_hash_apply_with_argument(ht, apply_to_col, &arg TSRMLS_CC);
972
973 if (SUCCESS == arg.status) {
974 return tmp;
975 } else {
976 efree(tmp);
977 return NULL;
978 }
979 }
980
981 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_map, 0, 0, 0)
982 ZEND_ARG_INFO(0, keys)
983 ZEND_ARG_INFO(0, vals)
984 ZEND_ARG_INFO(0, fetch_type)
985 ZEND_END_ARG_INFO();
986 static PHP_METHOD(pqres, map) {
987 zend_error_handling zeh;
988 zval *zkeys = 0, *zvals = 0;
989 long fetch_type = -1;
990 ZEND_RESULT_CODE rv;
991
992 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
993 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z/!z/!l", &zkeys, &zvals, &fetch_type);
994 zend_restore_error_handling(&zeh TSRMLS_CC);
995
996 if (SUCCESS == rv) {
997 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
998
999 if (!obj->intern) {
1000 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized");
1001 } else {
1002 int ks = 0, vs = 0;
1003 php_pqres_col_t def = {PQfname(obj->intern->res, 0), 0}, *keys = NULL, *vals = NULL;
1004
1005 if (zkeys) {
1006 convert_to_array(zkeys);
1007
1008 if ((ks = zend_hash_num_elements(Z_ARRVAL_P(zkeys)))) {
1009 keys = php_pqres_convert_to_cols(obj, Z_ARRVAL_P(zkeys) TSRMLS_CC);
1010 } else {
1011 ks = 1;
1012 keys = &def;
1013 }
1014 } else {
1015 ks = 1;
1016 keys = &def;
1017 }
1018 if (zvals) {
1019 convert_to_array(zvals);
1020
1021 if ((vs = zend_hash_num_elements(Z_ARRVAL_P(zvals)))) {
1022 vals = php_pqres_convert_to_cols(obj, Z_ARRVAL_P(zvals) TSRMLS_CC);
1023 }
1024 }
1025
1026 if (fetch_type == -1) {
1027 fetch_type = php_pqres_fetch_type(obj->intern);
1028 }
1029
1030 if (keys) {
1031 int rows, r;
1032 zval **cur;
1033
1034 switch (fetch_type) {
1035 case PHP_PQRES_FETCH_ARRAY:
1036 case PHP_PQRES_FETCH_ASSOC:
1037 array_init(return_value);
1038 break;
1039 case PHP_PQRES_FETCH_OBJECT:
1040 object_init(return_value);
1041 break;
1042 }
1043 for (r = 0, rows = PQntuples(obj->intern->res); r < rows; ++r) {
1044 int k, v;
1045
1046 cur = &return_value;
1047 for (k = 0; k < ks; ++k) {
1048 char *key = PQgetvalue(obj->intern->res, r, keys[k].num);
1049 int len = PQgetlength(obj->intern->res, r, keys[k].num);
1050
1051 if (SUCCESS != zend_symtable_find(HASH_OF(*cur), key, len + 1, (void *) &cur)) {
1052 zval *tmp;
1053
1054 MAKE_STD_ZVAL(tmp);
1055 switch (fetch_type) {
1056 case PHP_PQRES_FETCH_ARRAY:
1057 case PHP_PQRES_FETCH_ASSOC:
1058 array_init(tmp);
1059 break;
1060 case PHP_PQRES_FETCH_OBJECT:
1061 object_init(tmp);
1062 break;
1063 }
1064 if (SUCCESS != zend_symtable_update(HASH_OF(*cur), key, len + 1, (void *) &tmp, sizeof(zval *), (void *) &cur)) {
1065 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to create map");
1066 goto err;
1067 }
1068 }
1069 }
1070 if (vals && vs) {
1071 for (v = 0; v < vs; ++v) {
1072 char *val = PQgetvalue(obj->intern->res, r, vals[v].num);
1073 int len = PQgetlength(obj->intern->res, r, vals[v].num);
1074
1075 switch (fetch_type) {
1076 case PHP_PQRES_FETCH_ARRAY:
1077 add_index_stringl(*cur, vals[v].num, val, len, 1);
1078 break;
1079 case PHP_PQRES_FETCH_ASSOC:
1080 add_assoc_stringl(*cur, vals[v].name, val, len, 1);
1081 break;
1082 case PHP_PQRES_FETCH_OBJECT:
1083 add_property_stringl(*cur, vals[v].name, val, len, 1);
1084 break;
1085 }
1086 }
1087 } else {
1088 php_pqres_row_to_zval(obj->intern->res, r, fetch_type, cur TSRMLS_CC);
1089 }
1090 }
1091 }
1092
1093 err:
1094 if (keys && keys != &def) {
1095 efree(keys);
1096 }
1097 if (vals) {
1098 efree(vals);
1099 }
1100 }
1101 }
1102 }
1103
1104 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_all, 0, 0, 0)
1105 ZEND_ARG_INFO(0, fetch_type)
1106 ZEND_END_ARG_INFO();
1107 static PHP_METHOD(pqres, fetchAll) {
1108 zend_error_handling zeh;
1109 long fetch_type = -1;
1110 ZEND_RESULT_CODE rv;
1111
1112 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1113 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &fetch_type);
1114 zend_restore_error_handling(&zeh TSRMLS_CC);
1115
1116 if (SUCCESS == rv) {
1117 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1118 if (!obj->intern) {
1119 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized");
1120 } else {
1121 int r, rows = PQntuples(obj->intern->res);
1122
1123 if (fetch_type == -1) {
1124 fetch_type = php_pqres_fetch_type(obj->intern);
1125 }
1126
1127 array_init(return_value);
1128 for (r = 0; r < rows; ++r) {
1129 add_next_index_zval(return_value, php_pqres_row_to_zval(obj->intern->res, r, fetch_type, NULL TSRMLS_CC));
1130 }
1131 }
1132 }
1133 }
1134
1135 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_count, 0, 0, 0)
1136 ZEND_END_ARG_INFO();
1137 static PHP_METHOD(pqres, count) {
1138 zend_error_handling zeh;
1139 ZEND_RESULT_CODE rv;
1140
1141 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1142 rv = zend_parse_parameters_none();
1143 zend_restore_error_handling(&zeh TSRMLS_CC);
1144
1145 if (SUCCESS == rv) {
1146 long count;
1147
1148 if (SUCCESS != php_pqres_count_elements(getThis(), &count TSRMLS_CC)) {
1149 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized");
1150 } else {
1151 RETVAL_LONG(count);
1152 }
1153 }
1154 }
1155
1156 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_desc, 0, 0, 0)
1157 ZEND_END_ARG_INFO();
1158 static PHP_METHOD(pqres, desc) {
1159 zend_error_handling zeh;
1160 ZEND_RESULT_CODE rv;
1161
1162 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
1163 rv = zend_parse_parameters_none();
1164 zend_restore_error_handling(&zeh TSRMLS_CC);
1165
1166 if (SUCCESS == rv) {
1167 php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
1168
1169 if (!obj->intern) {
1170 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized");
1171 } else {
1172 int p, params;
1173
1174 array_init(return_value);
1175 for (p = 0, params = PQnparams(obj->intern->res); p < params; ++p) {
1176 add_next_index_long(return_value, PQparamtype(obj->intern->res, p));
1177 }
1178 }
1179 }
1180 }
1181
1182 static zend_function_entry php_pqres_methods[] = {
1183 PHP_ME(pqres, bind, ai_pqres_bind, ZEND_ACC_PUBLIC)
1184 PHP_ME(pqres, fetchBound, ai_pqres_fetch_bound, ZEND_ACC_PUBLIC)
1185 PHP_ME(pqres, fetchRow, ai_pqres_fetch_row, ZEND_ACC_PUBLIC)
1186 PHP_ME(pqres, fetchCol, ai_pqres_fetch_col, ZEND_ACC_PUBLIC)
1187 PHP_ME(pqres, fetchAll, ai_pqres_fetch_all, ZEND_ACC_PUBLIC)
1188 PHP_ME(pqres, fetchAllCols, ai_pqres_fetch_all_cols, ZEND_ACC_PUBLIC)
1189 PHP_ME(pqres, count, ai_pqres_count, ZEND_ACC_PUBLIC)
1190 PHP_ME(pqres, map, ai_pqres_map, ZEND_ACC_PUBLIC)
1191 PHP_ME(pqres, desc, ai_pqres_desc, ZEND_ACC_PUBLIC)
1192 {0}
1193 };
1194
1195 PHP_MSHUTDOWN_FUNCTION(pqres)
1196 {
1197 zend_hash_destroy(&php_pqres_object_prophandlers);
1198 return SUCCESS;
1199 }
1200
1201 PHP_MINIT_FUNCTION(pqres)
1202 {
1203 zend_class_entry ce = {0};
1204 php_pq_object_prophandler_t ph = {0};
1205
1206 INIT_NS_CLASS_ENTRY(ce, "pq", "Result", php_pqres_methods);
1207 php_pqres_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
1208 php_pqres_class_entry->create_object = php_pqres_create_object;
1209 php_pqres_class_entry->iterator_funcs.funcs = &php_pqres_iterator_funcs;
1210 php_pqres_class_entry->get_iterator = php_pqres_iterator_init;
1211 zend_class_implements(php_pqres_class_entry TSRMLS_CC, 2, zend_ce_traversable, spl_ce_Countable);
1212
1213 memcpy(&php_pqres_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1214 php_pqres_object_handlers.read_property = php_pq_object_read_prop;
1215 php_pqres_object_handlers.write_property = php_pq_object_write_prop;
1216 php_pqres_object_handlers.clone_obj = NULL;
1217 php_pqres_object_handlers.get_property_ptr_ptr = NULL;
1218 php_pqres_object_handlers.get_gc = NULL;
1219 php_pqres_object_handlers.get_debug_info = php_pq_object_debug_info;
1220 php_pqres_object_handlers.get_properties = php_pq_object_properties;
1221 php_pqres_object_handlers.count_elements = php_pqres_count_elements;
1222
1223 zend_hash_init(&php_pqres_object_prophandlers, 8, NULL, NULL, 1);
1224
1225 zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("status"), ZEND_ACC_PUBLIC TSRMLS_CC);
1226 ph.read = php_pqres_object_read_status;
1227 zend_hash_add(&php_pqres_object_prophandlers, "status", sizeof("status"), (void *) &ph, sizeof(ph), NULL);
1228
1229 zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("statusMessage"), ZEND_ACC_PUBLIC TSRMLS_CC);
1230 ph.read = php_pqres_object_read_status_message;
1231 zend_hash_add(&php_pqres_object_prophandlers, "statusMessage", sizeof("statusMessage"), (void *) &ph, sizeof(ph), NULL);
1232
1233 zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC TSRMLS_CC);
1234 ph.read = php_pqres_object_read_error_message;
1235 zend_hash_add(&php_pqres_object_prophandlers, "errorMessage", sizeof("errorMessage"), (void *) &ph, sizeof(ph), NULL);
1236
1237 zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("diag"), ZEND_ACC_PUBLIC TSRMLS_CC);
1238 ph.read = php_pqres_object_read_diag;
1239 zend_hash_add(&php_pqres_object_prophandlers, "diag", sizeof("diag"), (void *) &ph, sizeof(ph), NULL);
1240
1241 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("numRows"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
1242 ph.read = php_pqres_object_read_num_rows;
1243 zend_hash_add(&php_pqres_object_prophandlers, "numRows", sizeof("numRows"), (void *) &ph, sizeof(ph), NULL);
1244
1245 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("numCols"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
1246 ph.read = php_pqres_object_read_num_cols;
1247 zend_hash_add(&php_pqres_object_prophandlers, "numCols", sizeof("numCols"), (void *) &ph, sizeof(ph), NULL);
1248
1249 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("affectedRows"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
1250 ph.read = php_pqres_object_read_affected_rows;
1251 zend_hash_add(&php_pqres_object_prophandlers, "affectedRows", sizeof("affectedRows"), (void *) &ph, sizeof(ph), NULL);
1252
1253 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("fetchType"), PHP_PQRES_FETCH_ARRAY, ZEND_ACC_PUBLIC TSRMLS_CC);
1254 ph.read = php_pqres_object_read_fetch_type;
1255 ph.write = php_pqres_object_write_fetch_type;
1256 zend_hash_add(&php_pqres_object_prophandlers, "fetchType", sizeof("fetchType"), (void *) &ph, sizeof(ph), NULL);
1257 ph.write = NULL;
1258
1259 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("autoConvert"), PHP_PQRES_CONV_ALL, ZEND_ACC_PUBLIC TSRMLS_CC);
1260 ph.read = php_pqres_object_read_auto_conv;
1261 ph.write = php_pqres_object_write_auto_conv;
1262 zend_hash_add(&php_pqres_object_prophandlers, "autoConvert", sizeof("autoConvert"), (void *) &ph, sizeof(ph), NULL);
1263 ph.write = NULL;
1264
1265 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("EMPTY_QUERY"), PGRES_EMPTY_QUERY TSRMLS_CC);
1266 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COMMAND_OK"), PGRES_COMMAND_OK TSRMLS_CC);
1267 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("TUPLES_OK"), PGRES_TUPLES_OK TSRMLS_CC);
1268 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_OUT"), PGRES_COPY_OUT TSRMLS_CC);
1269 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_IN"), PGRES_COPY_IN TSRMLS_CC);
1270 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("BAD_RESPONSE"), PGRES_BAD_RESPONSE TSRMLS_CC);
1271 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("NONFATAL_ERROR"), PGRES_NONFATAL_ERROR TSRMLS_CC);
1272 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FATAL_ERROR"), PGRES_FATAL_ERROR TSRMLS_CC);
1273 #ifdef HAVE_PGRES_COPY_BOTH
1274 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_BOTH"), PGRES_COPY_BOTH TSRMLS_CC);
1275 #endif
1276 #ifdef HAVE_PGRES_SINGLE_TUPLE
1277 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("SINGLE_TUPLE"), PGRES_SINGLE_TUPLE TSRMLS_CC);
1278 #endif
1279
1280 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_ARRAY"), PHP_PQRES_FETCH_ARRAY TSRMLS_CC);
1281 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_ASSOC"), PHP_PQRES_FETCH_ASSOC TSRMLS_CC);
1282 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_OBJECT"), PHP_PQRES_FETCH_OBJECT TSRMLS_CC);
1283
1284 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_BOOL"), PHP_PQRES_CONV_BOOL TSRMLS_CC);
1285 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_INT"), PHP_PQRES_CONV_INT TSRMLS_CC);
1286 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_FLOAT"), PHP_PQRES_CONV_FLOAT TSRMLS_CC);
1287 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_SCALAR"), PHP_PQRES_CONV_SCALAR TSRMLS_CC);
1288 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_ARRAY"), PHP_PQRES_CONV_ARRAY TSRMLS_CC);
1289 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_DATETIME"), PHP_PQRES_CONV_DATETIME TSRMLS_CC);
1290 #if PHP_PQ_HAVE_PHP_JSON_H
1291 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_JSON"), PHP_PQRES_CONV_JSON TSRMLS_CC);
1292 #endif
1293 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_ALL"), PHP_PQRES_CONV_ALL TSRMLS_CC);
1294
1295 return SUCCESS;
1296 }
1297
1298 /*
1299 * Local variables:
1300 * tab-width: 4
1301 * c-basic-offset: 4
1302 * End:
1303 * vim600: noet sw=4 ts=4 fdm=marker
1304 * vim<600: noet sw=4 ts=4
1305 */