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: 1065 1307 81.5 %
Date: 2014-04-16 Functions: 58 75 77.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Wed, 16 Apr 2014 12:47:53 +0000 (2 days ago)

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