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: 278 336 82.7 %
Date: 2014-09-02 Functions: 15 15 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Tue, 02 Sep 2014 09:43:00 +0000 (18 hours ago)

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