Annotation of embedaddon/php/ext/oci8/oci8_statement.c, revision 1.1.1.2

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: 
1.1.1.2 ! misho      28: /* $Id$ */
1.1       misho      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>