PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/oci8 - oci8_statement.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 664 772 86.0 %
Date: 2014-08-30 Functions: 22 22 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 5                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2014 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Stig Sæther Bakken <ssb@php.net>                            |
      16             :    |          Thies C. Arntzen <thies@thieso.net>                         |
      17             :    |                                                                      |
      18             :    | Collection support by Andy Sautins <asautins@veripost.net>           |
      19             :    | Temporary LOB support by David Benson <dbenson@mancala.com>          |
      20             :    | ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at>        |
      21             :    |                                                                      |
      22             :    | Redesigned by: Antony Dovgal <antony@zend.com>                       |
      23             :    |                Andi Gutmans <andi@zend.com>                          |
      24             :    |                Wez Furlong <wez@omniti.com>                          |
      25             :    +----------------------------------------------------------------------+
      26             : */
      27             : 
      28             : /* $Id$ */
      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       34479 : 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       34479 :         statement = ecalloc(1,sizeof(php_oci_statement));
      51             : 
      52       34479 :         if (!query_len) {
      53             :                 /* do not allocate stmt handle for refcursors, we'll get it from OCIStmtPrepare2() */
      54        1445 :                 PHP_OCI_CALL(OCIHandleAlloc, (connection->env, (dvoid **)&(statement->stmt), OCI_HTYPE_STMT, 0, NULL));
      55             :         }
      56             :                         
      57       34479 :         PHP_OCI_CALL(OCIHandleAlloc, (connection->env, (dvoid **)&(statement->err), OCI_HTYPE_ERROR, 0, NULL));
      58             :         
      59       34479 :         if (query_len > 0) {
      60       33034 :                 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       33034 :                 if (connection->errcode != OCI_SUCCESS) {
      74           5 :                         connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
      75             : 
      76           5 :                         PHP_OCI_CALL(OCIStmtRelease, (statement->stmt, statement->err, NULL, 0, statement->errcode ? OCI_STRLS_CACHE_DELETE : OCI_DEFAULT));
      77           5 :                         PHP_OCI_CALL(OCIHandleFree,(statement->err, OCI_HTYPE_ERROR));
      78             :                         
      79           5 :                         efree(statement);
      80           5 :                         PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
      81           5 :                         return NULL;
      82             :                 }
      83             :         }
      84             :         
      85       67503 :         if (query && query_len) {
      86       33029 :                 statement->last_query = estrndup(query, query_len);
      87       33029 :                 statement->last_query_len = query_len;
      88             :         }
      89             :         else {
      90        1445 :                 statement->last_query = NULL;
      91        1445 :                 statement->last_query_len = 0;
      92             :         }
      93             : 
      94       34474 :         statement->connection = connection;
      95       34474 :         statement->has_data = 0;
      96       34474 :         statement->has_descr = 0;
      97       34474 :         statement->parent_stmtid = 0;
      98       34474 :         zend_list_addref(statement->connection->rsrc_id);
      99             : 
     100       34474 :         if (OCI_G(default_prefetch) >= 0) {
     101       34474 :                 php_oci_statement_set_prefetch(statement, OCI_G(default_prefetch) TSRMLS_CC);
     102             :         }
     103             :         
     104       34474 :         PHP_OCI_REGISTER_RESOURCE(statement, le_statement);
     105             : 
     106       34474 :         OCI_G(num_statements)++;
     107             :         
     108       34474 :         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       34492 : int php_oci_statement_set_prefetch(php_oci_statement *statement, long size TSRMLS_DC)
     115             : {
     116       34492 :         ub4 prefetch = size;
     117             : 
     118       34492 :         if (size < 0) {
     119           2 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of rows to be prefetched has to be greater than or equal to 0");
     120           2 :                 return 1;
     121             :         }
     122             :         
     123       34490 :         PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrSet, (statement->stmt, OCI_HTYPE_STMT, &prefetch, 0, OCI_ATTR_PREFETCH_ROWS, statement->err));
     124             :         
     125       34490 :         if (statement->errcode != OCI_SUCCESS) {
     126           0 :                 statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
     127           0 :                 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
     128           0 :                 return 1;
     129             :         }
     130             : 
     131       34490 :         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      445256 : int php_oci_cleanup_pre_fetch(void *data TSRMLS_DC)
     138             : {
     139      445256 :         php_oci_out_column *outcol = data;
     140             : 
     141      445256 :         if (!outcol->is_descr && !outcol->is_cursor)
     142      100306 :                 return ZEND_HASH_APPLY_KEEP;
     143             : 
     144      344950 :         switch(outcol->data_type) {
     145             :                 case SQLT_CLOB:
     146             :                 case SQLT_BLOB:
     147             :                 case SQLT_RDD:
     148             :                 case SQLT_BFILE:
     149      343524 :                         if (outcol->descid) {
     150      283363 :                                 zend_list_delete(outcol->descid);
     151      283363 :                                 outcol->descid = 0;
     152             :                         }
     153      343524 :                         break;
     154             :                 case SQLT_RSET:
     155        1426 :                         if (outcol->stmtid) {
     156          16 :                                 zend_list_delete(outcol->stmtid);
     157          16 :                                 outcol->stmtid = 0;
     158          16 :                                 outcol->nested_statement = NULL;
     159             :                         }
     160             :                         break;
     161             :                 default:
     162             :                         break;
     163             :         }
     164      344950 :         return ZEND_HASH_APPLY_KEEP;
     165             : 
     166             : } /* }}} */
     167             : 
     168             : 
     169             : /* {{{ php_oci_statement_fetch()
     170             :  Fetch a row from the statement */
     171      232055 : 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      232055 :         zend_bool piecewisecols = 0;
     178             : 
     179             :         php_oci_out_column *column;
     180             : 
     181      232055 :         if (statement->has_descr && statement->columns) {
     182      224470 :                 zend_hash_apply(statement->columns, (apply_func_t) php_oci_cleanup_pre_fetch TSRMLS_CC);
     183             :     }
     184             : 
     185      232055 :         PHP_OCI_CALL_RETURN(statement->errcode, OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT));
     186             : 
     187      232055 :         if ( statement->errcode == OCI_NO_DATA || nrows == 0 ) {
     188       30322 :                 if (statement->last_query == NULL) {
     189             :                         /* reset define-list for refcursors */
     190          20 :                         if (statement->columns) {
     191          18 :                                 zend_hash_destroy(statement->columns);
     192          18 :                                 efree(statement->columns);
     193          18 :                                 statement->columns = NULL;
     194          18 :                                 statement->ncolumns = 0;
     195             :                         }
     196          20 :                         statement->executed = 0;
     197             :                 }
     198             : 
     199       30322 :                 statement->errcode = 0; /* OCI_NO_DATA is NO error for us!!! */
     200       30322 :                 statement->has_data = 0;
     201             : 
     202       30322 :                 if (nrows == 0) {
     203             :                         /* this is exactly what we requested */
     204           8 :                         return 0;
     205             :                 }
     206       30314 :                 return 1;
     207             :         }
     208             : 
     209             :         /* reset length for all piecewise columns */
     210      594469 :         for (i = 0; i < statement->ncolumns; i++) {
     211      392736 :                 column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
     212      392736 :                 if (column->piecewise) {
     213          13 :                         column->retlen4 = 0;
     214          13 :                         piecewisecols = 1;
     215             :                 }
     216             :         }
     217             :         
     218      403482 :         while (statement->errcode == OCI_NEED_DATA) {
     219          16 :                 if (piecewisecols) {
     220          16 :                         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          42 :                         for (i = 0; i < statement->ncolumns; i++) {
     236          26 :                                 column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
     237          26 :                                 if (column->piecewise && handlepp == column->oci_define)   {
     238          16 :                                         if (!column->data) {
     239           5 :                                                 column->data = (text *) ecalloc(1, PHP_OCI_PIECE_SIZE + 1);
     240             :                                         } else {
     241          11 :                                                 column->data = erealloc(column->data, column->retlen4 + PHP_OCI_PIECE_SIZE + 1);
     242             :                                         }
     243          16 :                                         column->cb_retlen = PHP_OCI_PIECE_SIZE;
     244             : 
     245             :                                         /* and instruct fetch to fetch waiting piece into our buffer */
     246          16 :                                         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          16 :                 PHP_OCI_CALL_RETURN(statement->errcode,       OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT));
     263             : 
     264          16 :                 if (piecewisecols) {
     265          42 :                         for (i = 0; i < statement->ncolumns; i++) {
     266          26 :                                 column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
     267          26 :                                 if (column && column->piecewise && handlepp == column->oci_define)        {
     268          16 :                                         column->retlen4 += column->cb_retlen;
     269             :                                 }
     270             :                         }
     271             :                 }
     272             :         }
     273             : 
     274      201733 :         if (statement->errcode == OCI_SUCCESS_WITH_INFO || statement->errcode == OCI_SUCCESS) {
     275      201724 :                 statement->has_data = 1;
     276             : 
     277             :                 /* do the stuff needed for OCIDefineByName */
     278      594453 :                 for (i = 0; i < statement->ncolumns; i++) {
     279      392729 :                         column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
     280      392729 :                         if (column == NULL) {
     281           0 :                                 continue;
     282             :                         }
     283             :                         
     284      392729 :                         if (!column->define) {
     285      302682 :                                 continue;
     286             :                         }
     287             :                         
     288       90047 :                         zval_dtor(column->define->zval);
     289       90047 :                         php_oci_column_to_zval(column, column->define->zval, 0 TSRMLS_CC);
     290             :                 }
     291             : 
     292      201724 :                 return 0;
     293             :         }
     294             : 
     295           9 :         statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
     296           9 :         PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
     297             : 
     298           9 :         statement->has_data = 0;
     299             : 
     300           9 :         return 1;
     301             : }
     302             : /* }}} */
     303             : 
     304             : /* {{{ php_oci_statement_get_column()
     305             :  Get column from the result set */
     306     1178534 : 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     1178534 :         php_oci_out_column *column = NULL;
     309             :         int i;
     310             : 
     311     1178534 :         if (statement->columns == NULL) { /* we release the columns at the end of a fetch */
     312           0 :                 return NULL;
     313             :         }
     314             : 
     315     1178534 :         if (column_name) {
     316         344 :                 for (i = 0; i < statement->ncolumns; i++) {
     317         337 :                         column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
     318         337 :                         if (column == NULL) {
     319           0 :                                 continue;
     320         337 :                         } else if (((int) column->name_len == column_name_len) && (!strncmp(column->name, column_name, column_name_len))) {
     321          69 :                                 return column;
     322             :                         }
     323             :                 }
     324     1178458 :         } else if (column_index != -1) {
     325     1178451 :                 if (zend_hash_index_find(statement->columns, column_index, (void **)&column) == FAILURE) {
     326           7 :                         return NULL;
     327             :                 }
     328     1178444 :                 return column;
     329             :         }
     330             : 
     331          14 :         return NULL;
     332             : }
     333             : /* }}} */
     334             : 
     335             : /* php_oci_define_callback() {{{ */
     336      284855 : sb4 php_oci_define_callback(dvoid *ctx, OCIDefine *define, ub4 iter, dvoid **bufpp, ub4 **alenpp, ub1 *piecep, dvoid **indpp, ub2 **rcpp)
     337             : {
     338      284855 :         php_oci_out_column *outcol = (php_oci_out_column *)ctx;
     339             :         TSRMLS_FETCH();
     340             : 
     341      284855 :         if (!outcol) {
     342             :                 
     343           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid context pointer value");
     344           0 :                 return OCI_ERROR;
     345             :         }
     346             :         
     347      284855 :         switch(outcol->data_type) {
     348             :                 case SQLT_RSET: {
     349             :                                 php_oci_statement *nested_stmt;
     350             : 
     351        1417 :                                 nested_stmt = php_oci_statement_create(outcol->statement->connection, NULL, 0 TSRMLS_CC);
     352        1417 :                                 if (!nested_stmt) {
     353           0 :                                         return OCI_ERROR;
     354             :                                 }
     355        1417 :                                 nested_stmt->parent_stmtid = outcol->statement->id;
     356        1417 :                                 zend_list_addref(outcol->statement->id);
     357        1417 :                                 outcol->nested_statement = nested_stmt;
     358        1417 :                                 outcol->stmtid = nested_stmt->id;
     359             : 
     360        1417 :                                 *bufpp = nested_stmt->stmt;
     361        1417 :                                 *alenpp = &(outcol->retlen4);
     362        1417 :                                 *piecep = OCI_ONE_PIECE;
     363        1417 :                                 *indpp = &(outcol->indicator);
     364        1417 :                                 *rcpp = &(outcol->retcode);
     365        1417 :                                 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      283438 :                                 if (outcol->data_type == SQLT_BFILE) {
     376           3 :                                         dtype = OCI_DTYPE_FILE;
     377      283435 :                                 } else if (outcol->data_type == SQLT_RDD ) {
     378           1 :                                         dtype = OCI_DTYPE_ROWID;
     379             :                                 } else {
     380      283434 :                                         dtype = OCI_DTYPE_LOB;
     381             :                                 }
     382             : 
     383      283438 :                                 descr = php_oci_lob_create(outcol->statement->connection, dtype TSRMLS_CC);
     384      283438 :                                 if (!descr) {
     385           0 :                                         return OCI_ERROR;
     386             :                                 }
     387      283438 :                                 outcol->descid = descr->id;
     388      283438 :                                 descr->charset_form = outcol->charset_form;
     389             :                                 
     390      283438 :                                 *bufpp = descr->descriptor;
     391      283438 :                                 *alenpp = &(outcol->retlen4);
     392      283438 :                                 *piecep = OCI_ONE_PIECE;
     393      283438 :                                 *indpp = &(outcol->indicator);
     394      283438 :                                 *rcpp = &(outcol->retcode);
     395             : 
     396      283438 :                                 return OCI_CONTINUE;
     397             :                         }
     398             :                         break;
     399             :         }
     400           0 :         return OCI_ERROR;
     401             : }
     402             : /* }}} */
     403             : 
     404             : /* {{{ php_oci_statement_execute()
     405             :  Execute statement */
     406       37745 : 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       37745 :         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       37745 :         switch (mode) {
     420             :                 case OCI_COMMIT_ON_SUCCESS:
     421             :                 case OCI_DESCRIBE_ONLY:
     422             :                 case OCI_DEFAULT:
     423             :                         /* only these are allowed */
     424       37744 :                         break;
     425             :                 default:
     426           1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid execute mode given: %d", mode);
     427           1 :                         return 1;
     428             :                         break;
     429             :         }
     430             :         
     431       37744 :         if (!statement->stmttype) {
     432             :                 /* get statement type */
     433       34429 :                 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       34429 :                 if (statement->errcode != OCI_SUCCESS) {
     436           0 :                         statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
     437           0 :                         PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
     438           0 :                         return 1;
     439             :                 }
     440             :         }
     441             : 
     442       37744 :         if (statement->stmttype == OCI_STMT_SELECT) {
     443       32890 :                 iters = 0;
     444             :         } else {
     445        4854 :                 iters = 1;
     446             :         }
     447             :         
     448       37744 :         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       36306 :                 if (statement->binds) {
     453        3606 :                         int result = 0;
     454        3606 :                         zend_hash_apply_with_argument(statement->binds, (apply_func_arg_t) php_oci_bind_pre_exec, (void *)&result TSRMLS_CC);
     455        3606 :                         if (result) {
     456           2 :                                 return 1;
     457             :                         }
     458             :                 }
     459             : 
     460             :                 /* execute statement */
     461       36304 :                 PHP_OCI_CALL_RETURN(statement->errcode, OCIStmtExecute, (statement->connection->svc,   statement->stmt, statement->err, iters,   0, NULL, NULL, mode));
     462             : 
     463       36304 :                 if (statement->errcode != OCI_SUCCESS) {
     464         254 :                         statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
     465         254 :                         PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
     466         254 :                         return 1;
     467             :                 }
     468             :                 
     469       36050 :                 if (statement->binds) {
     470        3584 :                         zend_hash_apply(statement->binds, (apply_func_t) php_oci_bind_post_exec TSRMLS_CC);
     471             :                 }
     472             : 
     473       36050 :                 if (mode & OCI_COMMIT_ON_SUCCESS) {
     474       34370 :                         statement->connection->needs_commit = 0;
     475             :                 } else {
     476        1680 :                         statement->connection->needs_commit = 1;
     477             :                 }
     478             :         }
     479             : 
     480       37488 :         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       32847 :                 statement->executed = 1;
     483             :                 
     484       32847 :                 ALLOC_HASHTABLE(statement->columns);
     485       32847 :                 zend_hash_init(statement->columns, 13, NULL, php_oci_column_hash_dtor, 0);
     486             :                 
     487       32847 :                 counter = 1;
     488             : 
     489             :                 /* get number of columns */
     490       32847 :                 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       32847 :                 if (statement->errcode != OCI_SUCCESS) {
     493           0 :                         statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
     494           0 :                         PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
     495           0 :                         return 1;
     496             :                 }
     497             : 
     498       32847 :                 statement->ncolumns = colcount;
     499             :                 
     500       96312 :                 for (counter = 1; counter <= colcount; counter++) {
     501       63465 :                         memset(&column,0,sizeof(php_oci_out_column));
     502             :                         
     503       63465 :                         if (zend_hash_index_update(statement->columns, counter, &column, sizeof(php_oci_out_column), (void**) &outcol) == FAILURE) {
     504           0 :                                 efree(statement->columns);
     505             :                                 /* out of memory */
     506           0 :                                 return 1;
     507             :                         }
     508             :                         
     509             :                         /* get column */
     510       63465 :                         PHP_OCI_CALL_RETURN(statement->errcode, OCIParamGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, statement->err, (dvoid**)&param, counter));
     511             :                         
     512       63465 :                         if (statement->errcode != OCI_SUCCESS) {
     513           0 :                                 statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
     514           0 :                                 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
     515           0 :                                 return 1;
     516             :                         }
     517             : 
     518             :                         /* get column datatype */
     519       63465 :                         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       63465 :                         if (statement->errcode != OCI_SUCCESS) {
     522           0 :                                 PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
     523           0 :                                 statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
     524           0 :                                 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
     525           0 :                                 return 1;
     526             :                         }
     527             : 
     528             :                         /* get character set form  */
     529       63465 :                         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       63465 :                         if (statement->errcode != OCI_SUCCESS) {
     532           0 :                                 PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
     533           0 :                                 statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
     534           0 :                                 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
     535           0 :                                 return 1;
     536             :                         }
     537             :         
     538             :                         /* get character set id  */
     539       63465 :                         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       63465 :                         if (statement->errcode != OCI_SUCCESS) {
     542           0 :                                 PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
     543           0 :                                 statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
     544           0 :                                 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
     545           0 :                                 return 1;
     546             :                         }
     547             :         
     548             :                         /* get size of the column */
     549       63465 :                         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       63465 :                         if (statement->errcode != OCI_SUCCESS) {
     552           0 :                                 PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
     553           0 :                                 statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
     554           0 :                                 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
     555           0 :                                 return 1;
     556             :                         }
     557             : 
     558       63465 :                         outcol->storage_size4 = outcol->data_size;
     559       63465 :                         outcol->retlen = outcol->data_size;
     560             : 
     561             :                         /* get scale of the column */
     562       63465 :                         PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->scale, (dvoid *)0, OCI_ATTR_SCALE, statement->err));
     563             :                         
     564       63465 :                         if (statement->errcode != OCI_SUCCESS) {
     565           0 :                                 PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
     566           0 :                                 statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
     567           0 :                                 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
     568           0 :                                 return 1;
     569             :                         }
     570             : 
     571             :                         /* get precision of the column */
     572       63465 :                         PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->precision, (dvoid *)0, OCI_ATTR_PRECISION, statement->err));
     573             :                         
     574       63465 :                         if (statement->errcode != OCI_SUCCESS) {
     575           0 :                                 PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
     576           0 :                                 statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
     577           0 :                                 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
     578           0 :                                 return 1;
     579             :                         }
     580             :                         
     581             :                         /* get name of the column */
     582       63465 :                         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       63465 :                         if (statement->errcode != OCI_SUCCESS) {
     585           0 :                                 PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
     586           0 :                                 statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
     587           0 :                                 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
     588           0 :                                 return 1;
     589             :                         }
     590       63465 :                         PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
     591             : 
     592       63465 :                         outcol->name = estrndup((char*) colname, outcol->name_len);
     593             : 
     594             :                         /* find a user-setted define */
     595       63465 :                         if (statement->defines) {
     596       30051 :                                 if (zend_hash_find(statement->defines,outcol->name,outcol->name_len,(void **) &outcol->define) == SUCCESS) {
     597       30046 :                                         if (outcol->define->type) {
     598          10 :                                                 outcol->data_type = outcol->define->type;
     599             :                                         }
     600             :                                 }
     601             :                         }
     602             : 
     603       63465 :                         buf = 0;
     604       63465 :                         switch (outcol->data_type) {
     605             :                                 case SQLT_RSET:
     606        1411 :                                         outcol->statement = statement; /* parent handle */
     607             : 
     608        1411 :                                         define_type = SQLT_RSET;
     609        1411 :                                         outcol->is_cursor = 1;
     610        1411 :                                         outcol->statement->has_descr = 1;
     611        1411 :                                         outcol->storage_size4 = -1;
     612        1411 :                                         outcol->retlen = -1;
     613        1411 :                                         dynamic = OCI_DYNAMIC_FETCH;
     614        1411 :                                         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       60135 :                                         outcol->statement = statement; /* parent handle */
     621             : 
     622       60135 :                                         define_type = outcol->data_type;
     623       60135 :                                         outcol->is_descr = 1;
     624       60135 :                                         outcol->statement->has_descr = 1;
     625       60135 :                                         outcol->storage_size4 = -1;
     626       60135 :                                         dynamic = OCI_DYNAMIC_FETCH;
     627       60135 :                                         break;
     628             : 
     629             :                                 case SQLT_LNG:
     630             :                                 case SQLT_LBI:
     631           5 :                                         if (outcol->data_type == SQLT_LBI) {
     632           1 :                                                 define_type = SQLT_BIN;
     633             :                                         } else {
     634           4 :                                                 define_type = SQLT_CHR;
     635             :                                         }
     636           5 :                                         outcol->storage_size4 = PHP_OCI_MAX_DATA_SIZE;
     637           5 :                                         outcol->piecewise = 1;
     638           5 :                                         dynamic = OCI_DYNAMIC_FETCH;
     639           5 :                                         break;
     640             : 
     641             :                                 case SQLT_BIN:
     642             :                                 default:
     643        1914 :                                         define_type = SQLT_CHR;
     644        1914 :                                         if (outcol->data_type == SQLT_BIN) {
     645           5 :                                                 define_type = SQLT_BIN;
     646             :                                         }
     647        7168 :                                         if ((outcol->data_type == SQLT_DAT) || (outcol->data_type == SQLT_NUM)
     648             : #ifdef SQLT_TIMESTAMP
     649         838 :                                                 || (outcol->data_type == SQLT_TIMESTAMP)
     650             : #endif
     651             : #ifdef SQLT_TIMESTAMP_TZ
     652         835 :                                                 || (outcol->data_type == SQLT_TIMESTAMP_TZ)
     653             : #endif
     654             : #ifdef SQLT_TIMESTAMP_LTZ
     655         833 :                                                 || (outcol->data_type == SQLT_TIMESTAMP_LTZ)
     656             : #endif
     657             : #ifdef SQLT_INTERVAL_YM
     658         832 :                                                 || (outcol->data_type == SQLT_INTERVAL_YM)
     659             : #endif
     660             : #ifdef SQLT_INTERVAL_DS
     661         830 :                                                 || (outcol->data_type == SQLT_INTERVAL_DS)
     662             : #endif
     663             :                                                 ) {
     664        1086 :                                                 outcol->storage_size4 = 512; /* XXX this should fit "most" NLS date-formats and Numbers */
     665             : #if defined(SQLT_IBFLOAT) && defined(SQLT_IBDOUBLE)
     666         833 :                                         } else if (outcol->data_type == SQLT_IBFLOAT || outcol->data_type == SQLT_IBDOUBLE) {
     667           5 :                                                 outcol->storage_size4 = 1024;
     668             : #endif
     669             :                                         } else {
     670         823 :                                                 outcol->storage_size4++; /* add one for string terminator */
     671             :                                         }
     672             :                                         
     673        1914 :                                         outcol->storage_size4 *= 3;
     674             :                                         
     675        1914 :                                         dynamic = OCI_DEFAULT;
     676        1914 :                                         buf = outcol->data = (text *) safe_emalloc(1, outcol->storage_size4, 0);
     677        1914 :                                         memset(buf, 0, outcol->storage_size4);
     678             :                                         break;
     679             :                         }
     680             : 
     681       63465 :                         if (dynamic == OCI_DYNAMIC_FETCH) {
     682       61551 :                                 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        1914 :                                 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       63465 :                         if (statement->errcode != OCI_SUCCESS) {
     720           0 :                                 statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
     721           0 :                                 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
     722           0 :                                 return 0;
     723             :                         }
     724             : 
     725             :                         /* additional OCIDefineDynamic() call */
     726       63465 :                         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       61546 :                                         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       37488 :         return 0;
     748             : }
     749             : /* }}} */
     750             : 
     751             : /* {{{ php_oci_statement_cancel()
     752             :  Cancel statement */
     753           8 : int php_oci_statement_cancel(php_oci_statement *statement TSRMLS_DC)
     754             : {
     755             :         
     756           8 :         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       34474 : void php_oci_statement_free(php_oci_statement *statement TSRMLS_DC)
     763             : {
     764       34474 :         if (statement->stmt) {
     765       34474 :                 if (statement->last_query_len) { /* FIXME: magical */
     766       33029 :                         PHP_OCI_CALL(OCIStmtRelease, (statement->stmt, statement->err, NULL, 0, statement->errcode ? OCI_STRLS_CACHE_DELETE : OCI_DEFAULT));
     767             :                 } else {
     768        1445 :                         PHP_OCI_CALL(OCIHandleFree, (statement->stmt, OCI_HTYPE_STMT));
     769             :                 }
     770       34474 :                 statement->stmt = 0;
     771             :         }
     772             : 
     773       34474 :         if (statement->err) {
     774       34474 :                 PHP_OCI_CALL(OCIHandleFree, (statement->err, OCI_HTYPE_ERROR));
     775       34474 :                 statement->err = 0;
     776             :         }
     777             : 
     778       34474 :         if (statement->last_query) {
     779       33029 :                 efree(statement->last_query);
     780             :         }
     781             : 
     782       34474 :         if (statement->columns) {
     783       32829 :                 zend_hash_destroy(statement->columns);
     784       32829 :                 efree(statement->columns);
     785             :         }
     786             : 
     787       34474 :         if (statement->binds) {
     788         389 :                 zend_hash_destroy(statement->binds);
     789         389 :                 efree(statement->binds);
     790             :         }
     791             : 
     792       34474 :         if (statement->defines) {
     793       15037 :                 zend_hash_destroy(statement->defines);
     794       15037 :                 efree(statement->defines);
     795             :         }
     796             : 
     797       34474 :         if (statement->parent_stmtid) {
     798        1417 :                 zend_list_delete(statement->parent_stmtid);
     799             :         }
     800             : 
     801       34474 :         zend_list_delete(statement->connection->rsrc_id);
     802       34474 :         efree(statement);
     803             :         
     804       34474 :         OCI_G(num_statements)--;
     805       34474 : } /* }}} */
     806             : 
     807             : /* {{{ php_oci_bind_pre_exec()
     808             :  Helper function */
     809        5683 : int php_oci_bind_pre_exec(void *data, void *result TSRMLS_DC)
     810             : {
     811        5683 :         php_oci_bind *bind = (php_oci_bind *) data;
     812             : 
     813        5683 :         *(int *)result = 0;
     814             : 
     815        5683 :         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          23 :                 return 0;
     821             :         }       
     822        5660 :         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         192 :                         if (Z_TYPE_P(bind->zval) != IS_OBJECT) {
     830           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
     831           0 :                                 *(int *)result = 1;
     832             :                         }
     833         192 :                         break;
     834             :                         
     835             :                 case SQLT_INT:
     836             :                 case SQLT_NUM:
     837         655 :                         if (Z_TYPE_P(bind->zval) == IS_RESOURCE || Z_TYPE_P(bind->zval) == IS_OBJECT) {
     838           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
     839           0 :                                 *(int *)result = 1;
     840             :                         }
     841         655 :                         break;
     842             :                         
     843             :                 case SQLT_LBI:
     844             :                 case SQLT_BIN:
     845             :                 case SQLT_LNG:
     846             :                 case SQLT_AFC:
     847             :                 case SQLT_CHR:
     848        4778 :                         if (Z_TYPE_P(bind->zval) == IS_RESOURCE || Z_TYPE_P(bind->zval) == IS_OBJECT) {
     849           2 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
     850           2 :                                 *(int *)result = 1;
     851             :                         }
     852        4778 :                         break;
     853             : 
     854             :                 case SQLT_RSET:
     855          35 :                         if (Z_TYPE_P(bind->zval) != IS_RESOURCE) {
     856           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
     857           0 :                                 *(int *)result = 1;
     858             :                         }
     859             :                         break;
     860             :         }
     861             : 
     862             :         /* reset all bind stuff to a normal state..-. */
     863        5660 :         bind->indicator = 0;
     864             : 
     865        5660 :         return 0;
     866             : }
     867             : /* }}} */
     868             : 
     869             : /* {{{ php_oci_bind_post_exec()
     870             :  Helper function */
     871        5655 : int php_oci_bind_post_exec(void *data TSRMLS_DC)
     872             : {
     873        5655 :         php_oci_bind *bind = (php_oci_bind *) data;
     874        5655 :         php_oci_connection *connection = bind->parent_statement->connection;
     875             : 
     876        5655 :         if (bind->indicator == -1) { /* NULL */
     877          23 :                 zval *val = bind->zval;
     878          23 :                 if (Z_TYPE_P(val) == IS_STRING) {
     879           5 :                         *Z_STRVAL_P(val) = '\0'; /* XXX avoid warning in debug mode */
     880             :                 }
     881             :                 zval_dtor(val);
     882          23 :                 ZVAL_NULL(val);
     883       20747 :         } else if (Z_TYPE_P(bind->zval) == IS_STRING
     884       10377 :                            && Z_STRLEN_P(bind->zval) > 0
     885        9483 :                            && 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           0 :                 Z_STRVAL_P(bind->zval) = erealloc(Z_STRVAL_P(bind->zval), Z_STRLEN_P(bind->zval)+1);
     893           0 :                 Z_STRVAL_P(bind->zval)[ Z_STRLEN_P(bind->zval) ] = '\0';
     894        5632 :         } else if (Z_TYPE_P(bind->zval) == IS_ARRAY) {
     895             :                 int i;
     896             :                 zval **entry;
     897          20 :                 HashTable *hash = HASH_OF(bind->zval);
     898             :         
     899          20 :                 zend_hash_internal_pointer_reset(hash);
     900             : 
     901          20 :                 switch (bind->array.type) {
     902             :                         case SQLT_NUM:
     903             :                         case SQLT_INT:
     904             :                         case SQLT_LNG:
     905          18 :                                 for (i = 0; i < bind->array.current_length; i++) {
     906          25 :                                         if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
     907          10 :                                                 zval_dtor(*entry);
     908          10 :                                                 ZVAL_LONG(*entry, ((ub4 *)(bind->array.elements))[i]);
     909          10 :                                                 zend_hash_move_forward(hash);
     910             :                                         } else {
     911           5 :                                                 add_next_index_long(bind->zval, ((ub4 *)(bind->array.elements))[i]);
     912             :                                         }
     913             :                                 }
     914           3 :                                 break;
     915             :                         case SQLT_FLT:
     916          12 :                                 for (i = 0; i < bind->array.current_length; i++) {
     917          20 :                                         if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
     918          10 :                                                 zval_dtor(*entry);
     919          10 :                                                 ZVAL_DOUBLE(*entry, ((double *)(bind->array.elements))[i]);
     920          10 :                                                 zend_hash_move_forward(hash);
     921             :                                         } else {
     922           0 :                                                 add_next_index_double(bind->zval, ((double *)(bind->array.elements))[i]);
     923             :                                         }
     924             :                                 }
     925           2 :                                 break;
     926             :                         case SQLT_ODT:
     927          12 :                                 for (i = 0; i < bind->array.current_length; i++) {
     928             :                                         oratext buff[1024];
     929          10 :                                         ub4 buff_len = 1024;
     930             : 
     931          10 :                                         memset((void*)buff,0,sizeof(buff));
     932             :                                                         
     933          20 :                                         if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
     934          10 :                                                 PHP_OCI_CALL_RETURN(connection->errcode, OCIDateToText, (connection->err, &(((OCIDate *)(bind->array.elements))[i]), 0, 0, 0, 0, &buff_len, buff));
     935          10 :                                                 zval_dtor(*entry);
     936             : 
     937          10 :                                                 if (connection->errcode != OCI_SUCCESS) {
     938           0 :                                                         connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
     939           0 :                                                         PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
     940           0 :                                                         ZVAL_NULL(*entry);
     941             :                                                 } else {
     942          10 :                                                         ZVAL_STRINGL(*entry, (char *)buff, buff_len, 1);
     943             :                                                 }
     944          10 :                                                 zend_hash_move_forward(hash);
     945             :                                         } else {
     946           0 :                                                 PHP_OCI_CALL_RETURN(connection->errcode, OCIDateToText, (connection->err, &(((OCIDate *)(bind->array.elements))[i]), 0, 0, 0, 0, &buff_len, buff));
     947           0 :                                                 if (connection->errcode != OCI_SUCCESS) {
     948           0 :                                                         connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
     949           0 :                                                         PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
     950           0 :                                                         add_next_index_null(bind->zval);
     951             :                                                 } else {
     952           0 :                                                         add_next_index_stringl(bind->zval, (char *)buff, buff_len, 1);
     953             :                                                 }
     954             :                                         }
     955             :                                 }
     956           2 :                                 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         169 :                                 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         156 :                                         int curr_element_length = bind->array.element_lengths[i];
     967         206 :                                         if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
     968          50 :                                                 zval_dtor(*entry);
     969          50 :                                                 ZVAL_STRINGL(*entry, (char *)(((text *)bind->array.elements)+i*bind->array.max_length), curr_element_length, 1);
     970          50 :                                                 zend_hash_move_forward(hash);
     971             :                                         } else {
     972         106 :                                                 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        5655 :         return 0;
     980             : }
     981             : /* }}} */
     982             : 
     983             : /* {{{ php_oci_bind_by_name()
     984             :  Bind zval to the given placeholder */
     985        4066 : 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        4066 :         php_oci_collection *bind_collection = NULL;
     988        4066 :         php_oci_descriptor *bind_descriptor = NULL;
     989        4066 :         php_oci_statement  *bind_statement      = NULL;
     990        4066 :         dvoid *oci_desc                                 = NULL;
     991             :         /* dvoid *php_oci_collection               = NULL; */
     992        4066 :         OCIStmt *oci_stmt                               = NULL;
     993        4066 :         dvoid *bind_data                                = NULL;
     994             :         php_oci_bind bind, *old_bind, *bindp;
     995        4066 :         int mode = OCI_DATA_AT_EXEC;
     996        4066 :         sb4 value_sz = -1;
     997             : 
     998        4066 :         switch (type) {
     999             :                 case SQLT_NTY:
    1000             :                 {
    1001             :                         zval **tmp;
    1002             :                         
    1003           1 :                         if (Z_TYPE_P(var) != IS_OBJECT || zend_hash_find(Z_OBJPROP_P(var), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
    1004           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
    1005           0 :                                 return 1;
    1006             :                         }
    1007             : 
    1008           1 :                         PHP_OCI_ZVAL_TO_COLLECTION_EX(*tmp, bind_collection);
    1009           1 :                         value_sz = sizeof(void*);
    1010           1 :                         mode = OCI_DEFAULT;
    1011             :                 
    1012           1 :                         if (!bind_collection->collection) {
    1013           0 :                                 return 1;
    1014             :                         }
    1015             :                 }
    1016           1 :                         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         184 :                         if (Z_TYPE_P(var) != IS_OBJECT || zend_hash_find(Z_OBJPROP_P(var), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
    1026           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
    1027           0 :                                 return 1;
    1028             :                         }
    1029             : 
    1030         184 :                         PHP_OCI_ZVAL_TO_DESCRIPTOR_EX(*tmp, bind_descriptor);
    1031             : 
    1032         184 :                         value_sz = sizeof(void*);
    1033             :                         
    1034         184 :                         oci_desc = bind_descriptor->descriptor;
    1035             :                         
    1036         184 :                         if (!oci_desc) {
    1037           0 :                                 return 1;
    1038             :                         }
    1039             :                 }
    1040         184 :                         break;
    1041             :                         
    1042             :                 case SQLT_INT:
    1043             :                 case SQLT_NUM:
    1044          52 :                         if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) {
    1045           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
    1046           0 :                                 return 1;
    1047             :                         }
    1048          52 :                         convert_to_long(var);
    1049          52 :                         bind_data = (ub4 *)&Z_LVAL_P(var);
    1050          52 :                         value_sz = sizeof(ub4);
    1051          52 :                         mode = OCI_DEFAULT;
    1052          52 :                         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        3782 :                         if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) {
    1060           2 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
    1061           2 :                                 return 1;
    1062             :                         }
    1063        3780 :                         if (Z_TYPE_P(var) != IS_NULL) {
    1064        3749 :                                 convert_to_string(var);
    1065             :                         }
    1066        3780 :                         if (maxlength == -1) {
    1067        3754 :                                 value_sz = (Z_TYPE_P(var) == IS_STRING) ? Z_STRLEN_P(var) : 0;
    1068             :                         } else {
    1069          26 :                                 value_sz = maxlength;
    1070             :                         }
    1071        3780 :                         break;
    1072             : 
    1073             :                 case SQLT_RSET:
    1074          38 :                         if (Z_TYPE_P(var) != IS_RESOURCE) {
    1075           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
    1076           0 :                                 return 1;
    1077             :                         }
    1078          38 :                         PHP_OCI_ZVAL_TO_STATEMENT_EX(var, bind_statement);
    1079          38 :                         value_sz = sizeof(void*);
    1080             : 
    1081          38 :                         oci_stmt = bind_statement->stmt;
    1082             : 
    1083          38 :                         if (!oci_stmt) {
    1084           0 :                                 return 1;
    1085             :                         }
    1086          38 :                         break;
    1087             : 
    1088             :                 default:
    1089           9 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or unsupported datatype given: %d", (int)type);
    1090           9 :                         return 1;
    1091             :                         break;
    1092             :         }
    1093             :         
    1094        4055 :         if (value_sz == 0) {
    1095          17 :                 value_sz = 1;
    1096             :         }
    1097             :         
    1098        4055 :         if (!statement->binds) {
    1099         369 :                 ALLOC_HASHTABLE(statement->binds);
    1100         369 :                 zend_hash_init(statement->binds, 13, NULL, php_oci_bind_hash_dtor, 0);
    1101             :         }
    1102             : 
    1103        4055 :         memset((void*)&bind,0,sizeof(php_oci_bind));
    1104        4055 :         if (zend_hash_find(statement->binds, name, name_len + 1, (void **)&old_bind) == SUCCESS) {
    1105        3524 :                 bindp = old_bind;
    1106        3524 :                 if (bindp->zval) {
    1107        3524 :                         zval_ptr_dtor(&bindp->zval);
    1108             :                 }
    1109             :         } else {
    1110         531 :                 zend_hash_update(statement->binds, name, name_len + 1, &bind, sizeof(php_oci_bind), (void **)&bindp);
    1111             :         }
    1112             :         
    1113        4055 :         bindp->descriptor = oci_desc;
    1114        4055 :         bindp->statement = oci_stmt;
    1115        4055 :         bindp->parent_statement = statement;
    1116        4055 :         bindp->zval = var;
    1117        4055 :         bindp->type = type;
    1118        4055 :         zval_add_ref(&var);
    1119             :         
    1120        4055 :         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        4055 :         if (statement->errcode != OCI_SUCCESS) {
    1141           2 :                 statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
    1142           2 :                 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
    1143           2 :                 return 1;
    1144             :         }
    1145             : 
    1146        4053 :         if (mode == OCI_DATA_AT_EXEC) {
    1147        4000 :                 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        4000 :                 if (statement->errcode != OCI_SUCCESS) {
    1159           0 :                         statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
    1160           0 :                         PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
    1161           0 :                         return 1;
    1162             :                 }
    1163             :         }
    1164             : 
    1165        4053 :         if (type == SQLT_NTY) {
    1166             :                 /* Bind object */
    1167           1 :                 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           1 :                 if (statement->errcode) {
    1180           0 :                         statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
    1181           0 :                         PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
    1182           0 :                         return 1;
    1183             :                 }
    1184             :         }
    1185             :         
    1186        4053 :         return 0;
    1187             : } /* }}} */
    1188             : 
    1189             : /* {{{ php_oci_bind_in_callback()
    1190             :  Callback used when binding LOBs and VARCHARs */
    1191        4278 : 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        4278 :         if (!(phpbind=(php_oci_bind *)ictxp) || !(val = phpbind->zval)) {
    1206           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid phpbind pointer value");
    1207           0 :                 return OCI_ERROR;
    1208             :         }
    1209             : 
    1210        4278 :         if (ZVAL_IS_NULL(val)) {
    1211             :                 /* we're going to insert a NULL column */
    1212          25 :                 phpbind->indicator = -1;
    1213          25 :                 *bufpp = 0;
    1214          25 :                 *alenp = -1;
    1215          25 :                 *indpp = (dvoid *)&phpbind->indicator;
    1216        8301 :         } else  if ((phpbind->descriptor == 0) && (phpbind->statement == 0)) {
    1217             :                 /* "normal string bind */
    1218        4048 :                 convert_to_string(val);
    1219             : 
    1220        4048 :                 *bufpp = Z_STRVAL_P(val);
    1221        4048 :                 *alenp = Z_STRLEN_P(val);
    1222        4048 :                 *indpp = (dvoid *)&phpbind->indicator;
    1223         205 :         } else if (phpbind->statement != 0) {
    1224             :                 /* RSET */
    1225          23 :                 *bufpp = phpbind->statement;
    1226          23 :                 *alenp = -1;            /* seems to be allright */
    1227          23 :                 *indpp = (dvoid *)&phpbind->indicator;
    1228             :         } else {
    1229             :                 /* descriptor bind */
    1230         182 :                 *bufpp = phpbind->descriptor;
    1231         182 :                 *alenp = -1;            /* seems to be allright */
    1232         182 :                 *indpp = (dvoid *)&phpbind->indicator;
    1233             :         }
    1234             : 
    1235        4278 :         *piecep = OCI_ONE_PIECE; /* pass all data in one go */
    1236             : 
    1237        4278 :         return OCI_CONTINUE;
    1238             : }/* }}} */
    1239             : 
    1240             : /* {{{ php_oci_bind_out_callback()
    1241             :  Callback used when binding LOBs and VARCHARs */
    1242         827 : 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         827 :         sb4 retval = OCI_ERROR;
    1256             :         TSRMLS_FETCH();
    1257             : 
    1258         827 :         if (!(phpbind=(php_oci_bind *)octxp) || !(val = phpbind->zval)) {
    1259           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid phpbind pointer value");
    1260           0 :                 return retval;
    1261             :         }
    1262             : 
    1263         827 :         if (Z_TYPE_P(val) == IS_RESOURCE) {
    1264             :                 /* Processing for ref-cursor out binds */
    1265          31 :                 if (phpbind->statement != NULL) {
    1266          31 :                         *bufpp = phpbind->statement;
    1267          31 :                         *alenpp = &phpbind->dummy_len;
    1268          31 :                         *piecep = OCI_ONE_PIECE;
    1269          31 :                         *rcodepp = &phpbind->retcode;
    1270          31 :                         *indpp = &phpbind->indicator;
    1271             :                 }
    1272          31 :                 retval = OCI_CONTINUE;
    1273         796 :         } else if (Z_TYPE_P(val) == IS_OBJECT) {
    1274             :                 zval **tmp;
    1275             :                 php_oci_descriptor *desc;
    1276             : 
    1277          80 :                 if (!phpbind->descriptor) {
    1278           0 :                         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          80 :                 if (zend_hash_find(Z_OBJPROP_P(val), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
    1286           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find object outbind descriptor property");
    1287           0 :                         return OCI_ERROR;
    1288             :                 }
    1289          80 :                 PHP_OCI_ZVAL_TO_DESCRIPTOR_EX(*tmp, desc);
    1290          80 :                 desc->lob_size = -1; /* force OCI8 to update cached size */
    1291             : 
    1292          80 :                 *alenpp = &phpbind->dummy_len;
    1293          80 :                 *bufpp = phpbind->descriptor;
    1294          80 :                 *piecep = OCI_ONE_PIECE;
    1295          80 :                 *rcodepp = &phpbind->retcode;
    1296          80 :                 *indpp = &phpbind->indicator;
    1297          80 :                 retval = OCI_CONTINUE;
    1298             :         } else {
    1299         716 :                 convert_to_string(val);
    1300             :                 zval_dtor(val);
    1301             :                 
    1302         716 :                 Z_STRLEN_P(val) = PHP_OCI_PIECE_SIZE; /* 64K-1 is max XXX */
    1303         716 :                 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         716 :                 *alenpp = (ub4*) &Z_STRLEN_P(phpbind->zval);
    1307         716 :                 *bufpp = Z_STRVAL_P(phpbind->zval);
    1308         716 :                 *piecep = OCI_ONE_PIECE;
    1309         716 :                 *rcodepp = &phpbind->retcode;
    1310         716 :                 *indpp = &phpbind->indicator;
    1311         716 :                 retval = OCI_CONTINUE;
    1312             :         }
    1313             : 
    1314         827 :         return retval;
    1315             : }
    1316             : /* }}} */
    1317             : 
    1318             : /* {{{ php_oci_statement_get_column_helper()
    1319             :  Helper function to get column by name and index */
    1320         416 : 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         416 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &z_statement, &column_index) == FAILURE) {
    1327           9 :                 return NULL;
    1328             :         }
    1329             : 
    1330         407 :         statement = (php_oci_statement *) zend_fetch_resource(&z_statement TSRMLS_CC, -1, "oci8 statement", NULL, 1, le_statement);
    1331             : 
    1332         407 :         if (!statement) {
    1333           8 :                 return NULL;
    1334             :         }
    1335             : 
    1336         399 :         if (need_data && !statement->has_data) {
    1337           1 :                 return NULL;
    1338             :         }
    1339             :         
    1340         398 :         if (Z_TYPE_P(column_index) == IS_STRING) {
    1341          76 :                 column = php_oci_statement_get_column(statement, -1, Z_STRVAL_P(column_index), Z_STRLEN_P(column_index) TSRMLS_CC);
    1342          76 :                 if (!column) {
    1343           7 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid column name \"%s\"", Z_STRVAL_P(column_index));
    1344           7 :                         return NULL;
    1345             :                 }
    1346             :         } else {
    1347             :                 zval tmp;
    1348             :                 /* NB: for PHP4 compat only, it should be using 'Z' instead */
    1349         322 :                 tmp = *column_index;
    1350             :                 zval_copy_ctor(&tmp);
    1351         322 :                 convert_to_long(&tmp);
    1352         322 :                 column = php_oci_statement_get_column(statement, Z_LVAL(tmp), NULL, 0 TSRMLS_CC);
    1353         322 :                 if (!column) {
    1354          14 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid column index \"%ld\"", Z_LVAL(tmp));
    1355             :                         zval_dtor(&tmp);
    1356          14 :                         return NULL;
    1357             :                 }
    1358             :                 zval_dtor(&tmp);
    1359             :         }
    1360         377 :         return column;
    1361             : } /* }}} */
    1362             : 
    1363             : /* {{{ php_oci_statement_get_type()
    1364             :  Return type of the statement */
    1365          26 : int php_oci_statement_get_type(php_oci_statement *statement, ub2 *type TSRMLS_DC)
    1366             : {
    1367             :         ub2 statement_type;
    1368             :         
    1369          26 :         *type = 0;
    1370             :         
    1371          26 :         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          26 :         if (statement->errcode != OCI_SUCCESS) {
    1374           0 :                 statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
    1375           0 :                 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
    1376           0 :                 return 1;
    1377             :         }
    1378             : 
    1379          26 :         *type = statement_type;
    1380             : 
    1381          26 :         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          26 : int php_oci_statement_get_numrows(php_oci_statement *statement, ub4 *numrows TSRMLS_DC)
    1387             : {
    1388             :         ub4 statement_numrows;
    1389             :         
    1390          26 :         *numrows = 0;
    1391             :         
    1392          26 :         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          26 :         if (statement->errcode != OCI_SUCCESS) {
    1395           0 :                 statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
    1396           0 :                 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
    1397           0 :                 return 1;
    1398             :         }
    1399             : 
    1400          26 :         *numrows = statement_numrows;
    1401             : 
    1402          26 :         return 0;
    1403             : } /* }}} */
    1404             : 
    1405             : /* {{{ php_oci_bind_array_by_name()
    1406             :  Bind arrays to PL/SQL types */
    1407          32 : 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          32 :         convert_to_array(var);
    1412             : 
    1413          32 :         if (maxlength < -1) {
    1414           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid max length value (%ld)", maxlength);
    1415           1 :                 return 1;
    1416             :         }
    1417             :         
    1418          31 :         switch(type) {
    1419             :                 case SQLT_NUM:
    1420             :                 case SQLT_INT:
    1421             :                 case SQLT_LNG:
    1422           3 :                         bind = php_oci_bind_array_helper_number(var, max_table_length TSRMLS_CC);
    1423           3 :                         break;
    1424             : 
    1425             :                 case SQLT_FLT:
    1426           2 :                         bind = php_oci_bind_array_helper_double(var, max_table_length TSRMLS_CC);
    1427           2 :                         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          17 :                         if (maxlength == -1 && zend_hash_num_elements(Z_ARRVAL_P(var)) == 0) {
    1436           4 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must provide max length value for empty arrays");
    1437           4 :                                 return 1;
    1438             :                         }
    1439          13 :                         bind = php_oci_bind_array_helper_string(var, max_table_length, maxlength TSRMLS_CC);
    1440          13 :                         break;
    1441             :                 case SQLT_ODT:
    1442           5 :                         bind = php_oci_bind_array_helper_date(var, max_table_length, statement->connection TSRMLS_CC);
    1443           5 :                         break;
    1444             :                 default:
    1445           4 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or unsupported datatype given: %ld", type);
    1446           4 :                         return 1;
    1447             :                         break;
    1448             :         }
    1449             : 
    1450          23 :         if (bind == NULL) {
    1451             :                 /* failed to generate bind struct */
    1452           1 :                 return 1;
    1453             :         }
    1454             :         
    1455          22 :         if (!statement->binds) {
    1456          20 :                 ALLOC_HASHTABLE(statement->binds);
    1457          20 :                 zend_hash_init(statement->binds, 13, NULL, php_oci_bind_hash_dtor, 0);
    1458             :         }
    1459             : 
    1460          22 :         zend_hash_update(statement->binds, name, name_len + 1, bind, sizeof(php_oci_bind), (void **)&bindp);
    1461             : 
    1462          22 :         bindp->descriptor = NULL;
    1463          22 :         bindp->statement = NULL;
    1464          22 :         bindp->parent_statement = statement;
    1465          22 :         bindp->bind = NULL;
    1466          22 :         bindp->zval = var;
    1467          22 :         bindp->array.type = type;
    1468          22 :         bindp->indicator = 0;                /* not used for array binds */
    1469          22 :         bindp->type = 0;                     /* not used for array binds */
    1470             : 
    1471          22 :         zval_add_ref(&var);
    1472             : 
    1473          22 :         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          22 :         if (statement->errcode != OCI_SUCCESS) {
    1495           1 :                 efree(bind);
    1496           1 :                 statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
    1497           1 :                 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
    1498           1 :                 return 1;
    1499             :         }
    1500          21 :         efree(bind);
    1501          21 :         return 0;
    1502             : } /* }}} */
    1503             : 
    1504             : /* {{{ php_oci_bind_array_helper_string()
    1505             :  Bind arrays to PL/SQL types */
    1506          13 : 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          13 :         hash = HASH_OF(var);
    1514             : 
    1515          13 :         if (maxlength == -1) {
    1516           4 :                 zend_hash_internal_pointer_reset(hash);
    1517          28 :                 while (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE) {
    1518          20 :                         convert_to_string_ex(entry);
    1519          20 :                         if (Z_STRLEN_PP(entry) > maxlength) {
    1520           8 :                                 maxlength = Z_STRLEN_PP(entry) + 1;
    1521             :                         }
    1522          20 :                         zend_hash_move_forward(hash);
    1523             :                 }
    1524             :         }
    1525             :         
    1526          13 :         bind = emalloc(sizeof(php_oci_bind));
    1527          13 :         bind->array.elements         = (text *)safe_emalloc(max_table_length * (maxlength + 1), sizeof(text), 0);
    1528          13 :         memset(bind->array.elements, 0, max_table_length * (maxlength + 1) * sizeof(text));
    1529          13 :         bind->array.current_length   = zend_hash_num_elements(Z_ARRVAL_P(var));
    1530          13 :         bind->array.old_length               = bind->array.current_length;
    1531          13 :         bind->array.max_length               = maxlength;
    1532          13 :         bind->array.element_lengths  = safe_emalloc(max_table_length, sizeof(ub2), 0);
    1533          13 :         memset(bind->array.element_lengths, 0, max_table_length*sizeof(ub2));
    1534          13 :         bind->array.indicators               = safe_emalloc(max_table_length, sizeof(sb2), 0);
    1535          13 :         memset(bind->array.indicators, 0, max_table_length*sizeof(sb2));
    1536             :         
    1537          13 :         zend_hash_internal_pointer_reset(hash);
    1538             :         
    1539         126 :         for (i = 0; i < bind->array.current_length; i++) {
    1540          50 :                 if (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE) {
    1541          80 :                         convert_to_string_ex(entry);
    1542          50 :                         bind->array.element_lengths[i] = Z_STRLEN_PP(entry);
    1543          50 :                         if (Z_STRLEN_PP(entry) == 0) {
    1544           5 :                                 bind->array.indicators[i] = -1;
    1545             :                         }
    1546          50 :                         zend_hash_move_forward(hash);
    1547             :                 } else {
    1548           0 :                         break;
    1549             :                 }
    1550             :         }
    1551             : 
    1552          13 :         zend_hash_internal_pointer_reset(hash);
    1553         273 :         for (i = 0; i < max_table_length; i++) {
    1554         310 :                 if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
    1555             :                         int element_length;
    1556             :                         
    1557          50 :                         convert_to_string_ex(entry);
    1558          50 :                         element_length = (maxlength > Z_STRLEN_PP(entry)) ? Z_STRLEN_PP(entry) : maxlength;
    1559             :                         
    1560          50 :                         memcpy((text *)bind->array.elements + i*maxlength, Z_STRVAL_PP(entry), element_length);
    1561          50 :                         ((text *)bind->array.elements)[i*maxlength + element_length] = '\0';
    1562             :                         
    1563          50 :                         zend_hash_move_forward(hash);
    1564             :                 } else {
    1565         210 :                         ((text *)bind->array.elements)[i*maxlength] = '\0';
    1566             :                 }
    1567             :         }
    1568          13 :         zend_hash_internal_pointer_reset(hash);
    1569             : 
    1570          13 :         return bind;
    1571             : } /* }}} */
    1572             : 
    1573             : /* {{{ php_oci_bind_array_helper_number()
    1574             :  Bind arrays to PL/SQL types */
    1575           3 : 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           3 :         hash = HASH_OF(var);
    1583             : 
    1584           3 :         bind = emalloc(sizeof(php_oci_bind));
    1585           3 :         bind->array.elements         = (ub4 *)safe_emalloc(max_table_length, sizeof(ub4), 0);
    1586           3 :         bind->array.current_length   = zend_hash_num_elements(Z_ARRVAL_P(var));
    1587           3 :         bind->array.old_length               = bind->array.current_length;
    1588           3 :         bind->array.max_length               = sizeof(ub4);
    1589           3 :         bind->array.element_lengths  = safe_emalloc(max_table_length, sizeof(ub2), 0);
    1590           3 :         memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
    1591           3 :         bind->array.indicators               = NULL;
    1592             :         
    1593           3 :         zend_hash_internal_pointer_reset(hash);
    1594          23 :         for (i = 0; i < max_table_length; i++) {
    1595          20 :                 if (i < bind->array.current_length) {
    1596          10 :                         bind->array.element_lengths[i] = sizeof(ub4);
    1597             :                 }
    1598          30 :                 if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
    1599          10 :                         convert_to_long_ex(entry);
    1600          10 :                         ((ub4 *)bind->array.elements)[i] = (ub4) Z_LVAL_PP(entry);
    1601          10 :                         zend_hash_move_forward(hash);
    1602             :                 } else {
    1603          10 :                         ((ub4 *)bind->array.elements)[i] = 0;
    1604             :                 }
    1605             :         }
    1606           3 :         zend_hash_internal_pointer_reset(hash);
    1607             : 
    1608           3 :         return bind;
    1609             : } /* }}} */
    1610             : 
    1611             : /* {{{ php_oci_bind_array_helper_double()
    1612             :  Bind arrays to PL/SQL types */
    1613           2 : 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           2 :         hash = HASH_OF(var);
    1621             : 
    1622           2 :         bind = emalloc(sizeof(php_oci_bind));
    1623           2 :         bind->array.elements         = (double *)safe_emalloc(max_table_length, sizeof(double), 0);
    1624           2 :         bind->array.current_length   = zend_hash_num_elements(Z_ARRVAL_P(var));
    1625           2 :         bind->array.old_length               = bind->array.current_length;
    1626           2 :         bind->array.max_length               = sizeof(double);
    1627           2 :         bind->array.element_lengths  = safe_emalloc(max_table_length, sizeof(ub2), 0);
    1628           2 :         memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
    1629           2 :         bind->array.indicators               = NULL;
    1630             :         
    1631           2 :         zend_hash_internal_pointer_reset(hash);
    1632          17 :         for (i = 0; i < max_table_length; i++) {
    1633          15 :                 if (i < bind->array.current_length) {
    1634          10 :                         bind->array.element_lengths[i] = sizeof(double);
    1635             :                 }
    1636          25 :                 if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
    1637          10 :                         convert_to_double_ex(entry);
    1638          10 :                         ((double *)bind->array.elements)[i] = (double) Z_DVAL_PP(entry);
    1639          10 :                         zend_hash_move_forward(hash);
    1640             :                 } else {
    1641           5 :                         ((double *)bind->array.elements)[i] = 0;
    1642             :                 }
    1643             :         }
    1644           2 :         zend_hash_internal_pointer_reset(hash);
    1645             : 
    1646           2 :         return bind;
    1647             : } /* }}} */
    1648             : 
    1649             : /* {{{ php_oci_bind_array_helper_date()
    1650             :  Bind arrays to PL/SQL types */
    1651           5 : 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           5 :         hash = HASH_OF(var);
    1659             : 
    1660           5 :         bind = emalloc(sizeof(php_oci_bind));
    1661           5 :         bind->array.elements         = (OCIDate *)safe_emalloc(max_table_length, sizeof(OCIDate), 0);
    1662           5 :         bind->array.current_length   = zend_hash_num_elements(Z_ARRVAL_P(var));
    1663           5 :         bind->array.old_length               = bind->array.current_length;
    1664           5 :         bind->array.max_length               = sizeof(OCIDate);
    1665           5 :         bind->array.element_lengths  = safe_emalloc(max_table_length, sizeof(ub2), 0);
    1666           5 :         memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
    1667           5 :         bind->array.indicators               = NULL;
    1668             : 
    1669           5 :         zend_hash_internal_pointer_reset(hash);
    1670          30 :         for (i = 0; i < max_table_length; i++) {
    1671             :                 OCIDate oci_date;
    1672          26 :                 if (i < bind->array.current_length) {
    1673          15 :                         bind->array.element_lengths[i] = sizeof(OCIDate);
    1674             :                 }
    1675          40 :                 if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
    1676             :                         
    1677          15 :                         convert_to_string_ex(entry);
    1678          15 :                         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          15 :                         if (connection->errcode != OCI_SUCCESS) {
    1681             :                                 /* failed to convert string to date */
    1682           1 :                                 efree(bind->array.element_lengths);
    1683           1 :                                 efree(bind->array.elements);
    1684           1 :                                 efree(bind);
    1685           1 :                                 connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
    1686           1 :                                 PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
    1687           1 :                                 return NULL;
    1688             :                         }
    1689             :                         
    1690          14 :                         ((OCIDate *)bind->array.elements)[i] = oci_date;
    1691          14 :                         zend_hash_move_forward(hash);
    1692             :                 } else {
    1693          11 :                         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          11 :                         if (connection->errcode != OCI_SUCCESS) {
    1696             :                                 /* failed to convert string to date */
    1697           0 :                                 efree(bind->array.element_lengths);
    1698           0 :                                 efree(bind->array.elements);
    1699           0 :                                 efree(bind);
    1700           0 :                                 connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
    1701           0 :                                 PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
    1702           0 :                                 return NULL;
    1703             :                         }
    1704             :         
    1705          11 :                         ((OCIDate *)bind->array.elements)[i] = oci_date;
    1706             :                 }
    1707             :         }
    1708           4 :         zend_hash_internal_pointer_reset(hash);
    1709             : 
    1710           4 :         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             :  */

Generated by: LCOV version 1.10

Generated at Sun, 31 Aug 2014 02:21:47 +0000 (40 hours ago)

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