Annotation of embedaddon/php/ext/oci8/oci8_statement.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:    | Authors: Stig Sæther Bakken <ssb@php.net>                            |
        !            16:    |          Thies C. Arntzen <thies@thieso.net>                         |
        !            17:    |                                                                      |
        !            18:    | Collection support by Andy Sautins <asautins@veripost.net>           |
        !            19:    | Temporary LOB support by David Benson <dbenson@mancala.com>          |
        !            20:    | ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at>        |
        !            21:    |                                                                      |
        !            22:    | Redesigned by: Antony Dovgal <antony@zend.com>                       |
        !            23:    |                Andi Gutmans <andi@zend.com>                          |
        !            24:    |                Wez Furlong <wez@omniti.com>                          |
        !            25:    +----------------------------------------------------------------------+
        !            26: */
        !            27: 
        !            28: /* $Id: oci8_statement.c 321634 2012-01-01 13:15:04Z felipe $ */
        !            29: 
        !            30: 
        !            31: #ifdef HAVE_CONFIG_H
        !            32: #include "config.h"
        !            33: #endif
        !            34: 
        !            35: #include "php.h"
        !            36: #include "ext/standard/info.h"
        !            37: #include "php_ini.h"
        !            38: 
        !            39: #if HAVE_OCI8
        !            40: 
        !            41: #include "php_oci8.h"
        !            42: #include "php_oci8_int.h"
        !            43: 
        !            44: /* {{{ php_oci_statement_create()
        !            45:  Create statemend handle and allocate necessary resources */
        !            46: php_oci_statement *php_oci_statement_create (php_oci_connection *connection, char *query, int query_len TSRMLS_DC)
        !            47: {
        !            48:        php_oci_statement *statement;
        !            49:        
        !            50:        statement = ecalloc(1,sizeof(php_oci_statement));
        !            51: 
        !            52:        if (!query_len) {
        !            53:                /* do not allocate stmt handle for refcursors, we'll get it from OCIStmtPrepare2() */
        !            54:                PHP_OCI_CALL(OCIHandleAlloc, (connection->env, (dvoid **)&(statement->stmt), OCI_HTYPE_STMT, 0, NULL));
        !            55:        }
        !            56:                        
        !            57:        PHP_OCI_CALL(OCIHandleAlloc, (connection->env, (dvoid **)&(statement->err), OCI_HTYPE_ERROR, 0, NULL));
        !            58:        
        !            59:        if (query_len > 0) {
        !            60:                PHP_OCI_CALL_RETURN(connection->errcode, OCIStmtPrepare2,
        !            61:                                (
        !            62:                                 connection->svc,
        !            63:                                 &(statement->stmt),
        !            64:                                 connection->err,
        !            65:                                 (text *)query,
        !            66:                                 query_len,
        !            67:                                 NULL,
        !            68:                                 0,
        !            69:                                 OCI_NTV_SYNTAX,
        !            70:                                 OCI_DEFAULT
        !            71:                                )
        !            72:                );
        !            73:                if (connection->errcode != OCI_SUCCESS) {
        !            74:                        connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
        !            75: 
        !            76:                        PHP_OCI_CALL(OCIStmtRelease, (statement->stmt, statement->err, NULL, 0, statement->errcode ? OCI_STRLS_CACHE_DELETE : OCI_DEFAULT));
        !            77:                        PHP_OCI_CALL(OCIHandleFree,(statement->err, OCI_HTYPE_ERROR));
        !            78:                        
        !            79:                        efree(statement);
        !            80:                        PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
        !            81:                        return NULL;
        !            82:                }
        !            83:        }
        !            84:        
        !            85:        if (query && query_len) {
        !            86:                statement->last_query = estrndup(query, query_len);
        !            87:                statement->last_query_len = query_len;
        !            88:        }
        !            89:        else {
        !            90:                statement->last_query = NULL;
        !            91:                statement->last_query_len = 0;
        !            92:        }
        !            93: 
        !            94:        statement->connection = connection;
        !            95:        statement->has_data = 0;
        !            96:        statement->has_descr = 0;
        !            97:        statement->parent_stmtid = 0;
        !            98:        zend_list_addref(statement->connection->rsrc_id);
        !            99: 
        !           100:        if (OCI_G(default_prefetch) >= 0) {
        !           101:                php_oci_statement_set_prefetch(statement, OCI_G(default_prefetch) TSRMLS_CC);
        !           102:        }
        !           103:        
        !           104:        PHP_OCI_REGISTER_RESOURCE(statement, le_statement);
        !           105: 
        !           106:        OCI_G(num_statements)++;
        !           107:        
        !           108:        return statement;
        !           109: }
        !           110: /* }}} */
        !           111: 
        !           112: /* {{{ php_oci_statement_set_prefetch()
        !           113:  Set prefetch buffer size for the statement (we're assuming that one row is ~1K sized) */
        !           114: int php_oci_statement_set_prefetch(php_oci_statement *statement, long size TSRMLS_DC)
        !           115: {
        !           116:        ub4 prefetch = size;
        !           117: 
        !           118:        if (size < 0) {
        !           119:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of rows to be prefetched has to be greater than or equal to 0");
        !           120:                return 1;
        !           121:        }
        !           122:        
        !           123:        PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrSet, (statement->stmt, OCI_HTYPE_STMT, &prefetch, 0, OCI_ATTR_PREFETCH_ROWS, statement->err));
        !           124:        
        !           125:        if (statement->errcode != OCI_SUCCESS) {
        !           126:                statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !           127:                PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !           128:                return 1;
        !           129:        }
        !           130: 
        !           131:        return 0;
        !           132: }
        !           133: /* }}} */
        !           134: 
        !           135: /* {{{ php_oci_cleanup_pre_fetch()
        !           136:    Helper function to cleanup ref-cursors and descriptors from the previous row */
        !           137: int php_oci_cleanup_pre_fetch(void *data TSRMLS_DC)
        !           138: {
        !           139:        php_oci_out_column *outcol = data;
        !           140: 
        !           141:        if (!outcol->is_descr && !outcol->is_cursor)
        !           142:                return ZEND_HASH_APPLY_KEEP;
        !           143: 
        !           144:        switch(outcol->data_type) {
        !           145:                case SQLT_CLOB:
        !           146:                case SQLT_BLOB:
        !           147:                case SQLT_RDD:
        !           148:                case SQLT_BFILE:
        !           149:                        if (outcol->descid) {
        !           150:                                zend_list_delete(outcol->descid);
        !           151:                                outcol->descid = 0;
        !           152:                        }
        !           153:                        break;
        !           154:                case SQLT_RSET:
        !           155:                        if (outcol->stmtid) {
        !           156:                                zend_list_delete(outcol->stmtid);
        !           157:                                outcol->stmtid = 0;
        !           158:                                outcol->nested_statement = NULL;
        !           159:                        }
        !           160:                        break;
        !           161:                default:
        !           162:                        break;
        !           163:        }
        !           164:        return ZEND_HASH_APPLY_KEEP;
        !           165: 
        !           166: } /* }}} */
        !           167: 
        !           168: 
        !           169: /* {{{ php_oci_statement_fetch()
        !           170:  Fetch a row from the statement */
        !           171: int php_oci_statement_fetch(php_oci_statement *statement, ub4 nrows TSRMLS_DC)
        !           172: {
        !           173:        int i;
        !           174:        void *handlepp;
        !           175:        ub4 typep, iterp, idxp;
        !           176:        ub1 in_outp, piecep;
        !           177:        zend_bool piecewisecols = 0;
        !           178: 
        !           179:        php_oci_out_column *column;
        !           180: 
        !           181:        if (statement->has_descr && statement->columns) {
        !           182:                zend_hash_apply(statement->columns, (apply_func_t) php_oci_cleanup_pre_fetch TSRMLS_CC);
        !           183:     }
        !           184: 
        !           185:        PHP_OCI_CALL_RETURN(statement->errcode, OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT));
        !           186: 
        !           187:        if ( statement->errcode == OCI_NO_DATA || nrows == 0 ) {
        !           188:                if (statement->last_query == NULL) {
        !           189:                        /* reset define-list for refcursors */
        !           190:                        if (statement->columns) {
        !           191:                                zend_hash_destroy(statement->columns);
        !           192:                                efree(statement->columns);
        !           193:                                statement->columns = NULL;
        !           194:                                statement->ncolumns = 0;
        !           195:                        }
        !           196:                        statement->executed = 0;
        !           197:                }
        !           198: 
        !           199:                statement->errcode = 0; /* OCI_NO_DATA is NO error for us!!! */
        !           200:                statement->has_data = 0;
        !           201: 
        !           202:                if (nrows == 0) {
        !           203:                        /* this is exactly what we requested */
        !           204:                        return 0;
        !           205:                }
        !           206:                return 1;
        !           207:        }
        !           208: 
        !           209:        /* reset length for all piecewise columns */
        !           210:        for (i = 0; i < statement->ncolumns; i++) {
        !           211:                column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
        !           212:                if (column->piecewise) {
        !           213:                        column->retlen4 = 0;
        !           214:                        piecewisecols = 1;
        !           215:                }
        !           216:        }
        !           217:        
        !           218:        while (statement->errcode == OCI_NEED_DATA) {
        !           219:                if (piecewisecols) {
        !           220:                        PHP_OCI_CALL_RETURN(statement->errcode,
        !           221:                                OCIStmtGetPieceInfo,
        !           222:                                   (
        !           223:                                        statement->stmt,
        !           224:                                        statement->err,
        !           225:                                        &handlepp,
        !           226:                                        &typep,
        !           227:                                        &in_outp,
        !           228:                                        &iterp,
        !           229:                                        &idxp,
        !           230:                                        &piecep
        !           231:                                   )
        !           232:                        );
        !           233: 
        !           234:                        /* scan through our columns for a piecewise column with a matching handle */
        !           235:                        for (i = 0; i < statement->ncolumns; i++) {
        !           236:                                column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
        !           237:                                if (column->piecewise && handlepp == column->oci_define)   {
        !           238:                                        if (!column->data) {
        !           239:                                                column->data = (text *) ecalloc(1, PHP_OCI_PIECE_SIZE + 1);
        !           240:                                        } else {
        !           241:                                                column->data = erealloc(column->data, column->retlen4 + PHP_OCI_PIECE_SIZE + 1);
        !           242:                                        }
        !           243:                                        column->cb_retlen = PHP_OCI_PIECE_SIZE;
        !           244: 
        !           245:                                        /* and instruct fetch to fetch waiting piece into our buffer */
        !           246:                                        PHP_OCI_CALL(OCIStmtSetPieceInfo,
        !           247:                                                   (
        !           248:                                                        (void *) column->oci_define,
        !           249:                                                        OCI_HTYPE_DEFINE,
        !           250:                                                        statement->err,
        !           251:                                                        ((char*)column->data) + column->retlen4,
        !           252:                                                        &(column->cb_retlen),
        !           253:                                                        piecep,
        !           254:                                                        &column->indicator,
        !           255:                                                        &column->retcode
        !           256:                                                   )
        !           257:                                        );
        !           258:                                }
        !           259:                        }
        !           260:                }
        !           261: 
        !           262:                PHP_OCI_CALL_RETURN(statement->errcode,  OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT));
        !           263: 
        !           264:                if (piecewisecols) {
        !           265:                        for (i = 0; i < statement->ncolumns; i++) {
        !           266:                                column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
        !           267:                                if (column && column->piecewise && handlepp == column->oci_define)      {
        !           268:                                        column->retlen4 += column->cb_retlen;
        !           269:                                }
        !           270:                        }
        !           271:                }
        !           272:        }
        !           273: 
        !           274:        if (statement->errcode == OCI_SUCCESS_WITH_INFO || statement->errcode == OCI_SUCCESS) {
        !           275:                statement->has_data = 1;
        !           276: 
        !           277:                /* do the stuff needed for OCIDefineByName */
        !           278:                for (i = 0; i < statement->ncolumns; i++) {
        !           279:                        column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
        !           280:                        if (column == NULL) {
        !           281:                                continue;
        !           282:                        }
        !           283:                        
        !           284:                        if (!column->define) {
        !           285:                                continue;
        !           286:                        }
        !           287:                        
        !           288:                        zval_dtor(column->define->zval);
        !           289:                        php_oci_column_to_zval(column, column->define->zval, 0 TSRMLS_CC);
        !           290:                }
        !           291: 
        !           292:                return 0;
        !           293:        }
        !           294: 
        !           295:        statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !           296:        PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !           297: 
        !           298:        statement->has_data = 0;
        !           299: 
        !           300:        return 1;
        !           301: }
        !           302: /* }}} */
        !           303: 
        !           304: /* {{{ php_oci_statement_get_column()
        !           305:  Get column from the result set */
        !           306: php_oci_out_column *php_oci_statement_get_column(php_oci_statement *statement, long column_index, char *column_name, int column_name_len TSRMLS_DC)
        !           307: {
        !           308:        php_oci_out_column *column = NULL;
        !           309:        int i;
        !           310: 
        !           311:        if (statement->columns == NULL) { /* we release the columns at the end of a fetch */
        !           312:                return NULL;
        !           313:        }
        !           314: 
        !           315:        if (column_name) {
        !           316:                for (i = 0; i < statement->ncolumns; i++) {
        !           317:                        column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
        !           318:                        if (column == NULL) {
        !           319:                                continue;
        !           320:                        } else if (((int) column->name_len == column_name_len) && (!strncmp(column->name, column_name, column_name_len))) {
        !           321:                                return column;
        !           322:                        }
        !           323:                }
        !           324:        } else if (column_index != -1) {
        !           325:                if (zend_hash_index_find(statement->columns, column_index, (void **)&column) == FAILURE) {
        !           326:                        return NULL;
        !           327:                }
        !           328:                return column;
        !           329:        }
        !           330: 
        !           331:        return NULL;
        !           332: }
        !           333: /* }}} */
        !           334: 
        !           335: /* php_oci_define_callback() {{{ */
        !           336: sb4 php_oci_define_callback(dvoid *ctx, OCIDefine *define, ub4 iter, dvoid **bufpp, ub4 **alenpp, ub1 *piecep, dvoid **indpp, ub2 **rcpp)
        !           337: {
        !           338:        php_oci_out_column *outcol = (php_oci_out_column *)ctx;
        !           339:        TSRMLS_FETCH();
        !           340: 
        !           341:        if (!outcol) {
        !           342:                
        !           343:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid context pointer value");
        !           344:                return OCI_ERROR;
        !           345:        }
        !           346:        
        !           347:        switch(outcol->data_type) {
        !           348:                case SQLT_RSET: {
        !           349:                                php_oci_statement *nested_stmt;
        !           350: 
        !           351:                                nested_stmt = php_oci_statement_create(outcol->statement->connection, NULL, 0 TSRMLS_CC);
        !           352:                                if (!nested_stmt) {
        !           353:                                        return OCI_ERROR;
        !           354:                                }
        !           355:                                nested_stmt->parent_stmtid = outcol->statement->id;
        !           356:                                zend_list_addref(outcol->statement->id);
        !           357:                                outcol->nested_statement = nested_stmt;
        !           358:                                outcol->stmtid = nested_stmt->id;
        !           359: 
        !           360:                                *bufpp = nested_stmt->stmt;
        !           361:                                *alenpp = &(outcol->retlen4);
        !           362:                                *piecep = OCI_ONE_PIECE;
        !           363:                                *indpp = &(outcol->indicator);
        !           364:                                *rcpp = &(outcol->retcode);
        !           365:                                return OCI_CONTINUE;
        !           366:                        }
        !           367:                        break;
        !           368:                case SQLT_RDD:
        !           369:                case SQLT_BLOB:
        !           370:                case SQLT_CLOB:
        !           371:                case SQLT_BFILE: {
        !           372:                                php_oci_descriptor *descr;
        !           373:                                int dtype;
        !           374: 
        !           375:                                if (outcol->data_type == SQLT_BFILE) {
        !           376:                                        dtype = OCI_DTYPE_FILE;
        !           377:                                } else if (outcol->data_type == SQLT_RDD ) {
        !           378:                                        dtype = OCI_DTYPE_ROWID;
        !           379:                                } else {
        !           380:                                        dtype = OCI_DTYPE_LOB;
        !           381:                                }
        !           382: 
        !           383:                                descr = php_oci_lob_create(outcol->statement->connection, dtype TSRMLS_CC);
        !           384:                                if (!descr) {
        !           385:                                        return OCI_ERROR;
        !           386:                                }
        !           387:                                outcol->descid = descr->id;
        !           388:                                descr->charset_form = outcol->charset_form;
        !           389:                                
        !           390:                                *bufpp = descr->descriptor;
        !           391:                                *alenpp = &(outcol->retlen4);
        !           392:                                *piecep = OCI_ONE_PIECE;
        !           393:                                *indpp = &(outcol->indicator);
        !           394:                                *rcpp = &(outcol->retcode);
        !           395: 
        !           396:                                return OCI_CONTINUE;
        !           397:                        }
        !           398:                        break;
        !           399:        }
        !           400:        return OCI_ERROR;
        !           401: }
        !           402: /* }}} */
        !           403: 
        !           404: /* {{{ php_oci_statement_execute()
        !           405:  Execute statement */
        !           406: int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC)
        !           407: {
        !           408:        php_oci_out_column *outcol;
        !           409:        php_oci_out_column column;
        !           410:        OCIParam *param = NULL;
        !           411:        text *colname;
        !           412:        ub4 counter;
        !           413:        ub2 define_type;
        !           414:        ub4 iters;
        !           415:        ub4 colcount;
        !           416:        ub2 dynamic;
        !           417:        dvoid *buf;
        !           418: 
        !           419:        switch (mode) {
        !           420:                case OCI_COMMIT_ON_SUCCESS:
        !           421:                case OCI_DESCRIBE_ONLY:
        !           422:                case OCI_DEFAULT:
        !           423:                        /* only these are allowed */
        !           424:                        break;
        !           425:                default:
        !           426:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid execute mode given: %d", mode);
        !           427:                        return 1;
        !           428:                        break;
        !           429:        }
        !           430:        
        !           431:        if (!statement->stmttype) {
        !           432:                /* get statement type */
        !           433:                PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)&statement->stmttype, (ub4 *)0,   OCI_ATTR_STMT_TYPE,     statement->err));
        !           434: 
        !           435:                if (statement->errcode != OCI_SUCCESS) {
        !           436:                        statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !           437:                        PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !           438:                        return 1;
        !           439:                }
        !           440:        }
        !           441: 
        !           442:        if (statement->stmttype == OCI_STMT_SELECT) {
        !           443:                iters = 0;
        !           444:        } else {
        !           445:                iters = 1;
        !           446:        }
        !           447:        
        !           448:        if (statement->last_query) {
        !           449:                /* if we execute refcursors we don't have a query and
        !           450:                   we don't want to execute!!! */
        !           451: 
        !           452:                if (statement->binds) {
        !           453:                        int result = 0;
        !           454:                        zend_hash_apply_with_argument(statement->binds, (apply_func_arg_t) php_oci_bind_pre_exec, (void *)&result TSRMLS_CC);
        !           455:                        if (result) {
        !           456:                                return 1;
        !           457:                        }
        !           458:                }
        !           459: 
        !           460:                /* execute statement */
        !           461:                PHP_OCI_CALL_RETURN(statement->errcode, OCIStmtExecute, (statement->connection->svc,    statement->stmt, statement->err, iters, 0, NULL, NULL, mode));
        !           462: 
        !           463:                if (statement->errcode != OCI_SUCCESS) {
        !           464:                        statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !           465:                        PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !           466:                        return 1;
        !           467:                }
        !           468:                
        !           469:                if (statement->binds) {
        !           470:                        zend_hash_apply(statement->binds, (apply_func_t) php_oci_bind_post_exec TSRMLS_CC);
        !           471:                }
        !           472: 
        !           473:                if (mode & OCI_COMMIT_ON_SUCCESS) {
        !           474:                        statement->connection->needs_commit = 0;
        !           475:                } else {
        !           476:                        statement->connection->needs_commit = 1;
        !           477:                }
        !           478:        }
        !           479: 
        !           480:        if (statement->stmttype == OCI_STMT_SELECT && statement->executed == 0) {
        !           481:                /* we only need to do the define step is this very statement is executed the first time! */
        !           482:                statement->executed = 1;
        !           483:                
        !           484:                ALLOC_HASHTABLE(statement->columns);
        !           485:                zend_hash_init(statement->columns, 13, NULL, php_oci_column_hash_dtor, 0);
        !           486:                
        !           487:                counter = 1;
        !           488: 
        !           489:                /* get number of columns */
        !           490:                PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (dvoid *)&colcount, (ub4 *)0, OCI_ATTR_PARAM_COUNT, statement->err));
        !           491:                
        !           492:                if (statement->errcode != OCI_SUCCESS) {
        !           493:                        statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !           494:                        PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !           495:                        return 1;
        !           496:                }
        !           497: 
        !           498:                statement->ncolumns = colcount;
        !           499:                
        !           500:                for (counter = 1; counter <= colcount; counter++) {
        !           501:                        memset(&column,0,sizeof(php_oci_out_column));
        !           502:                        
        !           503:                        if (zend_hash_index_update(statement->columns, counter, &column, sizeof(php_oci_out_column), (void**) &outcol) == FAILURE) {
        !           504:                                efree(statement->columns);
        !           505:                                /* out of memory */
        !           506:                                return 1;
        !           507:                        }
        !           508:                        
        !           509:                        /* get column */
        !           510:                        PHP_OCI_CALL_RETURN(statement->errcode, OCIParamGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, statement->err, (dvoid**)&param, counter));
        !           511:                        
        !           512:                        if (statement->errcode != OCI_SUCCESS) {
        !           513:                                statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !           514:                                PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !           515:                                return 1;
        !           516:                        }
        !           517: 
        !           518:                        /* get column datatype */
        !           519:                        PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->data_type, (ub4 *)0, OCI_ATTR_DATA_TYPE, statement->err));
        !           520: 
        !           521:                        if (statement->errcode != OCI_SUCCESS) {
        !           522:                                PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
        !           523:                                statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !           524:                                PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !           525:                                return 1;
        !           526:                        }
        !           527: 
        !           528:                        /* get character set form  */
        !           529:                        PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->charset_form, (ub4 *)0, OCI_ATTR_CHARSET_FORM, statement->err));
        !           530: 
        !           531:                        if (statement->errcode != OCI_SUCCESS) {
        !           532:                                PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
        !           533:                                statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !           534:                                PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !           535:                                return 1;
        !           536:                        }
        !           537:        
        !           538:                        /* get character set id  */
        !           539:                        PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->charset_id, (ub4 *)0, OCI_ATTR_CHARSET_ID, statement->err));
        !           540: 
        !           541:                        if (statement->errcode != OCI_SUCCESS) {
        !           542:                                PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
        !           543:                                statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !           544:                                PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !           545:                                return 1;
        !           546:                        }
        !           547:        
        !           548:                        /* get size of the column */
        !           549:                        PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->data_size, (dvoid *)0, OCI_ATTR_DATA_SIZE, statement->err));
        !           550:                        
        !           551:                        if (statement->errcode != OCI_SUCCESS) {
        !           552:                                PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
        !           553:                                statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !           554:                                PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !           555:                                return 1;
        !           556:                        }
        !           557: 
        !           558:                        outcol->storage_size4 = outcol->data_size;
        !           559:                        outcol->retlen = outcol->data_size;
        !           560: 
        !           561:                        /* get scale of the column */
        !           562:                        PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->scale, (dvoid *)0, OCI_ATTR_SCALE, statement->err));
        !           563:                        
        !           564:                        if (statement->errcode != OCI_SUCCESS) {
        !           565:                                PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
        !           566:                                statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !           567:                                PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !           568:                                return 1;
        !           569:                        }
        !           570: 
        !           571:                        /* get precision of the column */
        !           572:                        PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->precision, (dvoid *)0, OCI_ATTR_PRECISION, statement->err));
        !           573:                        
        !           574:                        if (statement->errcode != OCI_SUCCESS) {
        !           575:                                PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
        !           576:                                statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !           577:                                PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !           578:                                return 1;
        !           579:                        }
        !           580:                        
        !           581:                        /* get name of the column */
        !           582:                        PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid **)&colname, (ub4 *)&outcol->name_len, (ub4)OCI_ATTR_NAME, statement->err));
        !           583:                        
        !           584:                        if (statement->errcode != OCI_SUCCESS) {
        !           585:                                PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
        !           586:                                statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !           587:                                PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !           588:                                return 1;
        !           589:                        }
        !           590:                        PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
        !           591: 
        !           592:                        outcol->name = estrndup((char*) colname, outcol->name_len);
        !           593: 
        !           594:                        /* find a user-setted define */
        !           595:                        if (statement->defines) {
        !           596:                                if (zend_hash_find(statement->defines,outcol->name,outcol->name_len,(void **) &outcol->define) == SUCCESS) {
        !           597:                                        if (outcol->define->type) {
        !           598:                                                outcol->data_type = outcol->define->type;
        !           599:                                        }
        !           600:                                }
        !           601:                        }
        !           602: 
        !           603:                        buf = 0;
        !           604:                        switch (outcol->data_type) {
        !           605:                                case SQLT_RSET:
        !           606:                                        outcol->statement = statement; /* parent handle */
        !           607: 
        !           608:                                        define_type = SQLT_RSET;
        !           609:                                        outcol->is_cursor = 1;
        !           610:                                        outcol->statement->has_descr = 1;
        !           611:                                        outcol->storage_size4 = -1;
        !           612:                                        outcol->retlen = -1;
        !           613:                                        dynamic = OCI_DYNAMIC_FETCH;
        !           614:                                        break;
        !           615: 
        !           616:                                case SQLT_RDD:   /* ROWID */
        !           617:                                case SQLT_BLOB:  /* binary LOB */
        !           618:                                case SQLT_CLOB:  /* character LOB */
        !           619:                                case SQLT_BFILE: /* binary file LOB */
        !           620:                                        outcol->statement = statement; /* parent handle */
        !           621: 
        !           622:                                        define_type = outcol->data_type;
        !           623:                                        outcol->is_descr = 1;
        !           624:                                        outcol->statement->has_descr = 1;
        !           625:                                        outcol->storage_size4 = -1;
        !           626:                                        dynamic = OCI_DYNAMIC_FETCH;
        !           627:                                        break;
        !           628: 
        !           629:                                case SQLT_LNG:
        !           630:                                case SQLT_LBI:
        !           631:                                        if (outcol->data_type == SQLT_LBI) {
        !           632:                                                define_type = SQLT_BIN;
        !           633:                                        } else {
        !           634:                                                define_type = SQLT_CHR;
        !           635:                                        }
        !           636:                                        outcol->storage_size4 = PHP_OCI_MAX_DATA_SIZE;
        !           637:                                        outcol->piecewise = 1;
        !           638:                                        dynamic = OCI_DYNAMIC_FETCH;
        !           639:                                        break;
        !           640: 
        !           641:                                case SQLT_BIN:
        !           642:                                default:
        !           643:                                        define_type = SQLT_CHR;
        !           644:                                        if (outcol->data_type == SQLT_BIN) {
        !           645:                                                define_type = SQLT_BIN;
        !           646:                                        }
        !           647:                                        if ((outcol->data_type == SQLT_DAT) || (outcol->data_type == SQLT_NUM)
        !           648: #ifdef SQLT_TIMESTAMP
        !           649:                                                || (outcol->data_type == SQLT_TIMESTAMP)
        !           650: #endif
        !           651: #ifdef SQLT_TIMESTAMP_TZ
        !           652:                                                || (outcol->data_type == SQLT_TIMESTAMP_TZ)
        !           653: #endif
        !           654: #ifdef SQLT_TIMESTAMP_LTZ
        !           655:                                                || (outcol->data_type == SQLT_TIMESTAMP_LTZ)
        !           656: #endif
        !           657: #ifdef SQLT_INTERVAL_YM
        !           658:                                                || (outcol->data_type == SQLT_INTERVAL_YM)
        !           659: #endif
        !           660: #ifdef SQLT_INTERVAL_DS
        !           661:                                                || (outcol->data_type == SQLT_INTERVAL_DS)
        !           662: #endif
        !           663:                                                ) {
        !           664:                                                outcol->storage_size4 = 512; /* XXX this should fit "most" NLS date-formats and Numbers */
        !           665: #if defined(SQLT_IBFLOAT) && defined(SQLT_IBDOUBLE)
        !           666:                                        } else if (outcol->data_type == SQLT_IBFLOAT || outcol->data_type == SQLT_IBDOUBLE) {
        !           667:                                                outcol->storage_size4 = 1024;
        !           668: #endif
        !           669:                                        } else {
        !           670:                                                outcol->storage_size4++; /* add one for string terminator */
        !           671:                                        }
        !           672:                                        
        !           673:                                        outcol->storage_size4 *= 3;
        !           674:                                        
        !           675:                                        dynamic = OCI_DEFAULT;
        !           676:                                        buf = outcol->data = (text *) safe_emalloc(1, outcol->storage_size4, 0);
        !           677:                                        memset(buf, 0, outcol->storage_size4);
        !           678:                                        break;
        !           679:                        }
        !           680: 
        !           681:                        if (dynamic == OCI_DYNAMIC_FETCH) {
        !           682:                                PHP_OCI_CALL_RETURN(statement->errcode,
        !           683:                                        OCIDefineByPos,
        !           684:                                        (
        !           685:                                                statement->stmt,                                                        /* IN/OUT handle to the requested SQL query */
        !           686:                                                (OCIDefine **)&outcol->oci_define,                      /* IN/OUT pointer to a pointer to a define handle */
        !           687:                                                statement->err,                                                         /* IN/OUT An error handle  */
        !           688:                                                counter,                                                                        /* IN     position in the select list */
        !           689:                                                (dvoid *)NULL,                                                          /* IN/OUT pointer to a buffer */
        !           690:                                                outcol->storage_size4,                                          /* IN     The size of each valuep buffer in bytes */
        !           691:                                                define_type,                                                            /* IN     The data type */
        !           692:                                                (dvoid *)&outcol->indicator,                            /* IN     pointer to an indicator variable or arr */
        !           693:                                                (ub2 *)NULL,                                                            /* IN/OUT Pointer to array of length of data fetched */
        !           694:                                                (ub2 *)NULL,                                                            /* OUT    Pointer to array of column-level return codes */
        !           695:                                                OCI_DYNAMIC_FETCH                                                       /* IN     mode (OCI_DEFAULT, OCI_DYNAMIC_FETCH) */
        !           696:                                        )
        !           697:                                );
        !           698: 
        !           699:                        } else {
        !           700:                                PHP_OCI_CALL_RETURN(statement->errcode,
        !           701:                                        OCIDefineByPos,
        !           702:                                        (
        !           703:                                                statement->stmt,                                                        /* IN/OUT handle to the requested SQL query */
        !           704:                                                (OCIDefine **)&outcol->oci_define,                      /* IN/OUT pointer to a pointer to a define handle */
        !           705:                                                statement->err,                                                         /* IN/OUT An error handle  */
        !           706:                                                counter,                                                                        /* IN     position in the select list */
        !           707:                                                (dvoid *)buf,                                                           /* IN/OUT pointer to a buffer */
        !           708:                                                outcol->storage_size4,                                          /* IN     The size of each valuep buffer in bytes */
        !           709:                                                define_type,                                                            /* IN     The data type */
        !           710:                                                (dvoid *)&outcol->indicator,                            /* IN     pointer to an indicator variable or arr */
        !           711:                                                (ub2 *)&outcol->retlen,                                         /* IN/OUT Pointer to array of length of data fetched */
        !           712:                                                (ub2 *)&outcol->retcode,                                        /* OUT    Pointer to array of column-level return codes */
        !           713:                                                OCI_DEFAULT                                                                     /* IN     mode (OCI_DEFAULT, OCI_DYNAMIC_FETCH) */
        !           714:                                        )
        !           715:                                );
        !           716: 
        !           717:                        }
        !           718:                        
        !           719:                        if (statement->errcode != OCI_SUCCESS) {
        !           720:                                statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !           721:                                PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !           722:                                return 0;
        !           723:                        }
        !           724: 
        !           725:                        /* additional OCIDefineDynamic() call */
        !           726:                        switch (outcol->data_type) {
        !           727:                                case SQLT_RSET:
        !           728:                                case SQLT_RDD:
        !           729:                                case SQLT_BLOB:
        !           730:                                case SQLT_CLOB:
        !           731:                                case SQLT_BFILE:
        !           732:                                        PHP_OCI_CALL_RETURN(statement->errcode,
        !           733:                                                OCIDefineDynamic,
        !           734:                                                (
        !           735:                                                        outcol->oci_define,
        !           736:                                                        statement->err,
        !           737:                                                        (dvoid *)outcol,
        !           738:                                                        php_oci_define_callback
        !           739:                                                )
        !           740:                                        );
        !           741: 
        !           742:                                        break;
        !           743:                        }
        !           744:                }
        !           745:        }
        !           746: 
        !           747:        return 0;
        !           748: }
        !           749: /* }}} */
        !           750: 
        !           751: /* {{{ php_oci_statement_cancel()
        !           752:  Cancel statement */
        !           753: int php_oci_statement_cancel(php_oci_statement *statement TSRMLS_DC)
        !           754: {
        !           755:        
        !           756:        return php_oci_statement_fetch(statement, 0 TSRMLS_CC);
        !           757:                
        !           758: } /* }}} */
        !           759: 
        !           760: /* {{{ php_oci_statement_free()
        !           761:  Destroy statement handle and free associated resources */
        !           762: void php_oci_statement_free(php_oci_statement *statement TSRMLS_DC)
        !           763: {
        !           764:        if (statement->stmt) {
        !           765:                if (statement->last_query_len) { /* FIXME: magical */
        !           766:                        PHP_OCI_CALL(OCIStmtRelease, (statement->stmt, statement->err, NULL, 0, statement->errcode ? OCI_STRLS_CACHE_DELETE : OCI_DEFAULT));
        !           767:                } else {
        !           768:                        PHP_OCI_CALL(OCIHandleFree, (statement->stmt, OCI_HTYPE_STMT));
        !           769:                }
        !           770:                statement->stmt = 0;
        !           771:        }
        !           772: 
        !           773:        if (statement->err) {
        !           774:                PHP_OCI_CALL(OCIHandleFree, (statement->err, OCI_HTYPE_ERROR));
        !           775:                statement->err = 0;
        !           776:        }
        !           777: 
        !           778:        if (statement->last_query) {
        !           779:                efree(statement->last_query);
        !           780:        }
        !           781: 
        !           782:        if (statement->columns) {
        !           783:                zend_hash_destroy(statement->columns);
        !           784:                efree(statement->columns);
        !           785:        }
        !           786: 
        !           787:        if (statement->binds) {
        !           788:                zend_hash_destroy(statement->binds);
        !           789:                efree(statement->binds);
        !           790:        }
        !           791: 
        !           792:        if (statement->defines) {
        !           793:                zend_hash_destroy(statement->defines);
        !           794:                efree(statement->defines);
        !           795:        }
        !           796: 
        !           797:        if (statement->parent_stmtid) {
        !           798:                zend_list_delete(statement->parent_stmtid);
        !           799:        }
        !           800: 
        !           801:        zend_list_delete(statement->connection->rsrc_id);
        !           802:        efree(statement);
        !           803:        
        !           804:        OCI_G(num_statements)--;
        !           805: } /* }}} */
        !           806: 
        !           807: /* {{{ php_oci_bind_pre_exec()
        !           808:  Helper function */
        !           809: int php_oci_bind_pre_exec(void *data, void *result TSRMLS_DC)
        !           810: {
        !           811:        php_oci_bind *bind = (php_oci_bind *) data;
        !           812: 
        !           813:        *(int *)result = 0;
        !           814: 
        !           815:        if (Z_TYPE_P(bind->zval) == IS_ARRAY) {
        !           816:                /* These checks are currently valid for oci_bind_by_name, not
        !           817:                 * oci_bind_array_by_name.  Also bind->type and
        !           818:                 * bind->indicator are not used for oci_bind_array_by_name.
        !           819:                 */
        !           820:                return 0;
        !           821:        }       
        !           822:        switch (bind->type) {
        !           823:                case SQLT_NTY:
        !           824:                case SQLT_BFILEE:
        !           825:                case SQLT_CFILEE:
        !           826:                case SQLT_CLOB:
        !           827:                case SQLT_BLOB:
        !           828:                case SQLT_RDD:
        !           829:                        if (Z_TYPE_P(bind->zval) != IS_OBJECT) {
        !           830:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
        !           831:                                *(int *)result = 1;
        !           832:                        }
        !           833:                        break;
        !           834:                        
        !           835:                case SQLT_INT:
        !           836:                case SQLT_NUM:
        !           837:                        if (Z_TYPE_P(bind->zval) == IS_RESOURCE || Z_TYPE_P(bind->zval) == IS_OBJECT) {
        !           838:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
        !           839:                                *(int *)result = 1;
        !           840:                        }
        !           841:                        break;
        !           842:                        
        !           843:                case SQLT_LBI:
        !           844:                case SQLT_BIN:
        !           845:                case SQLT_LNG:
        !           846:                case SQLT_AFC:
        !           847:                case SQLT_CHR:
        !           848:                        if (Z_TYPE_P(bind->zval) == IS_RESOURCE || Z_TYPE_P(bind->zval) == IS_OBJECT) {
        !           849:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
        !           850:                                *(int *)result = 1;
        !           851:                        }
        !           852:                        break;
        !           853: 
        !           854:                case SQLT_RSET:
        !           855:                        if (Z_TYPE_P(bind->zval) != IS_RESOURCE) {
        !           856:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
        !           857:                                *(int *)result = 1;
        !           858:                        }
        !           859:                        break;
        !           860:        }
        !           861: 
        !           862:        /* reset all bind stuff to a normal state..-. */
        !           863:        bind->indicator = 0;
        !           864: 
        !           865:        return 0;
        !           866: }
        !           867: /* }}} */
        !           868: 
        !           869: /* {{{ php_oci_bind_post_exec()
        !           870:  Helper function */
        !           871: int php_oci_bind_post_exec(void *data TSRMLS_DC)
        !           872: {
        !           873:        php_oci_bind *bind = (php_oci_bind *) data;
        !           874:        php_oci_connection *connection = bind->parent_statement->connection;
        !           875: 
        !           876:        if (bind->indicator == -1) { /* NULL */
        !           877:                zval *val = bind->zval;
        !           878:                if (Z_TYPE_P(val) == IS_STRING) {
        !           879:                        *Z_STRVAL_P(val) = '\0'; /* XXX avoid warning in debug mode */
        !           880:                }
        !           881:                zval_dtor(val);
        !           882:                ZVAL_NULL(val);
        !           883:        } else if (Z_TYPE_P(bind->zval) == IS_STRING
        !           884:                           && Z_STRLEN_P(bind->zval) > 0
        !           885:                           && Z_STRVAL_P(bind->zval)[ Z_STRLEN_P(bind->zval) ] != '\0') {
        !           886:                /* The post- PHP 5.3 feature for "interned" strings disallows
        !           887:                 * their reallocation but (i) any IN binds either interned or
        !           888:                 * not should already be null terminated and (ii) for OUT
        !           889:                 * binds, php_oci_bind_out_callback() should have allocated a
        !           890:                 * new string that we can modify here.
        !           891:                 */
        !           892:                Z_STRVAL_P(bind->zval) = erealloc(Z_STRVAL_P(bind->zval), Z_STRLEN_P(bind->zval)+1);
        !           893:                Z_STRVAL_P(bind->zval)[ Z_STRLEN_P(bind->zval) ] = '\0';
        !           894:        } else if (Z_TYPE_P(bind->zval) == IS_ARRAY) {
        !           895:                int i;
        !           896:                zval **entry;
        !           897:                HashTable *hash = HASH_OF(bind->zval);
        !           898:        
        !           899:                zend_hash_internal_pointer_reset(hash);
        !           900: 
        !           901:                switch (bind->array.type) {
        !           902:                        case SQLT_NUM:
        !           903:                        case SQLT_INT:
        !           904:                        case SQLT_LNG:
        !           905:                                for (i = 0; i < bind->array.current_length; i++) {
        !           906:                                        if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
        !           907:                                                zval_dtor(*entry);
        !           908:                                                ZVAL_LONG(*entry, ((ub4 *)(bind->array.elements))[i]);
        !           909:                                                zend_hash_move_forward(hash);
        !           910:                                        } else {
        !           911:                                                add_next_index_long(bind->zval, ((ub4 *)(bind->array.elements))[i]);
        !           912:                                        }
        !           913:                                }
        !           914:                                break;
        !           915:                        case SQLT_FLT:
        !           916:                                for (i = 0; i < bind->array.current_length; i++) {
        !           917:                                        if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
        !           918:                                                zval_dtor(*entry);
        !           919:                                                ZVAL_DOUBLE(*entry, ((double *)(bind->array.elements))[i]);
        !           920:                                                zend_hash_move_forward(hash);
        !           921:                                        } else {
        !           922:                                                add_next_index_double(bind->zval, ((double *)(bind->array.elements))[i]);
        !           923:                                        }
        !           924:                                }
        !           925:                                break;
        !           926:                        case SQLT_ODT:
        !           927:                                for (i = 0; i < bind->array.current_length; i++) {
        !           928:                                        oratext buff[1024];
        !           929:                                        ub4 buff_len = 1024;
        !           930: 
        !           931:                                        memset((void*)buff,0,sizeof(buff));
        !           932:                                                        
        !           933:                                        if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
        !           934:                                                PHP_OCI_CALL_RETURN(connection->errcode, OCIDateToText, (connection->err, &(((OCIDate *)(bind->array.elements))[i]), 0, 0, 0, 0, &buff_len, buff));
        !           935:                                                zval_dtor(*entry);
        !           936: 
        !           937:                                                if (connection->errcode != OCI_SUCCESS) {
        !           938:                                                        connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
        !           939:                                                        PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
        !           940:                                                        ZVAL_NULL(*entry);
        !           941:                                                } else {
        !           942:                                                        ZVAL_STRINGL(*entry, (char *)buff, buff_len, 1);
        !           943:                                                }
        !           944:                                                zend_hash_move_forward(hash);
        !           945:                                        } else {
        !           946:                                                PHP_OCI_CALL_RETURN(connection->errcode, OCIDateToText, (connection->err, &(((OCIDate *)(bind->array.elements))[i]), 0, 0, 0, 0, &buff_len, buff));
        !           947:                                                if (connection->errcode != OCI_SUCCESS) {
        !           948:                                                        connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
        !           949:                                                        PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
        !           950:                                                        add_next_index_null(bind->zval);
        !           951:                                                } else {
        !           952:                                                        add_next_index_stringl(bind->zval, (char *)buff, buff_len, 1);
        !           953:                                                }
        !           954:                                        }
        !           955:                                }
        !           956:                                break;
        !           957:        
        !           958:                        case SQLT_AFC:
        !           959:                        case SQLT_CHR:
        !           960:                        case SQLT_VCS:
        !           961:                        case SQLT_AVC:
        !           962:                        case SQLT_STR:
        !           963:                        case SQLT_LVC:
        !           964:                                for (i = 0; i < bind->array.current_length; i++) {
        !           965:                                        /* int curr_element_length = strlen(((text *)bind->array.elements)+i*bind->array.max_length); */
        !           966:                                        int curr_element_length = bind->array.element_lengths[i];
        !           967:                                        if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
        !           968:                                                zval_dtor(*entry);
        !           969:                                                ZVAL_STRINGL(*entry, (char *)(((text *)bind->array.elements)+i*bind->array.max_length), curr_element_length, 1);
        !           970:                                                zend_hash_move_forward(hash);
        !           971:                                        } else {
        !           972:                                                add_next_index_stringl(bind->zval, (char *)(((text *)bind->array.elements)+i*bind->array.max_length), curr_element_length, 1);
        !           973:                                        }
        !           974:                                }
        !           975:                                break;
        !           976:                }
        !           977:        }
        !           978: 
        !           979:        return 0;
        !           980: }
        !           981: /* }}} */
        !           982: 
        !           983: /* {{{ php_oci_bind_by_name()
        !           984:  Bind zval to the given placeholder */
        !           985: int php_oci_bind_by_name(php_oci_statement *statement, char *name, int name_len, zval* var, long maxlength, ub2 type TSRMLS_DC)
        !           986: {
        !           987:        php_oci_collection *bind_collection = NULL;
        !           988:        php_oci_descriptor *bind_descriptor = NULL;
        !           989:        php_oci_statement  *bind_statement      = NULL;
        !           990:        dvoid *oci_desc                                 = NULL;
        !           991:        /* dvoid *php_oci_collection               = NULL; */
        !           992:        OCIStmt *oci_stmt                               = NULL;
        !           993:        dvoid *bind_data                                = NULL;
        !           994:        php_oci_bind bind, *old_bind, *bindp;
        !           995:        int mode = OCI_DATA_AT_EXEC;
        !           996:        sb4 value_sz = -1;
        !           997: 
        !           998:        switch (type) {
        !           999:                case SQLT_NTY:
        !          1000:                {
        !          1001:                        zval **tmp;
        !          1002:                        
        !          1003:                        if (Z_TYPE_P(var) != IS_OBJECT || zend_hash_find(Z_OBJPROP_P(var), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
        !          1004:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
        !          1005:                                return 1;
        !          1006:                        }
        !          1007: 
        !          1008:                        PHP_OCI_ZVAL_TO_COLLECTION_EX(*tmp, bind_collection);
        !          1009:                        value_sz = sizeof(void*);
        !          1010:                        mode = OCI_DEFAULT;
        !          1011:                
        !          1012:                        if (!bind_collection->collection) {
        !          1013:                                return 1;
        !          1014:                        }
        !          1015:                }
        !          1016:                        break;
        !          1017:                case SQLT_BFILEE:
        !          1018:                case SQLT_CFILEE:
        !          1019:                case SQLT_CLOB:
        !          1020:                case SQLT_BLOB:
        !          1021:                case SQLT_RDD:
        !          1022:                {
        !          1023:                        zval **tmp;
        !          1024:                        
        !          1025:                        if (Z_TYPE_P(var) != IS_OBJECT || zend_hash_find(Z_OBJPROP_P(var), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
        !          1026:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
        !          1027:                                return 1;
        !          1028:                        }
        !          1029: 
        !          1030:                        PHP_OCI_ZVAL_TO_DESCRIPTOR_EX(*tmp, bind_descriptor);
        !          1031: 
        !          1032:                        value_sz = sizeof(void*);
        !          1033:                        
        !          1034:                        oci_desc = bind_descriptor->descriptor;
        !          1035:                        
        !          1036:                        if (!oci_desc) {
        !          1037:                                return 1;
        !          1038:                        }
        !          1039:                }
        !          1040:                        break;
        !          1041:                        
        !          1042:                case SQLT_INT:
        !          1043:                case SQLT_NUM:
        !          1044:                        if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) {
        !          1045:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
        !          1046:                                return 1;
        !          1047:                        }
        !          1048:                        convert_to_long(var);
        !          1049:                        bind_data = (ub4 *)&Z_LVAL_P(var);
        !          1050:                        value_sz = sizeof(ub4);
        !          1051:                        mode = OCI_DEFAULT;
        !          1052:                        break;
        !          1053:                        
        !          1054:                case SQLT_LBI:
        !          1055:                case SQLT_BIN:
        !          1056:                case SQLT_LNG:
        !          1057:                case SQLT_AFC:
        !          1058:                case SQLT_CHR: /* SQLT_CHR is the default value when type was not specified */
        !          1059:                        if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) {
        !          1060:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
        !          1061:                                return 1;
        !          1062:                        }
        !          1063:                        if (Z_TYPE_P(var) != IS_NULL) {
        !          1064:                                convert_to_string(var);
        !          1065:                        }
        !          1066:                        if (maxlength == -1) {
        !          1067:                                value_sz = (Z_TYPE_P(var) == IS_STRING) ? Z_STRLEN_P(var) : 0;
        !          1068:                        } else {
        !          1069:                                value_sz = maxlength;
        !          1070:                        }
        !          1071:                        break;
        !          1072: 
        !          1073:                case SQLT_RSET:
        !          1074:                        if (Z_TYPE_P(var) != IS_RESOURCE) {
        !          1075:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
        !          1076:                                return 1;
        !          1077:                        }
        !          1078:                        PHP_OCI_ZVAL_TO_STATEMENT_EX(var, bind_statement);
        !          1079:                        value_sz = sizeof(void*);
        !          1080: 
        !          1081:                        oci_stmt = bind_statement->stmt;
        !          1082: 
        !          1083:                        if (!oci_stmt) {
        !          1084:                                return 1;
        !          1085:                        }
        !          1086:                        break;
        !          1087: 
        !          1088:                default:
        !          1089:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or unsupported datatype given: %d", (int)type);
        !          1090:                        return 1;
        !          1091:                        break;
        !          1092:        }
        !          1093:        
        !          1094:        if (value_sz == 0) {
        !          1095:                value_sz = 1;
        !          1096:        }
        !          1097:        
        !          1098:        if (!statement->binds) {
        !          1099:                ALLOC_HASHTABLE(statement->binds);
        !          1100:                zend_hash_init(statement->binds, 13, NULL, php_oci_bind_hash_dtor, 0);
        !          1101:        }
        !          1102: 
        !          1103:        memset((void*)&bind,0,sizeof(php_oci_bind));
        !          1104:        if (zend_hash_find(statement->binds, name, name_len + 1, (void **)&old_bind) == SUCCESS) {
        !          1105:                bindp = old_bind;
        !          1106:                if (bindp->zval) {
        !          1107:                        zval_ptr_dtor(&bindp->zval);
        !          1108:                }
        !          1109:        } else {
        !          1110:                zend_hash_update(statement->binds, name, name_len + 1, &bind, sizeof(php_oci_bind), (void **)&bindp);
        !          1111:        }
        !          1112:        
        !          1113:        bindp->descriptor = oci_desc;
        !          1114:        bindp->statement = oci_stmt;
        !          1115:        bindp->parent_statement = statement;
        !          1116:        bindp->zval = var;
        !          1117:        bindp->type = type;
        !          1118:        zval_add_ref(&var);
        !          1119:        
        !          1120:        PHP_OCI_CALL_RETURN(statement->errcode,
        !          1121:                OCIBindByName,
        !          1122:                (
        !          1123:                        statement->stmt,                                 /* statement handle */
        !          1124:                        (OCIBind **)&bindp->bind,                /* bind hdl (will alloc) */
        !          1125:                        statement->err,                                  /* error handle */
        !          1126:                        (text*) name,                                    /* placeholder name */                                 
        !          1127:                        name_len,                                                /* placeholder length */
        !          1128:                        (dvoid *)bind_data,                              /* in/out data */
        !          1129:                        value_sz, /* PHP_OCI_MAX_DATA_SIZE, */ /* max size of input/output data */
        !          1130:                        type,                                                    /* in/out data type */
        !          1131:                        (dvoid *)&bindp->indicator,              /* indicator (ignored) */
        !          1132:                        (ub2 *)0,                                                /* size array (ignored) */
        !          1133:                        (ub2 *)&bindp->retcode,                  /* return code (ignored) */
        !          1134:                        (ub4)0,                                                  /* maxarr_len (PL/SQL only?) */
        !          1135:                        (ub4 *)0,                                                /* actual array size (PL/SQL only?) */
        !          1136:                        mode                                                     /* mode */
        !          1137:                )
        !          1138:        );
        !          1139: 
        !          1140:        if (statement->errcode != OCI_SUCCESS) {
        !          1141:                statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !          1142:                PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !          1143:                return 1;
        !          1144:        }
        !          1145: 
        !          1146:        if (mode == OCI_DATA_AT_EXEC) {
        !          1147:                PHP_OCI_CALL_RETURN(statement->errcode, OCIBindDynamic,
        !          1148:                                (
        !          1149:                                 bindp->bind,
        !          1150:                                 statement->err,
        !          1151:                                 (dvoid *)bindp,
        !          1152:                                 php_oci_bind_in_callback,
        !          1153:                                 (dvoid *)bindp,
        !          1154:                                 php_oci_bind_out_callback
        !          1155:                                )
        !          1156:                );
        !          1157: 
        !          1158:                if (statement->errcode != OCI_SUCCESS) {
        !          1159:                        statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !          1160:                        PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !          1161:                        return 1;
        !          1162:                }
        !          1163:        }
        !          1164: 
        !          1165:        if (type == SQLT_NTY) {
        !          1166:                /* Bind object */
        !          1167:                PHP_OCI_CALL_RETURN(statement->errcode, OCIBindObject,
        !          1168:                                (
        !          1169:                                 bindp->bind,
        !          1170:                                 statement->err,
        !          1171:                                 bind_collection->tdo,
        !          1172:                                 (dvoid **) &(bind_collection->collection),
        !          1173:                                 (ub4 *) 0,
        !          1174:                                 (dvoid **) 0,
        !          1175:                                 (ub4 *) 0
        !          1176:                                )
        !          1177:                );
        !          1178:                
        !          1179:                if (statement->errcode) {
        !          1180:                        statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !          1181:                        PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !          1182:                        return 1;
        !          1183:                }
        !          1184:        }
        !          1185:        
        !          1186:        return 0;
        !          1187: } /* }}} */
        !          1188: 
        !          1189: /* {{{ php_oci_bind_in_callback()
        !          1190:  Callback used when binding LOBs and VARCHARs */
        !          1191: sb4 php_oci_bind_in_callback(
        !          1192:                                        dvoid *ictxp,     /* context pointer */
        !          1193:                                        OCIBind *bindp,   /* bind handle */
        !          1194:                                        ub4 iter,                 /* 0-based execute iteration value */
        !          1195:                                        ub4 index,                /* index of current array for PL/SQL or row index for SQL */
        !          1196:                                        dvoid **bufpp,    /* pointer to data */
        !          1197:                                        ub4 *alenp,               /* size after value/piece has been read */
        !          1198:                                        ub1 *piecep,      /* which piece */
        !          1199:                                        dvoid **indpp)    /* indicator value */
        !          1200: {
        !          1201:        php_oci_bind *phpbind;
        !          1202:        zval *val;
        !          1203:        TSRMLS_FETCH();
        !          1204: 
        !          1205:        if (!(phpbind=(php_oci_bind *)ictxp) || !(val = phpbind->zval)) {
        !          1206:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid phpbind pointer value");
        !          1207:                return OCI_ERROR;
        !          1208:        }
        !          1209: 
        !          1210:        if (ZVAL_IS_NULL(val)) {
        !          1211:                /* we're going to insert a NULL column */
        !          1212:                phpbind->indicator = -1;
        !          1213:                *bufpp = 0;
        !          1214:                *alenp = -1;
        !          1215:                *indpp = (dvoid *)&phpbind->indicator;
        !          1216:        } else  if ((phpbind->descriptor == 0) && (phpbind->statement == 0)) {
        !          1217:                /* "normal string bind */
        !          1218:                convert_to_string(val);
        !          1219: 
        !          1220:                *bufpp = Z_STRVAL_P(val);
        !          1221:                *alenp = Z_STRLEN_P(val);
        !          1222:                *indpp = (dvoid *)&phpbind->indicator;
        !          1223:        } else if (phpbind->statement != 0) {
        !          1224:                /* RSET */
        !          1225:                *bufpp = phpbind->statement;
        !          1226:                *alenp = -1;            /* seems to be allright */
        !          1227:                *indpp = (dvoid *)&phpbind->indicator;
        !          1228:        } else {
        !          1229:                /* descriptor bind */
        !          1230:                *bufpp = phpbind->descriptor;
        !          1231:                *alenp = -1;            /* seems to be allright */
        !          1232:                *indpp = (dvoid *)&phpbind->indicator;
        !          1233:        }
        !          1234: 
        !          1235:        *piecep = OCI_ONE_PIECE; /* pass all data in one go */
        !          1236: 
        !          1237:        return OCI_CONTINUE;
        !          1238: }/* }}} */
        !          1239: 
        !          1240: /* {{{ php_oci_bind_out_callback()
        !          1241:  Callback used when binding LOBs and VARCHARs */
        !          1242: sb4 php_oci_bind_out_callback(
        !          1243:                                        dvoid *octxp,      /* context pointer */
        !          1244:                                        OCIBind *bindp,    /* bind handle */
        !          1245:                                        ub4 iter,                  /* 0-based execute iteration value */
        !          1246:                                        ub4 index,                 /* index of current array for PL/SQL or row index for SQL */
        !          1247:                                        dvoid **bufpp,     /* pointer to data */
        !          1248:                                        ub4 **alenpp,      /* size after value/piece has been read */
        !          1249:                                        ub1 *piecep,       /* which piece */
        !          1250:                                        dvoid **indpp,     /* indicator value */
        !          1251:                                        ub2 **rcodepp)     /* return code */
        !          1252: {
        !          1253:        php_oci_bind *phpbind;
        !          1254:        zval *val;
        !          1255:        sb4 retval = OCI_ERROR;
        !          1256:        TSRMLS_FETCH();
        !          1257: 
        !          1258:        if (!(phpbind=(php_oci_bind *)octxp) || !(val = phpbind->zval)) {
        !          1259:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid phpbind pointer value");
        !          1260:                return retval;
        !          1261:        }
        !          1262: 
        !          1263:        if (Z_TYPE_P(val) == IS_RESOURCE) {
        !          1264:                /* Processing for ref-cursor out binds */
        !          1265:                if (phpbind->statement != NULL) {
        !          1266:                        *bufpp = phpbind->statement;
        !          1267:                        *alenpp = &phpbind->dummy_len;
        !          1268:                        *piecep = OCI_ONE_PIECE;
        !          1269:                        *rcodepp = &phpbind->retcode;
        !          1270:                        *indpp = &phpbind->indicator;
        !          1271:                }
        !          1272:                retval = OCI_CONTINUE;
        !          1273:        } else if (Z_TYPE_P(val) == IS_OBJECT) {
        !          1274:                zval **tmp;
        !          1275:                php_oci_descriptor *desc;
        !          1276: 
        !          1277:                if (!phpbind->descriptor) {
        !          1278:                        return OCI_ERROR;
        !          1279:                }
        !          1280: 
        !          1281:                /* Do not use the cached lob size if the descriptor is an
        !          1282:                 * out-bind as the contents would have been changed for in/out
        !          1283:                 * binds (Bug #46994).
        !          1284:                 */
        !          1285:                if (zend_hash_find(Z_OBJPROP_P(val), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
        !          1286:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find object outbind descriptor property");
        !          1287:                        return OCI_ERROR;
        !          1288:                }
        !          1289:                PHP_OCI_ZVAL_TO_DESCRIPTOR_EX(*tmp, desc);
        !          1290:                desc->lob_size = -1;    /* force OCI8 to update cached size */
        !          1291: 
        !          1292:                *alenpp = &phpbind->dummy_len;
        !          1293:                *bufpp = phpbind->descriptor;
        !          1294:                *piecep = OCI_ONE_PIECE;
        !          1295:                *rcodepp = &phpbind->retcode;
        !          1296:                *indpp = &phpbind->indicator;
        !          1297:                retval = OCI_CONTINUE;
        !          1298:        } else {
        !          1299:                convert_to_string(val);
        !          1300:                zval_dtor(val);
        !          1301:                
        !          1302:                Z_STRLEN_P(val) = PHP_OCI_PIECE_SIZE; /* 64K-1 is max XXX */
        !          1303:                Z_STRVAL_P(val) = ecalloc(1, Z_STRLEN_P(phpbind->zval) + 1);
        !          1304:                
        !          1305:                /* XXX we assume that zend-zval len has 4 bytes */
        !          1306:                *alenpp = (ub4*) &Z_STRLEN_P(phpbind->zval);
        !          1307:                *bufpp = Z_STRVAL_P(phpbind->zval);
        !          1308:                *piecep = OCI_ONE_PIECE;
        !          1309:                *rcodepp = &phpbind->retcode;
        !          1310:                *indpp = &phpbind->indicator;
        !          1311:                retval = OCI_CONTINUE;
        !          1312:        }
        !          1313: 
        !          1314:        return retval;
        !          1315: }
        !          1316: /* }}} */
        !          1317: 
        !          1318: /* {{{ php_oci_statement_get_column_helper()
        !          1319:  Helper function to get column by name and index */
        !          1320: php_oci_out_column *php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAMETERS, int need_data)
        !          1321: {
        !          1322:        zval *z_statement, *column_index;
        !          1323:        php_oci_statement *statement;
        !          1324:        php_oci_out_column *column;
        !          1325: 
        !          1326:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &z_statement, &column_index) == FAILURE) {
        !          1327:                return NULL;
        !          1328:        }
        !          1329: 
        !          1330:        statement = (php_oci_statement *) zend_fetch_resource(&z_statement TSRMLS_CC, -1, "oci8 statement", NULL, 1, le_statement);
        !          1331: 
        !          1332:        if (!statement) {
        !          1333:                return NULL;
        !          1334:        }
        !          1335: 
        !          1336:        if (need_data && !statement->has_data) {
        !          1337:                return NULL;
        !          1338:        }
        !          1339:        
        !          1340:        if (Z_TYPE_P(column_index) == IS_STRING) {
        !          1341:                column = php_oci_statement_get_column(statement, -1, Z_STRVAL_P(column_index), Z_STRLEN_P(column_index) TSRMLS_CC);
        !          1342:                if (!column) {
        !          1343:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid column name \"%s\"", Z_STRVAL_P(column_index));
        !          1344:                        return NULL;
        !          1345:                }
        !          1346:        } else {
        !          1347:                zval tmp;
        !          1348:                /* NB: for PHP4 compat only, it should be using 'Z' instead */
        !          1349:                tmp = *column_index;
        !          1350:                zval_copy_ctor(&tmp);
        !          1351:                convert_to_long(&tmp);
        !          1352:                column = php_oci_statement_get_column(statement, Z_LVAL(tmp), NULL, 0 TSRMLS_CC);
        !          1353:                if (!column) {
        !          1354:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid column index \"%ld\"", Z_LVAL(tmp));
        !          1355:                        zval_dtor(&tmp);
        !          1356:                        return NULL;
        !          1357:                }
        !          1358:                zval_dtor(&tmp);
        !          1359:        }
        !          1360:        return column;
        !          1361: } /* }}} */
        !          1362: 
        !          1363: /* {{{ php_oci_statement_get_type()
        !          1364:  Return type of the statement */
        !          1365: int php_oci_statement_get_type(php_oci_statement *statement, ub2 *type TSRMLS_DC)
        !          1366: {
        !          1367:        ub2 statement_type;
        !          1368:        
        !          1369:        *type = 0;
        !          1370:        
        !          1371:        PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)&statement_type, (ub4 *)0, OCI_ATTR_STMT_TYPE, statement->err));
        !          1372: 
        !          1373:        if (statement->errcode != OCI_SUCCESS) {
        !          1374:                statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !          1375:                PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !          1376:                return 1;
        !          1377:        }
        !          1378: 
        !          1379:        *type = statement_type;
        !          1380: 
        !          1381:        return 0;
        !          1382: } /* }}} */
        !          1383: 
        !          1384: /* {{{ php_oci_statement_get_numrows()
        !          1385:  Get the number of rows fetched to the clientside (NOT the number of rows in the result set) */
        !          1386: int php_oci_statement_get_numrows(php_oci_statement *statement, ub4 *numrows TSRMLS_DC)
        !          1387: {
        !          1388:        ub4 statement_numrows;
        !          1389:        
        !          1390:        *numrows = 0;
        !          1391:        
        !          1392:        PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub4 *)&statement_numrows, (ub4 *)0, OCI_ATTR_ROW_COUNT, statement->err));
        !          1393: 
        !          1394:        if (statement->errcode != OCI_SUCCESS) {
        !          1395:                statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !          1396:                PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !          1397:                return 1;
        !          1398:        }
        !          1399: 
        !          1400:        *numrows = statement_numrows;
        !          1401: 
        !          1402:        return 0;
        !          1403: } /* }}} */
        !          1404: 
        !          1405: /* {{{ php_oci_bind_array_by_name()
        !          1406:  Bind arrays to PL/SQL types */
        !          1407: int php_oci_bind_array_by_name(php_oci_statement *statement, char *name, int name_len, zval* var, long max_table_length, long maxlength, long type TSRMLS_DC)
        !          1408: {
        !          1409:        php_oci_bind *bind, *bindp;
        !          1410: 
        !          1411:        convert_to_array(var);
        !          1412: 
        !          1413:        if (maxlength < -1) {
        !          1414:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid max length value (%ld)", maxlength);
        !          1415:                return 1;
        !          1416:        }
        !          1417:        
        !          1418:        switch(type) {
        !          1419:                case SQLT_NUM:
        !          1420:                case SQLT_INT:
        !          1421:                case SQLT_LNG:
        !          1422:                        bind = php_oci_bind_array_helper_number(var, max_table_length TSRMLS_CC);
        !          1423:                        break;
        !          1424: 
        !          1425:                case SQLT_FLT:
        !          1426:                        bind = php_oci_bind_array_helper_double(var, max_table_length TSRMLS_CC);
        !          1427:                        break;
        !          1428:                        
        !          1429:                case SQLT_AFC:
        !          1430:                case SQLT_CHR:
        !          1431:                case SQLT_VCS:
        !          1432:                case SQLT_AVC:
        !          1433:                case SQLT_STR:
        !          1434:                case SQLT_LVC:
        !          1435:                        if (maxlength == -1 && zend_hash_num_elements(Z_ARRVAL_P(var)) == 0) {
        !          1436:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must provide max length value for empty arrays");
        !          1437:                                return 1;
        !          1438:                        }
        !          1439:                        bind = php_oci_bind_array_helper_string(var, max_table_length, maxlength TSRMLS_CC);
        !          1440:                        break;
        !          1441:                case SQLT_ODT:
        !          1442:                        bind = php_oci_bind_array_helper_date(var, max_table_length, statement->connection TSRMLS_CC);
        !          1443:                        break;
        !          1444:                default:
        !          1445:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or unsupported datatype given: %ld", type);
        !          1446:                        return 1;
        !          1447:                        break;
        !          1448:        }
        !          1449: 
        !          1450:        if (bind == NULL) {
        !          1451:                /* failed to generate bind struct */
        !          1452:                return 1;
        !          1453:        }
        !          1454:        
        !          1455:        if (!statement->binds) {
        !          1456:                ALLOC_HASHTABLE(statement->binds);
        !          1457:                zend_hash_init(statement->binds, 13, NULL, php_oci_bind_hash_dtor, 0);
        !          1458:        }
        !          1459: 
        !          1460:        zend_hash_update(statement->binds, name, name_len + 1, bind, sizeof(php_oci_bind), (void **)&bindp);
        !          1461: 
        !          1462:        bindp->descriptor = NULL;
        !          1463:        bindp->statement = NULL;
        !          1464:        bindp->parent_statement = statement;
        !          1465:        bindp->bind = NULL;
        !          1466:        bindp->zval = var;
        !          1467:        bindp->array.type = type;
        !          1468:        bindp->indicator = 0;           /* not used for array binds */
        !          1469:        bindp->type = 0;                        /* not used for array binds */
        !          1470: 
        !          1471:        zval_add_ref(&var);
        !          1472: 
        !          1473:        PHP_OCI_CALL_RETURN(statement->errcode,
        !          1474:                                                        OCIBindByName,
        !          1475:                                                        (
        !          1476:                                                                statement->stmt,
        !          1477:                                                                (OCIBind **)&bindp->bind,
        !          1478:                                                                statement->err,
        !          1479:                                                                (text *)name,
        !          1480:                                                                name_len,
        !          1481:                                                                (dvoid *) bindp->array.elements,
        !          1482:                                                                (sb4) bind->array.max_length,
        !          1483:                                                                (ub2)type,
        !          1484:                                                                (dvoid *)bindp->array.indicators,
        !          1485:                                                                (ub2 *)bind->array.element_lengths,
        !          1486:                                                                (ub2 *)0, /* bindp->array.retcodes, */
        !          1487:                                                                (ub4) max_table_length,
        !          1488:                                                                (ub4 *) &(bindp->array.current_length),
        !          1489:                                                                (ub4) OCI_DEFAULT
        !          1490:                                                        )
        !          1491:                                                );
        !          1492:        
        !          1493:                
        !          1494:        if (statement->errcode != OCI_SUCCESS) {
        !          1495:                efree(bind);
        !          1496:                statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
        !          1497:                PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
        !          1498:                return 1;
        !          1499:        }
        !          1500:        efree(bind);
        !          1501:        return 0;
        !          1502: } /* }}} */
        !          1503: 
        !          1504: /* {{{ php_oci_bind_array_helper_string()
        !          1505:  Bind arrays to PL/SQL types */
        !          1506: php_oci_bind *php_oci_bind_array_helper_string(zval* var, long max_table_length, long maxlength TSRMLS_DC)
        !          1507: {
        !          1508:        php_oci_bind *bind;
        !          1509:        ub4 i;
        !          1510:        HashTable *hash;
        !          1511:        zval **entry;
        !          1512: 
        !          1513:        hash = HASH_OF(var);
        !          1514: 
        !          1515:        if (maxlength == -1) {
        !          1516:                zend_hash_internal_pointer_reset(hash);
        !          1517:                while (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE) {
        !          1518:                        convert_to_string_ex(entry);
        !          1519:                        if (Z_STRLEN_PP(entry) > maxlength) {
        !          1520:                                maxlength = Z_STRLEN_PP(entry) + 1;
        !          1521:                        }
        !          1522:                        zend_hash_move_forward(hash);
        !          1523:                }
        !          1524:        }
        !          1525:        
        !          1526:        bind = emalloc(sizeof(php_oci_bind));
        !          1527:        bind->array.elements            = (text *)safe_emalloc(max_table_length * (maxlength + 1), sizeof(text), 0);
        !          1528:        memset(bind->array.elements, 0, max_table_length * (maxlength + 1) * sizeof(text));
        !          1529:        bind->array.current_length      = zend_hash_num_elements(Z_ARRVAL_P(var));
        !          1530:        bind->array.old_length          = bind->array.current_length;
        !          1531:        bind->array.max_length          = maxlength;
        !          1532:        bind->array.element_lengths     = safe_emalloc(max_table_length, sizeof(ub2), 0);
        !          1533:        memset(bind->array.element_lengths, 0, max_table_length*sizeof(ub2));
        !          1534:        bind->array.indicators          = safe_emalloc(max_table_length, sizeof(sb2), 0);
        !          1535:        memset(bind->array.indicators, 0, max_table_length*sizeof(sb2));
        !          1536:        
        !          1537:        zend_hash_internal_pointer_reset(hash);
        !          1538:        
        !          1539:        for (i = 0; i < bind->array.current_length; i++) {
        !          1540:                if (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE) {
        !          1541:                        convert_to_string_ex(entry);
        !          1542:                        bind->array.element_lengths[i] = Z_STRLEN_PP(entry);
        !          1543:                        if (Z_STRLEN_PP(entry) == 0) {
        !          1544:                                bind->array.indicators[i] = -1;
        !          1545:                        }
        !          1546:                        zend_hash_move_forward(hash);
        !          1547:                } else {
        !          1548:                        break;
        !          1549:                }
        !          1550:        }
        !          1551: 
        !          1552:        zend_hash_internal_pointer_reset(hash);
        !          1553:        for (i = 0; i < max_table_length; i++) {
        !          1554:                if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
        !          1555:                        int element_length;
        !          1556:                        
        !          1557:                        convert_to_string_ex(entry);
        !          1558:                        element_length = (maxlength > Z_STRLEN_PP(entry)) ? Z_STRLEN_PP(entry) : maxlength;
        !          1559:                        
        !          1560:                        memcpy((text *)bind->array.elements + i*maxlength, Z_STRVAL_PP(entry), element_length);
        !          1561:                        ((text *)bind->array.elements)[i*maxlength + element_length] = '\0';
        !          1562:                        
        !          1563:                        zend_hash_move_forward(hash);
        !          1564:                } else {
        !          1565:                        ((text *)bind->array.elements)[i*maxlength] = '\0';
        !          1566:                }
        !          1567:        }
        !          1568:        zend_hash_internal_pointer_reset(hash);
        !          1569: 
        !          1570:        return bind;
        !          1571: } /* }}} */
        !          1572: 
        !          1573: /* {{{ php_oci_bind_array_helper_number()
        !          1574:  Bind arrays to PL/SQL types */
        !          1575: php_oci_bind *php_oci_bind_array_helper_number(zval* var, long max_table_length TSRMLS_DC)
        !          1576: {
        !          1577:        php_oci_bind *bind;
        !          1578:        ub4 i;
        !          1579:        HashTable *hash;
        !          1580:        zval **entry;
        !          1581: 
        !          1582:        hash = HASH_OF(var);
        !          1583: 
        !          1584:        bind = emalloc(sizeof(php_oci_bind));
        !          1585:        bind->array.elements            = (ub4 *)safe_emalloc(max_table_length, sizeof(ub4), 0);
        !          1586:        bind->array.current_length      = zend_hash_num_elements(Z_ARRVAL_P(var));
        !          1587:        bind->array.old_length          = bind->array.current_length;
        !          1588:        bind->array.max_length          = sizeof(ub4);
        !          1589:        bind->array.element_lengths     = safe_emalloc(max_table_length, sizeof(ub2), 0);
        !          1590:        memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
        !          1591:        bind->array.indicators          = NULL;
        !          1592:        
        !          1593:        zend_hash_internal_pointer_reset(hash);
        !          1594:        for (i = 0; i < max_table_length; i++) {
        !          1595:                if (i < bind->array.current_length) {
        !          1596:                        bind->array.element_lengths[i] = sizeof(ub4);
        !          1597:                }
        !          1598:                if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
        !          1599:                        convert_to_long_ex(entry);
        !          1600:                        ((ub4 *)bind->array.elements)[i] = (ub4) Z_LVAL_PP(entry);
        !          1601:                        zend_hash_move_forward(hash);
        !          1602:                } else {
        !          1603:                        ((ub4 *)bind->array.elements)[i] = 0;
        !          1604:                }
        !          1605:        }
        !          1606:        zend_hash_internal_pointer_reset(hash);
        !          1607: 
        !          1608:        return bind;
        !          1609: } /* }}} */
        !          1610: 
        !          1611: /* {{{ php_oci_bind_array_helper_double()
        !          1612:  Bind arrays to PL/SQL types */
        !          1613: php_oci_bind *php_oci_bind_array_helper_double(zval* var, long max_table_length TSRMLS_DC)
        !          1614: {
        !          1615:        php_oci_bind *bind;
        !          1616:        ub4 i;
        !          1617:        HashTable *hash;
        !          1618:        zval **entry;
        !          1619: 
        !          1620:        hash = HASH_OF(var);
        !          1621: 
        !          1622:        bind = emalloc(sizeof(php_oci_bind));
        !          1623:        bind->array.elements            = (double *)safe_emalloc(max_table_length, sizeof(double), 0);
        !          1624:        bind->array.current_length      = zend_hash_num_elements(Z_ARRVAL_P(var));
        !          1625:        bind->array.old_length          = bind->array.current_length;
        !          1626:        bind->array.max_length          = sizeof(double);
        !          1627:        bind->array.element_lengths     = safe_emalloc(max_table_length, sizeof(ub2), 0);
        !          1628:        memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
        !          1629:        bind->array.indicators          = NULL;
        !          1630:        
        !          1631:        zend_hash_internal_pointer_reset(hash);
        !          1632:        for (i = 0; i < max_table_length; i++) {
        !          1633:                if (i < bind->array.current_length) {
        !          1634:                        bind->array.element_lengths[i] = sizeof(double);
        !          1635:                }
        !          1636:                if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
        !          1637:                        convert_to_double_ex(entry);
        !          1638:                        ((double *)bind->array.elements)[i] = (double) Z_DVAL_PP(entry);
        !          1639:                        zend_hash_move_forward(hash);
        !          1640:                } else {
        !          1641:                        ((double *)bind->array.elements)[i] = 0;
        !          1642:                }
        !          1643:        }
        !          1644:        zend_hash_internal_pointer_reset(hash);
        !          1645: 
        !          1646:        return bind;
        !          1647: } /* }}} */
        !          1648: 
        !          1649: /* {{{ php_oci_bind_array_helper_date()
        !          1650:  Bind arrays to PL/SQL types */
        !          1651: php_oci_bind *php_oci_bind_array_helper_date(zval* var, long max_table_length, php_oci_connection *connection TSRMLS_DC)
        !          1652: {
        !          1653:        php_oci_bind *bind;
        !          1654:        ub4 i;
        !          1655:        HashTable *hash;
        !          1656:        zval **entry;
        !          1657: 
        !          1658:        hash = HASH_OF(var);
        !          1659: 
        !          1660:        bind = emalloc(sizeof(php_oci_bind));
        !          1661:        bind->array.elements            = (OCIDate *)safe_emalloc(max_table_length, sizeof(OCIDate), 0);
        !          1662:        bind->array.current_length      = zend_hash_num_elements(Z_ARRVAL_P(var));
        !          1663:        bind->array.old_length          = bind->array.current_length;
        !          1664:        bind->array.max_length          = sizeof(OCIDate);
        !          1665:        bind->array.element_lengths     = safe_emalloc(max_table_length, sizeof(ub2), 0);
        !          1666:        memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
        !          1667:        bind->array.indicators          = NULL;
        !          1668: 
        !          1669:        zend_hash_internal_pointer_reset(hash);
        !          1670:        for (i = 0; i < max_table_length; i++) {
        !          1671:                OCIDate oci_date;
        !          1672:                if (i < bind->array.current_length) {
        !          1673:                        bind->array.element_lengths[i] = sizeof(OCIDate);
        !          1674:                }
        !          1675:                if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
        !          1676:                        
        !          1677:                        convert_to_string_ex(entry);
        !          1678:                        PHP_OCI_CALL_RETURN(connection->errcode, OCIDateFromText, (connection->err, (CONST text *)Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), NULL, 0, NULL, 0, &oci_date));
        !          1679: 
        !          1680:                        if (connection->errcode != OCI_SUCCESS) {
        !          1681:                                /* failed to convert string to date */
        !          1682:                                efree(bind->array.element_lengths);
        !          1683:                                efree(bind->array.elements);
        !          1684:                                efree(bind);
        !          1685:                                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
        !          1686:                                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
        !          1687:                                return NULL;
        !          1688:                        }
        !          1689:                        
        !          1690:                        ((OCIDate *)bind->array.elements)[i] = oci_date;
        !          1691:                        zend_hash_move_forward(hash);
        !          1692:                } else {
        !          1693:                        PHP_OCI_CALL_RETURN(connection->errcode, OCIDateFromText, (connection->err, (CONST text *)"01-JAN-00", sizeof("01-JAN-00")-1, NULL, 0, NULL, 0, &oci_date));
        !          1694: 
        !          1695:                        if (connection->errcode != OCI_SUCCESS) {
        !          1696:                                /* failed to convert string to date */
        !          1697:                                efree(bind->array.element_lengths);
        !          1698:                                efree(bind->array.elements);
        !          1699:                                efree(bind);
        !          1700:                                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
        !          1701:                                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
        !          1702:                                return NULL;
        !          1703:                        }
        !          1704:        
        !          1705:                        ((OCIDate *)bind->array.elements)[i] = oci_date;
        !          1706:                }
        !          1707:        }
        !          1708:        zend_hash_internal_pointer_reset(hash);
        !          1709: 
        !          1710:        return bind;
        !          1711: } /* }}} */
        !          1712: 
        !          1713: #endif /* HAVE_OCI8 */
        !          1714: 
        !          1715: /*
        !          1716:  * Local variables:
        !          1717:  * tab-width: 4
        !          1718:  * c-basic-offset: 4
        !          1719:  * End:
        !          1720:  * vim600: noet sw=4 ts=4 fdm=marker
        !          1721:  * vim<600: noet sw=4 ts=4
        !          1722:  */

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