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

Generated by: LCOV version 1.10

Generated at Wed, 27 Apr 2016 15:51:43 +0000 (5 days ago)

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