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: 265 335 79.1 %
Date: 2014-07-23 Functions: 14 15 93.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Wed, 23 Jul 2014 19:58:36 +0000 (4 hours ago)

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