Annotation of embedaddon/php/ext/pdo/pdo_stmt.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>