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

Generated by: LCOV version 1.10

Generated at Mon, 15 Dec 2014 17:02:46 +0000 (5 days ago)

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