PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/pdo - pdo_stmt.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 1061 1307 81.2 %
Date: 2014-08-04 Functions: 58 75 77.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | PHP Version 5                                                        |
       4             :   +----------------------------------------------------------------------+
       5             :   | Copyright (c) 1997-2014 The PHP Group                                |
       6             :   +----------------------------------------------------------------------+
       7             :   | This source file is subject to version 3.01 of the PHP license,      |
       8             :   | that is bundled with this package in the file LICENSE, and is        |
       9             :   | available through the world-wide-web at the following url:           |
      10             :   | http://www.php.net/license/3_01.txt                                  |
      11             :   | If you did not receive a copy of the PHP license and are unable to   |
      12             :   | obtain it through the world-wide-web, please send a note to          |
      13             :   | license@php.net so we can mail you a copy immediately.               |
      14             :   +----------------------------------------------------------------------+
      15             :   | Author: Wez Furlong <wez@php.net>                                    |
      16             :   |         Marcus Boerger <helly@php.net>                               |
      17             :   |         Sterling Hughes <sterling@php.net>                           |
      18             :   +----------------------------------------------------------------------+
      19             : */
      20             : 
      21             : /* $Id$ */
      22             : 
      23             : /* The PDO Statement Handle Class */
      24             : 
      25             : #ifdef HAVE_CONFIG_H
      26             : #include "config.h"
      27             : #endif
      28             : 
      29             : #include "php.h"
      30             : #include "php_ini.h"
      31             : #include "ext/standard/info.h"
      32             : #include "ext/standard/php_var.h"
      33             : #include "php_pdo.h"
      34             : #include "php_pdo_driver.h"
      35             : #include "php_pdo_int.h"
      36             : #include "zend_exceptions.h"
      37             : #include "zend_interfaces.h"
      38             : #include "php_memory_streams.h"
      39             : 
      40             : /* {{{ arginfo */
      41             : ZEND_BEGIN_ARG_INFO(arginfo_pdostatement__void, 0)
      42             : ZEND_END_ARG_INFO()
      43             : 
      44             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pdostatement_execute, 0, 0, 0)
      45             :         ZEND_ARG_INFO(0, bound_input_params) /* array */
      46             : ZEND_END_ARG_INFO()
      47             : 
      48             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pdostatement_fetch, 0, 0, 0)
      49             :         ZEND_ARG_INFO(0, how)
      50             :         ZEND_ARG_INFO(0, orientation)
      51             :         ZEND_ARG_INFO(0, offset)
      52             : ZEND_END_ARG_INFO()
      53             : 
      54             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pdostatement_fetchobject, 0, 0, 0)
      55             :         ZEND_ARG_INFO(0, class_name)
      56             :         ZEND_ARG_INFO(0, ctor_args) /* array */
      57             : ZEND_END_ARG_INFO()
      58             : 
      59             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pdostatement_fetchcolumn, 0, 0, 0)
      60             :         ZEND_ARG_INFO(0, column_number)
      61             : ZEND_END_ARG_INFO()
      62             : 
      63             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pdostatement_fetchall, 0, 0, 0)
      64             :         ZEND_ARG_INFO(0, how)
      65             :         ZEND_ARG_INFO(0, class_name)
      66             :         ZEND_ARG_INFO(0, ctor_args) /* array */
      67             : ZEND_END_ARG_INFO()
      68             : 
      69             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pdostatement_bindvalue, 0, 0, 2)
      70             :         ZEND_ARG_INFO(0, paramno)
      71             :         ZEND_ARG_INFO(0, param)
      72             :         ZEND_ARG_INFO(0, type)
      73             : ZEND_END_ARG_INFO()
      74             : 
      75             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pdostatement_bindparam, 0, 0, 2)
      76             :         ZEND_ARG_INFO(0, paramno)
      77             :         ZEND_ARG_INFO(1, param)
      78             :         ZEND_ARG_INFO(0, type)
      79             :         ZEND_ARG_INFO(0, maxlen)
      80             :         ZEND_ARG_INFO(0, driverdata)
      81             : ZEND_END_ARG_INFO()
      82             : 
      83             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pdostatement_bindcolumn, 0, 0, 2)
      84             :         ZEND_ARG_INFO(0, column)
      85             :         ZEND_ARG_INFO(1, param)
      86             :         ZEND_ARG_INFO(0, type)
      87             :         ZEND_ARG_INFO(0, maxlen)
      88             :         ZEND_ARG_INFO(0, driverdata)
      89             : ZEND_END_ARG_INFO()
      90             : 
      91             : ZEND_BEGIN_ARG_INFO(arginfo_pdostatement_setattribute, 0)
      92             :         ZEND_ARG_INFO(0, attribute)
      93             :         ZEND_ARG_INFO(0, value)
      94             : ZEND_END_ARG_INFO()
      95             : 
      96             : ZEND_BEGIN_ARG_INFO(arginfo_pdostatement_getattribute, 0)
      97             :         ZEND_ARG_INFO(0, attribute)
      98             : ZEND_END_ARG_INFO()
      99             : 
     100             : ZEND_BEGIN_ARG_INFO(arginfo_pdostatement_getcolumnmeta, 0)
     101             :         ZEND_ARG_INFO(0, column)
     102             : ZEND_END_ARG_INFO()
     103             : 
     104             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pdostatement_setfetchmode, 0, 0, 1)
     105             :         ZEND_ARG_INFO(0, mode)
     106             :         ZEND_ARG_INFO(0, params)
     107             : ZEND_END_ARG_INFO()
     108             : /* }}} */
     109             : 
     110             : #define PHP_STMT_GET_OBJ        \
     111             :   pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC);    \
     112             :   if (!stmt->dbh) {  \
     113             :     RETURN_FALSE;       \
     114             :   }     \
     115             : 
     116          14 : static PHP_FUNCTION(dbstmt_constructor) /* {{{ */
     117             : {
     118          14 :         php_error_docref(NULL TSRMLS_CC, E_ERROR, "You should not create a PDOStatement manually");
     119           0 : }
     120             : /* }}} */
     121             : 
     122       11601 : static inline int rewrite_name_to_position(pdo_stmt_t *stmt, struct pdo_bound_param_data *param TSRMLS_DC) /* {{{ */
     123             : {
     124       11601 :         if (stmt->bound_param_map) {
     125             :                 /* rewriting :name to ? style.
     126             :                  * We need to fixup the parameter numbers on the parameters.
     127             :                  * If we find that a given named parameter has been used twice,
     128             :                  * we will raise an error, as we can't be sure that it is safe
     129             :                  * to bind multiple parameters onto the same zval in the underlying
     130             :                  * driver */
     131             :                 char *name;
     132         507 :                 int position = 0;
     133             : 
     134         507 :                 if (stmt->named_rewrite_template) {
     135             :                         /* this is not an error here */
     136         169 :                         return 1;
     137             :                 }
     138         338 :                 if (!param->name) {
     139             :                         /* do the reverse; map the parameter number to the name */
     140          81 :                         if (SUCCESS == zend_hash_index_find(stmt->bound_param_map, param->paramno, (void**)&name)) {
     141          81 :                                 param->name = estrdup(name);
     142          81 :                                 param->namelen = strlen(param->name);
     143          81 :                                 return 1;
     144             :                         }
     145           0 :                         pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "parameter was not defined" TSRMLS_CC);
     146           0 :                         return 0;
     147             :                 }
     148             :     
     149         257 :                 zend_hash_internal_pointer_reset(stmt->bound_param_map);
     150         257 :                 while (SUCCESS == zend_hash_get_current_data(stmt->bound_param_map, (void**)&name)) {
     151         292 :                         if (strcmp(name, param->name)) {
     152         136 :                                 position++;
     153         136 :                                 zend_hash_move_forward(stmt->bound_param_map);
     154         136 :                                 continue;
     155             :                         }
     156         156 :                         if (param->paramno >= 0) {
     157           0 :                                 pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "PDO refuses to handle repeating the same :named parameter for multiple positions with this driver, as it might be unsafe to do so.  Consider using a separate name for each parameter instead" TSRMLS_CC);
     158           0 :                                 return -1;
     159             :                         }
     160         156 :                         param->paramno = position;
     161         156 :                         return 1;
     162             :                 }
     163         101 :                 pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "parameter was not defined" TSRMLS_CC);
     164         101 :                 return 0;
     165             :         }
     166       11094 :         return 1;       
     167             : }
     168             : /* }}} */
     169             : 
     170             : /* trigger callback hook for parameters */
     171        8883 : static int dispatch_param_event(pdo_stmt_t *stmt, enum pdo_param_event event_type TSRMLS_DC) /* {{{ */
     172             : {
     173        8883 :         int ret = 1, is_param = 1;
     174             :         struct pdo_bound_param_data *param;
     175             :         HashTable *ht;
     176             : 
     177        8883 :         if (!stmt->methods->param_hook) {
     178           0 :                 return 1;
     179             :         }
     180             : 
     181        8883 :         ht = stmt->bound_params;
     182             : 
     183             : iterate:
     184       17760 :         if (ht) {
     185        3657 :                 zend_hash_internal_pointer_reset(ht);
     186       13184 :                 while (SUCCESS == zend_hash_get_current_data(ht, (void**)&param)) {
     187        5877 :                         if (!stmt->methods->param_hook(stmt, param, event_type TSRMLS_CC)) {
     188           7 :                                 ret = 0;
     189           7 :                                 break;
     190             :                         }
     191             :                         
     192        5870 :                         zend_hash_move_forward(ht);
     193             :                 }
     194             :         }
     195       17760 :         if (ret && is_param) {
     196        8877 :                 ht = stmt->bound_columns;
     197        8877 :                 is_param = 0;
     198        8877 :                 goto iterate;
     199             :         }
     200             : 
     201        8883 :         return ret;
     202             : }
     203             : /* }}} */
     204             : 
     205        1981 : int pdo_stmt_describe_columns(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
     206             : {
     207             :         int col;
     208             : 
     209        1981 :         stmt->columns = ecalloc(stmt->column_count, sizeof(struct pdo_column_data));
     210             : 
     211        4331 :         for (col = 0; col < stmt->column_count; col++) {
     212        2350 :                 if (!stmt->methods->describer(stmt, col TSRMLS_CC)) {
     213           0 :                         return 0;
     214             :                 }
     215             : 
     216             :                 /* if we are applying case conversions on column names, do so now */
     217        2350 :                 if (stmt->dbh->native_case != stmt->dbh->desired_case && stmt->dbh->desired_case != PDO_CASE_NATURAL) {
     218        2254 :                         char *s = stmt->columns[col].name;
     219             : 
     220        2254 :                         switch (stmt->dbh->desired_case) {
     221             :                                 case PDO_CASE_UPPER:
     222          70 :                                         while (*s != '\0') {
     223          44 :                                                 *s = toupper(*s);
     224          44 :                                                 s++;
     225             :                                         }
     226          13 :                                         break;
     227             :                                 case PDO_CASE_LOWER:
     228       12458 :                                         while (*s != '\0') {
     229        7976 :                                                 *s = tolower(*s);
     230        7976 :                                                 s++;
     231             :                                         }
     232             :                                         break;
     233             :                                 default:
     234             :                                         ;
     235             :                         }
     236             :                 }
     237             : 
     238             : #if 0
     239             :                 /* update the column index on named bound parameters */
     240             :                 if (stmt->bound_params) {
     241             :                         struct pdo_bound_param_data *param;
     242             : 
     243             :                         if (SUCCESS == zend_hash_find(stmt->bound_params, stmt->columns[col].name,
     244             :                                                 stmt->columns[col].namelen, (void**)&param)) {
     245             :                                 param->paramno = col;
     246             :                         }
     247             :                 }
     248             : #endif
     249        2350 :                 if (stmt->bound_columns) {
     250             :                         struct pdo_bound_param_data *param;
     251             : 
     252          54 :                         if (SUCCESS == zend_hash_find(stmt->bound_columns, stmt->columns[col].name,
     253          27 :                                                 stmt->columns[col].namelen, (void**)&param)) {
     254          22 :                                 param->paramno = col;
     255             :                         }
     256             :                 }
     257             : 
     258             :         }
     259        1981 :         return 1;
     260             : }
     261             : /* }}} */
     262             : 
     263          23 : static void get_lazy_object(pdo_stmt_t *stmt, zval *return_value TSRMLS_DC) /* {{{ */
     264             : {
     265          23 :         if (Z_TYPE(stmt->lazy_object_ref) == IS_NULL) {
     266          17 :                 Z_TYPE(stmt->lazy_object_ref) = IS_OBJECT;
     267          17 :                 Z_OBJ_HANDLE(stmt->lazy_object_ref) = zend_objects_store_put(stmt, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)pdo_row_free_storage, NULL TSRMLS_CC);
     268          17 :                 Z_OBJ_HT(stmt->lazy_object_ref) = &pdo_row_object_handlers;
     269          17 :                 stmt->refcount++;
     270             :         }
     271          23 :         Z_TYPE_P(return_value) = IS_OBJECT;
     272          23 :         Z_OBJ_HANDLE_P(return_value) = Z_OBJ_HANDLE(stmt->lazy_object_ref);
     273          23 :         Z_OBJ_HT_P(return_value) = Z_OBJ_HT(stmt->lazy_object_ref);
     274          23 :         zend_objects_store_add_ref(return_value TSRMLS_CC);
     275          23 : }
     276             : /* }}} */
     277             : 
     278       11913 : static void param_dtor(void *data) /* {{{ */
     279             : {
     280       11913 :         struct pdo_bound_param_data *param = (struct pdo_bound_param_data *)data;
     281             :         TSRMLS_FETCH();
     282             : 
     283             :         /* tell the driver that it is going away */
     284       11913 :         if (param->stmt->methods->param_hook) {
     285       11913 :                 param->stmt->methods->param_hook(param->stmt, param, PDO_PARAM_EVT_FREE TSRMLS_CC);
     286             :         }
     287             : 
     288       11913 :         if (param->name) {
     289        5598 :                 efree(param->name);
     290             :         }
     291             : 
     292       11913 :         if (param->parameter) {
     293       11913 :                 zval_ptr_dtor(&(param->parameter));
     294       11913 :                 param->parameter = NULL;
     295             :         }
     296       11913 :         if (param->driver_params) {
     297           0 :                 zval_ptr_dtor(&(param->driver_params));
     298             :         }
     299       11913 : }
     300             : /* }}} */
     301             : 
     302       12017 : static int really_register_bound_param(struct pdo_bound_param_data *param, pdo_stmt_t *stmt, int is_param TSRMLS_DC) /* {{{ */
     303             : {
     304             :         HashTable *hash;
     305       12017 :         struct pdo_bound_param_data *pparam = NULL;
     306             : 
     307       12017 :         hash = is_param ? stmt->bound_params : stmt->bound_columns;
     308             : 
     309       12017 :         if (!hash) {
     310        1288 :                 ALLOC_HASHTABLE(hash);
     311        1288 :                 zend_hash_init(hash, 13, NULL, param_dtor, 0);
     312             : 
     313        1288 :                 if (is_param) {
     314        1093 :                         stmt->bound_params = hash;
     315             :                 } else {
     316         195 :                         stmt->bound_columns = hash;
     317             :                 }
     318             :         }
     319             : 
     320       23548 :         if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_STR && param->max_value_len <= 0 && ! ZVAL_IS_NULL(param->parameter)) {
     321       11531 :                 if (Z_TYPE_P(param->parameter) == IS_DOUBLE) {
     322             :                         char *p;
     323          23 :                         int len = spprintf(&p, 0, "%.*H", (int) EG(precision), Z_DVAL_P(param->parameter));
     324          23 :                         ZVAL_STRINGL(param->parameter, p, len, 0);
     325             :                 } else {
     326       11508 :                         convert_to_string(param->parameter);
     327             :                 }
     328         493 :         } else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_INT && Z_TYPE_P(param->parameter) == IS_BOOL) {
     329           7 :                 convert_to_long(param->parameter);
     330         479 :         } else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_BOOL && Z_TYPE_P(param->parameter) == IS_LONG) {
     331           1 :                 convert_to_boolean(param->parameter);
     332             :         }
     333             : 
     334       12017 :         param->stmt = stmt;
     335       12017 :         param->is_param = is_param;
     336             : 
     337       12017 :         if (param->driver_params) {
     338           0 :                 Z_ADDREF_P(param->driver_params);
     339             :         }
     340             : 
     341       12017 :         if (!is_param && param->name && stmt->columns) {
     342             :                 /* try to map the name to the column */
     343             :                 int i;
     344             : 
     345         137 :                 for (i = 0; i < stmt->column_count; i++) {
     346         137 :                         if (strcmp(stmt->columns[i].name, param->name) == 0) {
     347         108 :                                 param->paramno = i;
     348         108 :                                 break;
     349             :                         }
     350             :                 }
     351             : 
     352             :                 /* if you prepare and then execute passing an array of params keyed by names,
     353             :                  * then this will trigger, and we don't want that */
     354         108 :                 if (param->paramno == -1) {
     355             :                         char *tmp;
     356           0 :                         spprintf(&tmp, 0, "Did not find column name '%s' in the defined columns; it will not be bound", param->name);
     357           0 :                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", tmp TSRMLS_CC);
     358           0 :                         efree(tmp);
     359             :                 }
     360             :         }
     361             : 
     362       12017 :         if (param->name) {
     363       10657 :                 if (is_param && param->name[0] != ':') {
     364        5036 :                         char *temp = emalloc(++param->namelen + 1);
     365        5036 :                         temp[0] = ':';
     366        5036 :                         memmove(temp+1, param->name, param->namelen);
     367        5036 :                         param->name = temp;
     368             :                 } else {
     369         585 :                         param->name = estrndup(param->name, param->namelen);
     370             :                 }
     371             :         }
     372             : 
     373       12017 :         if (is_param && !rewrite_name_to_position(stmt, param TSRMLS_CC)) {
     374         101 :                 if (param->name) {
     375         101 :                         efree(param->name);
     376         101 :                         param->name = NULL;
     377             :                 }
     378         101 :                 return 0;
     379             :         }
     380             : 
     381             :         /* ask the driver to perform any normalization it needs on the
     382             :          * parameter name.  Note that it is illegal for the driver to take
     383             :          * a reference to param, as it resides in transient storage only
     384             :          * at this time. */
     385       11916 :         if (stmt->methods->param_hook) {
     386       11916 :                 if (!stmt->methods->param_hook(stmt, param, PDO_PARAM_EVT_NORMALIZE
     387             :                                 TSRMLS_CC)) {
     388           3 :                         if (param->name) {
     389           3 :                                 efree(param->name);
     390           3 :                                 param->name = NULL;
     391             :                         }
     392           3 :                         return 0;
     393             :                 }
     394             :         }
     395             : 
     396             :         /* delete any other parameter registered with this number.
     397             :          * If the parameter is named, it will be removed and correctly
     398             :          * disposed of by the hash_update call that follows */
     399       11913 :         if (param->paramno >= 0) {
     400        6758 :                 zend_hash_index_del(hash, param->paramno);
     401             :         }
     402             : 
     403             :         /* allocate storage for the parameter, keyed by its "canonical" name */
     404       11913 :         if (param->name) {
     405        5598 :                 zend_hash_update(hash, param->name, param->namelen, param,
     406             :                         sizeof(*param), (void**)&pparam);
     407             :         } else {
     408        6315 :                 zend_hash_index_update(hash, param->paramno, param, sizeof(*param),
     409             :                         (void**)&pparam);
     410             :         }
     411             : 
     412             :         /* tell the driver we just created a parameter */
     413       11913 :         if (stmt->methods->param_hook) {
     414       11913 :                 if (!stmt->methods->param_hook(stmt, pparam, PDO_PARAM_EVT_ALLOC
     415             :                                         TSRMLS_CC)) {
     416             :                         /* undo storage allocation; the hash will free the parameter
     417             :                          * name if required */
     418         101 :                         if (pparam->name) {
     419           2 :                                 zend_hash_del(hash, pparam->name, pparam->namelen);
     420             :                         } else {
     421          99 :                                 zend_hash_index_del(hash, pparam->paramno);
     422             :                         }
     423             :                         /* param->parameter is freed by hash dtor */
     424         101 :                         param->parameter = NULL;
     425         101 :                         return 0;
     426             :                 }
     427             :         }
     428       11812 :         return 1;
     429             : }
     430             : /* }}} */
     431             : 
     432             : /* {{{ proto bool PDOStatement::execute([array $bound_input_params])
     433             :    Execute a prepared statement, optionally binding parameters */
     434        2206 : static PHP_METHOD(PDOStatement, execute)
     435             : {
     436        2206 :         zval *input_params = NULL;
     437        2206 :         int ret = 1;
     438        2206 :         PHP_STMT_GET_OBJ;
     439             : 
     440        2206 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &input_params)) {
     441           0 :                 RETURN_FALSE;
     442             :         }
     443             : 
     444        2206 :         PDO_STMT_CLEAR_ERR();
     445             :         
     446        2206 :         if (input_params) {
     447             :                 struct pdo_bound_param_data param;
     448             :                 zval **tmp;
     449             :                 uint str_length;
     450             :                 ulong num_index;
     451             :         
     452         804 :                 if (stmt->bound_params) {    
     453         161 :                         zend_hash_destroy(stmt->bound_params);
     454         161 :                         FREE_HASHTABLE(stmt->bound_params);
     455         161 :                         stmt->bound_params = NULL;
     456             :                 }
     457             : 
     458         804 :                 zend_hash_internal_pointer_reset(Z_ARRVAL_P(input_params));
     459       12490 :                 while (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(input_params), (void*)&tmp)) {
     460       11085 :                         memset(&param, 0, sizeof(param));
     461             : 
     462       11085 :                         if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(Z_ARRVAL_P(input_params),
     463             :                                                 &param.name, &str_length, &num_index, 0, NULL)) {
     464             :                                 /* yes this is correct.  we don't want to count the null byte.  ask wez */
     465        5384 :                                 param.namelen = str_length - 1;
     466        5384 :                                 param.paramno = -1;
     467             :                         } else {
     468             :                                 /* we're okay to be zero based here */
     469        5701 :                                 if (num_index < 0) {
     470             :                                         pdo_raise_impl_error(stmt->dbh, stmt, "HY093", NULL TSRMLS_CC);
     471             :                                         RETURN_FALSE;
     472             :                                 }
     473        5701 :                                 param.paramno = num_index;
     474             :                         }
     475             : 
     476       11085 :                         param.param_type = PDO_PARAM_STR;
     477       11085 :                         MAKE_STD_ZVAL(param.parameter);
     478       33255 :                         MAKE_COPY_ZVAL(tmp, param.parameter);
     479             : 
     480       11085 :                         if (!really_register_bound_param(&param, stmt, 1 TSRMLS_CC)) {
     481         203 :                                 if (param.parameter) {
     482         102 :                                         zval_ptr_dtor(&param.parameter);
     483             :                                 }
     484         203 :                                 RETURN_FALSE;
     485             :                         }
     486             : 
     487       10882 :                         zend_hash_move_forward(Z_ARRVAL_P(input_params));
     488             :                 }
     489             :         }
     490             : 
     491        2003 :         if (PDO_PLACEHOLDER_NONE == stmt->supports_placeholders) {
     492             :                 /* handle the emulated parameter binding,
     493             :          * stmt->active_query_string holds the query with binds expanded and 
     494             :                  * quoted.
     495             :          */
     496             : 
     497         725 :                 ret = pdo_parse_params(stmt, stmt->query_string, stmt->query_stringlen,
     498             :                         &stmt->active_query_string, &stmt->active_query_stringlen TSRMLS_CC);
     499             : 
     500         725 :                 if (ret == 0) {
     501             :                         /* no changes were made */
     502         265 :                         stmt->active_query_string = stmt->query_string;
     503         265 :                         stmt->active_query_stringlen = stmt->query_stringlen;
     504         265 :                         ret = 1;
     505         460 :                 } else if (ret == -1) {
     506             :                         /* something broke */
     507         201 :                         PDO_HANDLE_STMT_ERR();
     508         201 :                         RETURN_FALSE;
     509             :                 }
     510        1278 :         } else if (!dispatch_param_event(stmt, PDO_PARAM_EVT_EXEC_PRE TSRMLS_CC)) {
     511           6 :                 PDO_HANDLE_STMT_ERR();
     512           6 :                 RETURN_FALSE;
     513             :         }
     514        1796 :         if (stmt->methods->executer(stmt TSRMLS_CC)) {
     515        1760 :                 if (stmt->active_query_string && stmt->active_query_string != stmt->query_string) {
     516         254 :                         efree(stmt->active_query_string);
     517             :                 }
     518        1760 :                 stmt->active_query_string = NULL;
     519        1760 :                 if (!stmt->executed) {
     520             :                         /* this is the first execute */
     521             : 
     522        1376 :                         if (stmt->dbh->alloc_own_columns && !stmt->columns) {
     523             :                                 /* for "big boy" drivers, we need to allocate memory to fetch
     524             :                                  * the results into, so lets do that now */
     525        1173 :                                 ret = pdo_stmt_describe_columns(stmt TSRMLS_CC);
     526             :                         }
     527             : 
     528        1376 :                         stmt->executed = 1;
     529             :                 }
     530             : 
     531        1760 :                 if (ret && !dispatch_param_event(stmt, PDO_PARAM_EVT_EXEC_POST TSRMLS_CC)) {
     532           0 :                         RETURN_FALSE;
     533             :                 }
     534             :                         
     535        1760 :                 RETURN_BOOL(ret);
     536             :         }
     537          36 :         if (stmt->active_query_string && stmt->active_query_string != stmt->query_string) {
     538           5 :                 efree(stmt->active_query_string);
     539             :         }
     540          36 :         stmt->active_query_string = NULL;
     541          36 :         PDO_HANDLE_STMT_ERR();
     542          36 :         RETURN_FALSE;
     543             : }
     544             : /* }}} */
     545             : 
     546        5245 : static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno, int *type_override TSRMLS_DC) /* {{{ */
     547             : {
     548             :         struct pdo_column_data *col;
     549        5245 :         char *value = NULL;
     550        5245 :         unsigned long value_len = 0;
     551        5245 :         int caller_frees = 0;
     552             :         int type, new_type;
     553             : 
     554        5245 :         col = &stmt->columns[colno];
     555        5245 :         type = PDO_PARAM_TYPE(col->param_type);
     556        5245 :         new_type =  type_override ? PDO_PARAM_TYPE(*type_override) : type;
     557             : 
     558        5245 :         value = NULL;
     559        5245 :         value_len = 0;
     560             : 
     561        5245 :         stmt->methods->get_col(stmt, colno, &value, &value_len, &caller_frees TSRMLS_CC);
     562             : 
     563        5245 :         switch (type) {
     564             :                 case PDO_PARAM_ZVAL:
     565        2036 :                         if (value && value_len == sizeof(zval)) {
     566        1018 :                                 int need_copy = (new_type != PDO_PARAM_ZVAL || stmt->dbh->stringify) ? 1 : 0;
     567        1018 :                                 zval *zv = *(zval**)value;
     568        2036 :                                 ZVAL_ZVAL(dest, zv, need_copy, 1);
     569             :                         } else {
     570           0 :                                 ZVAL_NULL(dest);
     571             :                         }
     572             :                         
     573        1018 :                         if (Z_TYPE_P(dest) == IS_NULL) {
     574          12 :                                 type = new_type;
     575             :                         }
     576        1018 :                         break;
     577             :                         
     578             :                 case PDO_PARAM_INT:
     579         245 :                         if (value && value_len == sizeof(long)) {
     580         227 :                                 ZVAL_LONG(dest, *(long*)value);
     581         227 :                                 break;
     582             :                         }
     583          18 :                         ZVAL_NULL(dest);
     584          18 :                         break;
     585             : 
     586             :                 case PDO_PARAM_BOOL:
     587           0 :                         if (value && value_len == sizeof(zend_bool)) {
     588           0 :                                 ZVAL_BOOL(dest, *(zend_bool*)value);
     589           0 :                                 break;
     590             :                         }
     591           0 :                         ZVAL_NULL(dest);
     592           0 :                         break;
     593             : 
     594             :                 case PDO_PARAM_LOB:
     595          38 :                         if (value == NULL) {
     596           2 :                                 ZVAL_NULL(dest);
     597          36 :                         } else if (value_len == 0) {
     598             :                                 /* Warning, empty strings need to be passed as stream */
     599          55 :                                 if (stmt->dbh->stringify || new_type == PDO_PARAM_STR) {
     600          21 :                                         char *buf = NULL;
     601             :                                         size_t len;
     602          21 :                                         len = php_stream_copy_to_mem((php_stream*)value, &buf, PHP_STREAM_COPY_ALL, 0);
     603          21 :                                         if(buf == NULL) {
     604           3 :                                                 ZVAL_EMPTY_STRING(dest);
     605             :                                         } else {
     606          18 :                                                 ZVAL_STRINGL(dest, buf, len, 0);
     607             :                                         }
     608          21 :                                         php_stream_close((php_stream*)value);
     609             :                                 } else {
     610          13 :                                         php_stream_to_zval((php_stream*)value, dest);
     611             :                                 }
     612           3 :                         } else if (!stmt->dbh->stringify && new_type != PDO_PARAM_STR) {
     613             :                                 /* they gave us a string, but LOBs are represented as streams in PDO */
     614             :                                 php_stream *stm;
     615             : #ifdef TEMP_STREAM_TAKE_BUFFER
     616           1 :                                 if (caller_frees) {
     617           1 :                                         stm = php_stream_memory_open(TEMP_STREAM_TAKE_BUFFER, value, value_len);
     618           1 :                                         if (stm) {
     619           1 :                                                 caller_frees = 0;
     620             :                                         }
     621             :                                 } else
     622             : #endif
     623             :                                 {
     624           0 :                                         stm = php_stream_memory_open(TEMP_STREAM_READONLY, value, value_len);
     625             :                                 }
     626           1 :                                 if (stm) {
     627           1 :                                         php_stream_to_zval(stm, dest);
     628             :                                 } else {
     629           0 :                                         ZVAL_NULL(dest);
     630             :                                 }
     631             :                         } else {
     632           1 :                                 ZVAL_STRINGL(dest, value, value_len, !caller_frees);
     633           1 :                                 if (caller_frees) {
     634           1 :                                         caller_frees = 0;
     635             :                                 }
     636             :                         }
     637          38 :                         break;
     638             :                 
     639             :                 case PDO_PARAM_STR:
     640        3944 :                         if (value && !(value_len == 0 && stmt->dbh->oracle_nulls == PDO_NULL_EMPTY_STRING)) {
     641        3858 :                                 ZVAL_STRINGL(dest, value, value_len, !caller_frees);
     642        3858 :                                 if (caller_frees) {
     643           0 :                                         caller_frees = 0;
     644             :                                 }
     645        3858 :                                 break;
     646             :                         }
     647             :                 default:
     648          86 :                         ZVAL_NULL(dest);
     649             :         }
     650             : 
     651        5245 :         if (type != new_type) {
     652         369 :                 switch (new_type) {
     653             :                         case PDO_PARAM_INT:
     654         140 :                                 convert_to_long_ex(&dest);
     655          72 :                                 break;
     656             :                         case PDO_PARAM_BOOL:
     657           0 :                                 convert_to_boolean_ex(&dest);
     658           0 :                                 break;
     659             :                         case PDO_PARAM_STR:
     660         657 :                                 convert_to_string_ex(&dest);
     661         279 :                                 break;
     662             :                         case PDO_PARAM_NULL:
     663           0 :                                 convert_to_null_ex(&dest);
     664             :                                 break;
     665             :                         default:
     666             :                                 ;
     667             :                 }
     668             :         }
     669             :         
     670        5245 :         if (caller_frees && value) {
     671           0 :                 efree(value);
     672             :         }
     673             : 
     674        5245 :         if (stmt->dbh->stringify) {
     675        3348 :                 switch (Z_TYPE_P(dest)) {
     676             :                         case IS_LONG:
     677             :                         case IS_DOUBLE:
     678         289 :                                 convert_to_string(dest);
     679             :                                 break;
     680             :                 }
     681             :         }
     682             : 
     683        5245 :         if (Z_TYPE_P(dest) == IS_NULL && stmt->dbh->oracle_nulls == PDO_NULL_TO_STRING) {
     684           2 :                 ZVAL_EMPTY_STRING(dest);
     685             :         }
     686        5245 : }
     687             : /* }}} */
     688             : 
     689        3291 : static int do_fetch_common(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori,
     690             :         long offset, int do_bind TSRMLS_DC) /* {{{ */
     691             : {
     692        3291 :         if (!stmt->executed) {
     693          14 :                 return 0;
     694             :         }
     695             : 
     696        3277 :         if (!dispatch_param_event(stmt, PDO_PARAM_EVT_FETCH_PRE TSRMLS_CC)) {
     697           0 :                 return 0;
     698             :         }
     699             : 
     700        3277 :         if (!stmt->methods->fetcher(stmt, ori, offset TSRMLS_CC)) {
     701         709 :                 return 0;
     702             :         }
     703             : 
     704             :         /* some drivers might need to describe the columns now */
     705        2568 :         if (!stmt->columns && !pdo_stmt_describe_columns(stmt TSRMLS_CC)) {
     706           0 :                 return 0;
     707             :         }
     708             :         
     709        2568 :         if (!dispatch_param_event(stmt, PDO_PARAM_EVT_FETCH_POST TSRMLS_CC)) {
     710           1 :                 return 0;
     711             :         }
     712             : 
     713        2567 :         if (do_bind && stmt->bound_columns) {
     714             :                 /* update those bound column variables now */
     715             :                 struct pdo_bound_param_data *param;
     716             : 
     717         520 :                 zend_hash_internal_pointer_reset(stmt->bound_columns);
     718        1938 :                 while (SUCCESS == zend_hash_get_current_data(stmt->bound_columns, (void**)&param)) {
     719         898 :                         if (param->paramno >= 0) {
     720         898 :                                 convert_to_string(param->parameter);
     721             : 
     722             :                                 /* delete old value */
     723         898 :                                 zval_dtor(param->parameter);
     724             : 
     725             :                                 /* set new value */
     726         898 :                                 fetch_value(stmt, param->parameter, param->paramno, (int *)&param->param_type TSRMLS_CC);
     727             : 
     728             :                                 /* TODO: some smart thing that avoids duplicating the value in the
     729             :                                  * general loop below.  For now, if you're binding output columns,
     730             :                                  * it's better to use LAZY or BOUND fetches if you want to shave
     731             :                                  * off those cycles */
     732             :                         }
     733             : 
     734         898 :                         zend_hash_move_forward(stmt->bound_columns);
     735             :                 }
     736             :         }
     737             : 
     738        2567 :         return 1;
     739             : }
     740             : /* }}} */
     741             : 
     742         218 : static int do_fetch_class_prepare(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
     743             : {
     744         218 :         zend_class_entry * ce = stmt->fetch.cls.ce;
     745         218 :         zend_fcall_info * fci = &stmt->fetch.cls.fci;
     746         218 :         zend_fcall_info_cache * fcc = &stmt->fetch.cls.fcc;
     747             : 
     748         218 :         fci->size = sizeof(zend_fcall_info);
     749             : 
     750         218 :         if (!ce) {
     751           1 :                 stmt->fetch.cls.ce = ZEND_STANDARD_CLASS_DEF_PTR;
     752           1 :                 ce = ZEND_STANDARD_CLASS_DEF_PTR;
     753             :         }
     754             :         
     755         218 :         if (ce->constructor) {
     756         147 :                 fci->function_table = &ce->function_table;
     757         147 :                 fci->function_name = NULL;
     758         147 :                 fci->symbol_table = NULL;
     759         147 :                 fci->retval_ptr_ptr = &stmt->fetch.cls.retval_ptr;
     760         147 :                 fci->params = NULL;
     761         147 :                 fci->no_separation = 1;
     762             : 
     763         147 :                 zend_fcall_info_args(fci, stmt->fetch.cls.ctor_args TSRMLS_CC);
     764             : 
     765         147 :                 fcc->initialized = 1;
     766         147 :                 fcc->function_handler = ce->constructor;
     767         147 :                 fcc->calling_scope = EG(scope);
     768         147 :                 fcc->called_scope = ce;
     769         147 :                 return 1;
     770          71 :         } else if (stmt->fetch.cls.ctor_args) {
     771           0 :                 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "user-supplied class does not have a constructor, use NULL for the ctor_params parameter, or simply omit it" TSRMLS_CC);
     772           0 :                 return 0;
     773             :         } else {
     774          71 :                 return 1; /* no ctor no args is also ok */
     775             :         }
     776             : }
     777             : /* }}} */
     778             : 
     779          66 : static int make_callable_ex(pdo_stmt_t *stmt, zval *callable, zend_fcall_info * fci, zend_fcall_info_cache * fcc, int num_args TSRMLS_DC) /* {{{ */
     780             : {
     781          66 :         char *is_callable_error = NULL;
     782             : 
     783          66 :         if (zend_fcall_info_init(callable, 0, fci, fcc, NULL, &is_callable_error TSRMLS_CC) == FAILURE) { 
     784           7 :                 if (is_callable_error) {
     785           7 :                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", is_callable_error TSRMLS_CC);
     786           7 :                         efree(is_callable_error);
     787             :                 } else {
     788           0 :                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "user-supplied function must be a valid callback" TSRMLS_CC);
     789             :                 }
     790           7 :                 return 0;
     791             :         }
     792          59 :         if (is_callable_error) {
     793             :                 /* Possible E_STRICT error message */
     794           1 :                 efree(is_callable_error);
     795             :         }
     796             :         
     797          59 :         fci->param_count = num_args; /* probably less */
     798          59 :         fci->params = safe_emalloc(sizeof(zval**), num_args, 0);
     799             :         
     800          59 :         return 1;
     801             : }
     802             : /* }}} */
     803             : 
     804          66 : static int do_fetch_func_prepare(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
     805             : {
     806          66 :         zend_fcall_info * fci = &stmt->fetch.cls.fci;
     807          66 :         zend_fcall_info_cache * fcc = &stmt->fetch.cls.fcc;
     808             : 
     809          66 :         if (!make_callable_ex(stmt, stmt->fetch.func.function, fci, fcc, stmt->column_count TSRMLS_CC)) {
     810           7 :                 return 0;
     811             :         } else {
     812          59 :                 stmt->fetch.func.values = safe_emalloc(sizeof(zval*), stmt->column_count, 0);
     813          59 :                 return 1;
     814             :         }
     815             : }
     816             : /* }}} */
     817             : 
     818        3865 : static int do_fetch_opt_finish(pdo_stmt_t *stmt, int free_ctor_agrs TSRMLS_DC) /* {{{ */
     819             : {
     820             :         /* fci.size is used to check if it is valid */
     821        3865 :         if (stmt->fetch.cls.fci.size && stmt->fetch.cls.fci.params) {
     822         102 :                 efree(stmt->fetch.cls.fci.params);
     823         102 :                 stmt->fetch.cls.fci.params = NULL;
     824             :         }
     825        3865 :         stmt->fetch.cls.fci.size = 0;
     826        3865 :         if (stmt->fetch.cls.ctor_args && free_ctor_agrs) {
     827          25 :                 zval_ptr_dtor(&stmt->fetch.cls.ctor_args);
     828          25 :                 stmt->fetch.cls.ctor_args = NULL;
     829          25 :                 stmt->fetch.cls.fci.param_count = 0;
     830             :         }
     831        3865 :         if (stmt->fetch.func.values) {
     832          59 :                 efree(stmt->fetch.func.values);
     833          59 :                 stmt->fetch.func.values = NULL;
     834             :         }
     835        3865 :         return 1;
     836             : }
     837             : /* }}} */
     838             : 
     839             : /* perform a fetch.  If do_bind is true, update any bound columns.
     840             :  * If return_value is not null, store values into it according to HOW. */
     841        3206 : static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value,
     842             :         enum pdo_fetch_type how, enum pdo_fetch_orientation ori, long offset, zval *return_all TSRMLS_DC) /* {{{ */
     843             : {
     844        3206 :         int flags, idx, old_arg_count = 0;
     845        3206 :         zend_class_entry *ce = NULL, *old_ce = NULL;
     846        3206 :         zval grp_val, *grp, **pgrp, *retval, *old_ctor_args = NULL;
     847             :         int colno;
     848             : 
     849        3206 :         if (how == PDO_FETCH_USE_DEFAULT) {
     850         511 :                 how = stmt->default_fetch_type;
     851             :         }
     852        3206 :         flags = how & PDO_FETCH_FLAGS;
     853        3206 :         how = how & ~PDO_FETCH_FLAGS;
     854             : 
     855        3206 :         if (!do_fetch_common(stmt, ori, offset, do_bind TSRMLS_CC)) {
     856         720 :                 return 0;
     857             :         }
     858             : 
     859        2486 :         if (how == PDO_FETCH_BOUND) {
     860         406 :                 RETVAL_TRUE;
     861         406 :                 return 1;
     862             :         }
     863             : 
     864        2200 :         if (flags & PDO_FETCH_GROUP && stmt->fetch.column == -1) {
     865         120 :                 colno = 1;
     866             :         } else {
     867        1960 :                 colno = stmt->fetch.column;
     868             :         }
     869             : 
     870        2080 :         if (return_value) {
     871        2080 :                 int i = 0;
     872             : 
     873        2080 :                 if (how == PDO_FETCH_LAZY) {
     874          23 :                         get_lazy_object(stmt, return_value TSRMLS_CC);
     875          23 :                         return 1;
     876             :                 }
     877             : 
     878        2057 :                 RETVAL_FALSE;
     879             : 
     880        2057 :                 switch (how) {
     881             :                         case PDO_FETCH_USE_DEFAULT:
     882             :                         case PDO_FETCH_ASSOC:
     883             :                         case PDO_FETCH_BOTH:
     884             :                         case PDO_FETCH_NUM:
     885             :                         case PDO_FETCH_NAMED:
     886        1243 :                                 if (!return_all) {
     887        1147 :                                         ALLOC_HASHTABLE(return_value->value.ht);
     888        1147 :                                         zend_hash_init(return_value->value.ht, stmt->column_count, NULL, ZVAL_PTR_DTOR, 0);
     889        1147 :                                         Z_TYPE_P(return_value) = IS_ARRAY;
     890             :                                 } else {
     891          96 :                                         array_init(return_value);
     892             :                                 }
     893        1243 :                                 break;
     894             : 
     895             :                         case PDO_FETCH_KEY_PAIR:
     896         102 :                                 if (stmt->column_count != 2) {
     897           6 :                                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO::FETCH_KEY_PAIR fetch mode requires the result set to contain extactly 2 columns." TSRMLS_CC);
     898           6 :                                         return 0;
     899             :                                 }
     900          96 :                                 if (!return_all) {
     901           6 :                                         array_init(return_value);
     902             :                                 }
     903          96 :                                 break;
     904             : 
     905             :                         case PDO_FETCH_COLUMN:
     906         211 :                                 if (colno >= 0 && colno < stmt->column_count) {
     907         235 :                                         if (flags == PDO_FETCH_GROUP && stmt->fetch.column == -1) {
     908          24 :                                                 fetch_value(stmt, return_value, 1, NULL TSRMLS_CC);
     909         187 :                                         } else if (flags == PDO_FETCH_GROUP && colno) {
     910           0 :                                                 fetch_value(stmt, return_value, 0, NULL TSRMLS_CC);
     911             :                                         } else {
     912         187 :                                                 fetch_value(stmt, return_value, colno, NULL TSRMLS_CC); 
     913             :                                         }
     914         211 :                                         if (!return_all) {
     915          55 :                                                 return 1;
     916             :                                         } else {
     917         156 :                                                 break;
     918             :                                         }
     919             :                                 } else {
     920           0 :                                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Invalid column index" TSRMLS_CC);
     921             :                                 }
     922           0 :                                 return 0;
     923             : 
     924             :                         case PDO_FETCH_OBJ:
     925          18 :                                 object_init_ex(return_value, ZEND_STANDARD_CLASS_DEF_PTR);
     926          18 :                                 break;
     927             : 
     928             :                         case PDO_FETCH_CLASS:
     929         246 :                                 if (flags & PDO_FETCH_CLASSTYPE) {
     930             :                                         zval val;
     931             :                                         zend_class_entry **cep;
     932             : 
     933         100 :                                         old_ce = stmt->fetch.cls.ce;
     934         100 :                                         old_ctor_args = stmt->fetch.cls.ctor_args;
     935         100 :                                         old_arg_count = stmt->fetch.cls.fci.param_count;
     936         100 :                                         do_fetch_opt_finish(stmt, 0 TSRMLS_CC);
     937             : 
     938         100 :                                         INIT_PZVAL(&val);
     939         100 :                                         fetch_value(stmt, &val, i++, NULL TSRMLS_CC);
     940         100 :                                         if (Z_TYPE(val) != IS_NULL) {
     941          76 :                                                 convert_to_string(&val);
     942          76 :                                                 if (zend_lookup_class(Z_STRVAL(val), Z_STRLEN(val), &cep TSRMLS_CC) == FAILURE) {
     943           1 :                                                         stmt->fetch.cls.ce = ZEND_STANDARD_CLASS_DEF_PTR;
     944             :                                                 } else {
     945          75 :                                                         stmt->fetch.cls.ce = *cep;
     946             :                                                 }
     947             :                                         }
     948             : 
     949         100 :                                         do_fetch_class_prepare(stmt TSRMLS_CC);
     950             :                                         zval_dtor(&val);
     951             :                                 }
     952         246 :                                 ce = stmt->fetch.cls.ce;
     953         246 :                                 if (!ce) {
     954           6 :                                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "No fetch class specified" TSRMLS_CC);
     955           6 :                                         return 0;
     956             :                                 }
     957         240 :                                 if ((flags & PDO_FETCH_SERIALIZE) == 0) {
     958         206 :                                         object_init_ex(return_value, ce);
     959         206 :                                         if (!stmt->fetch.cls.fci.size) {
     960          18 :                                                 if (!do_fetch_class_prepare(stmt TSRMLS_CC))
     961             :                                                 {
     962           0 :                                                         return 0;
     963             :                                                 }
     964             :                                         }
     965         206 :                                         if (ce->constructor && (flags & PDO_FETCH_PROPS_LATE)) {
     966           9 :                                                 stmt->fetch.cls.fci.object_ptr = return_value;
     967           9 :                                                 stmt->fetch.cls.fcc.object_ptr = return_value;
     968           9 :                                                 if (zend_call_function(&stmt->fetch.cls.fci, &stmt->fetch.cls.fcc TSRMLS_CC) == FAILURE) {
     969           0 :                                                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "could not call class constructor" TSRMLS_CC);
     970           0 :                                                         return 0;
     971             :                                                 } else {
     972           9 :                                                         if (stmt->fetch.cls.retval_ptr) {
     973           9 :                                                                 zval_ptr_dtor(&stmt->fetch.cls.retval_ptr);
     974             :                                                         }
     975             :                                                 }
     976             :                                         }
     977             :                                 }
     978         240 :                                 break;
     979             :                         
     980             :                         case PDO_FETCH_INTO:
     981          42 :                                 if (!stmt->fetch.into) {
     982           0 :                                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "No fetch-into object specified." TSRMLS_CC);
     983           0 :                                         return 0;
     984             :                                         break;
     985             :                                 }
     986             : 
     987          42 :                                 Z_TYPE_P(return_value) = IS_OBJECT;
     988          42 :                                 Z_OBJ_HANDLE_P(return_value) = Z_OBJ_HANDLE_P(stmt->fetch.into);
     989          42 :                                 Z_OBJ_HT_P(return_value) = Z_OBJ_HT_P(stmt->fetch.into);
     990          42 :                                 zend_objects_store_add_ref(stmt->fetch.into TSRMLS_CC);
     991             : 
     992          42 :                                 if (zend_get_class_entry(return_value TSRMLS_CC) == ZEND_STANDARD_CLASS_DEF_PTR) {
     993           0 :                                         how = PDO_FETCH_OBJ;
     994             :                                 }
     995          42 :                                 break;
     996             : 
     997             :                         case PDO_FETCH_FUNC:
     998         195 :                                 if (!stmt->fetch.func.function) {
     999           5 :                                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "No fetch function specified" TSRMLS_CC);
    1000           5 :                                         return 0;
    1001             :                                 }
    1002         190 :                                 if (!stmt->fetch.func.fci.size) {
    1003           0 :                                         if (!do_fetch_func_prepare(stmt TSRMLS_CC))
    1004             :                                         {
    1005           0 :                                                 return 0;
    1006             :                                         }
    1007             :                                 }
    1008         190 :                                 break;
    1009             :                                 
    1010             : 
    1011             :                         default:
    1012             :                                 /* shouldn't happen */
    1013           0 :                                 return 0;
    1014             :                 }
    1015             :                 
    1016        1985 :                 if (return_all && how != PDO_FETCH_KEY_PAIR) {
    1017         324 :                         INIT_PZVAL(&grp_val);
    1018         324 :                         if (flags == PDO_FETCH_GROUP && how == PDO_FETCH_COLUMN && stmt->fetch.column > 0) {
    1019           0 :                                 fetch_value(stmt, &grp_val, colno, NULL TSRMLS_CC);
    1020             :                         } else {
    1021         324 :                                 fetch_value(stmt, &grp_val, i, NULL TSRMLS_CC);
    1022             :                         }
    1023         324 :                         convert_to_string(&grp_val);
    1024         324 :                         if (how == PDO_FETCH_COLUMN) {
    1025         156 :                                 i = stmt->column_count; /* no more data to fetch */
    1026             :                         } else {
    1027         168 :                                 i++;
    1028             :                         }
    1029             :                 }
    1030             : 
    1031        5380 :                 for (idx = 0; i < stmt->column_count; i++, idx++) {
    1032             :                         zval *val;
    1033        3503 :                         MAKE_STD_ZVAL(val);
    1034        3503 :                         fetch_value(stmt, val, i, NULL TSRMLS_CC);
    1035             : 
    1036        3503 :                         switch (how) {
    1037             :                                 case PDO_FETCH_ASSOC:
    1038        1636 :                                         add_assoc_zval(return_value, stmt->columns[i].name, val);
    1039        1636 :                                         break;
    1040             :                                         
    1041             :                                 case PDO_FETCH_KEY_PAIR:
    1042             :                                         {
    1043             :                                                 zval *tmp;
    1044          96 :                                                 MAKE_STD_ZVAL(tmp);
    1045          96 :                                                 fetch_value(stmt, tmp, ++i, NULL TSRMLS_CC);
    1046             : 
    1047          96 :                                                 if (Z_TYPE_P(val) == IS_LONG) {
    1048           0 :                                                         zend_hash_index_update((return_all ? Z_ARRVAL_P(return_all) : Z_ARRVAL_P(return_value)), Z_LVAL_P(val), &tmp, sizeof(zval *), NULL);
    1049             :                                                 } else {
    1050          96 :                                                         convert_to_string(val);
    1051          96 :                                                         zend_symtable_update((return_all ? Z_ARRVAL_P(return_all) : Z_ARRVAL_P(return_value)), Z_STRVAL_P(val), Z_STRLEN_P(val) + 1, &tmp, sizeof(zval *), NULL);
    1052             :                                                 }
    1053          96 :                                                 zval_ptr_dtor(&val);
    1054          96 :                                                 return 1;
    1055             :                                         }
    1056             :                                         break;
    1057             : 
    1058             :                                 case PDO_FETCH_USE_DEFAULT:
    1059             :                                 case PDO_FETCH_BOTH:
    1060         507 :                                         add_assoc_zval(return_value, stmt->columns[i].name, val);
    1061         507 :                                         Z_ADDREF_P(val);
    1062         507 :                                         add_next_index_zval(return_value, val);
    1063         507 :                                         break;
    1064             : 
    1065             :                                 case PDO_FETCH_NAMED:
    1066             :                                         /* already have an item with this name? */
    1067             :                                         {
    1068           0 :                                                 zval **curr_val = NULL;
    1069           0 :                                                 if (zend_hash_find(Z_ARRVAL_P(return_value), stmt->columns[i].name,
    1070           0 :                                                                         strlen(stmt->columns[i].name)+1,
    1071             :                                                                         (void**)&curr_val) == SUCCESS) {
    1072             :                                                         zval *arr;
    1073           0 :                                                         if (Z_TYPE_PP(curr_val) != IS_ARRAY) {
    1074             :                                                                 /* a little bit of black magic here:
    1075             :                                                                  * we're creating a new array and swapping it for the
    1076             :                                                                  * zval that's already stored in the hash under the name
    1077             :                                                                  * we want.  We then add that zval to the array.
    1078             :                                                                  * This is effectively the same thing as:
    1079             :                                                                  * if (!is_array($hash[$name])) {
    1080             :                                                                  *   $hash[$name] = array($hash[$name]);
    1081             :                                                                  * }
    1082             :                                                                  * */
    1083             :                                                                 zval *cur;
    1084             : 
    1085           0 :                                                                 MAKE_STD_ZVAL(arr);
    1086           0 :                                                                 array_init(arr);
    1087             : 
    1088           0 :                                                                 cur = *curr_val;
    1089           0 :                                                                 *curr_val = arr;
    1090             : 
    1091           0 :                                                                 add_next_index_zval(arr, cur);
    1092             :                                                         } else {
    1093           0 :                                                                 arr = *curr_val;
    1094             :                                                         }
    1095           0 :                                                         add_next_index_zval(arr, val);
    1096             :                                                 } else {
    1097           0 :                                                         add_assoc_zval(return_value, stmt->columns[i].name, val);
    1098             :                                                 }
    1099             :                                         }
    1100           0 :                                         break;
    1101             : 
    1102             :                                 case PDO_FETCH_NUM:
    1103         277 :                                         add_next_index_zval(return_value, val);
    1104         277 :                                         break;
    1105             : 
    1106             :                                 case PDO_FETCH_OBJ:
    1107             :                                 case PDO_FETCH_INTO:
    1108         450 :                                         zend_update_property(NULL, return_value,
    1109         300 :                                                 stmt->columns[i].name, stmt->columns[i].namelen,
    1110             :                                                 val TSRMLS_CC);
    1111         144 :                                         zval_ptr_dtor(&val);
    1112         144 :                                         break;
    1113             : 
    1114             :                                 case PDO_FETCH_CLASS:
    1115         956 :                                         if ((flags & PDO_FETCH_SERIALIZE) == 0 || idx) {
    1116        1383 :                                                 zend_update_property(ce, return_value,
    1117         922 :                                                         stmt->columns[i].name, stmt->columns[i].namelen,
    1118             :                                                         val TSRMLS_CC);
    1119         461 :                                                 zval_ptr_dtor(&val);
    1120             :                                         } else {
    1121             : #ifdef MBO_0
    1122             :                                                 php_unserialize_data_t var_hash;
    1123             : 
    1124             :                                                 PHP_VAR_UNSERIALIZE_INIT(var_hash);
    1125             :                                                 if (php_var_unserialize(&return_value, (const unsigned char**)&Z_STRVAL_P(val), Z_STRVAL_P(val)+Z_STRLEN_P(val), NULL TSRMLS_CC) == FAILURE) {
    1126             :                                                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "cannot unserialize data" TSRMLS_CC);
    1127             :                                                         PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
    1128             :                                                         return 0;
    1129             :                                                 }
    1130             :                                                 PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
    1131             : #endif
    1132             : #if PHP_MAJOR_VERSION > 5 || PHP_MINOR_VERSION >= 1
    1133          34 :                                                 if (!ce->unserialize) {
    1134           6 :                                                         zval_ptr_dtor(&val);
    1135           6 :                                                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "cannot unserialize class" TSRMLS_CC);
    1136           6 :                                                         return 0;
    1137          28 :                                                 } else if (ce->unserialize(&return_value, ce, (unsigned char *)(Z_TYPE_P(val) == IS_STRING ? Z_STRVAL_P(val) : ""), Z_TYPE_P(val) == IS_STRING ? Z_STRLEN_P(val) : 0, NULL TSRMLS_CC) == FAILURE) {
    1138           0 :                                                         zval_ptr_dtor(&val);
    1139           0 :                                                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "cannot unserialize class" TSRMLS_CC);
    1140           0 :                                                         zval_dtor(return_value);
    1141           0 :                                                         ZVAL_NULL(return_value);
    1142           0 :                                                         return 0;
    1143             :                                                 } else {
    1144          28 :                                                         zval_ptr_dtor(&val);
    1145             :                                                 }
    1146             : #endif
    1147             :                                         }
    1148         489 :                                         break;
    1149             :                                 
    1150             :                                 case PDO_FETCH_FUNC:
    1151         342 :                                         stmt->fetch.func.values[idx] = val;
    1152         342 :                                         stmt->fetch.cls.fci.params[idx] = &stmt->fetch.func.values[idx];
    1153         342 :                                         break;
    1154             :                                 
    1155             :                                 default:
    1156           0 :                                         zval_ptr_dtor(&val);
    1157           0 :                                         pdo_raise_impl_error(stmt->dbh, stmt, "22003", "mode is out of range" TSRMLS_CC);
    1158           0 :                                         return 0;
    1159             :                                         break;
    1160             :                         }
    1161             :                 }
    1162             :                 
    1163        1877 :                 switch (how) {
    1164             :                         case PDO_FETCH_CLASS:
    1165         234 :                                 if (ce->constructor && !(flags & (PDO_FETCH_PROPS_LATE | PDO_FETCH_SERIALIZE))) {
    1166         139 :                                         stmt->fetch.cls.fci.object_ptr = return_value;
    1167         139 :                                         stmt->fetch.cls.fcc.object_ptr = return_value;
    1168         139 :                                         if (zend_call_function(&stmt->fetch.cls.fci, &stmt->fetch.cls.fcc TSRMLS_CC) == FAILURE) {
    1169           0 :                                                 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "could not call class constructor" TSRMLS_CC);
    1170           0 :                                                 return 0;
    1171             :                                         } else {
    1172         139 :                                                 if (stmt->fetch.cls.retval_ptr) {
    1173         139 :                                                         zval_ptr_dtor(&stmt->fetch.cls.retval_ptr);
    1174             :                                                 }
    1175             :                                         }
    1176             :                                 }
    1177         234 :                                 if (flags & PDO_FETCH_CLASSTYPE) {
    1178          94 :                                         do_fetch_opt_finish(stmt, 0 TSRMLS_CC);
    1179          94 :                                         stmt->fetch.cls.ce = old_ce;
    1180          94 :                                         stmt->fetch.cls.ctor_args = old_ctor_args;
    1181          94 :                                         stmt->fetch.cls.fci.param_count = old_arg_count;
    1182             :                                 }
    1183         234 :                                 break;
    1184             : 
    1185             :                         case PDO_FETCH_FUNC:
    1186         190 :                                 stmt->fetch.func.fci.param_count = idx;
    1187         190 :                                 stmt->fetch.func.fci.retval_ptr_ptr = &retval;
    1188         190 :                                 if (zend_call_function(&stmt->fetch.func.fci, &stmt->fetch.func.fcc TSRMLS_CC) == FAILURE) {
    1189           0 :                                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "could not call user-supplied function" TSRMLS_CC);
    1190           0 :                                         return 0;
    1191             :                                 } else {
    1192         190 :                                         if (return_all) {
    1193          24 :                                                 zval_ptr_dtor(&return_value); /* we don't need that */
    1194          24 :                                                 return_value = retval;
    1195         166 :                                         } else if (retval) {
    1196         498 :                                                 MAKE_COPY_ZVAL(&retval, return_value);
    1197         166 :                                                 zval_ptr_dtor(&retval);
    1198             :                                         }
    1199             :                                 }
    1200         722 :                                 while(idx--) {
    1201         342 :                                         zval_ptr_dtor(&stmt->fetch.func.values[idx]);
    1202             :                                 }
    1203             :                                 break;
    1204             :                         
    1205             :                         default:
    1206             :                                 break;
    1207             :                 }
    1208             : 
    1209        1877 :                 if (return_all) {
    1210         324 :                         if ((flags & PDO_FETCH_UNIQUE) == PDO_FETCH_UNIQUE) {
    1211         210 :                                 add_assoc_zval(return_all, Z_STRVAL(grp_val), return_value);
    1212             :                         } else {
    1213         114 :                                 if (zend_symtable_find(Z_ARRVAL_P(return_all), Z_STRVAL(grp_val), Z_STRLEN(grp_val)+1, (void**)&pgrp) == FAILURE) {
    1214          72 :                                         MAKE_STD_ZVAL(grp);
    1215          72 :                                         array_init(grp);
    1216          72 :                                         add_assoc_zval(return_all, Z_STRVAL(grp_val), grp);
    1217             :                                 } else {
    1218          42 :                                         grp = *pgrp;
    1219             :                                 }
    1220         114 :                                 add_next_index_zval(grp, return_value);
    1221             :                         }
    1222             :                         zval_dtor(&grp_val);
    1223             :                 }
    1224             : 
    1225             :         }
    1226             : 
    1227        1877 :         return 1;
    1228             : }
    1229             : /* }}} */
    1230             : 
    1231        1781 : static int pdo_stmt_verify_mode(pdo_stmt_t *stmt, long mode, int fetch_all TSRMLS_DC) /* {{{ */
    1232             : {
    1233        1781 :         int flags = mode & PDO_FETCH_FLAGS;
    1234             : 
    1235        1781 :         mode = mode & ~PDO_FETCH_FLAGS;
    1236             : 
    1237        1781 :         if (mode < 0 || mode > PDO_FETCH__MAX) {
    1238           0 :                 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "invalid fetch mode" TSRMLS_CC);
    1239           0 :                 return 0;
    1240             :         }
    1241             :         
    1242        1781 :         if (mode == PDO_FETCH_USE_DEFAULT) {
    1243         138 :                 flags = stmt->default_fetch_type & PDO_FETCH_FLAGS;
    1244         138 :                 mode = stmt->default_fetch_type & ~PDO_FETCH_FLAGS;
    1245             :         }
    1246             : 
    1247             : #if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 1
    1248             :         if ((flags & PDO_FETCH_SERIALIZE) == PDO_FETCH_SERIALIZE) {
    1249             :                 pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "PDO::FETCH_SERIALIZE is not supported in this PHP version" TSRMLS_CC);
    1250             :                 return 0;
    1251             :         }
    1252             : #endif
    1253             : 
    1254        1781 :         switch(mode) {
    1255             :         case PDO_FETCH_FUNC:
    1256          71 :                 if (!fetch_all) {
    1257           0 :                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO::FETCH_FUNC is only allowed in PDOStatement::fetchAll()" TSRMLS_CC);
    1258           0 :                         return 0;
    1259             :                 }
    1260          71 :                 return 1;
    1261             : 
    1262             :         case PDO_FETCH_LAZY:
    1263          23 :                 if (fetch_all) {
    1264           0 :                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO::FETCH_LAZY can't be used with PDOStatement::fetchAll()" TSRMLS_CC);
    1265           0 :                         return 0;
    1266             :                 }
    1267             :                 /* fall through */
    1268             :         
    1269             :         default:
    1270        1565 :                 if ((flags & PDO_FETCH_SERIALIZE) == PDO_FETCH_SERIALIZE) {
    1271           0 :                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO::FETCH_SERIALIZE can only be used together with PDO::FETCH_CLASS" TSRMLS_CC);
    1272           0 :                         return 0;
    1273             :                 }
    1274        1565 :                 if ((flags & PDO_FETCH_CLASSTYPE) == PDO_FETCH_CLASSTYPE) {
    1275           0 :                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO::FETCH_CLASSTYPE can only be used together with PDO::FETCH_CLASS" TSRMLS_CC);
    1276           0 :                         return 0;
    1277             :                 }
    1278        1565 :                 if (mode >= PDO_FETCH__MAX) {
    1279           0 :                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "invalid fetch mode" TSRMLS_CC);
    1280           0 :                         return 0;
    1281             :                 }
    1282             :                 /* no break; */
    1283             : 
    1284             :         case PDO_FETCH_CLASS:
    1285        1710 :                 return 1;
    1286             :         }
    1287             : }
    1288             : /* }}} */
    1289             : 
    1290             : /* {{{ proto mixed PDOStatement::fetch([int $how = PDO_FETCH_BOTH [, int $orientation [, int $offset]]])
    1291             :    Fetches the next row and returns it, or false if there are no more rows */
    1292        1098 : static PHP_METHOD(PDOStatement, fetch)
    1293             : {
    1294        1098 :         long how = PDO_FETCH_USE_DEFAULT;
    1295        1098 :         long ori = PDO_FETCH_ORI_NEXT;
    1296        1098 :         long off = 0;
    1297        1098 :         PHP_STMT_GET_OBJ;
    1298             : 
    1299        1098 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lll", &how,
    1300             :                         &ori, &off)) {
    1301           0 :                 RETURN_FALSE;
    1302             :         }
    1303             : 
    1304        1098 :         PDO_STMT_CLEAR_ERR();
    1305             : 
    1306        1098 :         if (!pdo_stmt_verify_mode(stmt, how, 0 TSRMLS_CC)) {
    1307           0 :                 RETURN_FALSE;
    1308             :         }
    1309             : 
    1310        1098 :         if (!do_fetch(stmt, TRUE, return_value, how, ori, off, 0 TSRMLS_CC)) {
    1311         130 :                 PDO_HANDLE_STMT_ERR();
    1312         130 :                 RETURN_FALSE;
    1313             :         }
    1314             : }
    1315             : /* }}} */
    1316             : 
    1317             : /* {{{ proto mixed PDOStatement::fetchObject([string class_name [, NULL|array ctor_args]])
    1318             :    Fetches the next row and returns it as an object. */
    1319           6 : static PHP_METHOD(PDOStatement, fetchObject)
    1320             : {
    1321           6 :         long how = PDO_FETCH_CLASS;
    1322           6 :         long ori = PDO_FETCH_ORI_NEXT;
    1323           6 :         long off = 0;
    1324           6 :         char *class_name = NULL;
    1325             :         int class_name_len;
    1326             :         zend_class_entry *old_ce;
    1327           6 :         zval *old_ctor_args, *ctor_args = NULL;
    1328           6 :         int error = 0, old_arg_count;
    1329             : 
    1330           6 :         PHP_STMT_GET_OBJ;
    1331             : 
    1332           6 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!a", &class_name, &class_name_len, &ctor_args)) {
    1333           0 :                 RETURN_FALSE;
    1334             :         }
    1335             : 
    1336           6 :         PDO_STMT_CLEAR_ERR();
    1337             : 
    1338           6 :         if (!pdo_stmt_verify_mode(stmt, how, 0 TSRMLS_CC)) {
    1339           0 :                 RETURN_FALSE;
    1340             :         }
    1341             : 
    1342           6 :         old_ce = stmt->fetch.cls.ce;
    1343           6 :         old_ctor_args = stmt->fetch.cls.ctor_args;
    1344           6 :         old_arg_count = stmt->fetch.cls.fci.param_count;
    1345             :         
    1346           6 :         do_fetch_opt_finish(stmt, 0 TSRMLS_CC);
    1347             : 
    1348           6 :         if (ctor_args) {
    1349           8 :                 if (Z_TYPE_P(ctor_args) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_P(ctor_args))) {
    1350           4 :                         ALLOC_ZVAL(stmt->fetch.cls.ctor_args);
    1351           4 :                         *stmt->fetch.cls.ctor_args = *ctor_args;
    1352           4 :                         zval_copy_ctor(stmt->fetch.cls.ctor_args);
    1353             :                 } else {
    1354           0 :                         stmt->fetch.cls.ctor_args = NULL;
    1355             :                 }
    1356             :         }
    1357          10 :         if (class_name && !error) {
    1358           4 :                 stmt->fetch.cls.ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
    1359             : 
    1360           4 :                 if (!stmt->fetch.cls.ce) {
    1361           0 :                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Could not find user-supplied class" TSRMLS_CC);
    1362           0 :                         error = 1;
    1363             :                 }
    1364           2 :         } else if (!error) {
    1365           2 :                 stmt->fetch.cls.ce = zend_standard_class_def;
    1366             :         }
    1367             : 
    1368           6 :         if (!error && !do_fetch(stmt, TRUE, return_value, how, ori, off, 0 TSRMLS_CC)) {
    1369           1 :                 error = 1;
    1370             :         }
    1371           6 :         if (error) {
    1372           1 :                 PDO_HANDLE_STMT_ERR();
    1373             :         }
    1374           6 :         do_fetch_opt_finish(stmt, 1 TSRMLS_CC);
    1375             : 
    1376           6 :         stmt->fetch.cls.ce = old_ce;
    1377           6 :         stmt->fetch.cls.ctor_args = old_ctor_args;
    1378           6 :         stmt->fetch.cls.fci.param_count = old_arg_count;
    1379           6 :         if (error) {
    1380           1 :                 RETURN_FALSE;
    1381             :         }
    1382             : }
    1383             : /* }}} */
    1384             : 
    1385             : /* {{{ proto string PDOStatement::fetchColumn([int column_number])
    1386             :    Returns a data of the specified column in the result set. */
    1387          85 : static PHP_METHOD(PDOStatement, fetchColumn)
    1388             : {
    1389          85 :         long col_n = 0;
    1390          85 :         PHP_STMT_GET_OBJ;
    1391             : 
    1392          85 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &col_n)) {
    1393           0 :                 RETURN_FALSE;
    1394             :         }
    1395             : 
    1396          85 :         PDO_STMT_CLEAR_ERR();
    1397             : 
    1398          85 :         if (!do_fetch_common(stmt, PDO_FETCH_ORI_NEXT, 0, TRUE TSRMLS_CC)) {
    1399           4 :                 PDO_HANDLE_STMT_ERR();
    1400           4 :                 RETURN_FALSE;
    1401             :         }
    1402             : 
    1403          81 :         fetch_value(stmt, return_value, col_n, NULL TSRMLS_CC);
    1404             : }
    1405             : /* }}} */
    1406             : 
    1407             : /* {{{ proto array PDOStatement::fetchAll([int $how = PDO_FETCH_BOTH [, string class_name [, NULL|array ctor_args]]])
    1408             :    Returns an array of all of the results. */
    1409         534 : static PHP_METHOD(PDOStatement, fetchAll)
    1410             : {
    1411         534 :         long how = PDO_FETCH_USE_DEFAULT;
    1412             :         zval *data, *return_all;
    1413             :         zval *arg2;
    1414             :         zend_class_entry *old_ce;
    1415         534 :         zval *old_ctor_args, *ctor_args = NULL;
    1416         534 :         int error = 0, flags, old_arg_count;
    1417         534 :         PHP_STMT_GET_OBJ;         
    1418             : 
    1419         534 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lzz", &how, &arg2, &ctor_args)) {
    1420           0 :                 RETURN_FALSE;
    1421             :         }
    1422             : 
    1423         534 :         if (!pdo_stmt_verify_mode(stmt, how, 1 TSRMLS_CC)) {
    1424           0 :                 RETURN_FALSE;
    1425             :         }
    1426             : 
    1427         534 :         old_ce = stmt->fetch.cls.ce;
    1428         534 :         old_ctor_args = stmt->fetch.cls.ctor_args;
    1429         534 :         old_arg_count = stmt->fetch.cls.fci.param_count;
    1430             : 
    1431         534 :         do_fetch_opt_finish(stmt, 0 TSRMLS_CC);
    1432             : 
    1433         534 :         switch(how & ~PDO_FETCH_FLAGS) {
    1434             :         case PDO_FETCH_CLASS:
    1435          63 :                 switch(ZEND_NUM_ARGS()) {
    1436             :                 case 0:
    1437             :                 case 1:
    1438           6 :                         stmt->fetch.cls.ce = zend_standard_class_def;
    1439           6 :                         break;
    1440             :                 case 3:
    1441          19 :                         if (Z_TYPE_P(ctor_args) != IS_NULL && Z_TYPE_P(ctor_args) != IS_ARRAY) {
    1442           0 :                                 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "ctor_args must be either NULL or an array" TSRMLS_CC);
    1443           0 :                                 error = 1;
    1444           0 :                                 break;
    1445             :                         }
    1446          19 :                         if (Z_TYPE_P(ctor_args) != IS_ARRAY || !zend_hash_num_elements(Z_ARRVAL_P(ctor_args))) {
    1447           6 :                                 ctor_args = NULL;
    1448             :                         }
    1449             :                         /* no break */
    1450             :                 case 2:
    1451          57 :                         stmt->fetch.cls.ctor_args = ctor_args; /* we're not going to free these */
    1452          57 :                         if (Z_TYPE_P(arg2) != IS_STRING) {
    1453           0 :                                 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Invalid class name (should be a string)" TSRMLS_CC);
    1454           0 :                                 error = 1;
    1455           0 :                                 break;
    1456             :                         } else {
    1457          57 :                                 stmt->fetch.cls.ce = zend_fetch_class(Z_STRVAL_P(arg2), Z_STRLEN_P(arg2), ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
    1458          57 :                                 if (!stmt->fetch.cls.ce) {
    1459           0 :                                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "could not find user-specified class" TSRMLS_CC);
    1460           0 :                                         error = 1;
    1461             :                                         break;
    1462             :                                 }
    1463             :                         }
    1464             :                 }
    1465          63 :                 if (!error) {
    1466          63 :                         do_fetch_class_prepare(stmt TSRMLS_CC);
    1467             :                 }
    1468          63 :                 break;
    1469             : 
    1470             :         case PDO_FETCH_FUNC:
    1471          66 :                 switch(ZEND_NUM_ARGS()) {
    1472             :                 case 0:
    1473             :                 case 1:
    1474           0 :                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "no fetch function specified" TSRMLS_CC);
    1475           0 :                         error = 1;
    1476           0 :                         break;
    1477             :                 case 3:
    1478             :                 case 2:
    1479          66 :                         stmt->fetch.func.function = arg2;
    1480          66 :                         if (do_fetch_func_prepare(stmt TSRMLS_CC) == 0) {
    1481           7 :                                 error = 1;
    1482             :                         }
    1483             :                         break;
    1484             :                 }
    1485          66 :                 break;
    1486             :         
    1487             :         case PDO_FETCH_COLUMN:
    1488          83 :                 switch(ZEND_NUM_ARGS()) {
    1489             :                 case 0:
    1490             :                 case 1:
    1491          59 :                         stmt->fetch.column = how & PDO_FETCH_GROUP ? -1 : 0;
    1492          59 :                         break;
    1493             :                 case 2:
    1494          24 :                         convert_to_long(arg2);
    1495          24 :                         stmt->fetch.column = Z_LVAL_P(arg2);
    1496          24 :                         break;
    1497             :                 case 3:
    1498           0 :                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Third parameter not allowed for PDO::FETCH_COLUMN" TSRMLS_CC);
    1499           0 :                         error = 1;
    1500             :                 }
    1501          83 :                 break;
    1502             : 
    1503             :         default:
    1504         322 :                 if (ZEND_NUM_ARGS() > 1) {
    1505           0 :                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Extraneous additional parameters" TSRMLS_CC);
    1506           0 :                         error = 1;
    1507             :                 }
    1508             :         }
    1509             : 
    1510         534 :         flags = how & PDO_FETCH_FLAGS;
    1511             :         
    1512         534 :         if ((how & ~PDO_FETCH_FLAGS) == PDO_FETCH_USE_DEFAULT) {
    1513          52 :                 flags |= stmt->default_fetch_type & PDO_FETCH_FLAGS;
    1514          52 :                 how |= stmt->default_fetch_type & ~PDO_FETCH_FLAGS;
    1515             :         }
    1516             : 
    1517         534 :         if (!error)     {
    1518         527 :                 PDO_STMT_CLEAR_ERR();
    1519         527 :                 MAKE_STD_ZVAL(data);
    1520        1054 :                 if (    (how & PDO_FETCH_GROUP) || how == PDO_FETCH_KEY_PAIR || 
    1521         391 :                         (how == PDO_FETCH_USE_DEFAULT && stmt->default_fetch_type == PDO_FETCH_KEY_PAIR)
    1522             :                 ) {
    1523         136 :                         array_init(return_value);
    1524         136 :                         return_all = return_value;
    1525             :                 } else {
    1526         391 :                         return_all = 0;
    1527             :                 }
    1528         527 :                 if (!do_fetch(stmt, TRUE, data, how | flags, PDO_FETCH_ORI_NEXT, 0, return_all TSRMLS_CC)) {
    1529          45 :                         FREE_ZVAL(data);
    1530          45 :                         error = 2;
    1531             :                 }
    1532             :         }
    1533         534 :         if (!error) {
    1534         482 :                 if ((how & PDO_FETCH_GROUP)) {
    1535             :                         do {
    1536         324 :                                 MAKE_STD_ZVAL(data);
    1537         324 :                         } while (do_fetch(stmt, TRUE, data, how | flags, PDO_FETCH_ORI_NEXT, 0, return_all TSRMLS_CC));
    1538         382 :                 } else if (how == PDO_FETCH_KEY_PAIR || (how == PDO_FETCH_USE_DEFAULT && stmt->default_fetch_type == PDO_FETCH_KEY_PAIR)) {
    1539          90 :                         while (do_fetch(stmt, TRUE, data, how | flags, PDO_FETCH_ORI_NEXT, 0, return_all TSRMLS_CC));
    1540             :                 } else {
    1541         346 :                         array_init(return_value);
    1542             :                         do {
    1543         736 :                                 add_next_index_zval(return_value, data);
    1544         736 :                                 MAKE_STD_ZVAL(data);
    1545         736 :                         } while (do_fetch(stmt, TRUE, data, how | flags, PDO_FETCH_ORI_NEXT, 0, 0 TSRMLS_CC));
    1546             :                 }
    1547         482 :                 FREE_ZVAL(data);
    1548             :         }
    1549             :         
    1550         534 :         do_fetch_opt_finish(stmt, 0 TSRMLS_CC);
    1551             : 
    1552         534 :         stmt->fetch.cls.ce = old_ce;
    1553         534 :         stmt->fetch.cls.ctor_args = old_ctor_args;
    1554         534 :         stmt->fetch.cls.fci.param_count = old_arg_count;
    1555             :         
    1556         534 :         if (error) {
    1557          52 :                 PDO_HANDLE_STMT_ERR();
    1558          52 :                 if (error != 2) {
    1559           7 :                         RETURN_FALSE;
    1560             :                 } else { /* on no results, return an empty array */
    1561          45 :                         if (Z_TYPE_P(return_value) != IS_ARRAY) {
    1562          45 :                                 array_init(return_value);
    1563             :                         }
    1564          45 :                         return;
    1565             :                 }
    1566             :         }
    1567             : }
    1568             : /* }}} */
    1569             : 
    1570         652 : static int register_bound_param(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, int is_param) /* {{{ */
    1571             : {
    1572         652 :         struct pdo_bound_param_data param = {0};
    1573         652 :         long param_type = PDO_PARAM_STR;
    1574             : 
    1575         652 :         param.paramno = -1;
    1576             : 
    1577         652 :         if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
    1578             :                         "lz|llz!", &param.paramno, &param.parameter, &param_type, &param.max_value_len,
    1579             :                         &param.driver_params)) {
    1580         209 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|llz!", &param.name,
    1581             :                                 &param.namelen, &param.parameter, &param_type, &param.max_value_len, 
    1582             :                                 &param.driver_params)) {
    1583           0 :                         return 0;
    1584             :                 }       
    1585             :         }
    1586             :         
    1587         652 :         param.param_type = (int) param_type;
    1588             :         
    1589         652 :         if (param.paramno > 0) {
    1590         443 :                 --param.paramno; /* make it zero-based internally */
    1591         209 :         } else if (!param.name) {
    1592           0 :                 pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "Columns/Parameters are 1-based" TSRMLS_CC);
    1593           0 :                 return 0;
    1594             :         }
    1595             : 
    1596         652 :         Z_ADDREF_P(param.parameter);
    1597         652 :         if (!really_register_bound_param(&param, stmt, is_param TSRMLS_CC)) {
    1598           1 :                 if (param.parameter) {
    1599           1 :                         zval_ptr_dtor(&(param.parameter));
    1600           1 :                         param.parameter = NULL;
    1601             :                 }
    1602           1 :                 return 0;
    1603             :         }
    1604         651 :         return 1;
    1605             : } /* }}} */
    1606             : 
    1607             : /* {{{ proto bool PDOStatement::bindValue(mixed $paramno, mixed $param [, int $type ])
    1608             :    bind an input parameter to the value of a PHP variable.  $paramno is the 1-based position of the placeholder in the SQL statement (but can be the parameter name for drivers that support named placeholders).  It should be called prior to execute(). */
    1609         280 : static PHP_METHOD(PDOStatement, bindValue)
    1610             : {
    1611         280 :         struct pdo_bound_param_data param = {0};
    1612         280 :         long param_type = PDO_PARAM_STR;
    1613         280 :         PHP_STMT_GET_OBJ;
    1614             : 
    1615         280 :         param.paramno = -1;
    1616             :         
    1617         280 :         if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
    1618             :                         "lz/|l", &param.paramno, &param.parameter, &param_type)) {
    1619          28 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz/|l", &param.name,
    1620             :                                 &param.namelen, &param.parameter, &param_type)) {
    1621           0 :                         RETURN_FALSE;
    1622             :                 }
    1623             :         }
    1624             : 
    1625         280 :         param.param_type = (int) param_type;
    1626             :         
    1627         280 :         if (param.paramno > 0) {
    1628         252 :                 --param.paramno; /* make it zero-based internally */
    1629          28 :         } else if (!param.name) {
    1630           0 :                 pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "Columns/Parameters are 1-based" TSRMLS_CC);
    1631           0 :                 RETURN_FALSE;
    1632             :         }
    1633             :         
    1634         280 :         Z_ADDREF_P(param.parameter);
    1635         280 :         if (!really_register_bound_param(&param, stmt, TRUE TSRMLS_CC)) {
    1636           1 :                 if (param.parameter) {
    1637           1 :                         zval_ptr_dtor(&(param.parameter));
    1638           1 :                         param.parameter = NULL;
    1639             :                 }
    1640           1 :                 RETURN_FALSE;
    1641             :         }
    1642         279 :         RETURN_TRUE;
    1643             : }
    1644             : /* }}} */
    1645             : 
    1646             : 
    1647             : /* {{{ proto bool PDOStatement::bindParam(mixed $paramno, mixed &$param [, int $type [, int $maxlen [, mixed $driverdata]]])
    1648             :    bind a parameter to a PHP variable.  $paramno is the 1-based position of the placeholder in the SQL statement (but can be the parameter name for drivers that support named placeholders).  This isn't supported by all drivers.  It should be called prior to execute(). */
    1649         236 : static PHP_METHOD(PDOStatement, bindParam)
    1650             : {
    1651         236 :         PHP_STMT_GET_OBJ;
    1652         236 :         RETURN_BOOL(register_bound_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, stmt, TRUE));
    1653             : }
    1654             : /* }}} */
    1655             : 
    1656             : /* {{{ proto bool PDOStatement::bindColumn(mixed $column, mixed &$param [, int $type [, int $maxlen [, mixed $driverdata]]])
    1657             :    bind a column to a PHP variable.  On each row fetch $param will contain the value of the corresponding column.  $column is the 1-based offset of the column, or the column name.  For portability, don't call this before execute(). */
    1658         416 : static PHP_METHOD(PDOStatement, bindColumn)
    1659             : {
    1660         416 :         PHP_STMT_GET_OBJ;
    1661         416 :         RETURN_BOOL(register_bound_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, stmt, FALSE));
    1662             : }
    1663             : /* }}} */
    1664             : 
    1665             : /* {{{ proto int PDOStatement::rowCount()
    1666             :    Returns the number of rows in a result set, or the number of rows affected by the last execute().  It is not always meaningful. */
    1667          14 : static PHP_METHOD(PDOStatement, rowCount)
    1668             : {
    1669          14 :         PHP_STMT_GET_OBJ;
    1670             : 
    1671          14 :         RETURN_LONG(stmt->row_count);
    1672             : }
    1673             : /* }}} */
    1674             : 
    1675             : /* {{{ proto string PDOStatement::errorCode()
    1676             :    Fetch the error code associated with the last operation on the statement handle */
    1677          37 : static PHP_METHOD(PDOStatement, errorCode)
    1678             : {
    1679          37 :         PHP_STMT_GET_OBJ;
    1680             : 
    1681          37 :         if (zend_parse_parameters_none() == FAILURE) {
    1682           0 :                 return;
    1683             :         }
    1684             : 
    1685          37 :         if (stmt->error_code[0] == '\0') {
    1686           0 :                 RETURN_NULL();
    1687             :         }
    1688             : 
    1689          37 :         RETURN_STRING(stmt->error_code, 1);
    1690             : }
    1691             : /* }}} */
    1692             : 
    1693             : /* {{{ proto array PDOStatement::errorInfo()
    1694             :    Fetch extended error information associated with the last operation on the statement handle */
    1695         512 : static PHP_METHOD(PDOStatement, errorInfo)
    1696             : {
    1697             :         int error_count;
    1698         512 :         int error_count_diff     = 0;
    1699         512 :         int error_expected_count = 3;
    1700             : 
    1701         512 :         PHP_STMT_GET_OBJ;
    1702             : 
    1703         512 :         if (zend_parse_parameters_none() == FAILURE) {
    1704           0 :                 return;
    1705             :         }
    1706             : 
    1707         512 :         array_init(return_value);
    1708         512 :         add_next_index_string(return_value, stmt->error_code, 1);
    1709             : 
    1710         512 :         if (stmt->dbh->methods->fetch_err) {
    1711         512 :                 stmt->dbh->methods->fetch_err(stmt->dbh, stmt, return_value TSRMLS_CC);
    1712             :         }
    1713             : 
    1714         512 :         error_count = zend_hash_num_elements(Z_ARRVAL_P(return_value));
    1715             : 
    1716         512 :         if (error_expected_count > error_count) {
    1717             :                 int current_index;
    1718             : 
    1719         488 :                 error_count_diff = error_expected_count - error_count;
    1720        1464 :                 for (current_index = 0; current_index < error_count_diff; current_index++) {
    1721         976 :                         add_next_index_null(return_value);
    1722             :                 }
    1723             :         }
    1724             : }
    1725             : /* }}} */
    1726             : 
    1727             : /* {{{ proto bool PDOStatement::setAttribute(long attribute, mixed value)
    1728             :    Set an attribute */
    1729           2 : static PHP_METHOD(PDOStatement, setAttribute)
    1730             : {
    1731             :         long attr;
    1732           2 :         zval *value = NULL;
    1733           2 :         PHP_STMT_GET_OBJ;
    1734             : 
    1735           2 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz!", &attr, &value)) {
    1736           0 :                 RETURN_FALSE;
    1737             :         }
    1738             : 
    1739           2 :         if (!stmt->methods->set_attribute) {
    1740           1 :                 goto fail;
    1741             :         }
    1742             : 
    1743           1 :         PDO_STMT_CLEAR_ERR();
    1744           1 :         if (stmt->methods->set_attribute(stmt, attr, value TSRMLS_CC)) {
    1745           1 :                 RETURN_TRUE;
    1746             :         }
    1747             : 
    1748             : fail:
    1749           1 :         if (!stmt->methods->set_attribute) {
    1750           1 :                 pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "This driver doesn't support setting attributes" TSRMLS_CC);
    1751             :         } else {
    1752           0 :                 PDO_HANDLE_STMT_ERR();
    1753             :         }
    1754           1 :         RETURN_FALSE;
    1755             : }
    1756             : /* }}} */
    1757             : 
    1758             : /* {{{ proto mixed PDOStatement::getAttribute(long attribute)
    1759             :    Get an attribute */
    1760             : 
    1761           0 : static int generic_stmt_attr_get(pdo_stmt_t *stmt, zval *return_value, long attr)
    1762             : {
    1763           0 :         switch (attr) {
    1764             :                 case PDO_ATTR_EMULATE_PREPARES:
    1765           0 :                         RETVAL_BOOL(stmt->supports_placeholders == PDO_PLACEHOLDER_NONE);
    1766           0 :                         return 1;
    1767             :         }
    1768           0 :         return 0;
    1769             : }
    1770             :    
    1771           0 : static PHP_METHOD(PDOStatement, getAttribute)
    1772             : {
    1773             :         long attr;
    1774           0 :         PHP_STMT_GET_OBJ;
    1775             : 
    1776           0 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &attr)) {
    1777           0 :                 RETURN_FALSE;
    1778             :         }
    1779             : 
    1780           0 :         if (!stmt->methods->get_attribute) {
    1781           0 :                 if (!generic_stmt_attr_get(stmt, return_value, attr)) {
    1782           0 :                         pdo_raise_impl_error(stmt->dbh, stmt, "IM001",
    1783             :                                 "This driver doesn't support getting attributes" TSRMLS_CC);
    1784           0 :                         RETURN_FALSE;
    1785             :                 }
    1786           0 :                 return;
    1787             :         }
    1788             : 
    1789           0 :         PDO_STMT_CLEAR_ERR();
    1790           0 :         switch (stmt->methods->get_attribute(stmt, attr, return_value TSRMLS_CC)) {
    1791             :                 case -1:
    1792           0 :                         PDO_HANDLE_STMT_ERR();
    1793           0 :                         RETURN_FALSE;
    1794             : 
    1795             :                 case 0:
    1796           0 :                         if (!generic_stmt_attr_get(stmt, return_value, attr)) {
    1797             :                                 /* XXX: should do something better here */
    1798           0 :                                 pdo_raise_impl_error(stmt->dbh, stmt, "IM001",
    1799             :                                         "driver doesn't support getting that attribute" TSRMLS_CC);
    1800           0 :                                 RETURN_FALSE;
    1801             :                         }
    1802           0 :                         return;
    1803             : 
    1804             :                 default:
    1805           0 :                         return;
    1806             :         }
    1807             : }
    1808             : /* }}} */
    1809             : 
    1810             : /* {{{ proto int PDOStatement::columnCount()
    1811             :    Returns the number of columns in the result set */
    1812          32 : static PHP_METHOD(PDOStatement, columnCount)
    1813             : {
    1814          32 :         PHP_STMT_GET_OBJ;
    1815          32 :         if (zend_parse_parameters_none() == FAILURE) {
    1816           0 :                 return;
    1817             :         }
    1818          32 :         RETURN_LONG(stmt->column_count);
    1819             : }
    1820             : /* }}} */
    1821             : 
    1822             : /* {{{ proto array PDOStatement::getColumnMeta(int $column)
    1823             :    Returns meta data for a numbered column */
    1824          79 : static PHP_METHOD(PDOStatement, getColumnMeta)
    1825             : {
    1826             :         long colno;
    1827             :         struct pdo_column_data *col;
    1828          79 :         PHP_STMT_GET_OBJ;
    1829             : 
    1830          79 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &colno)) {
    1831           3 :                 RETURN_FALSE;
    1832             :         }
    1833          76 :         if(colno < 0) {
    1834           1 :                 pdo_raise_impl_error(stmt->dbh, stmt, "42P10", "column number must be non-negative" TSRMLS_CC);
    1835           1 :                 RETURN_FALSE;
    1836             :         }
    1837             : 
    1838          75 :         if (!stmt->methods->get_column_meta) {
    1839           0 :                 pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "driver doesn't support meta data" TSRMLS_CC);
    1840           0 :                 RETURN_FALSE;
    1841             :         }
    1842             : 
    1843          75 :         PDO_STMT_CLEAR_ERR();
    1844          75 :         if (FAILURE == stmt->methods->get_column_meta(stmt, colno, return_value TSRMLS_CC)) {
    1845           3 :                 PDO_HANDLE_STMT_ERR();
    1846           3 :                 RETURN_FALSE;
    1847             :         }
    1848             : 
    1849             :         /* add stock items */
    1850          72 :         col = &stmt->columns[colno];
    1851          72 :         add_assoc_string(return_value, "name", col->name, 1);
    1852          72 :         add_assoc_long(return_value, "len", col->maxlen); /* FIXME: unsigned ? */
    1853          72 :         add_assoc_long(return_value, "precision", col->precision);
    1854          72 :         if (col->param_type != PDO_PARAM_ZVAL) {
    1855             :                 /* if param_type is PDO_PARAM_ZVAL the driver has to provide correct data */
    1856           6 :                 add_assoc_long(return_value, "pdo_type", col->param_type);
    1857             :         }
    1858             : }
    1859             : /* }}} */
    1860             : 
    1861             : /* {{{ proto bool PDOStatement::setFetchMode(int mode [mixed* params])
    1862             :    Changes the default fetch mode for subsequent fetches (params have different meaning for different fetch modes) */
    1863             : 
    1864         149 : int pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, int skip)
    1865             : {
    1866         149 :         long mode = PDO_FETCH_BOTH;
    1867         149 :         int flags = 0, argc = ZEND_NUM_ARGS() - skip;
    1868             :         zval ***args;
    1869             :         zend_class_entry **cep;
    1870             :         int retval;
    1871             :         
    1872         149 :         do_fetch_opt_finish(stmt, 1 TSRMLS_CC);
    1873             : 
    1874         149 :         switch (stmt->default_fetch_type) {
    1875             :                 case PDO_FETCH_INTO:
    1876          15 :                         if (stmt->fetch.into) {
    1877          15 :                                 zval_ptr_dtor(&stmt->fetch.into);
    1878          15 :                                 stmt->fetch.into = NULL;
    1879             :                         }
    1880             :                         break;
    1881             :                 default:
    1882             :                         ;
    1883             :         }
    1884             :         
    1885         149 :         stmt->default_fetch_type = PDO_FETCH_BOTH;
    1886             : 
    1887         149 :         if (argc == 0) {
    1888           0 :                 return SUCCESS;
    1889             :         }
    1890             : 
    1891         149 :         args = safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval*), 0);
    1892             : 
    1893         149 :         retval = zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args);
    1894             :         
    1895         149 :         if (SUCCESS == retval) {
    1896         149 :                 if (Z_TYPE_PP(args[skip]) != IS_LONG) {
    1897           6 :                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "mode must be an integer" TSRMLS_CC);
    1898           6 :                         retval = FAILURE;
    1899             :                 } else {
    1900         143 :                         mode = Z_LVAL_PP(args[skip]);
    1901         143 :                         flags = mode & PDO_FETCH_FLAGS;
    1902             :         
    1903         143 :                         retval = pdo_stmt_verify_mode(stmt, mode, 0 TSRMLS_CC);
    1904             :                 }
    1905             :         }
    1906             :         
    1907         149 :         if (FAILURE == retval) {
    1908           6 :                 PDO_STMT_CLEAR_ERR();
    1909           6 :                 efree(args);
    1910           6 :                 return FAILURE;
    1911             :         }
    1912             : 
    1913         143 :         retval = FAILURE;
    1914         143 :         switch (mode & ~PDO_FETCH_FLAGS) {
    1915             :                 case PDO_FETCH_USE_DEFAULT:
    1916             :                 case PDO_FETCH_LAZY:
    1917             :                 case PDO_FETCH_ASSOC:
    1918             :                 case PDO_FETCH_NUM:
    1919             :                 case PDO_FETCH_BOTH:
    1920             :                 case PDO_FETCH_OBJ:
    1921             :                 case PDO_FETCH_BOUND:
    1922             :                 case PDO_FETCH_NAMED:
    1923             :                 case PDO_FETCH_KEY_PAIR:
    1924          60 :                         if (argc != 1) {
    1925           6 :                                 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode doesn't allow any extra arguments" TSRMLS_CC);
    1926             :                         } else {
    1927          54 :                                 retval = SUCCESS;
    1928             :                         }
    1929          60 :                         break;
    1930             : 
    1931             :                 case PDO_FETCH_COLUMN:
    1932           6 :                         if (argc != 2) {
    1933           6 :                                 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode requires the colno argument" TSRMLS_CC);
    1934           0 :                         } else  if (Z_TYPE_PP(args[skip+1]) != IS_LONG) {
    1935           0 :                                 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "colno must be an integer" TSRMLS_CC);
    1936             :                         } else {
    1937           0 :                                 stmt->fetch.column = Z_LVAL_PP(args[skip+1]);
    1938           0 :                                 retval = SUCCESS;
    1939             :                         }
    1940           6 :                         break;
    1941             : 
    1942             :                 case PDO_FETCH_CLASS:
    1943             :                         /* Gets its class name from 1st column */
    1944          49 :                         if ((flags & PDO_FETCH_CLASSTYPE) == PDO_FETCH_CLASSTYPE) {
    1945           1 :                                 if (argc != 1) {
    1946           0 :                                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode doesn't allow any extra arguments" TSRMLS_CC);
    1947             :                                 } else {
    1948           1 :                                         stmt->fetch.cls.ce = NULL;
    1949           1 :                                         retval = SUCCESS;
    1950             :                                 }
    1951             :                         } else {
    1952          48 :                                 if (argc < 2) {
    1953           6 :                                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode requires the classname argument" TSRMLS_CC);
    1954          42 :                                 } else if (argc > 3) {
    1955           6 :                                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "too many arguments" TSRMLS_CC);
    1956          36 :                                 } else if (Z_TYPE_PP(args[skip+1]) != IS_STRING) {
    1957           0 :                                         pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "classname must be a string" TSRMLS_CC);
    1958             :                                 } else {
    1959          36 :                                         retval = zend_lookup_class(Z_STRVAL_PP(args[skip+1]),
    1960          36 :                                                 Z_STRLEN_PP(args[skip+1]), &cep TSRMLS_CC);
    1961             : 
    1962          36 :                                         if (SUCCESS == retval && cep && *cep) {
    1963          36 :                                                 stmt->fetch.cls.ce = *cep;
    1964             :                                         }
    1965             :                                 }
    1966             :                         }
    1967             : 
    1968          49 :                         if (SUCCESS == retval) {
    1969          37 :                                 stmt->fetch.cls.ctor_args = NULL;
    1970             : #ifdef ilia_0 /* we'll only need this when we have persistent statements, if ever */
    1971             :                                 if (stmt->dbh->is_persistent) {
    1972             :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP might crash if you don't call $stmt->setFetchMode() to reset to defaults on this persistent statement.  This will be fixed in a later release");
    1973             :                                 }
    1974             : #endif
    1975          37 :                                 if (argc == 3) {
    1976          21 :                                         if (Z_TYPE_PP(args[skip+2]) != IS_NULL && Z_TYPE_PP(args[skip+2]) != IS_ARRAY) {
    1977           0 :                                                 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "ctor_args must be either NULL or an array" TSRMLS_CC);
    1978           0 :                                                 retval = FAILURE;
    1979          21 :                                         } else if (Z_TYPE_PP(args[skip+2]) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_PP(args[skip+2]))) {
    1980          21 :                                                 ALLOC_ZVAL(stmt->fetch.cls.ctor_args);
    1981          21 :                                                 *stmt->fetch.cls.ctor_args = **args[skip+2];
    1982          21 :                                                 zval_copy_ctor(stmt->fetch.cls.ctor_args);
    1983             :                                         }
    1984             :                                 }
    1985             : 
    1986          37 :                                 if (SUCCESS == retval) {
    1987          37 :                                         do_fetch_class_prepare(stmt TSRMLS_CC);
    1988             :                                 }
    1989             :                         }
    1990             :                         
    1991          49 :                         break;
    1992             : 
    1993             :                 case PDO_FETCH_INTO:
    1994          28 :                         if (argc != 2) {
    1995           6 :                                 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode requires the object parameter" TSRMLS_CC);
    1996          22 :                         } else if (Z_TYPE_PP(args[skip+1]) != IS_OBJECT) {
    1997           0 :                                 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "object must be an object" TSRMLS_CC);
    1998             :                         } else {
    1999          22 :                                 retval = SUCCESS;
    2000             :                         }
    2001             :                         
    2002          28 :                         if (SUCCESS == retval) {
    2003             : #ifdef ilia_0 /* we'll only need this when we have persistent statements, if ever */
    2004             :                                 if (stmt->dbh->is_persistent) {
    2005             :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP might crash if you don't call $stmt->setFetchMode() to reset to defaults on this persistent statement.  This will be fixed in a later release");
    2006             :                                 }
    2007             : #endif  
    2008          22 :                                 MAKE_STD_ZVAL(stmt->fetch.into);
    2009             : 
    2010          22 :                                 Z_TYPE_P(stmt->fetch.into) = IS_OBJECT;
    2011          22 :                                 Z_OBJ_HANDLE_P(stmt->fetch.into) = Z_OBJ_HANDLE_PP(args[skip+1]);
    2012          22 :                                 Z_OBJ_HT_P(stmt->fetch.into) = Z_OBJ_HT_PP(args[skip+1]);
    2013          22 :                                 zend_objects_store_add_ref(stmt->fetch.into TSRMLS_CC);
    2014             :                         }
    2015             :                         
    2016          28 :                         break;
    2017             :                 
    2018             :                 default:
    2019           0 :                         pdo_raise_impl_error(stmt->dbh, stmt, "22003", "Invalid fetch mode specified" TSRMLS_CC);
    2020             :         }
    2021             : 
    2022         143 :         if (SUCCESS == retval) {
    2023         113 :                 stmt->default_fetch_type = mode;
    2024             :         }
    2025             : 
    2026             :         /*
    2027             :          * PDO error (if any) has already been raised at this point.
    2028             :          *
    2029             :          * The error_code is cleared, otherwise the caller will read the
    2030             :          * last error message from the driver.
    2031             :          *
    2032             :          */
    2033         143 :         PDO_STMT_CLEAR_ERR();
    2034             : 
    2035         143 :         efree(args);
    2036             :                 
    2037         143 :         return retval;
    2038             : }
    2039             :    
    2040          71 : static PHP_METHOD(PDOStatement, setFetchMode)
    2041             : {
    2042          71 :         PHP_STMT_GET_OBJ;
    2043             : 
    2044          71 :         RETVAL_BOOL(
    2045             :                 pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAM_PASSTHRU,
    2046             :                         stmt, 0) == SUCCESS ? 1 : 0
    2047             :                 );
    2048             : }
    2049             : /* }}} */
    2050             : 
    2051             : /* {{{ proto bool PDOStatement::nextRowset()
    2052             :    Advances to the next rowset in a multi-rowset statement handle. Returns true if it succeded, false otherwise */
    2053             : 
    2054          94 : static int pdo_stmt_do_next_rowset(pdo_stmt_t *stmt TSRMLS_DC)
    2055             : {
    2056             :         /* un-describe */
    2057          94 :         if (stmt->columns) {
    2058             :                 int i;
    2059          88 :                 struct pdo_column_data *cols = stmt->columns;
    2060             :                 
    2061         182 :                 for (i = 0; i < stmt->column_count; i++) {
    2062          94 :                         efree(cols[i].name);
    2063             :                 }
    2064          88 :                 efree(stmt->columns);
    2065          88 :                 stmt->columns = NULL;
    2066          88 :                 stmt->column_count = 0;
    2067             :         }
    2068             : 
    2069          94 :         if (!stmt->methods->next_rowset(stmt TSRMLS_CC)) {
    2070             :                 /* Set the executed flag to 0 to reallocate columns on next execute */
    2071          70 :                 stmt->executed = 0;
    2072          70 :                 return 0;
    2073             :         }
    2074             : 
    2075          24 :         pdo_stmt_describe_columns(stmt TSRMLS_CC);
    2076             : 
    2077          24 :         return 1;
    2078             : }
    2079             : 
    2080          67 : static PHP_METHOD(PDOStatement, nextRowset)
    2081             : {
    2082          67 :         PHP_STMT_GET_OBJ;
    2083             : 
    2084          67 :         if (!stmt->methods->next_rowset) {
    2085           0 :                 pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "driver does not support multiple rowsets" TSRMLS_CC);
    2086           0 :                 RETURN_FALSE;
    2087             :         }
    2088             : 
    2089          67 :         PDO_STMT_CLEAR_ERR();
    2090             :         
    2091          67 :         if (!pdo_stmt_do_next_rowset(stmt TSRMLS_CC)) {
    2092          43 :                 PDO_HANDLE_STMT_ERR();
    2093          43 :                 RETURN_FALSE;
    2094             :         }
    2095             : 
    2096          24 :         RETURN_TRUE;
    2097             : }
    2098             : /* }}} */
    2099             : 
    2100             : /* {{{ proto bool PDOStatement::closeCursor()
    2101             :    Closes the cursor, leaving the statement ready for re-execution. */
    2102         429 : static PHP_METHOD(PDOStatement, closeCursor)
    2103             : {
    2104         429 :         PHP_STMT_GET_OBJ;
    2105             : 
    2106         429 :         if (!stmt->methods->cursor_closer) {
    2107             :                 /* emulate it by fetching and discarding rows */
    2108             :                 do {
    2109          32 :                         while (stmt->methods->fetcher(stmt, PDO_FETCH_ORI_NEXT, 0 TSRMLS_CC))
    2110             :                                 ;
    2111          30 :                         if (!stmt->methods->next_rowset) {
    2112           3 :                                 break;
    2113             :                         }
    2114             : 
    2115          27 :                         if (!pdo_stmt_do_next_rowset(stmt TSRMLS_CC)) {
    2116          27 :                                 break;
    2117             :                         }
    2118             :                                 
    2119           0 :                 } while (1);
    2120          30 :                 stmt->executed = 0;
    2121          30 :                 RETURN_TRUE;
    2122             :         }
    2123             : 
    2124         399 :         PDO_STMT_CLEAR_ERR();
    2125             : 
    2126         399 :         if (!stmt->methods->cursor_closer(stmt TSRMLS_CC)) {
    2127           0 :                 PDO_HANDLE_STMT_ERR();
    2128           0 :                 RETURN_FALSE;
    2129             :         }
    2130         399 :         stmt->executed = 0;
    2131         399 :         RETURN_TRUE;
    2132             : }
    2133             : /* }}} */
    2134             : 
    2135             : /* {{{ proto void PDOStatement::debugDumpParams()
    2136             :    A utility for internals hackers to debug parameter internals */
    2137           1 : static PHP_METHOD(PDOStatement, debugDumpParams)
    2138             : {
    2139           1 :         php_stream *out = php_stream_open_wrapper("php://output", "w", 0, NULL);
    2140             :         HashPosition pos;
    2141             :         struct pdo_bound_param_data *param;
    2142           1 :         PHP_STMT_GET_OBJ;
    2143             : 
    2144           1 :         if (out == NULL) {
    2145           0 :                 RETURN_FALSE;
    2146             :         }
    2147             :         
    2148           1 :         php_stream_printf(out TSRMLS_CC, "SQL: [%d] %.*s\n",
    2149             :                 stmt->query_stringlen,
    2150             :                 stmt->query_stringlen, stmt->query_string);
    2151             : 
    2152           2 :         php_stream_printf(out TSRMLS_CC, "Params:  %d\n",
    2153           2 :                 stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0);
    2154             :         
    2155           1 :         if (stmt->bound_params) {
    2156           1 :                 zend_hash_internal_pointer_reset_ex(stmt->bound_params, &pos);
    2157           5 :                 while (SUCCESS == zend_hash_get_current_data_ex(stmt->bound_params,
    2158             :                                 (void**)&param, &pos)) {
    2159             :                         char *str;
    2160             :                         uint len;
    2161             :                         ulong num;
    2162             :                         int res;
    2163             : 
    2164           3 :                         res = zend_hash_get_current_key_ex(stmt->bound_params, &str, &len, &num, 0, &pos);
    2165           3 :                         if (res == HASH_KEY_IS_LONG) {
    2166           1 :                                 php_stream_printf(out TSRMLS_CC, "Key: Position #%ld:\n", num);
    2167           2 :                         } else if (res == HASH_KEY_IS_STRING) {
    2168           2 :                                 php_stream_printf(out TSRMLS_CC, "Key: Name: [%d] %.*s\n", len, len, str);
    2169             :                         }
    2170             : 
    2171          17 :                         php_stream_printf(out TSRMLS_CC, "paramno=%ld\nname=[%d] \"%.*s\"\nis_param=%d\nparam_type=%d\n",
    2172          14 :                                 param->paramno, param->namelen, param->namelen, param->name ? param->name : "",
    2173           3 :                                 param->is_param,
    2174           3 :                                 param->param_type);
    2175             :                         
    2176           3 :                         zend_hash_move_forward_ex(stmt->bound_params, &pos);
    2177             :                 }
    2178             :         }
    2179             : 
    2180           1 :         php_stream_close(out);
    2181             : }
    2182             : /* }}} */
    2183             : 
    2184             : /* {{{ proto int PDOStatement::__wakeup()
    2185             :    Prevents use of a PDOStatement instance that has been unserialized */
    2186           0 : static PHP_METHOD(PDOStatement, __wakeup)
    2187             : {
    2188           0 :         zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "You cannot serialize or unserialize PDOStatement instances");
    2189           0 : }
    2190             : /* }}} */
    2191             : 
    2192             : /* {{{ proto int PDOStatement::__sleep()
    2193             :    Prevents serialization of a PDOStatement instance */
    2194           0 : static PHP_METHOD(PDOStatement, __sleep)
    2195             : {
    2196           0 :         zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "You cannot serialize or unserialize PDOStatement instances");
    2197           0 : }
    2198             : /* }}} */
    2199             : 
    2200             : const zend_function_entry pdo_dbstmt_functions[] = {
    2201             :         PHP_ME(PDOStatement, execute,           arginfo_pdostatement_execute,           ZEND_ACC_PUBLIC)
    2202             :         PHP_ME(PDOStatement, fetch,                     arginfo_pdostatement_fetch,                     ZEND_ACC_PUBLIC)
    2203             :         PHP_ME(PDOStatement, bindParam,         arginfo_pdostatement_bindparam,         ZEND_ACC_PUBLIC)
    2204             :         PHP_ME(PDOStatement, bindColumn,        arginfo_pdostatement_bindcolumn,        ZEND_ACC_PUBLIC)
    2205             :         PHP_ME(PDOStatement, bindValue,         arginfo_pdostatement_bindvalue,         ZEND_ACC_PUBLIC)
    2206             :         PHP_ME(PDOStatement, rowCount,          arginfo_pdostatement__void,                     ZEND_ACC_PUBLIC)
    2207             :         PHP_ME(PDOStatement, fetchColumn,       arginfo_pdostatement_fetchcolumn,       ZEND_ACC_PUBLIC)
    2208             :         PHP_ME(PDOStatement, fetchAll,          arginfo_pdostatement_fetchall,          ZEND_ACC_PUBLIC)
    2209             :         PHP_ME(PDOStatement, fetchObject,       arginfo_pdostatement_fetchobject,       ZEND_ACC_PUBLIC)
    2210             :         PHP_ME(PDOStatement, errorCode,         arginfo_pdostatement__void,                     ZEND_ACC_PUBLIC)
    2211             :         PHP_ME(PDOStatement, errorInfo,         arginfo_pdostatement__void,                     ZEND_ACC_PUBLIC)
    2212             :         PHP_ME(PDOStatement, setAttribute,      arginfo_pdostatement_setattribute,      ZEND_ACC_PUBLIC)
    2213             :         PHP_ME(PDOStatement, getAttribute,      arginfo_pdostatement_getattribute,      ZEND_ACC_PUBLIC)
    2214             :         PHP_ME(PDOStatement, columnCount,       arginfo_pdostatement__void,                     ZEND_ACC_PUBLIC)
    2215             :         PHP_ME(PDOStatement, getColumnMeta,     arginfo_pdostatement_getcolumnmeta,     ZEND_ACC_PUBLIC)
    2216             :         PHP_ME(PDOStatement, setFetchMode,      arginfo_pdostatement_setfetchmode,      ZEND_ACC_PUBLIC)
    2217             :         PHP_ME(PDOStatement, nextRowset,        arginfo_pdostatement__void,                     ZEND_ACC_PUBLIC)
    2218             :         PHP_ME(PDOStatement, closeCursor,       arginfo_pdostatement__void,                     ZEND_ACC_PUBLIC)
    2219             :         PHP_ME(PDOStatement, debugDumpParams, arginfo_pdostatement__void,               ZEND_ACC_PUBLIC)
    2220             :         PHP_ME(PDOStatement, __wakeup,          arginfo_pdostatement__void,                     ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
    2221             :         PHP_ME(PDOStatement, __sleep,           arginfo_pdostatement__void,                     ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
    2222             :         {NULL, NULL, NULL}
    2223             : };
    2224             : 
    2225             : /* {{{ overloaded handlers for PDOStatement class */
    2226          73 : static void dbstmt_prop_write(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
    2227             : {
    2228          73 :         pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC);
    2229             : 
    2230          73 :         convert_to_string(member);
    2231             : 
    2232          73 :         if(strcmp(Z_STRVAL_P(member), "queryString") == 0) {
    2233           0 :                 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "property queryString is read only" TSRMLS_CC);
    2234             :         } else {
    2235          73 :                 std_object_handlers.write_property(object, member, value, key TSRMLS_CC);
    2236             :         }
    2237          73 : }
    2238             : 
    2239           0 : static void dbstmt_prop_delete(zval *object, zval *member, const zend_literal *key TSRMLS_DC)
    2240             : {
    2241           0 :         pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC);
    2242             : 
    2243           0 :         convert_to_string(member);
    2244             : 
    2245           0 :         if(strcmp(Z_STRVAL_P(member), "queryString") == 0) {
    2246           0 :                 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "property queryString is read only" TSRMLS_CC);
    2247             :         } else {
    2248           0 :                 std_object_handlers.unset_property(object, member, key TSRMLS_CC);
    2249             :         }
    2250           0 : }
    2251             : 
    2252        2253 : static union _zend_function *dbstmt_method_get(
    2253             : #if PHP_API_VERSION >= 20041225
    2254             :         zval **object_pp,
    2255             : #else
    2256             :         zval *object,
    2257             : #endif
    2258             :         char *method_name, int method_len, const zend_literal *key TSRMLS_DC)
    2259             : {
    2260        2253 :         zend_function *fbc = NULL;
    2261             :         char *lc_method_name;
    2262             : #if PHP_API_VERSION >= 20041225
    2263        2253 :         zval *object = *object_pp;
    2264             : #endif
    2265             : 
    2266        2253 :         lc_method_name = emalloc(method_len + 1);
    2267        2253 :         zend_str_tolower_copy(lc_method_name, method_name, method_len);
    2268             : 
    2269        4506 :         if (zend_hash_find(&Z_OBJCE_P(object)->function_table, lc_method_name, 
    2270        2253 :                         method_len+1, (void**)&fbc) == FAILURE) {
    2271           7 :                 pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(object TSRMLS_CC);
    2272             :                 /* instance not created by PDO object */
    2273           7 :                 if (!stmt->dbh) {
    2274           7 :                         goto out;
    2275             :                 }
    2276             :                 /* not a pre-defined method, nor a user-defined method; check
    2277             :                  * the driver specific methods */
    2278           0 :                 if (!stmt->dbh->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_STMT]) {
    2279           0 :                         if (!pdo_hash_methods(stmt->dbh, 
    2280             :                                 PDO_DBH_DRIVER_METHOD_KIND_STMT TSRMLS_CC)
    2281           0 :                                 || !stmt->dbh->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_STMT]) {
    2282             :                                 goto out;
    2283             :                         }
    2284             :                 }
    2285             : 
    2286           0 :                 if (zend_hash_find(stmt->dbh->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_STMT],
    2287           0 :                                 lc_method_name, method_len+1, (void**)&fbc) == FAILURE) {
    2288           0 :                         fbc = NULL;
    2289             :                         goto out;
    2290             :                 }
    2291             :                 /* got it */
    2292             :         }
    2293             :         
    2294             : out:
    2295        2253 :         efree(lc_method_name);
    2296        2253 :         return fbc;
    2297             : }
    2298             : 
    2299           0 : static int dbstmt_compare(zval *object1, zval *object2 TSRMLS_DC)
    2300             : {
    2301           0 :         return -1;
    2302             : }
    2303             : 
    2304           0 : static zend_object_value dbstmt_clone_obj(zval *zobject TSRMLS_DC)
    2305             : {
    2306             :         zend_object_value retval;
    2307             :         pdo_stmt_t *stmt;
    2308             :         pdo_stmt_t *old_stmt;
    2309           0 :         zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
    2310             : 
    2311           0 :         stmt = ecalloc(1, sizeof(*stmt));
    2312           0 :         zend_object_std_init(&stmt->std, Z_OBJCE_P(zobject) TSRMLS_CC);
    2313           0 :         object_properties_init(&stmt->std, Z_OBJCE_P(zobject));
    2314           0 :         stmt->refcount = 1;
    2315             : 
    2316           0 :         old_stmt = (pdo_stmt_t *)zend_object_store_get_object(zobject TSRMLS_CC);
    2317             :         
    2318           0 :         retval.handle = zend_objects_store_put(stmt, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)pdo_dbstmt_free_storage, (zend_objects_store_clone_t)dbstmt_clone_obj TSRMLS_CC);
    2319           0 :         retval.handlers = Z_OBJ_HT_P(zobject);
    2320             : 
    2321           0 :         zend_objects_clone_members((zend_object *)stmt, retval, (zend_object *)old_stmt, handle TSRMLS_CC);
    2322             :         
    2323           0 :         zend_objects_store_add_ref(&old_stmt->database_object_handle TSRMLS_CC);
    2324           0 :         stmt->database_object_handle = old_stmt->database_object_handle;
    2325             :                         
    2326           0 :         return retval;
    2327             : }
    2328             : 
    2329             : zend_object_handlers pdo_dbstmt_object_handlers;
    2330             : static int pdo_row_serialize(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC);
    2331             : 
    2332       21265 : void pdo_stmt_init(TSRMLS_D)
    2333             : {
    2334             :         zend_class_entry ce;
    2335             : 
    2336       21265 :         INIT_CLASS_ENTRY(ce, "PDOStatement", pdo_dbstmt_functions);
    2337       21265 :         pdo_dbstmt_ce = zend_register_internal_class(&ce TSRMLS_CC);
    2338       21265 :         pdo_dbstmt_ce->get_iterator = pdo_stmt_iter_get;
    2339       21265 :         pdo_dbstmt_ce->create_object = pdo_dbstmt_new;
    2340       21265 :         zend_class_implements(pdo_dbstmt_ce TSRMLS_CC, 1, zend_ce_traversable); 
    2341       21265 :         zend_declare_property_null(pdo_dbstmt_ce, "queryString", sizeof("queryString")-1, ZEND_ACC_PUBLIC TSRMLS_CC);
    2342             : 
    2343       21265 :         memcpy(&pdo_dbstmt_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
    2344       21265 :         pdo_dbstmt_object_handlers.write_property = dbstmt_prop_write;
    2345       21265 :         pdo_dbstmt_object_handlers.unset_property = dbstmt_prop_delete;
    2346       21265 :         pdo_dbstmt_object_handlers.get_method = dbstmt_method_get;
    2347       21265 :         pdo_dbstmt_object_handlers.compare_objects = dbstmt_compare;
    2348       21265 :         pdo_dbstmt_object_handlers.clone_obj = dbstmt_clone_obj;
    2349             : 
    2350       21265 :         INIT_CLASS_ENTRY(ce, "PDORow", pdo_row_functions);
    2351       21265 :         pdo_row_ce = zend_register_internal_class(&ce TSRMLS_CC);
    2352       21265 :         pdo_row_ce->ce_flags |= ZEND_ACC_FINAL_CLASS; /* when removing this a lot of handlers need to be redone */
    2353       21265 :         pdo_row_ce->create_object = pdo_row_new;
    2354       21265 :         pdo_row_ce->serialize = pdo_row_serialize;
    2355       21265 : }
    2356             : 
    2357        2442 : static void free_statement(pdo_stmt_t *stmt TSRMLS_DC)
    2358             : {
    2359        2442 :         if (stmt->bound_params) {
    2360         932 :                 zend_hash_destroy(stmt->bound_params);
    2361         932 :                 FREE_HASHTABLE(stmt->bound_params);
    2362         932 :                 stmt->bound_params = NULL;
    2363             :         }
    2364        2442 :         if (stmt->bound_param_map) {
    2365         186 :                 zend_hash_destroy(stmt->bound_param_map);
    2366         186 :                 FREE_HASHTABLE(stmt->bound_param_map);
    2367         186 :                 stmt->bound_param_map = NULL;
    2368             :         }
    2369        2442 :         if (stmt->bound_columns) {
    2370         195 :                 zend_hash_destroy(stmt->bound_columns);
    2371         195 :                 FREE_HASHTABLE(stmt->bound_columns);
    2372         195 :                 stmt->bound_columns = NULL;
    2373             :         }
    2374             : 
    2375        2442 :         if (stmt->methods && stmt->methods->dtor) {
    2376        2425 :                 stmt->methods->dtor(stmt TSRMLS_CC);
    2377             :         }
    2378        2442 :         if (stmt->query_string) {
    2379        2428 :                 efree(stmt->query_string);
    2380             :         }
    2381             : 
    2382        2442 :         if (stmt->columns) {
    2383             :                 int i;
    2384        1887 :                 struct pdo_column_data *cols = stmt->columns;
    2385             : 
    2386        4125 :                 for (i = 0; i < stmt->column_count; i++) {
    2387        2238 :                         if (cols[i].name) {
    2388        2238 :                                 efree(cols[i].name);
    2389        2238 :                                 cols[i].name = NULL;
    2390             :                         }
    2391             :                 }
    2392        1887 :                 efree(stmt->columns);
    2393        1887 :                 stmt->columns = NULL;
    2394             :         }
    2395             : 
    2396        2442 :         if (stmt->fetch.into && stmt->default_fetch_type == PDO_FETCH_INTO) {
    2397           1 :                 FREE_ZVAL(stmt->fetch.into);
    2398           1 :                 stmt->fetch.into = NULL;
    2399             :         }
    2400             :         
    2401        2442 :         do_fetch_opt_finish(stmt, 1 TSRMLS_CC);
    2402             : 
    2403        2442 :         zend_objects_store_del_ref(&stmt->database_object_handle TSRMLS_CC);
    2404        2442 :         if (stmt->dbh) {
    2405        2428 :                 php_pdo_dbh_delref(stmt->dbh TSRMLS_CC);
    2406             :         }
    2407        2442 :         zend_object_std_dtor(&stmt->std TSRMLS_CC);
    2408        2442 :         efree(stmt);
    2409        2442 : }
    2410             : 
    2411          32 : PDO_API void php_pdo_stmt_addref(pdo_stmt_t *stmt TSRMLS_DC)
    2412             : {
    2413          32 :         stmt->refcount++;
    2414          32 : }
    2415             : 
    2416        2480 : PDO_API void php_pdo_stmt_delref(pdo_stmt_t *stmt TSRMLS_DC)
    2417             : {
    2418        2480 :         if (--stmt->refcount == 0) {
    2419        2394 :                 free_statement(stmt TSRMLS_CC);
    2420             :         }
    2421        2480 : }
    2422             : 
    2423        2448 : void pdo_dbstmt_free_storage(pdo_stmt_t *stmt TSRMLS_DC)
    2424             : {
    2425        2448 :         php_pdo_stmt_delref(stmt TSRMLS_CC);
    2426        2448 : }
    2427             : 
    2428        2448 : zend_object_value pdo_dbstmt_new(zend_class_entry *ce TSRMLS_DC)
    2429             : {
    2430             :         zend_object_value retval;
    2431             : 
    2432             :         pdo_stmt_t *stmt;
    2433        2448 :         stmt = emalloc(sizeof(*stmt));
    2434        2448 :         memset(stmt, 0, sizeof(*stmt));
    2435        2448 :         zend_object_std_init(&stmt->std, ce TSRMLS_CC);
    2436        2448 :         object_properties_init(&stmt->std, ce);
    2437        2448 :         stmt->refcount = 1;
    2438             : 
    2439        2448 :         retval.handle = zend_objects_store_put(stmt, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)pdo_dbstmt_free_storage, (zend_objects_store_clone_t)dbstmt_clone_obj TSRMLS_CC);
    2440        2448 :         retval.handlers = &pdo_dbstmt_object_handlers;
    2441             : 
    2442        2448 :         return retval;
    2443             : }
    2444             : /* }}} */
    2445             : 
    2446             : /* {{{ statement iterator */
    2447             : 
    2448             : struct php_pdo_iterator {
    2449             :         zend_object_iterator iter;
    2450             :         pdo_stmt_t *stmt;
    2451             :         ulong key;
    2452             :         zval *fetch_ahead;
    2453             : };
    2454             : 
    2455          98 : static void pdo_stmt_iter_dtor(zend_object_iterator *iter TSRMLS_DC)
    2456             : {
    2457          98 :         struct php_pdo_iterator *I = (struct php_pdo_iterator*)iter->data;
    2458             : 
    2459          98 :         if (--I->stmt->refcount == 0) {
    2460          31 :                 free_statement(I->stmt TSRMLS_CC);
    2461             :         }
    2462             :                 
    2463          98 :         if (I->fetch_ahead) {
    2464          19 :                 zval_ptr_dtor(&I->fetch_ahead);
    2465             :         }
    2466             : 
    2467          98 :         efree(I);
    2468          98 : }
    2469             : 
    2470         419 : static int pdo_stmt_iter_valid(zend_object_iterator *iter TSRMLS_DC)
    2471             : {
    2472         419 :         struct php_pdo_iterator *I = (struct php_pdo_iterator*)iter->data;
    2473             : 
    2474         419 :         return I->fetch_ahead ? SUCCESS : FAILURE;
    2475             : }
    2476             : 
    2477         334 : static void pdo_stmt_iter_get_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
    2478             : {
    2479         334 :         struct php_pdo_iterator *I = (struct php_pdo_iterator*)iter->data;
    2480             : 
    2481             :         /* sanity */
    2482         334 :         if (!I->fetch_ahead) {
    2483           0 :                 *data = NULL;
    2484           0 :                 return;
    2485             :         }
    2486             : 
    2487         334 :         *data = &I->fetch_ahead;
    2488             : }
    2489             : 
    2490          25 : static void pdo_stmt_iter_get_key(zend_object_iterator *iter, zval *key TSRMLS_DC)
    2491             : {
    2492          25 :         struct php_pdo_iterator *I = (struct php_pdo_iterator*)iter->data;
    2493             : 
    2494          25 :         if (I->key == (ulong)-1) {
    2495           0 :                 ZVAL_NULL(key);
    2496             :         } else {
    2497          25 :                 ZVAL_LONG(key, I->key);
    2498             :         }
    2499          25 : }
    2500             : 
    2501         321 : static void pdo_stmt_iter_move_forwards(zend_object_iterator *iter TSRMLS_DC)
    2502             : {
    2503         321 :         struct php_pdo_iterator *I = (struct php_pdo_iterator*)iter->data;
    2504             : 
    2505         321 :         if (I->fetch_ahead) {
    2506         315 :                 zval_ptr_dtor(&I->fetch_ahead);
    2507         315 :                 I->fetch_ahead = NULL;
    2508             :         }
    2509             : 
    2510         321 :         MAKE_STD_ZVAL(I->fetch_ahead);
    2511             : 
    2512         321 :         if (!do_fetch(I->stmt, TRUE, I->fetch_ahead, PDO_FETCH_USE_DEFAULT,
    2513             :                         PDO_FETCH_ORI_NEXT, 0, 0 TSRMLS_CC)) {
    2514          85 :                 pdo_stmt_t *stmt = I->stmt; /* for PDO_HANDLE_STMT_ERR() */
    2515             : 
    2516          85 :                 PDO_HANDLE_STMT_ERR();
    2517          85 :                 I->key = (ulong)-1;
    2518          85 :                 FREE_ZVAL(I->fetch_ahead);
    2519          85 :                 I->fetch_ahead = NULL;
    2520             : 
    2521          85 :                 return;
    2522             :         }
    2523             : 
    2524         236 :         I->key++;
    2525             : }
    2526             : 
    2527             : static zend_object_iterator_funcs pdo_stmt_iter_funcs = {
    2528             :         pdo_stmt_iter_dtor,
    2529             :         pdo_stmt_iter_valid,
    2530             :         pdo_stmt_iter_get_data,
    2531             :         pdo_stmt_iter_get_key,
    2532             :         pdo_stmt_iter_move_forwards,
    2533             :         NULL
    2534             : };
    2535             : 
    2536         104 : zend_object_iterator *pdo_stmt_iter_get(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
    2537             : {
    2538         104 :         pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(object TSRMLS_CC);
    2539             :         struct php_pdo_iterator *I;
    2540             : 
    2541         104 :         if (by_ref) {
    2542           0 :                 zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
    2543             :         }
    2544             : 
    2545         104 :         I = ecalloc(1, sizeof(*I));
    2546         104 :         I->iter.funcs = &pdo_stmt_iter_funcs;
    2547         104 :         I->iter.data = I;
    2548         104 :         I->stmt = stmt;
    2549         104 :         stmt->refcount++;
    2550             : 
    2551         104 :         MAKE_STD_ZVAL(I->fetch_ahead);
    2552         104 :         if (!do_fetch(I->stmt, TRUE, I->fetch_ahead, PDO_FETCH_USE_DEFAULT,
    2553             :                         PDO_FETCH_ORI_NEXT, 0, 0 TSRMLS_CC)) {
    2554           0 :                 PDO_HANDLE_STMT_ERR();
    2555           0 :                 I->key = (ulong)-1;
    2556           0 :                 FREE_ZVAL(I->fetch_ahead);
    2557           0 :                 I->fetch_ahead = NULL;
    2558             :         }
    2559             : 
    2560          98 :         return &I->iter;
    2561             : }
    2562             : 
    2563             : /* }}} */
    2564             : 
    2565             : /* {{{ overloaded handlers for PDORow class (used by PDO_FETCH_LAZY) */
    2566             : 
    2567             : const zend_function_entry pdo_row_functions[] = {
    2568             :         {NULL, NULL, NULL}
    2569             : };
    2570             : 
    2571          34 : static zval *row_prop_read(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
    2572             : {
    2573             :         zval *return_value;
    2574          34 :         pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC);
    2575          34 :         int colno = -1;
    2576             : 
    2577          34 :         MAKE_STD_ZVAL(return_value);
    2578          34 :         RETVAL_NULL();
    2579             : 
    2580          34 :         if (stmt) {
    2581          34 :                 if (Z_TYPE_P(member) == IS_LONG) {
    2582           3 :                         if (Z_LVAL_P(member) >= 0 && Z_LVAL_P(member) < stmt->column_count) {
    2583           1 :                                 fetch_value(stmt, return_value, Z_LVAL_P(member), NULL TSRMLS_CC);
    2584             :                         }
    2585             :                 } else {
    2586          31 :                         convert_to_string(member);
    2587             :                         /* TODO: replace this with a hash of available column names to column
    2588             :                          * numbers */
    2589          47 :                         for (colno = 0; colno < stmt->column_count; colno++) {
    2590          43 :                                 if (strcmp(stmt->columns[colno].name, Z_STRVAL_P(member)) == 0) {
    2591          27 :                                         fetch_value(stmt, return_value, colno, NULL TSRMLS_CC);
    2592          27 :                                         Z_SET_REFCOUNT_P(return_value, 0);
    2593          27 :                                         Z_UNSET_ISREF_P(return_value);
    2594          27 :                                         return return_value;
    2595             :                                 }
    2596             :                         }
    2597           4 :                         if (strcmp(Z_STRVAL_P(member), "queryString") == 0) {
    2598           3 :                                 zval_ptr_dtor(&return_value);
    2599           3 :                                 return std_object_handlers.read_property(object, member, type, key TSRMLS_CC);
    2600             :                         }
    2601             :                 }
    2602             :         }
    2603             : 
    2604           4 :         Z_SET_REFCOUNT_P(return_value, 0);
    2605           4 :         Z_UNSET_ISREF_P(return_value);
    2606             :         
    2607           4 :         return return_value;
    2608             : }
    2609             : 
    2610           1 : static zval *row_dim_read(zval *object, zval *member, int type TSRMLS_DC)
    2611             : {
    2612           1 :         return row_prop_read(object, member, type, NULL TSRMLS_CC);
    2613             : }
    2614             : 
    2615           0 : static void row_prop_write(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
    2616             : {
    2617           0 :         php_error_docref(NULL TSRMLS_CC, E_WARNING, "This PDORow is not from a writable result set");
    2618           0 : }
    2619             : 
    2620           0 : static void row_dim_write(zval *object, zval *member, zval *value TSRMLS_DC)
    2621             : {
    2622           0 :         php_error_docref(NULL TSRMLS_CC, E_WARNING, "This PDORow is not from a writable result set");
    2623           0 : }
    2624             : 
    2625           0 : static int row_prop_exists(zval *object, zval *member, int check_empty, const zend_literal *key TSRMLS_DC)
    2626             : {
    2627           0 :         pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC);
    2628           0 :         int colno = -1;
    2629             : 
    2630           0 :         if (stmt) {
    2631           0 :                 if (Z_TYPE_P(member) == IS_LONG) {
    2632           0 :                         return Z_LVAL_P(member) >= 0 && Z_LVAL_P(member) < stmt->column_count;
    2633             :                 } else {
    2634           0 :                         convert_to_string(member);
    2635             : 
    2636             :                         /* TODO: replace this with a hash of available column names to column
    2637             :                          * numbers */
    2638           0 :                         for (colno = 0; colno < stmt->column_count; colno++) {
    2639           0 :                                 if (strcmp(stmt->columns[colno].name, Z_STRVAL_P(member)) == 0) {
    2640           0 :                                         return 1;
    2641             :                                 }
    2642             :                         }
    2643             :                 }
    2644             :         }
    2645             : 
    2646           0 :         return 0;
    2647             : }
    2648             : 
    2649           0 : static int row_dim_exists(zval *object, zval *member, int check_empty TSRMLS_DC)
    2650             : {
    2651           0 :         return row_prop_exists(object, member, check_empty, NULL TSRMLS_CC);
    2652             : }
    2653             : 
    2654           0 : static void row_prop_delete(zval *object, zval *offset, const zend_literal *key TSRMLS_DC)
    2655             : {
    2656           0 :         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a PDORow");
    2657           0 : }
    2658             : 
    2659           0 : static void row_dim_delete(zval *object, zval *offset TSRMLS_DC)
    2660             : {
    2661           0 :         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a PDORow");
    2662           0 : }
    2663             : 
    2664           4 : static HashTable *row_get_properties(zval *object TSRMLS_DC)
    2665             : {
    2666           4 :         pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC);
    2667             :         int i;
    2668             : 
    2669           4 :         if (stmt == NULL) {
    2670           0 :                 return NULL;
    2671             :         }
    2672             :         
    2673           4 :         if (!stmt->std.properties) {
    2674           3 :                 rebuild_object_properties(&stmt->std);
    2675             :         }
    2676           8 :         for (i = 0; i < stmt->column_count; i++) {
    2677             :                 zval *val;
    2678           4 :                 MAKE_STD_ZVAL(val);
    2679           4 :                 fetch_value(stmt, val, i, NULL TSRMLS_CC);
    2680             : 
    2681           4 :                 zend_hash_update(stmt->std.properties, stmt->columns[i].name, stmt->columns[i].namelen + 1, (void *)&val, sizeof(zval *), NULL);
    2682             :         }
    2683             : 
    2684           4 :         return stmt->std.properties;
    2685             : }
    2686             : 
    2687           0 : static union _zend_function *row_method_get(
    2688             : #if PHP_API_VERSION >= 20041225
    2689             :         zval **object_pp,
    2690             : #else
    2691             :         zval *object,
    2692             : #endif
    2693             :         char *method_name, int method_len, const zend_literal *key TSRMLS_DC)
    2694             : {
    2695             :         zend_function *fbc;
    2696             :         char *lc_method_name;
    2697             : 
    2698           0 :         lc_method_name = emalloc(method_len + 1);
    2699           0 :         zend_str_tolower_copy(lc_method_name, method_name, method_len);
    2700             : 
    2701           0 :         if (zend_hash_find(&pdo_row_ce->function_table, lc_method_name, method_len+1, (void**)&fbc) == FAILURE) {
    2702           0 :                 efree(lc_method_name);
    2703           0 :                 return NULL;
    2704             :         }
    2705             :         
    2706           0 :         efree(lc_method_name);
    2707           0 :         return fbc;
    2708             : }
    2709             : 
    2710           0 : static int row_call_method(const char *method, INTERNAL_FUNCTION_PARAMETERS)
    2711             : {
    2712           0 :         return FAILURE;
    2713             : }
    2714             : 
    2715          14 : static union _zend_function *row_get_ctor(zval *object TSRMLS_DC)
    2716             : {
    2717             :         static zend_internal_function ctor = {0};
    2718             : 
    2719          14 :         ctor.type = ZEND_INTERNAL_FUNCTION;
    2720          14 :         ctor.function_name = "__construct";
    2721          14 :         ctor.scope = pdo_row_ce;
    2722          14 :         ctor.handler = ZEND_FN(dbstmt_constructor);
    2723          14 :         ctor.fn_flags = ZEND_ACC_PUBLIC;
    2724             : 
    2725          14 :         return (union _zend_function*)&ctor;
    2726             : }
    2727             : 
    2728          14 : static zend_class_entry *row_get_ce(const zval *object TSRMLS_DC)
    2729             : {
    2730          14 :         return pdo_row_ce;
    2731             : }
    2732             : 
    2733          18 : static int row_get_classname(const zval *object, const char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC)
    2734             : {
    2735          18 :         if (parent) {
    2736           7 :                 return FAILURE;
    2737             :         } else {
    2738          11 :                 *class_name = estrndup("PDORow", sizeof("PDORow")-1);
    2739          11 :                 *class_name_len = sizeof("PDORow")-1;
    2740          11 :                 return SUCCESS;
    2741             :         }
    2742             : }
    2743             : 
    2744           0 : static int row_compare(zval *object1, zval *object2 TSRMLS_DC)
    2745             : {
    2746           0 :         return -1;
    2747             : }
    2748             : 
    2749             : zend_object_handlers pdo_row_object_handlers = {
    2750             :         zend_objects_store_add_ref,
    2751             :         zend_objects_store_del_ref,
    2752             :         NULL,
    2753             :         row_prop_read,
    2754             :         row_prop_write,
    2755             :         row_dim_read,
    2756             :         row_dim_write,
    2757             :         NULL,
    2758             :         NULL,
    2759             :         NULL,
    2760             :         row_prop_exists,
    2761             :         row_prop_delete,
    2762             :         row_dim_exists,
    2763             :         row_dim_delete,
    2764             :         row_get_properties,
    2765             :         row_method_get,
    2766             :         row_call_method,
    2767             :         row_get_ctor,
    2768             :         row_get_ce,
    2769             :         row_get_classname,
    2770             :         row_compare,
    2771             :         NULL, /* cast */
    2772             :         NULL
    2773             : };
    2774             : 
    2775          31 : void pdo_row_free_storage(pdo_stmt_t *stmt TSRMLS_DC)
    2776             : {
    2777          31 :         if (stmt) {
    2778          17 :                 ZVAL_NULL(&stmt->lazy_object_ref);
    2779             :                 
    2780          17 :                 if (--stmt->refcount == 0) {
    2781          17 :                         free_statement(stmt TSRMLS_CC);
    2782             :                 }
    2783             :         }
    2784          31 : }
    2785             : 
    2786          14 : zend_object_value pdo_row_new(zend_class_entry *ce TSRMLS_DC)
    2787             : {
    2788             :         zend_object_value retval;
    2789             : 
    2790          14 :         retval.handle = zend_objects_store_put(NULL, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)pdo_row_free_storage, NULL TSRMLS_CC);
    2791          14 :         retval.handlers = &pdo_row_object_handlers;
    2792             : 
    2793          14 :         return retval;
    2794             : }
    2795             : 
    2796           0 : static int pdo_row_serialize(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC)
    2797             : {
    2798           0 :         php_error_docref(NULL TSRMLS_CC, E_WARNING, "PDORow instances may not be serialized");
    2799           0 :         return FAILURE;
    2800             : }
    2801             : /* }}} */
    2802             : 
    2803             : /*
    2804             :  * Local variables:
    2805             :  * tab-width: 4
    2806             :  * c-basic-offset: 4
    2807             :  * End:
    2808             :  * vim600: noet sw=4 ts=4 fdm=marker
    2809             :  * vim<600: noet sw=4 ts=4
    2810             :  */

Generated by: LCOV version 1.10

Generated at Mon, 04 Aug 2014 15:49:09 +0000 (26 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.