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: 689 809 85.2 %
Date: 2016-09-27 Functions: 22 23 95.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Tue, 27 Sep 2016 10:26:01 +0000 (3 days ago)

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