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/pdo_oci - oci_statement.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 297 354 83.9 %
Date: 2016-07-26 Functions: 15 15 100.0 %
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             :   | Author: Wez Furlong <wez@php.net>                                    |
      16             :   +----------------------------------------------------------------------+
      17             : */
      18             : 
      19             : /* $Id$ */
      20             : 
      21             : #ifdef HAVE_CONFIG_H
      22             : #include "config.h"
      23             : #endif
      24             : 
      25             : #include "php.h"
      26             : #include "php_ini.h"
      27             : #include "ext/standard/info.h"
      28             : #include "pdo/php_pdo.h"
      29             : #include "pdo/php_pdo_driver.h"
      30             : #include "php_pdo_oci.h"
      31             : #include "php_pdo_oci_int.h"
      32             : #include "Zend/zend_extensions.h"
      33             : 
      34             : #define PDO_OCI_LOBMAXSIZE (4294967295UL) /* OCI_LOBMAXSIZE */
      35             : 
      36             : #define STMT_CALL(name, params)                                                                                 \
      37             :         do {                                                                                                                            \
      38             :                 S->last_err = name params;                                                                           \
      39             :                 S->last_err = _oci_error(S->err, stmt->dbh, stmt, #name, S->last_err, FALSE, __FILE__, __LINE__); \
      40             :                 if (S->last_err) {                                                                                           \
      41             :                         return 0;                                                                                                       \
      42             :                 }                                                                                                                               \
      43             :         } while(0)
      44             : 
      45             : #define STMT_CALL_MSG(name, msg, params)                                                                \
      46             :         do {                                                                                                                            \
      47             :                 S->last_err = name params;                                                                           \
      48             :                 S->last_err = _oci_error(S->err, stmt->dbh, stmt, #name ": " #msg, S->last_err, FALSE, __FILE__, __LINE__); \
      49             :                 if (S->last_err) {                                                                                           \
      50             :                         return 0;                                                                                                       \
      51             :                 }                                                                                                                               \
      52             :         } while(0)
      53             : 
      54             : static php_stream *oci_create_lob_stream(zval *dbh, pdo_stmt_t *stmt, OCILobLocator *lob);
      55             : 
      56             : #define OCI_TEMPLOB_CLOSE(envhp, svchp, errhp, lob)                             \
      57             :         do                                                                                                                      \
      58             :         {                                                                                                                       \
      59             :                 boolean isTempLOB;                                                                              \
      60             :                 OCILobIsTemporary(envhp, errhp, lob, &isTempLOB);           \
      61             :                 if (isTempLOB)                                                                                  \
      62             :                         OCILobFreeTemporary(svchp, errhp, lob);                         \
      63             :         } while(0)
      64             : 
      65       10189 : static int oci_stmt_dtor(pdo_stmt_t *stmt) /* {{{ */
      66             : {
      67       10189 :         pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
      68       10189 :         HashTable *BC = stmt->bound_columns;
      69       10189 :         HashTable *BP = stmt->bound_params;
      70             : 
      71             :         int i;
      72             : 
      73       10189 :         if (S->stmt) {
      74             :                 /* cancel server side resources for the statement if we didn't
      75             :                  * fetch it all */
      76       10189 :                 OCIStmtFetch(S->stmt, S->err, 0, OCI_FETCH_NEXT, OCI_DEFAULT);
      77             : 
      78             :                 /* free the handle */
      79       10189 :                 OCIHandleFree(S->stmt, OCI_HTYPE_STMT);
      80       10189 :                 S->stmt = NULL;
      81             :         }
      82       10189 :         if (S->err) {
      83       10189 :                 OCIHandleFree(S->err, OCI_HTYPE_ERROR);
      84       10189 :                 S->err = NULL;
      85             :         }
      86             : 
      87             :         /* need to ensure these go away now */
      88       10189 :         if (BC) {
      89           0 :                 zend_hash_destroy(BC);
      90           0 :                 FREE_HASHTABLE(stmt->bound_columns);
      91           0 :                 stmt->bound_columns = NULL;
      92             :         }
      93             : 
      94       10189 :         if (BP) {
      95           0 :                 zend_hash_destroy(BP);
      96           0 :                 FREE_HASHTABLE(stmt->bound_params);
      97           0 :                 stmt->bound_params = NULL;
      98             :         }
      99             : 
     100       10189 :         if (S->einfo.errmsg) {
     101           4 :                 pefree(S->einfo.errmsg, stmt->dbh->is_persistent);
     102           4 :                 S->einfo.errmsg = NULL;
     103             :         }
     104             : 
     105       10189 :         if (S->cols) {
     106       10390 :                 for (i = 0; i < stmt->column_count; i++) {
     107         213 :                         if (S->cols[i].data) {
     108         213 :                                 switch (S->cols[i].dtype) {
     109             :                                         case SQLT_BLOB:
     110             :                                         case SQLT_CLOB:
     111          31 :                                                 OCI_TEMPLOB_CLOSE(S->H->env, S->H->svc, S->H->err,
     112             :                                                         (OCILobLocator *) S->cols[i].data);
     113          31 :                                                 OCIDescriptorFree(S->cols[i].data, OCI_DTYPE_LOB);
     114          31 :                                                 break;
     115             :                                         default:
     116         182 :                                                 efree(S->cols[i].data);
     117             :                                 }
     118             :                         }
     119             :                 }
     120       10177 :                 efree(S->cols);
     121       10177 :                 S->cols = NULL;
     122             :         }
     123       10189 :         efree(S);
     124             : 
     125       10189 :         stmt->driver_data = NULL;
     126             : 
     127       10189 :         return 1;
     128             : } /* }}} */
     129             : 
     130       10249 : static int oci_stmt_execute(pdo_stmt_t *stmt) /* {{{ */
     131             : {
     132       10249 :         pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
     133             :         ub4 rowcount;
     134             :         b4 mode;
     135             : 
     136       10249 :         if (!S->stmt_type) {
     137       10181 :                 STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_STMT_TYPE",
     138             :                                 (S->stmt, OCI_HTYPE_STMT, &S->stmt_type, 0, OCI_ATTR_STMT_TYPE, S->err));
     139             :         }
     140             : 
     141       10249 :         if (stmt->executed) {
     142             :                 /* ensure that we cancel the cursor from a previous fetch */
     143          68 :                 OCIStmtFetch(S->stmt, S->err, 0, OCI_FETCH_NEXT, OCI_DEFAULT);
     144             :         }
     145             : 
     146             : #ifdef OCI_STMT_SCROLLABLE_READONLY /* needed for oci8 ? */
     147       10249 :         if (S->exec_type == OCI_STMT_SCROLLABLE_READONLY) {
     148           3 :                 mode = OCI_STMT_SCROLLABLE_READONLY;
     149             :         } else
     150             : #endif
     151       10475 :         if (stmt->dbh->auto_commit && !stmt->dbh->in_txn) {
     152         229 :                 mode = OCI_COMMIT_ON_SUCCESS;
     153             :         } else {
     154       10017 :                 mode = OCI_DEFAULT;
     155             :         }
     156             : 
     157       10249 :         STMT_CALL(OCIStmtExecute, (S->H->svc, S->stmt, S->err,
     158             :                                 (S->stmt_type == OCI_STMT_SELECT && !S->have_blobs) ? 0 : 1, 0, NULL, NULL,
     159             :                                 mode));
     160             : 
     161       10245 :         if (!stmt->executed) {
     162             :                 ub4 colcount;
     163             :                 /* do first-time-only definition of bind/mapping stuff */
     164             : 
     165             :                 /* how many columns do we have ? */
     166       10177 :                 STMT_CALL_MSG(OCIAttrGet, "ATTR_PARAM_COUNT",
     167             :                                 (S->stmt, OCI_HTYPE_STMT, &colcount, 0, OCI_ATTR_PARAM_COUNT, S->err));
     168             : 
     169       10177 :                 stmt->column_count = (int)colcount;
     170             : 
     171       10177 :                 if (S->cols) {
     172             :                         int i;
     173           0 :                         for (i = 0; i < stmt->column_count; i++) {
     174           0 :                                 if (S->cols[i].data) {
     175           0 :                                         switch (S->cols[i].dtype) {
     176             :                                                 case SQLT_BLOB:
     177             :                                                 case SQLT_CLOB:
     178             :                                                         /* do nothing */
     179           0 :                                                         break;
     180             :                                                 default:
     181           0 :                                                         efree(S->cols[i].data);
     182             :                                         }
     183             :                                 }
     184             :                         }
     185           0 :                         efree(S->cols);
     186             :                 }
     187             : 
     188       10177 :                 S->cols = ecalloc(colcount, sizeof(pdo_oci_column));
     189             :         }
     190             : 
     191       10245 :         STMT_CALL_MSG(OCIAttrGet, "ATTR_ROW_COUNT",
     192             :                         (S->stmt, OCI_HTYPE_STMT, &rowcount, 0, OCI_ATTR_ROW_COUNT, S->err));
     193       10245 :         stmt->row_count = (long)rowcount;
     194             : 
     195       10245 :         return 1;
     196             : } /* }}} */
     197             : 
     198       30146 : static sb4 oci_bind_input_cb(dvoid *ctx, OCIBind *bindp, ub4 iter, ub4 index, dvoid **bufpp, ub4 *alenp, ub1 *piecep, dvoid **indpp) /* {{{ */
     199             : {
     200       30146 :         struct pdo_bound_param_data *param = (struct pdo_bound_param_data*)ctx;
     201       30146 :         pdo_oci_bound_param *P = (pdo_oci_bound_param*)param->driver_data;
     202             :         zval *parameter;
     203             : 
     204       30146 :         if (!param) {
     205           0 :                 php_error_docref(NULL, E_WARNING, "param is NULL in oci_bind_input_cb; this should not happen");
     206           0 :                 return OCI_ERROR;
     207             :         }
     208             : 
     209       30146 :         *indpp = &P->indicator;
     210             : 
     211       60292 :     if (Z_ISREF(param->parameter))
     212       30032 :                 parameter = Z_REFVAL(param->parameter);
     213             :         else
     214         114 :                 parameter = &param->parameter;
     215             : 
     216       30146 :         if (P->thing) {
     217       20007 :                 *bufpp = P->thing;
     218       20007 :                 *alenp = sizeof(void*);
     219       10139 :         } else if (ZVAL_IS_NULL(parameter)) {
     220             :                 /* insert a NULL value into the column */
     221           2 :                 P->indicator = -1; /* NULL */
     222           2 :                 *bufpp = 0;
     223           2 :                 *alenp = -1;
     224       10137 :         } else if (!P->thing) {
     225             :                 /* regular string bind */
     226       10137 :                 convert_to_string(parameter);
     227       10137 :                 *bufpp = Z_STRVAL_P(parameter);
     228       10137 :                 *alenp = (ub4) Z_STRLEN_P(parameter);
     229             :         }
     230             : 
     231       30146 :         *piecep = OCI_ONE_PIECE;
     232       30146 :         return OCI_CONTINUE;
     233             : } /* }}} */
     234             : 
     235       20011 : static sb4 oci_bind_output_cb(dvoid *ctx, OCIBind *bindp, ub4 iter, ub4 index, dvoid **bufpp, ub4 **alenpp, ub1 *piecep, dvoid **indpp, ub2 **rcodepp) /* {{{ */
     236             : {
     237       20011 :         struct pdo_bound_param_data *param = (struct pdo_bound_param_data*)ctx;
     238       20011 :         pdo_oci_bound_param *P = (pdo_oci_bound_param*)param->driver_data;
     239             :         zval *parameter;
     240             : 
     241       20011 :         if (!param) {
     242           0 :                 php_error_docref(NULL, E_WARNING, "param is NULL in oci_bind_output_cb; this should not happen");
     243           0 :                 return OCI_ERROR;
     244             :         }
     245             : 
     246       40022 :         if (Z_ISREF(param->parameter))
     247       20010 :         parameter = Z_REFVAL(param->parameter);
     248             :     else
     249           1 :         parameter = &param->parameter;
     250             : 
     251       20011 :         if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB) {
     252       20009 :                 P->actual_len = sizeof(OCILobLocator*);
     253       20009 :                 *bufpp = P->thing;
     254       20009 :                 *alenpp = &P->actual_len;
     255       20009 :                 *piecep = OCI_ONE_PIECE;
     256       20009 :                 *rcodepp = &P->retcode;
     257       20009 :                 *indpp = &P->indicator;
     258       20009 :                 return OCI_CONTINUE;
     259             :         }
     260             : 
     261           4 :         if (Z_TYPE_P(parameter) == IS_OBJECT || Z_TYPE_P(parameter) == IS_RESOURCE) {
     262           0 :                 return OCI_CONTINUE;
     263             :         }
     264             : 
     265           2 :         convert_to_string(parameter);
     266             :         zval_dtor(parameter);
     267             : 
     268           4 :         Z_STR_P(parameter) = zend_string_alloc(param->max_value_len, 1);
     269           2 :         P->used_for_output = 1;
     270             : 
     271           2 :         P->actual_len = (ub4) Z_STRLEN_P(parameter);
     272           2 :         *alenpp = &P->actual_len;
     273           2 :         *bufpp = (Z_STR_P(parameter))->val;
     274           2 :         *piecep = OCI_ONE_PIECE;
     275           2 :         *rcodepp = &P->retcode;
     276           2 :         *indpp = &P->indicator;
     277             : 
     278           2 :         return OCI_CONTINUE;
     279             : } /* }}} */
     280             : 
     281      150804 : static int oci_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param, enum pdo_param_event event_type) /* {{{ */
     282             : {
     283      150804 :         pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
     284             : 
     285             :         /* we're only interested in parameters for prepared SQL right now */
     286      150804 :         if (param->is_param) {
     287             :                 pdo_oci_bound_param *P;
     288      150735 :                 sb4 value_sz = -1;
     289             :                 zval *parameter;
     290             : 
     291      301470 :                 if (Z_ISREF(param->parameter))
     292      150143 :                         parameter = Z_REFVAL(param->parameter);
     293             :                 else
     294         592 :                         parameter = &param->parameter;
     295             : 
     296      150735 :                 P = (pdo_oci_bound_param*)param->driver_data;
     297             : 
     298      150735 :                 switch (event_type) {
     299             :                         case PDO_PARAM_EVT_FETCH_PRE:
     300             :                         case PDO_PARAM_EVT_FETCH_POST:
     301             :                         case PDO_PARAM_EVT_NORMALIZE:
     302             :                                 /* Do nothing */
     303       30163 :                                 break;
     304             : 
     305             :                         case PDO_PARAM_EVT_FREE:
     306       30138 :                                 P = param->driver_data;
     307       50142 :                                 if (P && P->thing) {
     308       20004 :                                         OCI_TEMPLOB_CLOSE(S->H->env, S->H->svc, S->H->err, P->thing);
     309       20004 :                                         OCIDescriptorFree(P->thing, OCI_DTYPE_LOB);
     310       20004 :                                         P->thing = NULL;
     311       20004 :                                         efree(P);
     312             :                                 }
     313       10134 :                                 else if (P) {
     314       10134 :                                         efree(P);
     315             :                                 }
     316       30138 :                                 break;
     317             : 
     318             :                         case PDO_PARAM_EVT_ALLOC:
     319       30138 :                                 P = (pdo_oci_bound_param*)ecalloc(1, sizeof(pdo_oci_bound_param));
     320       30138 :                                 param->driver_data = P;
     321             : 
     322             :                                 /* figure out what we're doing */
     323       30138 :                                 switch (PDO_PARAM_TYPE(param->param_type)) {
     324             :                                         case PDO_PARAM_STMT:
     325           0 :                                                 return 0;
     326             : 
     327             :                                         case PDO_PARAM_LOB:
     328             :                                                 /* P->thing is now an OCILobLocator * */
     329       20009 :                                                 P->oci_type = SQLT_BLOB;
     330       20009 :                                                 value_sz = (sb4) sizeof(OCILobLocator*);
     331       20009 :                                                 break;
     332             : 
     333             :                                         case PDO_PARAM_STR:
     334             :                                         default:
     335       10129 :                                                 P->oci_type = SQLT_CHR;
     336       10129 :                                                 value_sz = (sb4) param->max_value_len;
     337       10129 :                                                 if (param->max_value_len == 0) {
     338       10127 :                                                         value_sz = (sb4) 1332; /* maximum size before value is interpreted as a LONG value */
     339             :                                                 }
     340             : 
     341             :                                 }
     342             : 
     343       30138 :                                 if (param->name) {
     344       30138 :                                         STMT_CALL(OCIBindByName, (S->stmt,
     345             :                                                         &P->bind, S->err, (text*)param->name->val,
     346             :                                                         (sb4) param->name->len, 0, value_sz, P->oci_type,
     347             :                                                         &P->indicator, 0, &P->retcode, 0, 0,
     348             :                                                         OCI_DATA_AT_EXEC));
     349             :                                 } else {
     350           0 :                                         STMT_CALL(OCIBindByPos, (S->stmt,
     351             :                                                         &P->bind, S->err, ((ub4)param->paramno)+1,
     352             :                                                         0, value_sz, P->oci_type,
     353             :                                                         &P->indicator, 0, &P->retcode, 0, 0,
     354             :                                                         OCI_DATA_AT_EXEC));
     355             :                                 }
     356             : 
     357       30137 :                                 STMT_CALL(OCIBindDynamic, (P->bind,
     358             :                                                         S->err,
     359             :                                                         param, oci_bind_input_cb,
     360             :                                                         param, oci_bind_output_cb));
     361             : 
     362       30137 :                                 return 1;
     363             : 
     364             :                         case PDO_PARAM_EVT_EXEC_PRE:
     365       30148 :                                 P->indicator = 0;
     366       30148 :                                 P->used_for_output = 0;
     367       30148 :                                 if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB) {
     368       20009 :                                         ub4 empty = 0;
     369       20009 :                                         STMT_CALL(OCIDescriptorAlloc, (S->H->env, &P->thing, OCI_DTYPE_LOB, 0, NULL));
     370       20009 :                                         STMT_CALL(OCIAttrSet, (P->thing, OCI_DTYPE_LOB, &empty, 0, OCI_ATTR_LOBEMPTY, S->err));
     371       20009 :                                         S->have_blobs = 1;
     372             :                                 }
     373       30148 :                                 return 1;
     374             : 
     375             :                         case PDO_PARAM_EVT_EXEC_POST:
     376             :                                 /* fixup stuff set in motion in oci_bind_output_cb */
     377       30148 :                                 if (P->used_for_output) {
     378           2 :                                         if (P->indicator == -1) {
     379             :                                                 /* set up a NULL value */
     380           0 :                                                 if (Z_TYPE_P(parameter) == IS_STRING) {
     381             :                                                         /* OCI likes to stick non-terminated strings in things */
     382           0 :                                                         *Z_STRVAL_P(parameter) = '\0';
     383             :                                                 }
     384             :                                                 zval_dtor(parameter);
     385           0 :                                                 ZVAL_UNDEF(parameter);
     386           2 :                                         } else if (Z_TYPE_P(parameter) == IS_STRING) {
     387           4 :                                                 Z_STR_P(parameter) = zend_string_init(Z_STRVAL_P(parameter), P->actual_len, 1);
     388             :                                         }
     389       30146 :                                 } else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB && P->thing) {
     390             :                                         php_stream *stm;
     391             : 
     392       20009 :                                         if (Z_TYPE_P(parameter) == IS_NULL) {
     393             :                                                 /* if the param is NULL, then we assume that they
     394             :                                                  * wanted to bind a lob locator into it from the query
     395             :                                                  * */
     396             : 
     397       20004 :                                                 stm = oci_create_lob_stream(&stmt->database_object_handle, stmt, (OCILobLocator*)P->thing);
     398       20004 :                                                 if (stm) {
     399       20004 :                                                         OCILobOpen(S->H->svc, S->err, (OCILobLocator*)P->thing, OCI_LOB_READWRITE);
     400       20004 :                                                         php_stream_to_zval(stm, parameter);
     401             :                                                 }
     402             :                                         } else {
     403             :                                                 /* we're a LOB being used for insert; transfer the data now */
     404             :                                                 size_t n;
     405           5 :                                                 ub4 amt, offset = 1;
     406             :                                                 char *consume;
     407             : 
     408           5 :                                                 php_stream_from_zval_no_verify(stm, parameter);
     409           5 :                                                 if (stm) {
     410           5 :                                                         OCILobOpen(S->H->svc, S->err, (OCILobLocator*)P->thing, OCI_LOB_READWRITE);
     411             :                                                         do {
     412             :                                                                 char buf[8192];
     413           8 :                                                                 n = php_stream_read(stm, buf, sizeof(buf));
     414           8 :                                                                 if ((int)n <= 0) {
     415           5 :                                                                         break;
     416             :                                                                 }
     417           3 :                                                                 consume = buf;
     418             :                                                                 do {
     419           3 :                                                                         amt = (ub4) n;
     420           3 :                                                                         OCILobWrite(S->H->svc, S->err, (OCILobLocator*)P->thing,
     421             :                                                                                         &amt, offset, consume, (ub4) n,
     422             :                                                                                         OCI_ONE_PIECE,
     423             :                                                                                         NULL, NULL, 0, SQLCS_IMPLICIT);
     424           3 :                                                                         offset += amt;
     425           3 :                                                                         n -= amt;
     426           3 :                                                                         consume += amt;
     427           3 :                                                                 } while (n);
     428           3 :                                                         } while (1);
     429           5 :                                                         OCILobClose(S->H->svc, S->err, (OCILobLocator*)P->thing);
     430           5 :                                                         OCILobFlushBuffer(S->H->svc, S->err, (OCILobLocator*)P->thing, 0);
     431           0 :                                                 } else if (Z_TYPE_P(parameter) == IS_STRING) {
     432             :                                                         /* stick the string into the LOB */
     433           0 :                                                         consume = Z_STRVAL_P(parameter);
     434           0 :                                                         n = Z_STRLEN_P(parameter);
     435           0 :                                                         if (n) {
     436           0 :                                                                 OCILobOpen(S->H->svc, S->err, (OCILobLocator*)P->thing, OCI_LOB_READWRITE);
     437           0 :                                                                 while (n) {
     438           0 :                                                                         amt = (ub4) n;
     439           0 :                                                                         OCILobWrite(S->H->svc, S->err, (OCILobLocator*)P->thing,
     440             :                                                                                         &amt, offset, consume, (ub4) n,
     441             :                                                                                         OCI_ONE_PIECE,
     442             :                                                                                         NULL, NULL, 0, SQLCS_IMPLICIT);
     443           0 :                                                                         consume += amt;
     444           0 :                                                                         n -= amt;
     445             :                                                                 }
     446           0 :                                                                 OCILobClose(S->H->svc, S->err, (OCILobLocator*)P->thing);
     447             :                                                         }
     448             :                                                 }
     449           5 :                                                 OCI_TEMPLOB_CLOSE(S->H->env, S->H->svc, S->H->err, P->thing);
     450           5 :                                                 OCIDescriptorFree(P->thing, OCI_DTYPE_LOB);
     451           5 :                                                 P->thing = NULL;
     452             :                                         }
     453             :                                 }
     454             : 
     455       30148 :                                 return 1;
     456             :                 }
     457             :         }
     458             : 
     459       60370 :         return 1;
     460             : } /* }}} */
     461             : 
     462       10419 : static int oci_stmt_fetch(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori,     zend_long offset) /* {{{ */
     463             : {
     464             : #if HAVE_OCISTMTFETCH2
     465             :         ub4 ociori;
     466             : #endif
     467       10419 :         pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
     468             : 
     469             : #if HAVE_OCISTMTFETCH2
     470       10419 :         switch (ori) {
     471       10414 :                 case PDO_FETCH_ORI_NEXT:        ociori = OCI_FETCH_NEXT; break;
     472           1 :                 case PDO_FETCH_ORI_PRIOR:       ociori = OCI_FETCH_PRIOR; break;
     473           1 :                 case PDO_FETCH_ORI_FIRST:       ociori = OCI_FETCH_FIRST; break;
     474           1 :                 case PDO_FETCH_ORI_LAST:        ociori = OCI_FETCH_LAST; break;
     475           1 :                 case PDO_FETCH_ORI_ABS:         ociori = OCI_FETCH_ABSOLUTE; break;
     476           1 :                 case PDO_FETCH_ORI_REL:         ociori = OCI_FETCH_RELATIVE; break;
     477             :         }
     478       10419 :         S->last_err = OCIStmtFetch2(S->stmt, S->err, 1, ociori, (sb4) offset, OCI_DEFAULT);
     479             : #else
     480             :         S->last_err = OCIStmtFetch(S->stmt, S->err, 1, OCI_FETCH_NEXT, OCI_DEFAULT);
     481             : #endif
     482             : 
     483       10419 :         if (S->last_err == OCI_NO_DATA) {
     484             :                 /* no (more) data */
     485         117 :                 return 0;
     486             :         }
     487             : 
     488       10302 :         if (S->last_err == OCI_NEED_DATA) {
     489           0 :                 oci_stmt_error("OCI_NEED_DATA");
     490           0 :                 return 0;
     491             :         }
     492             : 
     493       10302 :         if (S->last_err == OCI_SUCCESS_WITH_INFO || S->last_err == OCI_SUCCESS) {
     494       10302 :                 return 1;
     495             :         }
     496             : 
     497           0 :         oci_stmt_error("OCIStmtFetch");
     498             : 
     499           0 :         return 0;
     500             : } /* }}} */
     501             : 
     502       20043 : static sb4 oci_define_callback(dvoid *octxp, OCIDefine *define, ub4 iter, dvoid **bufpp,
     503             :                 ub4 **alenpp, ub1 *piecep, dvoid **indpp, ub2 **rcodepp)
     504             : {
     505       20043 :         pdo_oci_column *col = (pdo_oci_column*)octxp;
     506             : 
     507       20043 :         switch (col->dtype) {
     508             :                 case SQLT_BLOB:
     509             :                 case SQLT_CLOB:
     510       20043 :                         *piecep = OCI_ONE_PIECE;
     511       20043 :                         *bufpp = col->data;
     512       20043 :                         *alenpp = &col->datalen;
     513       20043 :                         *indpp = (dvoid *)&col->indicator;
     514       20043 :                         break;
     515             : 
     516             :                 default:
     517           0 :                         php_error_docref(NULL, E_WARNING,
     518             :                                 "unhandled datatype in oci_define_callback; this should not happen");
     519           0 :                         return OCI_ERROR;
     520             :         }
     521             : 
     522       20043 :         return OCI_CONTINUE;
     523             : }
     524             : 
     525         213 : static int oci_stmt_describe(pdo_stmt_t *stmt, int colno) /* {{{ */
     526             : {
     527         213 :         pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
     528         213 :         OCIParam *param = NULL;
     529             :         text *colname;
     530             :         ub2 dtype, data_size, scale, precis;
     531             :         ub4 namelen;
     532         213 :         struct pdo_column_data *col = &stmt->columns[colno];
     533         213 :         zend_bool dyn = FALSE;
     534             : 
     535             :         /* describe the column */
     536         213 :         STMT_CALL(OCIParamGet, (S->stmt, OCI_HTYPE_STMT, S->err, (dvoid*)&param, colno+1));
     537             : 
     538             :         /* what type ? */
     539         213 :         STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_DATA_TYPE",
     540             :                         (param, OCI_DTYPE_PARAM, &dtype, 0, OCI_ATTR_DATA_TYPE, S->err));
     541             : 
     542             :         /* how big ? */
     543         213 :         STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_DATA_SIZE",
     544             :                         (param, OCI_DTYPE_PARAM, &data_size, 0, OCI_ATTR_DATA_SIZE, S->err));
     545             : 
     546             :         /* scale ? */
     547         213 :         STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_SCALE",
     548             :                         (param, OCI_DTYPE_PARAM, &scale, 0, OCI_ATTR_SCALE, S->err));
     549             : 
     550             :         /* precision ? */
     551         213 :         STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_PRECISION",
     552             :                         (param, OCI_DTYPE_PARAM, &precis, 0, OCI_ATTR_PRECISION, S->err));
     553             : 
     554             :         /* name ? */
     555         213 :         STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_NAME",
     556             :                         (param, OCI_DTYPE_PARAM, &colname, &namelen, OCI_ATTR_NAME, S->err));
     557             : 
     558         213 :         col->precision = scale;
     559         213 :         col->maxlen = data_size;
     560         426 :         col->name = zend_string_init((char *)colname, namelen, 0);
     561             : 
     562         213 :         S->cols[colno].dtype = dtype;
     563             : 
     564             :         /* how much room do we need to store the field */
     565         213 :         switch (dtype) {
     566             :                 case SQLT_LBI:
     567             :                 case SQLT_LNG:
     568           0 :                         if (dtype == SQLT_LBI) {
     569           0 :                                 dtype = SQLT_BIN;
     570             :                         } else {
     571           0 :                                 dtype = SQLT_CHR;
     572             :                         }
     573           0 :                         S->cols[colno].datalen = 512; /* XXX should be INT_MAX and fetched by pieces */
     574           0 :                         S->cols[colno].data = emalloc(S->cols[colno].datalen + 1);
     575           0 :                         col->param_type = PDO_PARAM_STR;
     576           0 :                         break;
     577             : 
     578             :                 case SQLT_BLOB:
     579             :                 case SQLT_CLOB:
     580          31 :                         col->param_type = PDO_PARAM_LOB;
     581          31 :                         STMT_CALL(OCIDescriptorAlloc, (S->H->env, (dvoid**)&S->cols[colno].data, OCI_DTYPE_LOB, 0, NULL));
     582          31 :                         S->cols[colno].datalen = sizeof(OCILobLocator*);
     583          31 :                         dyn = TRUE;
     584          31 :                         break;
     585             : 
     586             :                 case SQLT_BIN:
     587             :                 default:
     588         613 :                         if (dtype == SQLT_DAT || dtype == SQLT_NUM || dtype == SQLT_RDD
     589             : #ifdef SQLT_TIMESTAMP
     590         125 :                                         || dtype == SQLT_TIMESTAMP
     591             : #endif
     592             : #ifdef SQLT_TIMESTAMP_TZ
     593         248 :                                         || dtype == SQLT_TIMESTAMP_TZ
     594             : #endif
     595             :                                         ) {
     596             :                                 /* should be big enough for most date formats and numbers */
     597          58 :                                 S->cols[colno].datalen = 512;
     598             : #if defined(SQLT_IBFLOAT) && defined(SQLT_IBDOUBLE)
     599         124 :                         } else if (dtype == SQLT_IBFLOAT || dtype == SQLT_IBDOUBLE) {
     600           0 :                                 S->cols[colno].datalen = 1024;
     601             : #endif
     602             :                         } else {
     603         124 :                                 S->cols[colno].datalen = (ub4) col->maxlen;
     604             :                         }
     605         182 :                         if (dtype == SQLT_BIN) {
     606           0 :                                 S->cols[colno].datalen *= 3;
     607             :                         }
     608         182 :                         S->cols[colno].data = emalloc(S->cols[colno].datalen + 1);
     609         182 :                         dtype = SQLT_CHR;
     610             : 
     611             :                         /* returning data as a string */
     612         182 :                         col->param_type = PDO_PARAM_STR;
     613             :         }
     614             : 
     615         213 :         STMT_CALL(OCIDefineByPos, (S->stmt, &S->cols[colno].def, S->err, colno+1,
     616             :                                 S->cols[colno].data, S->cols[colno].datalen, dtype, &S->cols[colno].indicator,
     617             :                                 &S->cols[colno].fetched_len, &S->cols[colno].retcode, dyn ? OCI_DYNAMIC_FETCH : OCI_DEFAULT));
     618             : 
     619         213 :         if (dyn) {
     620          31 :                 STMT_CALL(OCIDefineDynamic, (S->cols[colno].def, S->err, &S->cols[colno],
     621             :                                 oci_define_callback));
     622             :         }
     623             : 
     624         213 :         return 1;
     625             : } /* }}} */
     626             : 
     627             : struct _oci_lob_env {
     628             :         OCISvcCtx *svc;
     629             :         OCIError  *err;
     630             : };
     631             : typedef struct _oci_lob_env oci_lob_env;
     632             : 
     633             : struct oci_lob_self {
     634             :         zval dbh;
     635             :         pdo_stmt_t *stmt;
     636             :         pdo_oci_stmt *S;
     637             :         OCILobLocator *lob;
     638             :         oci_lob_env   *E;
     639             :         ub4 offset;
     640             : };
     641             : 
     642       20004 : static size_t oci_blob_write(php_stream *stream, const char *buf, size_t count)
     643             : {
     644       20004 :         struct oci_lob_self *self = (struct oci_lob_self*)stream->abstract;
     645             :         ub4 amt;
     646             :         sword r;
     647             : 
     648       20004 :         amt = (ub4) count;
     649       20004 :         r = OCILobWrite(self->E->svc, self->E->err, self->lob,
     650             :                 &amt, self->offset, (char*)buf, (ub4) count,
     651             :                 OCI_ONE_PIECE,
     652             :                 NULL, NULL, 0, SQLCS_IMPLICIT);
     653             : 
     654       20004 :         if (r != OCI_SUCCESS) {
     655           0 :                 return (size_t)-1;
     656             :         }
     657             : 
     658       20004 :         self->offset += amt;
     659       20004 :         return amt;
     660             : }
     661             : 
     662       40101 : static size_t oci_blob_read(php_stream *stream, char *buf, size_t count)
     663             : {
     664       40101 :         struct oci_lob_self *self = (struct oci_lob_self*)stream->abstract;
     665             :         ub4 amt;
     666             :         sword r;
     667             : 
     668       40101 :         amt = (ub4) count;
     669       40101 :         r = OCILobRead(self->E->svc, self->E->err, self->lob,
     670             :                 &amt, self->offset, buf, (ub4) count,
     671             :                 NULL, NULL, 0, SQLCS_IMPLICIT);
     672             : 
     673       40101 :         if (r != OCI_SUCCESS && r != OCI_NEED_DATA) {
     674           0 :                 return (size_t)-1;
     675             :         }
     676             : 
     677       40101 :         self->offset += amt;
     678       40101 :         if (amt < count) {
     679       40094 :                 stream->eof = 1;
     680             :         }
     681       40101 :         return amt;
     682             : }
     683             : 
     684       40046 : static int oci_blob_close(php_stream *stream, int close_handle)
     685             : {
     686       40046 :         struct oci_lob_self *self = (struct oci_lob_self *)stream->abstract;
     687       40046 :         pdo_stmt_t *stmt = self->stmt;
     688             : 
     689       40046 :         if (close_handle) {
     690       40046 :                 zend_object *obj = &stmt->std;
     691             : 
     692       40046 :                 OCILobClose(self->E->svc, self->E->err, self->lob);
     693       40046 :                 zval_ptr_dtor(&self->dbh);
     694       40046 :                 GC_REFCOUNT(obj)--;
     695       40046 :                 efree(self->E);
     696       40046 :                 efree(self);
     697             :         }
     698             : 
     699             :         /* php_pdo_free_statement(stmt); */
     700       40046 :         return 0;
     701             : }
     702             : 
     703       20004 : static int oci_blob_flush(php_stream *stream)
     704             : {
     705       20004 :         struct oci_lob_self *self = (struct oci_lob_self*)stream->abstract;
     706       20004 :         OCILobFlushBuffer(self->E->svc, self->E->err, self->lob, 0);
     707       20004 :         return 0;
     708             : }
     709             : 
     710          18 : static int oci_blob_seek(php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffset)
     711             : {
     712          18 :         struct oci_lob_self *self = (struct oci_lob_self*)stream->abstract;
     713             : 
     714          18 :         if (offset >= PDO_OCI_LOBMAXSIZE) {
     715           0 :                 return -1;
     716             :         } else {
     717          18 :                 self->offset = (ub4) offset + 1;  /* Oracle LOBS are 1-based, but PHP is 0-based */
     718          18 :                 return 0;
     719             :         }
     720             : }
     721             : 
     722             : static php_stream_ops oci_blob_stream_ops = {
     723             :         oci_blob_write,
     724             :         oci_blob_read,
     725             :         oci_blob_close,
     726             :         oci_blob_flush,
     727             :         "pdo_oci blob stream",
     728             :         oci_blob_seek,
     729             :         NULL,
     730             :         NULL,
     731             :         NULL
     732             : };
     733             : 
     734       40046 : static php_stream *oci_create_lob_stream(zval *dbh, pdo_stmt_t *stmt, OCILobLocator *lob)
     735             : {
     736             :         php_stream *stm;
     737       40046 :         struct oci_lob_self *self = ecalloc(1, sizeof(*self));
     738             : 
     739       40046 :         ZVAL_COPY_VALUE(&self->dbh, dbh);
     740       40046 :         self->lob = lob;
     741       40046 :         self->offset = 1; /* 1-based */
     742       40046 :         self->stmt = stmt;
     743       40046 :         self->S = (pdo_oci_stmt*)stmt->driver_data;
     744       40046 :         self->E = ecalloc(1, sizeof(oci_lob_env));
     745       40046 :         self->E->svc = self->S->H->svc;
     746       40046 :         self->E->err = self->S->err;
     747             : 
     748       40046 :         stm = php_stream_alloc(&oci_blob_stream_ops, self, 0, "r+b");
     749             : 
     750       40046 :         if (stm) {
     751             :                 zend_object *obj;
     752       40046 :                 obj = &stmt->std;
     753       40046 :                 Z_ADDREF(self->dbh);
     754       40046 :                 GC_REFCOUNT(obj)++;
     755       40046 :                 return stm;
     756             :         }
     757             : 
     758           0 :         efree(self);
     759           0 :         return NULL;
     760             : }
     761             : 
     762       20554 : static int oci_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, size_t *len, int *caller_frees) /* {{{ */
     763             : {
     764       20554 :         pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
     765       20554 :         pdo_oci_column *C = &S->cols[colno];
     766             : 
     767             :         /* check the indicator to ensure that the data is intact */
     768       20554 :         if (C->indicator == -1) {
     769             :                 /* A NULL value */
     770          21 :                 *ptr = NULL;
     771          21 :                 *len = 0;
     772          21 :                 return 1;
     773       20533 :         } else if (C->indicator == 0) {
     774             :                 /* it was stored perfectly */
     775             : 
     776       20533 :                 if (C->dtype == SQLT_BLOB || C->dtype == SQLT_CLOB) {
     777       20042 :                         if (C->data) {
     778       20042 :                                 *ptr = (char*)oci_create_lob_stream(&stmt->database_object_handle, stmt, (OCILobLocator*)C->data);
     779       20042 :                                 OCILobOpen(S->H->svc, S->err, (OCILobLocator*)C->data, OCI_LOB_READONLY);
     780             :                         }
     781       20042 :                         *len = (size_t) 0;
     782       20042 :                         return *ptr ? 1 : 0;
     783             :                 }
     784             : 
     785         491 :                 *ptr = C->data;
     786         491 :                 *len = (size_t) C->fetched_len;
     787         491 :                 return 1;
     788             :         } else {
     789             :                 /* it was truncated */
     790           0 :                 php_error_docref(NULL, E_WARNING, "column %d data was too large for buffer and was truncated to fit it", colno);
     791             : 
     792           0 :                 *ptr = C->data;
     793           0 :                 *len = (size_t) C->fetched_len;
     794           0 :                 return 1;
     795             :         }
     796             : } /* }}} */
     797             : 
     798             : struct pdo_stmt_methods oci_stmt_methods = {
     799             :         oci_stmt_dtor,
     800             :         oci_stmt_execute,
     801             :         oci_stmt_fetch,
     802             :         oci_stmt_describe,
     803             :         oci_stmt_get_col,
     804             :         oci_stmt_param_hook
     805             : };
     806             : 
     807             : /*
     808             :  * Local variables:
     809             :  * tab-width: 4
     810             :  * c-basic-offset: 4
     811             :  * End:
     812             :  * vim600: noet sw=4 ts=4 fdm=marker
     813             :  * vim<600: noet sw=4 ts=4
     814             :  */

Generated by: LCOV version 1.10

Generated at Tue, 26 Jul 2016 17:07:41 +0000 (3 days ago)

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