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-08-24 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       34525 : 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       34525 :         connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
      52             : 
      53       34525 :         statement = ecalloc(1,sizeof(php_oci_statement));
      54             : 
      55       34525 :         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       34525 :         PHP_OCI_CALL(OCIHandleAlloc, (connection->env, (dvoid **)&(statement->err), OCI_HTYPE_ERROR, 0, NULL));
      61             :         
      62       34525 :         if (query_len > 0) {
      63       33080 :                 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       33080 :                 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       67595 :         if (query && query_len) {
      94       33075 :                 statement->last_query = ecalloc(1, query_len + 1);
      95       33075 :                 memcpy(statement->last_query, query, query_len);
      96       33075 :                 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       34520 :         statement->connection = connection;
     104       34520 :         statement->has_data = 0;
     105       34520 :         statement->has_descr = 0;
     106       34520 :         statement->parent_stmtid = 0;
     107       34520 :         statement->impres_child_stmt = NULL;
     108       34520 :         statement->impres_count = 0;
     109       34520 :         statement->impres_flag = PHP_OCI_IMPRES_UNKNOWN;  /* may or may not have Implicit Result Set children */
     110       34520 :         ++GC_REFCOUNT(statement->connection->id);
     111             : 
     112       34520 :         if (OCI_G(default_prefetch) >= 0) {
     113       34520 :                 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       34520 :         PHP_OCI_REGISTER_RESOURCE(statement, le_statement);
     119             : 
     120       34520 :         OCI_G(num_statements)++;
     121             :         
     122       34520 :         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       34536 : int php_oci_statement_set_prefetch(php_oci_statement *statement, ub4 prefetch )
     188             : {
     189             :         sword errstatus;
     190             : 
     191       34536 :         if (prefetch > 20000) {
     192           0 :                 prefetch = 20000;               /* keep it somewhat sane */
     193             :         }
     194             : 
     195       34536 :         PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, (statement->stmt, OCI_HTYPE_STMT, &prefetch, 0, OCI_ATTR_PREFETCH_ROWS, statement->err));
     196             :         
     197       34536 :         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       34536 :         statement->prefetch_count = prefetch;
     204       34536 :         statement->errcode = 0; /* retain backwards compat with OCI8 1.4 */
     205       34536 :         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      232116 : 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      232116 :         zend_bool piecewisecols = 0;
     252             :         php_oci_out_column *column;
     253             :         sword errstatus;
     254             : 
     255      232116 :         statement->errcode = 0; /* retain backwards compat with OCI8 1.4 */
     256             : 
     257      232116 :         if (statement->has_descr && statement->columns) {
     258      224472 :                 zend_hash_apply(statement->columns, php_oci_cleanup_pre_fetch);
     259             :     }
     260             : 
     261      232116 :         PHP_OCI_CALL_RETURN(errstatus, OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT));
     262             : 
     263      232116 :         if (errstatus == OCI_NO_DATA || nrows == 0) {
     264       30359 :                 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       30359 :                 statement->has_data = 0;
     276             : 
     277       30359 :                 if (nrows == 0) {
     278             :                         /* this is exactly what we requested */
     279           8 :                         return 0;
     280             :                 }
     281       30351 :                 return 1;
     282             :         }
     283             : 
     284             :         /* reset length for all piecewise columns */
     285      594572 :         for (i = 0; i < statement->ncolumns; i++) {
     286      392815 :                 column = php_oci_statement_get_column(statement, i + 1, NULL, 0);
     287      392815 :                 if (column && column->piecewise) {
     288          13 :                         column->retlen4 = 0;
     289          13 :                         piecewisecols = 1;
     290             :                 }
     291             :         }
     292             :         
     293      403530 :         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      201757 :         if (errstatus == OCI_SUCCESS_WITH_INFO || errstatus == OCI_SUCCESS) {
     350      201748 :                 statement->has_data = 1;
     351             : 
     352             :                 /* do the stuff needed for OCIDefineByName */
     353      594556 :                 for (i = 0; i < statement->ncolumns; i++) {
     354      392808 :                         column = php_oci_statement_get_column(statement, i + 1, NULL, 0);
     355      392808 :                         if (column == NULL) {
     356           0 :                                 continue;
     357             :                         }
     358             :                         
     359      392808 :                         if (!column->define) {
     360      302761 :                                 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      201748 :                 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     1178752 : php_oci_out_column *php_oci_statement_get_column(php_oci_statement *statement, zend_long column_index, char *column_name, int column_name_len)
     382             : {
     383     1178752 :         php_oci_out_column *column = NULL;
     384             :         int i;
     385             : 
     386     1178752 :         if (statement->columns == NULL) { /* we release the columns at the end of a fetch */
     387           0 :                 return NULL;
     388             :         }
     389             : 
     390     1178752 :         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     1178676 :         } else if (column_index != -1) {
     400     2357338 :                 if ((column = zend_hash_index_find_ptr(statement->columns, column_index)) == NULL) {
     401           7 :                         return NULL;
     402             :                 }
     403     1178662 :                 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       37854 : int php_oci_statement_execute(php_oci_statement *statement, ub4 mode)
     481             : {
     482             :         php_oci_out_column *outcol;
     483       37854 :         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       37854 :         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       37853 :                         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       37853 :         if (!statement->stmttype) {
     511             :                 /* get statement type */
     512       34475 :                 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       34475 :                 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       34475 :                         statement->errcode = 0; /* retain backwards compat with OCI8 1.4 */
     520             :                 }
     521             :         }
     522             : 
     523       37853 :         if (statement->stmttype == OCI_STMT_SELECT) {
     524       32927 :                 iters = 0;
     525             :         } else {
     526        4926 :                 iters = 1;
     527             :         }
     528             :         
     529       37853 :         if (statement->last_query) { /* Don't execute REFCURSORS or Implicit Result Set handles */
     530             : 
     531       36415 :                 if (statement->binds) {
     532        3680 :                         int result = 0;
     533        3680 :                         zend_hash_apply_with_argument(statement->binds, php_oci_bind_pre_exec, (void *)&result);
     534        3680 :                         if (result) {
     535           2 :                                 return 1;
     536             :                         }
     537             :                 }
     538             : 
     539             :                 /* execute statement */
     540       36413 :                 PHP_OCI_CALL_RETURN(errstatus, OCIStmtExecute, (statement->connection->svc, statement->stmt, statement->err, iters, 0, NULL, NULL, mode));
     541             : 
     542       36413 :                 if (errstatus != OCI_SUCCESS) {
     543         260 :                         statement->errcode = php_oci_error(statement->err, errstatus);
     544         260 :                         PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
     545         260 :                         return 1;
     546             :                 }
     547             :                 
     548       36153 :                 if (statement->binds) {
     549        3656 :                         zend_hash_apply(statement->binds, php_oci_bind_post_exec);
     550             :                 }
     551             : 
     552       36153 :                 if (mode & OCI_COMMIT_ON_SUCCESS) {
     553             :                         /* No need to rollback on disconnect */
     554       34470 :                         statement->connection->rb_on_disconnect = 0;
     555        1683 :                 } 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       36153 :                 statement->errcode = 0; /* retain backwards compat with OCI8 1.4 */
     567             :         }
     568             : 
     569       37591 :         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       32859 :                 statement->executed = 1;
     572             :                 
     573       32859 :                 ALLOC_HASHTABLE(statement->columns);
     574       32859 :                 zend_hash_init(statement->columns, 13, NULL, php_oci_column_hash_dtor, 0);
     575             :                 
     576       32859 :                 counter = 1;
     577             : 
     578             :                 /* get number of columns */
     579       32859 :                 PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (dvoid *)&colcount, (ub4 *)0, OCI_ATTR_PARAM_COUNT, statement->err));
     580             :                 
     581       32859 :                 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       32859 :                 statement->ncolumns = colcount;
     588             :                 
     589       96361 :                 for (counter = 1; counter <= colcount; counter++) {
     590       63502 :                         outcol = (php_oci_out_column *) ecalloc(1, sizeof(php_oci_out_column));
     591             :                         
     592      127004 :                         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       63502 :                         PHP_OCI_CALL_RETURN(errstatus, OCIParamGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, statement->err, (dvoid**)&param, counter));
     600             :                         
     601       63502 :                         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       63502 :                         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       63502 :                         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       63502 :                         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       63502 :                         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       63502 :                         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       63502 :                         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       63502 :                         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       63502 :                         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       63502 :                         outcol->storage_size4 = outcol->data_size;
     648       63502 :                         outcol->retlen = outcol->data_size;
     649             : 
     650             :                         /* get scale of the column */
     651       63502 :                         PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->scale, (dvoid *)0, OCI_ATTR_SCALE, statement->err));
     652             :                         
     653       63502 :                         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       63502 :                         PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->precision, (dvoid *)0, OCI_ATTR_PRECISION, statement->err));
     662             :                         
     663       63502 :                         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       63502 :                         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       63502 :                         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       63502 :                         PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
     680             : 
     681       63502 :                         outcol->name = ecalloc(1, outcol->name_len + 1);
     682       63502 :                         memcpy(outcol->name, colname, outcol->name_len);
     683             : 
     684             :                         /* find a user-set define */
     685       63502 :                         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       63502 :                         buf = 0;
     694       63502 :                         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        1950 :                                         define_type = SQLT_CHR;
     735        1950 :                                         if (outcol->data_type == SQLT_BIN) {
     736           5 :                                                 define_type = SQLT_BIN;
     737             :                                         }
     738        7284 :                                         if ((outcol->data_type == SQLT_DAT) || (outcol->data_type == SQLT_NUM)
     739             : #ifdef SQLT_TIMESTAMP
     740         849 :                                                 || (outcol->data_type == SQLT_TIMESTAMP)
     741             : #endif
     742             : #ifdef SQLT_TIMESTAMP_TZ
     743         846 :                                                 || (outcol->data_type == SQLT_TIMESTAMP_TZ)
     744             : #endif
     745             : #ifdef SQLT_TIMESTAMP_LTZ
     746         844 :                                                 || (outcol->data_type == SQLT_TIMESTAMP_LTZ)
     747             : #endif
     748             : #ifdef SQLT_INTERVAL_YM
     749         843 :                                                 || (outcol->data_type == SQLT_INTERVAL_YM)
     750             : #endif
     751             : #ifdef SQLT_INTERVAL_DS
     752         841 :                                                 || (outcol->data_type == SQLT_INTERVAL_DS)
     753             : #endif
     754             :                                                 ) {
     755        1111 :                                                 outcol->storage_size4 = 512; /* XXX this should fit "most" NLS date-formats and Numbers */
     756             : #if defined(SQLT_IBFLOAT) && defined(SQLT_IBDOUBLE)
     757         844 :                                         } else if (outcol->data_type == SQLT_IBFLOAT || outcol->data_type == SQLT_IBDOUBLE) {
     758           5 :                                                 outcol->storage_size4 = 1024;
     759             : #endif
     760             :                                         } else {
     761         834 :                                                 outcol->storage_size4++; /* add one for string terminator */
     762             :                                         }
     763             :                                         
     764        1950 :                                         outcol->storage_size4 *= 3;
     765             :                                         
     766        1950 :                                         dynamic = OCI_DEFAULT;
     767        1950 :                                         buf = outcol->data = (text *) safe_emalloc(1, outcol->storage_size4, 0);
     768        1950 :                                         memset(buf, 0, outcol->storage_size4);
     769             :                                         break;
     770             :                         }
     771             : 
     772       63502 :                         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        1950 :                                 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       63502 :                         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       63502 :                         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       32859 :                 statement->errcode = 0; /* retain backwards compat with OCI8 1.4 */
     842             :         }
     843             : 
     844       37591 :         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       34520 : void php_oci_statement_free(php_oci_statement *statement)
     859             : {
     860       34520 :         if (statement->stmt) {
     861       34520 :                 if (statement->last_query_len) { /* FIXME: magical */
     862       33075 :                         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       34520 :                 statement->stmt = NULL;
     867             :         }
     868             : 
     869       34520 :         if (statement->err) {
     870       34520 :                 PHP_OCI_CALL(OCIHandleFree, (statement->err, OCI_HTYPE_ERROR));
     871       34520 :                 statement->err = NULL;
     872             :         }
     873             : 
     874       34520 :         if (statement->last_query) {
     875       33075 :                 efree(statement->last_query);
     876             :         }
     877             : 
     878       34520 :         if (statement->binds) {
     879         400 :                 zend_hash_destroy(statement->binds);
     880         400 :                 efree(statement->binds);
     881             :         }
     882             : 
     883       34520 :         if (statement->defines) {
     884       15037 :                 zend_hash_destroy(statement->defines);
     885       15037 :                 efree(statement->defines);
     886             :         }
     887             : 
     888       34520 :         if (statement->columns) {
     889       32841 :                 zend_hash_destroy(statement->columns);
     890       32841 :                 efree(statement->columns);
     891             :         }
     892             : 
     893       34520 :         if (statement->parent_stmtid) {
     894        1417 :                 zend_list_delete(statement->parent_stmtid);
     895             :         }
     896             : 
     897       34520 :         zend_list_delete(statement->connection->id);
     898       34520 :         efree(statement);
     899             :         
     900       34520 :         OCI_G(num_statements)--;
     901       34520 : }
     902             : /* }}} */
     903             : 
     904             : /* {{{ php_oci_bind_pre_exec()
     905             :  Helper function */
     906        5797 : int php_oci_bind_pre_exec(zval *data, void *result)
     907             : {
     908        5797 :         php_oci_bind *bind = (php_oci_bind *) Z_PTR_P(data);
     909             : 
     910        5797 :         *(int *)result = 0;
     911             : 
     912       11594 :         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        5775 :         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       16639 :                         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        5547 :                         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        5775 :         bind->indicator = 0;
     958             : 
     959        5775 :         return 0;
     960             : }
     961             : /* }}} */
     962             : 
     963             : /* {{{ php_oci_bind_post_exec()
     964             :  Helper function */
     965        5765 : int php_oci_bind_post_exec(zval *data)
     966             : {
     967        5765 :         php_oci_bind *bind = (php_oci_bind *) Z_PTR_P(data);
     968        5765 :         php_oci_connection *connection = bind->parent_statement->connection;
     969             :         sword errstatus;
     970             : 
     971        5765 :         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       20967 :         } else if (Z_TYPE_P(bind->zval) == IS_STRING
     979        4802 :                            && Z_STRLEN_P(bind->zval) > 0
     980        9583 :                            && 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       11384 :         } 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       17019 :         } 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        5765 :         return 0;
    1082             : }
    1083             : /* }}} */
    1084             : 
    1085             : /* {{{ php_oci_bind_by_name()
    1086             :  Bind zval to the given placeholder */
    1087        4181 : 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        4181 :         php_oci_collection *bind_collection = NULL;
    1090        4181 :         php_oci_descriptor *bind_descriptor = NULL;
    1091        4181 :         php_oci_statement  *bind_statement      = NULL;
    1092        4181 :         dvoid *oci_desc                                 = NULL;
    1093             :         /* dvoid *php_oci_collection               = NULL; */
    1094        4181 :         OCIStmt *oci_stmt                               = NULL;
    1095        4181 :         dvoid *bind_data                                = NULL;
    1096             :         php_oci_bind *old_bind, *bindp;
    1097        4181 :         int mode = OCI_DATA_AT_EXEC;
    1098        4181 :         sb4 value_sz = -1;
    1099             :         sword errstatus;
    1100             : 
    1101        4181 :         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         110 :                         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          55 :                         convert_to_long(var);
    1152             : #if defined(OCI_MAJOR_VERSION) && (OCI_MAJOR_VERSION > 10) &&                        \
    1153             :         (defined(__x86_64__) || defined(__LP64__) || defined(_LP64) || defined(_WIN64)) 
    1154          55 :                         bind_data = (ub8 *)&Z_LVAL_P(var);
    1155          55 :                         value_sz = sizeof(ub8);
    1156             : #else
    1157             :                         bind_data = (ub4 *)&Z_LVAL_P(var);
    1158             :                         value_sz = sizeof(ub4);
    1159             : #endif
    1160          55 :                         mode = OCI_DEFAULT;
    1161          55 :                         break;
    1162             :                         
    1163             :                 case SQLT_LBI:
    1164             :                 case SQLT_BIN:
    1165             :                 case SQLT_LNG:
    1166             :                 case SQLT_AFC:
    1167             :                 case SQLT_CHR: /* SQLT_CHR is the default value when type was not specified */
    1168        7784 :                         if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) {
    1169           2 :                                 php_error_docref(NULL, E_WARNING, "Invalid variable used for bind");
    1170           2 :                                 return 1;
    1171             :                         }
    1172        3891 :                         if (Z_TYPE_P(var) != IS_NULL) {
    1173        3810 :                                 convert_to_string(var);
    1174             :                         }
    1175        7706 :                         if ((maxlength == -1) || (maxlength == 0)) {
    1176        3815 :                                 if (type == SQLT_LNG) {
    1177           2 :                                         value_sz = SB4MAXVAL;
    1178        3813 :                                 } else if (Z_TYPE_P(var) == IS_STRING) {
    1179        3773 :                                         value_sz = (sb4) Z_STRLEN_P(var);
    1180             :                                 } else {
    1181          40 :                                         value_sz = PHP_OCI_PIECE_SIZE;
    1182             :                                 }
    1183             :                         } else {
    1184          76 :                                 value_sz = (sb4) maxlength;
    1185             :                         }
    1186        3891 :                         break;
    1187             : 
    1188             :                 case SQLT_RSET:
    1189          38 :                         if (Z_TYPE_P(var) != IS_RESOURCE) {
    1190           0 :                                 php_error_docref(NULL, E_WARNING, "Invalid variable used for bind");
    1191           0 :                                 return 1;
    1192             :                         }
    1193          38 :                         PHP_OCI_ZVAL_TO_STATEMENT_EX(var, bind_statement);
    1194          38 :                         value_sz = sizeof(void*);
    1195             : 
    1196          38 :                         oci_stmt = bind_statement->stmt;
    1197             : 
    1198          38 :                         if (!oci_stmt) {
    1199           0 :                                 return 1;
    1200             :                         }
    1201          38 :                         break;
    1202             : 
    1203             : #if defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION >= 12
    1204             :                 case SQLT_BOL:
    1205             :                         if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) {
    1206             :                                 php_error_docref(NULL, E_WARNING, "Invalid variable used for bind");
    1207             :                                 return 1;
    1208             :                         }
    1209             :                         convert_to_boolean(var);
    1210             :                         bind_data = (zend_long *)&Z_LVAL_P(var);
    1211             :                         if (Z_TYPE_P(var) == IS_TRUE)
    1212             :                                 *(zend_long *)bind_data = 1;
    1213             :                         else if (Z_TYPE_P(var) == IS_FALSE)
    1214             :                                 *(zend_long *)bind_data = 0;
    1215             :                         else {
    1216             :                                 php_error_docref(NULL, E_WARNING, "Invalid variable used for bind");
    1217             :                                 return 1;
    1218             :                         }
    1219             : 
    1220             :                         value_sz = sizeof(zend_long);
    1221             : 
    1222             :                         mode = OCI_DEFAULT;
    1223             :                         break;
    1224             : #endif
    1225             : 
    1226             :                 default:
    1227           9 :                         php_error_docref(NULL, E_WARNING, "Unknown or unsupported datatype given: %d", (int)type);
    1228           9 :                         return 1;
    1229             :                         break;
    1230             :         }
    1231             : 
    1232        4170 :         if (!statement->binds) {
    1233         381 :                 ALLOC_HASHTABLE(statement->binds);
    1234         381 :                 zend_hash_init(statement->binds, 13, NULL, php_oci_bind_hash_dtor, 0);
    1235             :         }
    1236             : 
    1237        8340 :         if ((old_bind = zend_hash_str_find_ptr(statement->binds, name, name_len)) != NULL) {
    1238        3625 :                 bindp = old_bind;
    1239             :         } else {
    1240             :                 zend_string *zvtmp;
    1241         545 :                 zvtmp = zend_string_init(name, name_len, 0);
    1242         545 :                 bindp = (php_oci_bind *) ecalloc(1, sizeof(php_oci_bind));
    1243        1090 :                 bindp = zend_hash_update_ptr(statement->binds, zvtmp, bindp);
    1244             :                 zend_string_release(zvtmp);
    1245             :         }
    1246             :         
    1247        4170 :         bindp->descriptor = oci_desc;
    1248        4170 :         bindp->statement = oci_stmt;
    1249        4170 :         bindp->parent_statement = statement;
    1250        4170 :         bindp->zval = var;
    1251        4170 :         bindp->type = type;
    1252             :         /* Storing max length set in OCIBindByName() to check it later in
    1253             :          * php_oci_bind_in_callback() function to avoid ORA-1406 error while
    1254             :          * executing OCIStmtExecute()
    1255             :      */
    1256        4170 :         bindp->dummy_len = value_sz;
    1257             : 
    1258        4170 :         PHP_OCI_CALL_RETURN(errstatus,
    1259             :                 OCIBindByName,
    1260             :                 (
    1261             :                         statement->stmt,                              /* statement handle */
    1262             :                         (OCIBind **)&bindp->bind,                 /* bind hdl (will alloc) */
    1263             :                         statement->err,                                       /* error handle */
    1264             :                         (text*) name,                                    /* placeholder name */                                 
    1265             :                         (sb4) name_len,                                  /* placeholder length */
    1266             :                         (dvoid *)bind_data,                              /* in/out data */
    1267             :                         value_sz, /* PHP_OCI_MAX_DATA_SIZE, */ /* max size of input/output data */
    1268             :                         type,                                                    /* in/out data type */
    1269             :                         (dvoid *)&bindp->indicator,               /* indicator (ignored) */
    1270             :                         (ub2 *)0,                                                /* size array (ignored) */
    1271             :                         (ub2 *)&bindp->retcode,                   /* return code (ignored) */
    1272             :                         (ub4)0,                                                  /* maxarr_len (PL/SQL only?) */
    1273             :                         (ub4 *)0,                                                /* actual array size (PL/SQL only?) */
    1274             :                         mode                                                     /* mode */
    1275             :                 )
    1276             :         );
    1277             : 
    1278        4170 :         if (errstatus != OCI_SUCCESS) {
    1279           2 :                 statement->errcode = php_oci_error(statement->err, errstatus);
    1280           2 :                 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
    1281           2 :                 return 1;
    1282             :         }
    1283             : 
    1284        4168 :         if (mode == OCI_DATA_AT_EXEC) {
    1285        4112 :                 PHP_OCI_CALL_RETURN(errstatus, OCIBindDynamic,
    1286             :                                 (
    1287             :                                  bindp->bind,
    1288             :                                  statement->err,
    1289             :                                  (dvoid *)bindp,
    1290             :                                  php_oci_bind_in_callback,
    1291             :                                  (dvoid *)bindp,
    1292             :                                  php_oci_bind_out_callback
    1293             :                                 )
    1294             :                 );
    1295             : 
    1296        4112 :                 if (errstatus != OCI_SUCCESS) {
    1297           0 :                         statement->errcode = php_oci_error(statement->err, errstatus);
    1298           0 :                         PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
    1299           0 :                         return 1;
    1300             :                 }
    1301             :         }
    1302             : 
    1303        4168 :         if (type == SQLT_NTY) {
    1304             :                 /* Bind object */
    1305           1 :                 PHP_OCI_CALL_RETURN(errstatus, OCIBindObject,
    1306             :                                 (
    1307             :                                  bindp->bind,
    1308             :                                  statement->err,
    1309             :                                  bind_collection->tdo,
    1310             :                                  (dvoid **) &(bind_collection->collection),
    1311             :                                  (ub4 *) 0,
    1312             :                                  (dvoid **) 0,
    1313             :                                  (ub4 *) 0
    1314             :                                 )
    1315             :                 );
    1316             :                 
    1317           1 :                 if (errstatus) {
    1318           0 :                         statement->errcode = php_oci_error(statement->err, errstatus);
    1319           0 :                         PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
    1320           0 :                         return 1;
    1321             :                 }
    1322             :         }
    1323             :         
    1324        4168 :         statement->errcode = 0; /* retain backwards compat with OCI8 1.4 */
    1325        4168 :         return 0;
    1326             : }
    1327             : /* }}} */
    1328             : 
    1329             : /* {{{ php_oci_bind_in_callback()
    1330             :  Callback used when binding LOBs and VARCHARs */
    1331        4333 : sb4 php_oci_bind_in_callback(
    1332             :                                         dvoid *ictxp,     /* context pointer */
    1333             :                                         OCIBind *bindp,   /* bind handle */
    1334             :                                         ub4 iter,                 /* 0-based execute iteration value */
    1335             :                                         ub4 index,                /* index of current array for PL/SQL or row index for SQL */
    1336             :                                         dvoid **bufpp,    /* pointer to data */
    1337             :                                         ub4 *alenp,               /* size after value/piece has been read */
    1338             :                                         ub1 *piecep,      /* which piece */
    1339             :                                         dvoid **indpp)    /* indicator value */
    1340             : {
    1341             :         php_oci_bind *phpbind;
    1342             :         zval *val;
    1343             : 
    1344        4333 :         if (!(phpbind=(php_oci_bind *)ictxp) || !(val = phpbind->zval)) {
    1345           0 :                 php_error_docref(NULL, E_WARNING, "Invalid phpbind pointer value");
    1346           0 :                 return OCI_ERROR;
    1347             :         }
    1348             : 
    1349        4333 :         if (Z_ISNULL_P(val)) {
    1350             :                 /* we're going to insert a NULL column */
    1351          51 :                 phpbind->indicator = -1;
    1352          51 :                 *bufpp = 0;
    1353          51 :                 *alenp = -1;
    1354          51 :                 *indpp = (dvoid *)&phpbind->indicator;
    1355        8358 :         } else  if ((phpbind->descriptor == 0) && (phpbind->statement == 0)) {
    1356             :                 /* "normal string bind */
    1357        4076 :                 convert_to_string(val);
    1358             : 
    1359        4076 :                 *bufpp = Z_STRVAL_P(val);
    1360        4076 :                 *alenp = (ub4) Z_STRLEN_P(val);
    1361             :                 /*
    1362             :                  * bind_char_1: If max length set in OCIBindByName is less than the
    1363             :                  * actual length of input string, then we have to overwrite alenp with
    1364             :                  * max value set in OCIBindByName (dummy_len). Or else it will cause
    1365             :                  * ORA-1406 error in OCIStmtExecute
    1366             :                  */
    1367        4076 :                 if ((phpbind->dummy_len > 0) && (phpbind->dummy_len < *alenp))
    1368           3 :                         *alenp = phpbind->dummy_len;
    1369        4076 :                 *indpp = (dvoid *)&phpbind->indicator;
    1370         206 :         } else if (phpbind->statement != 0) {
    1371             :                 /* RSET */
    1372          23 :                 *bufpp = phpbind->statement;
    1373          23 :                 *alenp = -1;            /* seems to be allright */
    1374          23 :                 *indpp = (dvoid *)&phpbind->indicator;
    1375             :         } else {
    1376             :                 /* descriptor bind */
    1377         183 :                 *bufpp = phpbind->descriptor;
    1378         183 :                 *alenp = -1;            /* seems to be allright */
    1379         183 :                 *indpp = (dvoid *)&phpbind->indicator;
    1380             :         }
    1381             : 
    1382        4333 :         *piecep = OCI_ONE_PIECE; /* pass all data in one go */
    1383             : 
    1384        4333 :         return OCI_CONTINUE;
    1385             : }
    1386             : /* }}} */
    1387             : 
    1388             : /* {{{ php_oci_bind_out_callback()
    1389             :  Callback used when binding LOBs and VARCHARs */
    1390         865 : sb4 php_oci_bind_out_callback(
    1391             :                                         dvoid *octxp,      /* context pointer */
    1392             :                                         OCIBind *bindp,    /* bind handle */
    1393             :                                         ub4 iter,                  /* 0-based execute iteration value */
    1394             :                                         ub4 index,                 /* index of current array for PL/SQL or row index for SQL */
    1395             :                                         dvoid **bufpp,     /* pointer to data */
    1396             :                                         ub4 **alenpp,      /* size after value/piece has been read */
    1397             :                                         ub1 *piecep,       /* which piece */
    1398             :                                         dvoid **indpp,     /* indicator value */
    1399             :                                         ub2 **rcodepp)     /* return code */
    1400             : {
    1401             :         php_oci_bind *phpbind;
    1402             :         zval *val;
    1403         865 :         sb4 retval = OCI_ERROR;
    1404             : 
    1405         865 :         if (!(phpbind=(php_oci_bind *)octxp) || !(val = phpbind->zval)) {
    1406           0 :                 php_error_docref(NULL, E_WARNING, "Invalid phpbind pointer value");
    1407           0 :                 return retval;
    1408             :         }
    1409             : 
    1410         865 :         if (Z_TYPE_P(val) == IS_RESOURCE) {
    1411             :                 /* Processing for ref-cursor out binds */
    1412          31 :                 if (phpbind->statement != NULL) {
    1413          31 :                         *bufpp = phpbind->statement;
    1414          31 :                         *alenpp = &phpbind->dummy_len;
    1415          31 :                         *piecep = OCI_ONE_PIECE;
    1416          31 :                         *rcodepp = &phpbind->retcode;
    1417          31 :                         *indpp = &phpbind->indicator;
    1418             :                 }
    1419          31 :                 retval = OCI_CONTINUE;
    1420         834 :         } else if (Z_TYPE_P(val) == IS_OBJECT) {
    1421             :                 zval *tmp;
    1422             :                 php_oci_descriptor *desc;
    1423             : 
    1424          80 :                 if (!phpbind->descriptor) {
    1425           0 :                         return OCI_ERROR;
    1426             :                 }
    1427             : 
    1428             :                 /* Do not use the cached lob size if the descriptor is an
    1429             :                  * out-bind as the contents would have been changed for in/out
    1430             :                  * binds (Bug #46994).
    1431             :                  */
    1432          80 :                 if ((tmp = zend_hash_str_find(Z_OBJPROP_P(val), "descriptor", sizeof("descriptor")-1)) == NULL) {
    1433           0 :                         php_error_docref(NULL, E_WARNING, "Unable to find object outbind descriptor property");
    1434           0 :                         return OCI_ERROR;
    1435             :                 }
    1436          80 :                 PHP_OCI_ZVAL_TO_DESCRIPTOR_EX(tmp, desc);
    1437          80 :                 desc->lob_size = -1; /* force OCI8 to update cached size */
    1438             : 
    1439          80 :                 *alenpp = &phpbind->dummy_len;
    1440          80 :                 *bufpp = phpbind->descriptor;
    1441          80 :                 *piecep = OCI_ONE_PIECE;
    1442          80 :                 *rcodepp = &phpbind->retcode;
    1443          80 :                 *indpp = &phpbind->indicator;
    1444          80 :                 retval = OCI_CONTINUE;
    1445             :         } else {
    1446         754 :                 convert_to_string(val);
    1447             :                 zval_dtor(val);
    1448             : 
    1449             :                 {
    1450         754 :                         char *p = ecalloc(1, PHP_OCI_PIECE_SIZE);
    1451        1508 :                         ZVAL_STRINGL(val, p, PHP_OCI_PIECE_SIZE);
    1452         754 :                         efree(p);
    1453             :                 }
    1454             : #if 0
    1455             :                 Z_STRLEN_P(val) = PHP_OCI_PIECE_SIZE; /* 64K-1 is max XXX */
    1456             :                 Z_STRVAL_P(val) = ecalloc(1, Z_STRLEN_P(val) + 1);
    1457             :                 /* XXX is this right? */
    1458             :                 ZVAL_STRINGL(val, NULL, Z_STRLEN(phpbind->zval) + 1);
    1459             : #endif          
    1460             : 
    1461             :                 /* XXX we assume that zend-zval len has 4 bytes */
    1462         754 :                 *alenpp = (ub4*) &Z_STRLEN_P(phpbind->zval);
    1463         754 :                 *bufpp = Z_STRVAL_P(phpbind->zval);
    1464         754 :                 *piecep = OCI_ONE_PIECE;
    1465         754 :                 *rcodepp = &phpbind->retcode;
    1466         754 :                 *indpp = &phpbind->indicator;
    1467         754 :                 retval = OCI_CONTINUE;
    1468             :         }
    1469             : 
    1470         865 :         return retval;
    1471             : }
    1472             : /* }}} */
    1473             : 
    1474             : /* {{{ php_oci_statement_get_column_helper()
    1475             :  Helper function to get column by name and index */
    1476         416 : php_oci_out_column *php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAMETERS, int need_data)
    1477             : {
    1478             :         zval *z_statement, *column_index;
    1479             :         php_oci_statement *statement;
    1480             :         php_oci_out_column *column;
    1481             : 
    1482         416 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz", &z_statement, &column_index) == FAILURE) {
    1483           9 :                 return NULL;
    1484             :         }
    1485             : 
    1486         407 :         statement = (php_oci_statement *) zend_fetch_resource_ex(z_statement, "oci8 statement", le_statement);
    1487             : 
    1488         407 :         if (!statement) {
    1489           8 :                 return NULL;
    1490             :         }
    1491             : 
    1492         399 :         if (need_data && !statement->has_data) {
    1493           1 :                 return NULL;
    1494             :         }
    1495             :         
    1496         796 :         if (Z_TYPE_P(column_index) == IS_STRING) {
    1497          76 :                 column = php_oci_statement_get_column(statement, -1, Z_STRVAL_P(column_index), (int) Z_STRLEN_P(column_index));
    1498          76 :                 if (!column) {
    1499           7 :                         php_error_docref(NULL, E_WARNING, "Invalid column name \"%s\"", Z_STRVAL_P(column_index));
    1500           7 :                         return NULL;
    1501             :                 }
    1502             :         } else {
    1503             :                 zval tmp;
    1504             :                 /* NB: for PHP4 compat only, it should be using 'Z' instead */
    1505         322 :                 tmp = *column_index;
    1506             :                 zval_copy_ctor(&tmp);
    1507         322 :                 convert_to_long(&tmp);
    1508         322 :                 column = php_oci_statement_get_column(statement, Z_LVAL(tmp), NULL, 0);
    1509         322 :                 if (!column) {
    1510          14 :                         php_error_docref(NULL, E_WARNING, "Invalid column index \"" ZEND_LONG_FMT "\"", Z_LVAL(tmp));
    1511             :                         zval_dtor(&tmp);
    1512          14 :                         return NULL;
    1513             :                 }
    1514             :                 zval_dtor(&tmp);
    1515             :         }
    1516         377 :         return column;
    1517             : }
    1518             : /* }}} */
    1519             : 
    1520             : /* {{{ php_oci_statement_get_type()
    1521             :  Return type of the statement */
    1522          26 : int php_oci_statement_get_type(php_oci_statement *statement, ub2 *type)
    1523             : {
    1524             :         ub2 statement_type;
    1525             :         sword errstatus;
    1526             :         
    1527          26 :         *type = 0;
    1528             :         
    1529          26 :         PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)&statement_type, (ub4 *)0, OCI_ATTR_STMT_TYPE, statement->err));
    1530             : 
    1531          26 :         if (errstatus != OCI_SUCCESS) {
    1532           0 :                 statement->errcode = php_oci_error(statement->err, errstatus);
    1533           0 :                 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
    1534           0 :                 return 1;
    1535             :         }
    1536          26 :         statement->errcode = 0; /* retain backwards compat with OCI8 1.4 */
    1537          26 :         *type = statement_type;
    1538             : 
    1539          26 :         return 0;
    1540             : }
    1541             : /* }}} */
    1542             : 
    1543             : /* {{{ php_oci_statement_get_numrows()
    1544             :  Get the number of rows fetched to the clientside (NOT the number of rows in the result set) */
    1545          26 : int php_oci_statement_get_numrows(php_oci_statement *statement, ub4 *numrows)
    1546             : {
    1547             :         ub4 statement_numrows;
    1548             :         sword errstatus;
    1549             :         
    1550          26 :         *numrows = 0;
    1551             :         
    1552          26 :         PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub4 *)&statement_numrows, (ub4 *)0, OCI_ATTR_ROW_COUNT, statement->err));
    1553             : 
    1554          26 :         if (errstatus != OCI_SUCCESS) {
    1555           0 :                 statement->errcode = php_oci_error(statement->err, errstatus);
    1556           0 :                 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
    1557           0 :                 return 1;
    1558             :         }
    1559          26 :         statement->errcode = 0; /* retain backwards compat with OCI8 1.4 */
    1560          26 :         *numrows = statement_numrows;
    1561             : 
    1562          26 :         return 0;
    1563             : }
    1564             : /* }}} */
    1565             : 
    1566             : /* {{{ php_oci_bind_array_by_name()
    1567             :  Bind arrays to PL/SQL types */
    1568          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)
    1569             : {
    1570             :         php_oci_bind *bind, *bindp;
    1571             :         sword errstatus;
    1572             :         zend_string *zvtmp;
    1573             : 
    1574          32 :         convert_to_array(var);
    1575             : 
    1576          32 :         if (maxlength < -1) {
    1577           1 :                 php_error_docref(NULL, E_WARNING, "Invalid max length value (" ZEND_LONG_FMT ")", maxlength);
    1578           1 :                 return 1;
    1579             :         }
    1580             :         
    1581          31 :         switch(type) {
    1582             :                 case SQLT_NUM:
    1583             :                 case SQLT_INT:
    1584             :                 case SQLT_LNG:
    1585           3 :                         bind = php_oci_bind_array_helper_number(var, max_table_length);
    1586           3 :                         break;
    1587             : 
    1588             :                 case SQLT_FLT:
    1589           2 :                         bind = php_oci_bind_array_helper_double(var, max_table_length);
    1590           2 :                         break;
    1591             :                         
    1592             :                 case SQLT_AFC:
    1593             :                 case SQLT_CHR:
    1594             :                 case SQLT_VCS:
    1595             :                 case SQLT_AVC:
    1596             :                 case SQLT_STR:
    1597             :                 case SQLT_LVC:
    1598          17 :                         if (maxlength == -1 && zend_hash_num_elements(Z_ARRVAL_P(var)) == 0) {
    1599           4 :                                 php_error_docref(NULL, E_WARNING, "You must provide max length value for empty arrays");
    1600           4 :                                 return 1;
    1601             :                         }
    1602          13 :                         bind = php_oci_bind_array_helper_string(var, max_table_length, maxlength);
    1603          13 :                         break;
    1604             :                 case SQLT_ODT:
    1605           5 :                         bind = php_oci_bind_array_helper_date(var, max_table_length, statement->connection);
    1606           5 :                         break;
    1607             :                 default:
    1608           4 :                         php_error_docref(NULL, E_WARNING, "Unknown or unsupported datatype given: " ZEND_LONG_FMT, type);
    1609           4 :                         return 1;
    1610             :                         break;
    1611             :         }
    1612             : 
    1613          23 :         if (bind == NULL) {
    1614             :                 /* failed to generate bind struct */
    1615           1 :                 return 1;
    1616             :         }
    1617             :         
    1618          22 :         bind->descriptor = NULL;
    1619          22 :         bind->statement = NULL;
    1620          22 :         bind->parent_statement = statement;
    1621          22 :         bind->bind = NULL;
    1622          22 :         bind->zval = var;
    1623          22 :         bind->array.type = type;
    1624          22 :         bind->indicator = 0;                 /* not used for array binds */
    1625          22 :         bind->type = 0;                      /* not used for array binds */
    1626             : 
    1627          22 :         PHP_OCI_CALL_RETURN(errstatus,
    1628             :                                                         OCIBindByName,
    1629             :                                                         (
    1630             :                                                                 statement->stmt,
    1631             :                                                                 (OCIBind **)&bind->bind,
    1632             :                                                                 statement->err,
    1633             :                                                                 (text *)name,
    1634             :                                                                 (sb4) name_len,
    1635             :                                                                 (dvoid *) bind->array.elements,
    1636             :                                                                 (sb4) bind->array.max_length,
    1637             :                                                                 (ub2)type,
    1638             :                                                                 (dvoid *)bind->array.indicators,
    1639             :                                                                 (ub2 *)bind->array.element_lengths,
    1640             :                                                                 (ub2 *)0, /* bindp->array.retcodes, */
    1641             :                                                                 (ub4) max_table_length,
    1642             :                                                                 (ub4 *) &(bind->array.current_length),
    1643             :                                                                 (ub4) OCI_DEFAULT
    1644             :                                                         )
    1645             :                                                 );
    1646             :         
    1647             :                 
    1648          22 :         if (errstatus != OCI_SUCCESS) {
    1649           1 :                 if (bind->array.elements) {
    1650           1 :                         efree(bind->array.elements);
    1651             :                 }
    1652             : 
    1653           1 :                 if (bind->array.element_lengths) {
    1654           1 :                         efree(bind->array.element_lengths);
    1655             :                 }
    1656             : 
    1657           1 :                 if (bind->array.indicators) {
    1658           1 :                         efree(bind->array.indicators);
    1659             :                 }
    1660             : 
    1661           1 :                 efree(bind);
    1662             : 
    1663           1 :                 statement->errcode = php_oci_error(statement->err, errstatus);
    1664           1 :                 PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
    1665           1 :                 return 1;
    1666             :         }
    1667             : 
    1668          21 :         if (!statement->binds) {
    1669          19 :                 ALLOC_HASHTABLE(statement->binds);
    1670          19 :                 zend_hash_init(statement->binds, 13, NULL, php_oci_bind_hash_dtor, 0);
    1671             :         }
    1672             : 
    1673          21 :         zvtmp = zend_string_init(name, name_len, 0);
    1674          42 :         bindp = zend_hash_update_ptr(statement->binds, zvtmp, bind);
    1675             :         zend_string_release(zvtmp);
    1676             : 
    1677          21 :         statement->errcode = 0; /* retain backwards compat with OCI8 1.4 */
    1678          21 :         return 0;
    1679             : }
    1680             : /* }}} */
    1681             : 
    1682             : /* {{{ php_oci_bind_array_helper_string()
    1683             :  Bind arrays to PL/SQL types */
    1684          13 : php_oci_bind *php_oci_bind_array_helper_string(zval *var, zend_long max_table_length, zend_long maxlength)
    1685             : {
    1686             :         php_oci_bind *bind;
    1687             :         ub4 i;
    1688             :         HashTable *hash;
    1689             :         zval *entry;
    1690             : 
    1691          13 :         hash = HASH_OF(var);
    1692             : 
    1693          13 :         if (maxlength == -1) {
    1694           4 :                 zend_hash_internal_pointer_reset(hash);
    1695          28 :                 while ((entry = zend_hash_get_current_data(hash)) != NULL) {
    1696          20 :                         convert_to_string_ex(entry);
    1697             : 
    1698          20 :                         if (maxlength == -1 || Z_STRLEN_P(entry) > (size_t) maxlength) {
    1699           8 :                                 maxlength = Z_STRLEN_P(entry) + 1;
    1700             :                         }
    1701             : 
    1702          20 :                         zend_hash_move_forward(hash);
    1703             :                 }
    1704             :         }
    1705             :         
    1706          13 :         bind = emalloc(sizeof(php_oci_bind));
    1707          13 :         bind->array.elements         = (text *)safe_emalloc(max_table_length * (maxlength + 1), sizeof(text), 0);
    1708          13 :         memset(bind->array.elements, 0, max_table_length * (maxlength + 1) * sizeof(text));
    1709          13 :         bind->array.current_length   = zend_hash_num_elements(Z_ARRVAL_P(var));
    1710          13 :         bind->array.old_length               = bind->array.current_length;
    1711          13 :         bind->array.max_length               = (ub4) maxlength;
    1712          13 :         bind->array.element_lengths  = safe_emalloc(max_table_length, sizeof(ub2), 0);
    1713          13 :         memset(bind->array.element_lengths, 0, max_table_length*sizeof(ub2));
    1714          13 :         bind->array.indicators               = safe_emalloc(max_table_length, sizeof(sb2), 0);
    1715          13 :         memset(bind->array.indicators, 0, max_table_length*sizeof(sb2));
    1716             :         
    1717          13 :         zend_hash_internal_pointer_reset(hash);
    1718             :         
    1719         126 :         for (i = 0; i < bind->array.current_length; i++) {
    1720          50 :                 if ((entry = zend_hash_get_current_data(hash)) != NULL) {
    1721          60 :                         convert_to_string_ex(entry);
    1722          50 :                         bind->array.element_lengths[i] = (ub2) Z_STRLEN_P(entry);
    1723          50 :                         if (Z_STRLEN_P(entry) == 0) {
    1724           5 :                                 bind->array.indicators[i] = -1;
    1725             :                         }
    1726          50 :                         zend_hash_move_forward(hash);
    1727             :                 } else {
    1728           0 :                         break;
    1729             :                 }
    1730             :         }
    1731             : 
    1732          13 :         zend_hash_internal_pointer_reset(hash);
    1733         273 :         for (i = 0; i < max_table_length; i++) {
    1734         310 :                 if ((i < bind->array.current_length) && (entry = zend_hash_get_current_data(hash)) != NULL) {
    1735             :                         int element_length;
    1736             :                         
    1737          50 :                         convert_to_string_ex(entry);
    1738          50 :                         element_length = ((size_t) maxlength > Z_STRLEN_P(entry)) ? (int) Z_STRLEN_P(entry) : (int) maxlength;
    1739             :                         
    1740          50 :                         memcpy((text *)bind->array.elements + i*maxlength, Z_STRVAL_P(entry), element_length);
    1741          50 :                         ((text *)bind->array.elements)[i*maxlength + element_length] = '\0';
    1742             :                         
    1743          50 :                         zend_hash_move_forward(hash);
    1744             :                 } else {
    1745         210 :                         ((text *)bind->array.elements)[i*maxlength] = '\0';
    1746             :                 }
    1747             :         }
    1748          13 :         zend_hash_internal_pointer_reset(hash);
    1749             : 
    1750          13 :         return bind;
    1751             : }
    1752             : /* }}} */
    1753             : 
    1754             : /* {{{ php_oci_bind_array_helper_number()
    1755             :  Bind arrays to PL/SQL types */
    1756           3 : php_oci_bind *php_oci_bind_array_helper_number(zval *var, zend_long max_table_length)
    1757             : {
    1758             :         php_oci_bind *bind;
    1759             :         ub4 i;
    1760             :         HashTable *hash;
    1761             :         zval *entry;
    1762             : 
    1763           3 :         hash = HASH_OF(var);
    1764             : 
    1765           3 :         bind = emalloc(sizeof(php_oci_bind));
    1766           3 :         bind->array.elements         = (ub4 *)safe_emalloc(max_table_length, sizeof(ub4), 0);
    1767           3 :         bind->array.current_length   = zend_hash_num_elements(Z_ARRVAL_P(var));
    1768           3 :         bind->array.old_length               = bind->array.current_length;
    1769           3 :         bind->array.max_length               = sizeof(ub4);
    1770           3 :         bind->array.element_lengths  = safe_emalloc(max_table_length, sizeof(ub2), 0);
    1771           3 :         memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
    1772           3 :         bind->array.indicators               = NULL;
    1773             :         
    1774           3 :         zend_hash_internal_pointer_reset(hash);
    1775          23 :         for (i = 0; i < max_table_length; i++) {
    1776          20 :                 if (i < bind->array.current_length) {
    1777          10 :                         bind->array.element_lengths[i] = sizeof(ub4);
    1778             :                 }
    1779          30 :                 if ((i < bind->array.current_length) && (entry = zend_hash_get_current_data(hash)) != NULL) {
    1780          10 :                         convert_to_long_ex(entry);
    1781          10 :                         ((ub4 *)bind->array.elements)[i] = (ub4) Z_LVAL_P(entry);
    1782          10 :                         zend_hash_move_forward(hash);
    1783             :                 } else {
    1784          10 :                         ((ub4 *)bind->array.elements)[i] = 0;
    1785             :                 }
    1786             :         }
    1787           3 :         zend_hash_internal_pointer_reset(hash);
    1788             : 
    1789           3 :         return bind;
    1790             : }
    1791             : /* }}} */
    1792             : 
    1793             : /* {{{ php_oci_bind_array_helper_double()
    1794             :  Bind arrays to PL/SQL types */
    1795           2 : php_oci_bind *php_oci_bind_array_helper_double(zval *var, zend_long max_table_length)
    1796             : {
    1797             :         php_oci_bind *bind;
    1798             :         ub4 i;
    1799             :         HashTable *hash;
    1800             :         zval *entry;
    1801             : 
    1802           2 :         hash = HASH_OF(var);
    1803             : 
    1804           2 :         bind = emalloc(sizeof(php_oci_bind));
    1805           2 :         bind->array.elements         = (double *)safe_emalloc(max_table_length, sizeof(double), 0);
    1806           2 :         bind->array.current_length   = zend_hash_num_elements(Z_ARRVAL_P(var));
    1807           2 :         bind->array.old_length               = bind->array.current_length;
    1808           2 :         bind->array.max_length               = sizeof(double);
    1809           2 :         bind->array.element_lengths  = safe_emalloc(max_table_length, sizeof(ub2), 0);
    1810           2 :         memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
    1811           2 :         bind->array.indicators               = NULL;
    1812             :         
    1813           2 :         zend_hash_internal_pointer_reset(hash);
    1814          17 :         for (i = 0; i < max_table_length; i++) {
    1815          15 :                 if (i < bind->array.current_length) {
    1816          10 :                         bind->array.element_lengths[i] = sizeof(double);
    1817             :                 }
    1818          25 :                 if ((i < bind->array.current_length) && (entry = zend_hash_get_current_data(hash)) != NULL) {
    1819          10 :                         convert_to_double_ex(entry);
    1820          10 :                         ((double *)bind->array.elements)[i] = (double) Z_DVAL_P(entry);
    1821          10 :                         zend_hash_move_forward(hash);
    1822             :                 } else {
    1823           5 :                         ((double *)bind->array.elements)[i] = 0;
    1824             :                 }
    1825             :         }
    1826           2 :         zend_hash_internal_pointer_reset(hash);
    1827             : 
    1828           2 :         return bind;
    1829             : }
    1830             : /* }}} */
    1831             : 
    1832             : /* {{{ php_oci_bind_array_helper_date()
    1833             :  Bind arrays to PL/SQL types */
    1834           5 : php_oci_bind *php_oci_bind_array_helper_date(zval *var, zend_long max_table_length, php_oci_connection *connection)
    1835             : {
    1836             :         php_oci_bind *bind;
    1837             :         ub4 i;
    1838             :         HashTable *hash;
    1839             :         zval *entry;
    1840             :         sword errstatus;
    1841             : 
    1842           5 :         hash = HASH_OF(var);
    1843             : 
    1844           5 :         bind = emalloc(sizeof(php_oci_bind));
    1845           5 :         bind->array.elements         = (OCIDate *)safe_emalloc(max_table_length, sizeof(OCIDate), 0);
    1846           5 :         bind->array.current_length   = zend_hash_num_elements(Z_ARRVAL_P(var));
    1847           5 :         bind->array.old_length               = bind->array.current_length;
    1848           5 :         bind->array.max_length               = sizeof(OCIDate);
    1849           5 :         bind->array.element_lengths  = safe_emalloc(max_table_length, sizeof(ub2), 0);
    1850           5 :         memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
    1851           5 :         bind->array.indicators               = NULL;
    1852             : 
    1853           5 :         zend_hash_internal_pointer_reset(hash);
    1854          30 :         for (i = 0; i < max_table_length; i++) {
    1855             :                 OCIDate oci_date;
    1856          26 :                 if (i < bind->array.current_length) {
    1857          15 :                         bind->array.element_lengths[i] = sizeof(OCIDate);
    1858             :                 }
    1859          40 :                 if ((i < bind->array.current_length) && (entry = zend_hash_get_current_data(hash)) != NULL) {
    1860             :                         
    1861          15 :                         convert_to_string_ex(entry);
    1862          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));
    1863             : 
    1864          15 :                         if (errstatus != OCI_SUCCESS) {
    1865             :                                 /* failed to convert string to date */
    1866           1 :                                 efree(bind->array.element_lengths);
    1867           1 :                                 efree(bind->array.elements);
    1868           1 :                                 efree(bind);
    1869           1 :                                 connection->errcode = php_oci_error(connection->err, errstatus);
    1870           1 :                                 PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
    1871           1 :                                 return NULL;
    1872             :                         }
    1873             :                         
    1874          14 :                         ((OCIDate *)bind->array.elements)[i] = oci_date;
    1875          14 :                         zend_hash_move_forward(hash);
    1876             :                 } else {
    1877          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));
    1878             : 
    1879          11 :                         if (errstatus != OCI_SUCCESS) {
    1880             :                                 /* failed to convert string to date */
    1881           0 :                                 efree(bind->array.element_lengths);
    1882           0 :                                 efree(bind->array.elements);
    1883           0 :                                 efree(bind);
    1884           0 :                                 connection->errcode = php_oci_error(connection->err, errstatus);
    1885           0 :                                 PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
    1886           0 :                                 return NULL;
    1887             :                         }
    1888             :         
    1889          11 :                         ((OCIDate *)bind->array.elements)[i] = oci_date;
    1890             :                 }
    1891          25 :                 connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
    1892             :         }
    1893           4 :         zend_hash_internal_pointer_reset(hash);
    1894             : 
    1895           4 :         return bind;
    1896             : }
    1897             : /* }}} */
    1898             : 
    1899             : #endif /* HAVE_OCI8 */
    1900             : 
    1901             : /*
    1902             :  * Local variables:
    1903             :  * tab-width: 4
    1904             :  * c-basic-offset: 4
    1905             :  * End:
    1906             :  * vim600: noet sw=4 ts=4 fdm=marker
    1907             :  * vim<600: noet sw=4 ts=4
    1908             :  */

Generated by: LCOV version 1.10

Generated at Wed, 24 Aug 2016 12:20:24 +0000 (19 hours ago)

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