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: 1074 1312 81.9 %
Date: 2014-07-23 Functions: 57 71 80.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Wed, 23 Jul 2014 19:58:35 +0000 (17 hours ago)

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