PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - pdo_oci - oci_statement.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 324
Code covered: 74.7 % Executed lines: 242
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:35 +0000 (34 hours ago)

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