2 +--------------------------------------------------------------------+
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 +--------------------------------------------------------------------+
19 #include <ext/spl/spl_iterators.h>
20 #include <libpq-events.h>
23 #include "php_pq_misc.h"
24 #include "php_pq_object.h"
25 #include "php_pqexc.h"
26 #include "php_pqres.h"
28 zend_class_entry
*php_pqres_class_entry
;
29 static zend_object_handlers php_pqres_object_handlers
;
30 static HashTable php_pqres_object_prophandlers
;
31 static zend_object_iterator_funcs php_pqres_iterator_funcs
;
33 static zend_object_iterator
*php_pqres_iterator_init(zend_class_entry
*ce
, zval
*object
, int by_ref TSRMLS_DC
)
35 php_pqres_iterator_t
*iter
;
36 zval
*prop
, *zfetch_type
;
38 iter
= ecalloc(1, sizeof(*iter
));
39 iter
->zi
.funcs
= &php_pqres_iterator_funcs
;
40 iter
->zi
.data
= object
;
43 zfetch_type
= prop
= zend_read_property(ce
, object
, ZEND_STRL("fetchType"), 0 TSRMLS_CC
);
44 if (Z_TYPE_P(zfetch_type
) != IS_LONG
) {
45 convert_to_long_ex(&zfetch_type
);
47 iter
->fetch_type
= Z_LVAL_P(zfetch_type
);
48 if (zfetch_type
!= prop
) {
49 zval_ptr_dtor(&zfetch_type
);
51 if (Z_REFCOUNT_P(prop
)) {
58 return (zend_object_iterator
*) iter
;
61 static void php_pqres_iterator_dtor(zend_object_iterator
*i TSRMLS_DC
)
63 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
65 if (iter
->current_val
) {
66 zval_ptr_dtor(&iter
->current_val
);
67 iter
->current_val
= NULL
;
69 zval_ptr_dtor((zval
**) &iter
->zi
.data
);
73 static STATUS
php_pqres_iterator_valid(zend_object_iterator
*i TSRMLS_DC
)
75 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
76 php_pqres_object_t
*obj
= zend_object_store_get_object(iter
->zi
.data TSRMLS_CC
);
78 switch (PQresultStatus(obj
->intern
->res
)) {
80 case PGRES_SINGLE_TUPLE
:
81 if (PQntuples(obj
->intern
->res
) <= iter
->index
) {
92 zval
*php_pqres_row_to_zval(PGresult
*res
, unsigned row
, php_pqres_fetch_t fetch_type
, zval
**data_ptr TSRMLS_DC
)
102 if (PHP_PQRES_FETCH_OBJECT
== fetch_type
) {
112 if (PQntuples(res
) > row
) {
113 for (c
= 0, cols
= PQnfields(res
); c
< cols
; ++c
) {
114 if (PQgetisnull(res
, row
, c
)) {
115 switch (fetch_type
) {
116 case PHP_PQRES_FETCH_OBJECT
:
117 add_property_null(data
, PQfname(res
, c
));
120 case PHP_PQRES_FETCH_ASSOC
:
121 add_assoc_null(data
, PQfname(res
, c
));
124 case PHP_PQRES_FETCH_ARRAY
:
125 add_index_null(data
, c
);
129 char *val
= PQgetvalue(res
, row
, c
);
130 int len
= PQgetlength(res
, row
, c
);
132 switch (fetch_type
) {
133 case PHP_PQRES_FETCH_OBJECT
:
134 add_property_stringl(data
, PQfname(res
, c
), val
, len
, 1);
137 case PHP_PQRES_FETCH_ASSOC
:
138 add_assoc_stringl(data
, PQfname(res
, c
), val
, len
, 1);
141 case PHP_PQRES_FETCH_ARRAY
:
142 add_index_stringl(data
, c
, val
, len
,1);
152 static void php_pqres_iterator_current(zend_object_iterator
*i
, zval
***data_ptr TSRMLS_DC
)
154 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
155 php_pqres_object_t
*obj
= zend_object_store_get_object(iter
->zi
.data TSRMLS_CC
);
157 if (!iter
->current_val
) {
158 iter
->current_val
= php_pqres_row_to_zval(obj
->intern
->res
, iter
->index
, iter
->fetch_type
, NULL TSRMLS_CC
);
160 *data_ptr
= &iter
->current_val
;
163 #if PHP_VERSION_ID >= 50500
164 static void php_pqres_iterator_key(zend_object_iterator
*i
, zval
*key TSRMLS_DC
)
166 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
168 ZVAL_LONG(key
, iter
->index
);
171 static int php_pqres_iterator_key(zend_object_iterator
*i
, char **key_str
, uint
*key_len
, ulong
*key_num TSRMLS_DC
)
173 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
175 *key_num
= (ulong
) iter
->index
;
177 return HASH_KEY_IS_LONG
;
181 static void php_pqres_iterator_invalidate(zend_object_iterator
*i TSRMLS_DC
)
183 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
185 if (iter
->current_val
) {
186 zval_ptr_dtor(&iter
->current_val
);
187 iter
->current_val
= NULL
;
191 static void php_pqres_iterator_next(zend_object_iterator
*i TSRMLS_DC
)
193 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
195 php_pqres_iterator_invalidate(i TSRMLS_CC
);
199 static void php_pqres_iterator_rewind(zend_object_iterator
*i TSRMLS_DC
)
201 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
203 php_pqres_iterator_invalidate(i TSRMLS_CC
);
207 static zend_object_iterator_funcs php_pqres_iterator_funcs
= {
208 php_pqres_iterator_dtor
,
209 /* check for end of iteration (FAILURE or SUCCESS if data is valid) */
210 php_pqres_iterator_valid
,
211 /* fetch the item data for the current element */
212 php_pqres_iterator_current
,
213 /* fetch the key for the current element (return HASH_KEY_IS_STRING or HASH_KEY_IS_LONG) (optional, may be NULL) */
214 php_pqres_iterator_key
,
215 /* step forwards to next element */
216 php_pqres_iterator_next
,
217 /* rewind to start of data (optional, may be NULL) */
218 php_pqres_iterator_rewind
,
219 /* invalidate current value/key (optional, may be NULL) */
220 php_pqres_iterator_invalidate
223 static int php_pqres_count_elements(zval
*object
, long *count TSRMLS_DC
)
225 php_pqres_object_t
*obj
= zend_object_store_get_object(object TSRMLS_CC
);
230 *count
= (long) PQntuples(obj
->intern
->res
);
235 STATUS
php_pqres_success(PGresult
*res TSRMLS_DC
)
239 switch (PQresultStatus(res
)) {
240 case PGRES_BAD_RESPONSE
:
241 case PGRES_NONFATAL_ERROR
:
242 case PGRES_FATAL_ERROR
:
243 zexc
= throw_exce(EX_SQL TSRMLS_CC
, "%s", PHP_PQresultErrorMessage(res
));
244 zend_update_property_string(Z_OBJCE_P(zexc
), zexc
, ZEND_STRL("sqlstate"), PQresultErrorField(res
, PG_DIAG_SQLSTATE
) TSRMLS_CC
);
251 void php_pqres_init_instance_data(PGresult
*res
, php_pqres_object_t
**ptr TSRMLS_DC
)
253 php_pqres_object_t
*obj
;
254 php_pqres_t
*r
= ecalloc(1, sizeof(*r
));
257 ZEND_INIT_SYMTABLE(&r
->bound
);
258 php_pqres_create_object_ex(php_pqres_class_entry
, r
, &obj TSRMLS_CC
);
260 PQresultSetInstanceData(res
, php_pqconn_event
, obj
);
267 static void php_pqres_object_free(void *o TSRMLS_DC
)
269 php_pqres_object_t
*obj
= o
;
271 fprintf(stderr
, "FREE res(#%d) %p\n", obj
->zv
.handle
, obj
);
274 if (obj
->intern
->res
) {
275 PQresultSetInstanceData(obj
->intern
->res
, php_pqconn_event
, NULL
);
276 PQclear(obj
->intern
->res
);
277 obj
->intern
->res
= NULL
;
280 if (obj
->intern
->iter
) {
281 php_pqres_iterator_dtor((zend_object_iterator
*) obj
->intern
->iter TSRMLS_CC
);
282 obj
->intern
->iter
= NULL
;
285 zend_hash_destroy(&obj
->intern
->bound
);
290 zend_object_std_dtor((zend_object
*) o TSRMLS_CC
);
294 zend_object_value
php_pqres_create_object_ex(zend_class_entry
*ce
, php_pqres_t
*intern
, php_pqres_object_t
**ptr TSRMLS_DC
)
296 php_pqres_object_t
*o
;
298 o
= ecalloc(1, sizeof(*o
));
299 zend_object_std_init((zend_object
*) o
, ce TSRMLS_CC
);
300 object_properties_init((zend_object
*) o
, ce
);
301 o
->prophandler
= &php_pqres_object_prophandlers
;
311 o
->zv
.handle
= zend_objects_store_put((zend_object
*) o
, NULL
, php_pqres_object_free
, NULL TSRMLS_CC
);
312 o
->zv
.handlers
= &php_pqres_object_handlers
;
317 static zend_object_value
php_pqres_create_object(zend_class_entry
*class_type TSRMLS_DC
)
319 return php_pqres_create_object_ex(class_type
, NULL
, NULL TSRMLS_CC
);
322 static void php_pqres_object_read_status(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
324 php_pqres_object_t
*obj
= o
;
326 RETVAL_LONG(PQresultStatus(obj
->intern
->res
));
329 static void php_pqres_object_read_status_message(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
331 php_pqres_object_t
*obj
= o
;
333 RETVAL_STRING(PQresStatus(PQresultStatus(obj
->intern
->res
))+sizeof("PGRES"), 1);
336 static void php_pqres_object_read_error_message(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
338 php_pqres_object_t
*obj
= o
;
339 char *error
= PHP_PQresultErrorMessage(obj
->intern
->res
);
342 RETVAL_STRING(error
, 1);
348 static void php_pqres_object_read_num_rows(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
350 php_pqres_object_t
*obj
= o
;
352 RETVAL_LONG(PQntuples(obj
->intern
->res
));
355 static void php_pqres_object_read_num_cols(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
357 php_pqres_object_t
*obj
= o
;
359 RETVAL_LONG(PQnfields(obj
->intern
->res
));
362 static void php_pqres_object_read_affected_rows(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
364 php_pqres_object_t
*obj
= o
;
366 RETVAL_LONG(atoi(PQcmdTuples(obj
->intern
->res
)));
369 static void php_pqres_object_read_fetch_type(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
371 php_pqres_object_t
*obj
= o
;
373 if (obj
->intern
->iter
) {
374 RETVAL_LONG(obj
->intern
->iter
->fetch_type
);
376 RETVAL_LONG(PHP_PQRES_FETCH_ARRAY
);
380 static void php_pqres_object_write_fetch_type(zval
*object
, void *o
, zval
*value TSRMLS_DC
)
382 php_pqres_object_t
*obj
= o
;
383 zval
*zfetch_type
= value
;
385 if (Z_TYPE_P(value
) != IS_LONG
) {
386 if (Z_REFCOUNT_P(value
) > 1) {
389 ZVAL_ZVAL(tmp
, zfetch_type
, 1, 0);
390 convert_to_long(tmp
);
393 convert_to_long_ex(&zfetch_type
);
397 if (!obj
->intern
->iter
) {
398 obj
->intern
->iter
= (php_pqres_iterator_t
*) php_pqres_iterator_init(Z_OBJCE_P(object
), object
, 0 TSRMLS_CC
);
399 obj
->intern
->iter
->zi
.funcs
->rewind((zend_object_iterator
*) obj
->intern
->iter TSRMLS_CC
);
401 obj
->intern
->iter
->fetch_type
= Z_LVAL_P(zfetch_type
);
403 if (zfetch_type
!= value
) {
404 zval_ptr_dtor(&zfetch_type
);
408 static STATUS
php_pqres_iteration(zval
*this_ptr
, php_pqres_object_t
*obj
, php_pqres_fetch_t fetch_type
, zval
***row TSRMLS_DC
)
411 php_pqres_fetch_t orig_fetch
;
414 obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
417 if (obj
->intern
->iter
) {
418 obj
->intern
->iter
->zi
.funcs
->move_forward((zend_object_iterator
*) obj
->intern
->iter TSRMLS_CC
);
420 obj
->intern
->iter
= (php_pqres_iterator_t
*) php_pqres_iterator_init(Z_OBJCE_P(getThis()), getThis(), 0 TSRMLS_CC
);
421 obj
->intern
->iter
->zi
.funcs
->rewind((zend_object_iterator
*) obj
->intern
->iter TSRMLS_CC
);
423 orig_fetch
= obj
->intern
->iter
->fetch_type
;
424 obj
->intern
->iter
->fetch_type
= fetch_type
;
425 if (SUCCESS
== (rv
= obj
->intern
->iter
->zi
.funcs
->valid((zend_object_iterator
*) obj
->intern
->iter TSRMLS_CC
))) {
426 obj
->intern
->iter
->zi
.funcs
->get_current_data((zend_object_iterator
*) obj
->intern
->iter
, row TSRMLS_CC
);
428 obj
->intern
->iter
->fetch_type
= orig_fetch
;
433 typedef struct php_pqres_col
{
438 static STATUS
column_nn(php_pqres_object_t
*obj
, zval
*zcol
, php_pqres_col_t
*col TSRMLS_DC
)
443 switch (Z_TYPE_P(zcol
)) {
445 convert_to_string(zcol
);
449 if (!is_numeric_string(Z_STRVAL_P(zcol
), Z_STRLEN_P(zcol
), &index
, NULL
, 0)) {
450 name
= Z_STRVAL_P(zcol
);
455 index
= Z_LVAL_P(zcol
);
461 col
->num
= PQfnumber(obj
->intern
->res
, name
);
463 col
->name
= PQfname(obj
->intern
->res
, index
);
468 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Failed to find column at index %ld", index
);
471 if (col
->num
== -1) {
472 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Failed to find column with name '%s'", name
);
478 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_bind
, 0, 0, 2)
479 ZEND_ARG_INFO(0, col
)
480 ZEND_ARG_INFO(1, ref
)
482 static PHP_METHOD(pqres
, bind
) {
485 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "z/z", &zcol
, &zref
)) {
486 php_pqres_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
489 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Result not initialized");
493 if (SUCCESS
!= column_nn(obj
, zcol
, &col TSRMLS_CC
)) {
498 if (SUCCESS
!= zend_hash_index_update(&obj
->intern
->bound
, col
.num
, (void *) &zref
, sizeof(zval
*), NULL
)) {
499 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Failed to bind column %s@%d", col
.name
, col
.num
);
502 zend_hash_sort(&obj
->intern
->bound
, zend_qsort
, compare_index
, 0 TSRMLS_CC
);
510 static int apply_bound(void *p TSRMLS_DC
, int argc
, va_list argv
, zend_hash_key
*key
)
512 zval
**zvalue
, **zbound
= p
;
513 zval
**zrow
= va_arg(argv
, zval
**);
514 STATUS
*rv
= va_arg(argv
, STATUS
*);
516 if (SUCCESS
!= zend_hash_index_find(Z_ARRVAL_PP(zrow
), key
->h
, (void *) &zvalue
)) {
517 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Failed to find column ad index %lu", key
->h
);
519 return ZEND_HASH_APPLY_STOP
;
522 ZVAL_COPY_VALUE(*zbound
, *zvalue
);
524 zval_ptr_dtor(zvalue
);
528 return ZEND_HASH_APPLY_KEEP
;
532 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_bound
, 0, 0, 0)
534 static PHP_METHOD(pqres
, fetchBound
) {
535 zend_error_handling zeh
;
538 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
539 rv
= zend_parse_parameters_none();
540 zend_restore_error_handling(&zeh TSRMLS_CC
);
543 php_pqres_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
546 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Result not initialized");
550 if (SUCCESS
== php_pqres_iteration(getThis(), obj
, PHP_PQRES_FETCH_ARRAY
, &row TSRMLS_CC
) && row
) {
551 zend_replace_error_handling(EH_THROW
, exce(EX_RUNTIME
), &zeh TSRMLS_CC
);
552 zend_hash_apply_with_arguments(&obj
->intern
->bound TSRMLS_CC
, apply_bound
, 2, row
, &rv
);
553 zend_restore_error_handling(&zeh TSRMLS_CC
);
558 RETVAL_ZVAL(*row
, 1, 0);
565 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_row
, 0, 0, 0)
566 ZEND_ARG_INFO(0, fetch_type
)
568 static PHP_METHOD(pqres
, fetchRow
) {
569 zend_error_handling zeh
;
570 php_pqres_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
571 long fetch_type
= -1;
574 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
575 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|l", &fetch_type
);
576 zend_restore_error_handling(&zeh TSRMLS_CC
);
580 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Result not initialized");
584 if (fetch_type
== -1) {
585 fetch_type
= obj
->intern
->iter
? obj
->intern
->iter
->fetch_type
: PHP_PQRES_FETCH_ARRAY
;
588 zend_replace_error_handling(EH_THROW
, exce(EX_RUNTIME
), &zeh TSRMLS_CC
);
589 php_pqres_iteration(getThis(), obj
, fetch_type
, &row TSRMLS_CC
);
590 zend_restore_error_handling(&zeh TSRMLS_CC
);
593 RETVAL_ZVAL(*row
, 1, 0);
599 static zval
**column_at(zval
*row
, int col TSRMLS_DC
)
602 HashTable
*ht
= HASH_OF(row
);
603 int count
= zend_hash_num_elements(ht
);
606 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Column index %d exceeds column count %d", col
, count
);
608 zend_hash_internal_pointer_reset(ht
);
610 zend_hash_move_forward(ht
);
612 zend_hash_get_current_data(ht
, (void *) &data
);
617 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_col
, 0, 0, 0)
618 ZEND_ARG_INFO(0, col_num
)
620 static PHP_METHOD(pqres
, fetchCol
) {
621 zend_error_handling zeh
;
625 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
626 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|l", &fetch_col
);
627 zend_restore_error_handling(&zeh TSRMLS_CC
);
630 php_pqres_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
633 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Result not initialized");
637 zend_replace_error_handling(EH_THROW
, exce(EX_RUNTIME
), &zeh TSRMLS_CC
);
638 php_pqres_iteration(getThis(), obj
, obj
->intern
->iter
? obj
->intern
->iter
->fetch_type
: 0, &row TSRMLS_CC
);
640 zval
**col
= column_at(*row
, fetch_col TSRMLS_CC
);
643 RETVAL_ZVAL(*col
, 1, 0);
646 zend_restore_error_handling(&zeh TSRMLS_CC
);
651 static int apply_to_col(void *p TSRMLS_DC
, int argc
, va_list argv
, zend_hash_key
*key
)
654 php_pqres_object_t
*obj
= va_arg(argv
, php_pqres_object_t
*);
655 php_pqres_col_t
*col
, **cols
= va_arg(argv
, php_pqres_col_t
**);
656 STATUS
*rv
= va_arg(argv
, STATUS
*);
660 if (SUCCESS
!= column_nn(obj
, *c
, col TSRMLS_CC
)) {
662 return ZEND_HASH_APPLY_STOP
;
666 return ZEND_HASH_APPLY_KEEP
;
670 static php_pqres_col_t
*php_pqres_convert_to_cols(php_pqres_object_t
*obj
, HashTable
*ht TSRMLS_DC
)
672 php_pqres_col_t
*tmp
, *cols
= ecalloc(zend_hash_num_elements(ht
), sizeof(*cols
));
676 zend_hash_apply_with_arguments(ht TSRMLS_CC
, apply_to_col
, 2, obj
, &tmp
, &rv
);
686 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_map
, 0, 0, 0)
687 ZEND_ARG_INFO(0, keys
)
688 ZEND_ARG_INFO(0, vals
)
689 ZEND_ARG_INFO(0, fetch_type
)
691 static PHP_METHOD(pqres
, map
) {
692 zend_error_handling zeh
;
693 zval
*zkeys
= 0, *zvals
= 0;
694 long fetch_type
= -1;
697 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
698 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|z/!z/!l", &zkeys
, &zvals
, &fetch_type
);
699 zend_restore_error_handling(&zeh TSRMLS_CC
);
702 php_pqres_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
705 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Result not initialized");
708 php_pqres_col_t def
= {PQfname(obj
->intern
->res
, 0), 0}, *keys
= NULL
, *vals
= NULL
;
711 convert_to_array(zkeys
);
713 if ((ks
= zend_hash_num_elements(Z_ARRVAL_P(zkeys
)))) {
714 keys
= php_pqres_convert_to_cols(obj
, Z_ARRVAL_P(zkeys
) TSRMLS_CC
);
724 convert_to_array(zvals
);
726 if ((vs
= zend_hash_num_elements(Z_ARRVAL_P(zvals
)))) {
727 vals
= php_pqres_convert_to_cols(obj
, Z_ARRVAL_P(zvals
) TSRMLS_CC
);
731 if (fetch_type
== -1) {
732 fetch_type
= obj
->intern
->iter
? obj
->intern
->iter
->fetch_type
: PHP_PQRES_FETCH_ARRAY
;
739 switch (fetch_type
) {
740 case PHP_PQRES_FETCH_ARRAY
:
741 case PHP_PQRES_FETCH_ASSOC
:
742 array_init(return_value
);
744 case PHP_PQRES_FETCH_OBJECT
:
745 object_init(return_value
);
748 for (r
= 0, rows
= PQntuples(obj
->intern
->res
); r
< rows
; ++r
) {
752 for (k
= 0; k
< ks
; ++k
) {
753 char *key
= PQgetvalue(obj
->intern
->res
, r
, keys
[k
].num
);
754 int len
= PQgetlength(obj
->intern
->res
, r
, keys
[k
].num
);
756 if (SUCCESS
!= zend_symtable_find(HASH_OF(*cur
), key
, len
+ 1, (void *) &cur
)) {
760 switch (fetch_type
) {
761 case PHP_PQRES_FETCH_ARRAY
:
762 case PHP_PQRES_FETCH_ASSOC
:
765 case PHP_PQRES_FETCH_OBJECT
:
769 if (SUCCESS
!= zend_symtable_update(HASH_OF(*cur
), key
, len
+ 1, (void *) &tmp
, sizeof(zval
*), (void *) &cur
)) {
770 throw_exce(EX_RUNTIME TSRMLS_CC
, "Failed to create map");
776 for (v
= 0; v
< vs
; ++v
) {
777 char *val
= PQgetvalue(obj
->intern
->res
, r
, vals
[v
].num
);
778 int len
= PQgetlength(obj
->intern
->res
, r
, vals
[v
].num
);
780 switch (fetch_type
) {
781 case PHP_PQRES_FETCH_ARRAY
:
782 add_index_stringl(*cur
, vals
[v
].num
, val
, len
, 1);
784 case PHP_PQRES_FETCH_ASSOC
:
785 add_assoc_stringl(*cur
, vals
[v
].name
, val
, len
, 1);
787 case PHP_PQRES_FETCH_OBJECT
:
788 add_property_stringl(*cur
, vals
[v
].name
, val
, len
, 1);
793 php_pqres_row_to_zval(obj
->intern
->res
, r
, fetch_type
, cur TSRMLS_CC
);
799 if (keys
&& keys
!= &def
) {
809 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_all
, 0, 0, 0)
810 ZEND_ARG_INFO(0, fetch_type
)
812 static PHP_METHOD(pqres
, fetchAll
) {
813 zend_error_handling zeh
;
814 long fetch_type
= -1;
817 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
818 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|l", &fetch_type
);
819 zend_restore_error_handling(&zeh TSRMLS_CC
);
822 php_pqres_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
824 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Result not initialized");
826 int r
, rows
= PQntuples(obj
->intern
->res
);
828 if (fetch_type
== -1) {
829 fetch_type
= obj
->intern
->iter
? obj
->intern
->iter
->fetch_type
: PHP_PQRES_FETCH_ARRAY
;
832 array_init(return_value
);
833 for (r
= 0; r
< rows
; ++r
) {
834 add_next_index_zval(return_value
, php_pqres_row_to_zval(obj
->intern
->res
, r
, fetch_type
, NULL TSRMLS_CC
));
840 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_count
, 0, 0, 0)
842 static PHP_METHOD(pqres
, count
) {
843 if (SUCCESS
== zend_parse_parameters_none()) {
846 if (SUCCESS
!= php_pqres_count_elements(getThis(), &count TSRMLS_CC
)) {
847 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Result not initialized");
854 static zend_function_entry php_pqres_methods
[] = {
855 PHP_ME(pqres
, bind
, ai_pqres_bind
, ZEND_ACC_PUBLIC
)
856 PHP_ME(pqres
, fetchBound
, ai_pqres_fetch_bound
, ZEND_ACC_PUBLIC
)
857 PHP_ME(pqres
, fetchRow
, ai_pqres_fetch_row
, ZEND_ACC_PUBLIC
)
858 PHP_ME(pqres
, fetchCol
, ai_pqres_fetch_col
, ZEND_ACC_PUBLIC
)
859 PHP_ME(pqres
, fetchAll
, ai_pqres_fetch_all
, ZEND_ACC_PUBLIC
)
860 PHP_ME(pqres
, count
, ai_pqres_count
, ZEND_ACC_PUBLIC
)
861 PHP_ME(pqres
, map
, ai_pqres_map
, ZEND_ACC_PUBLIC
)
865 PHP_MINIT_FUNCTION(pqres
)
867 zend_class_entry ce
= {0};
868 php_pq_object_prophandler_t ph
= {0};
870 INIT_NS_CLASS_ENTRY(ce
, "pq", "Result", php_pqres_methods
);
871 php_pqres_class_entry
= zend_register_internal_class_ex(&ce
, NULL
, NULL TSRMLS_CC
);
872 php_pqres_class_entry
->create_object
= php_pqres_create_object
;
873 php_pqres_class_entry
->iterator_funcs
.funcs
= &php_pqres_iterator_funcs
;
874 php_pqres_class_entry
->get_iterator
= php_pqres_iterator_init
;
875 zend_class_implements(php_pqres_class_entry TSRMLS_CC
, 2, zend_ce_traversable
, spl_ce_Countable
);
877 memcpy(&php_pqres_object_handlers
, zend_get_std_object_handlers(), sizeof(zend_object_handlers
));
878 php_pqres_object_handlers
.read_property
= php_pq_object_read_prop
;
879 php_pqres_object_handlers
.write_property
= php_pq_object_write_prop
;
880 php_pqres_object_handlers
.clone_obj
= NULL
;
881 php_pqres_object_handlers
.get_property_ptr_ptr
= NULL
;
882 php_pqres_object_handlers
.get_debug_info
= php_pq_object_debug_info
;
883 php_pqres_object_handlers
.count_elements
= php_pqres_count_elements
;
885 zend_hash_init(&php_pqres_object_prophandlers
, 6, NULL
, NULL
, 1);
887 zend_declare_property_null(php_pqres_class_entry
, ZEND_STRL("status"), ZEND_ACC_PUBLIC TSRMLS_CC
);
888 ph
.read
= php_pqres_object_read_status
;
889 zend_hash_add(&php_pqres_object_prophandlers
, "status", sizeof("status"), (void *) &ph
, sizeof(ph
), NULL
);
891 zend_declare_property_null(php_pqres_class_entry
, ZEND_STRL("statusMessage"), ZEND_ACC_PUBLIC TSRMLS_CC
);
892 ph
.read
= php_pqres_object_read_status_message
;
893 zend_hash_add(&php_pqres_object_prophandlers
, "statusMessage", sizeof("statusMessage"), (void *) &ph
, sizeof(ph
), NULL
);
895 zend_declare_property_null(php_pqres_class_entry
, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC TSRMLS_CC
);
896 ph
.read
= php_pqres_object_read_error_message
;
897 zend_hash_add(&php_pqres_object_prophandlers
, "errorMessage", sizeof("errorMessage"), (void *) &ph
, sizeof(ph
), NULL
);
899 zend_declare_property_long(php_pqres_class_entry
, ZEND_STRL("numRows"), 0, ZEND_ACC_PUBLIC TSRMLS_CC
);
900 ph
.read
= php_pqres_object_read_num_rows
;
901 zend_hash_add(&php_pqres_object_prophandlers
, "numRows", sizeof("numRows"), (void *) &ph
, sizeof(ph
), NULL
);
903 zend_declare_property_long(php_pqres_class_entry
, ZEND_STRL("numCols"), 0, ZEND_ACC_PUBLIC TSRMLS_CC
);
904 ph
.read
= php_pqres_object_read_num_cols
;
905 zend_hash_add(&php_pqres_object_prophandlers
, "numCols", sizeof("numCols"), (void *) &ph
, sizeof(ph
), NULL
);
907 zend_declare_property_long(php_pqres_class_entry
, ZEND_STRL("affectedRows"), 0, ZEND_ACC_PUBLIC TSRMLS_CC
);
908 ph
.read
= php_pqres_object_read_affected_rows
;
909 zend_hash_add(&php_pqres_object_prophandlers
, "affectedRows", sizeof("affectedRows"), (void *) &ph
, sizeof(ph
), NULL
);
911 zend_declare_property_long(php_pqres_class_entry
, ZEND_STRL("fetchType"), PHP_PQRES_FETCH_ARRAY
, ZEND_ACC_PUBLIC TSRMLS_CC
);
912 ph
.read
= php_pqres_object_read_fetch_type
;
913 ph
.write
= php_pqres_object_write_fetch_type
;
914 zend_hash_add(&php_pqres_object_prophandlers
, "fetchType", sizeof("fetchType"), (void *) &ph
, sizeof(ph
), NULL
);
917 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("EMPTY_QUERY"), PGRES_EMPTY_QUERY TSRMLS_CC
);
918 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("COMMAND_OK"), PGRES_COMMAND_OK TSRMLS_CC
);
919 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("TUPLES_OK"), PGRES_TUPLES_OK TSRMLS_CC
);
920 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("COPY_OUT"), PGRES_COPY_OUT TSRMLS_CC
);
921 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("COPY_IN"), PGRES_COPY_IN TSRMLS_CC
);
922 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("BAD_RESPONSE"), PGRES_BAD_RESPONSE TSRMLS_CC
);
923 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("NONFATAL_ERROR"), PGRES_NONFATAL_ERROR TSRMLS_CC
);
924 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("FATAL_ERROR"), PGRES_FATAL_ERROR TSRMLS_CC
);
925 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("COPY_BOTH"), PGRES_COPY_BOTH TSRMLS_CC
);
926 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("SINGLE_TUPLE"), PGRES_SINGLE_TUPLE TSRMLS_CC
);
928 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("FETCH_ARRAY"), PHP_PQRES_FETCH_ARRAY TSRMLS_CC
);
929 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("FETCH_ASSOC"), PHP_PQRES_FETCH_ASSOC TSRMLS_CC
);
930 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("FETCH_OBJECT"), PHP_PQRES_FETCH_OBJECT TSRMLS_CC
);
940 * vim600: noet sw=4 ts=4 fdm=marker
941 * vim<600: noet sw=4 ts=4