wez             Sun Oct 30 21:11:29 2005 EDT

  Modified files:              (Branch: PHP_5_1)
    /php-src/ext/pdo_oci        oci_statement.c php_pdo_oci_int.h 
  Log:
  Closes PECL Bug #5722; BLOB support was half-baked.
  
  
http://cvs.php.net/diff.php/php-src/ext/pdo_oci/oci_statement.c?r1=1.16.2.4&r2=1.16.2.5&ty=u
Index: php-src/ext/pdo_oci/oci_statement.c
diff -u php-src/ext/pdo_oci/oci_statement.c:1.16.2.4 
php-src/ext/pdo_oci/oci_statement.c:1.16.2.5
--- php-src/ext/pdo_oci/oci_statement.c:1.16.2.4        Sat Oct 29 16:41:54 2005
+++ php-src/ext/pdo_oci/oci_statement.c Sun Oct 30 21:11:27 2005
@@ -16,7 +16,7 @@
   +----------------------------------------------------------------------+
 */
 
-/* $Id: oci_statement.c,v 1.16.2.4 2005/10/29 20:41:54 wez Exp $ */
+/* $Id: oci_statement.c,v 1.16.2.5 2005/10/31 02:11:27 wez Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -45,6 +45,7 @@
                return 0; \
        }
 
+static php_stream *oci_create_lob_stream(pdo_stmt_t *stmt, OCILobLocator *lob 
TSRMLS_DC);
 
 static int oci_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
 {
@@ -89,7 +90,14 @@
        if (S->cols) {
                for (i = 0; i < stmt->column_count; i++) {
                        if (S->cols[i].data) {
-                               efree(S->cols[i].data);
+                               switch (S->cols[i].dtype) {
+                                       case SQLT_BLOB:
+                                       case SQLT_CLOB:
+                                               /* do nothing */
+                                               break;
+                                       default:
+                                               efree(S->cols[i].data);
+                               }
                        }
                }
                efree(S->cols);
@@ -130,7 +138,7 @@
        }
 
        STMT_CALL(OCIStmtExecute, (S->H->svc, S->stmt, S->err,
-                               S->stmt_type == OCI_STMT_SELECT ? 0 : 1, 0, 
NULL, NULL,
+                               (S->stmt_type == OCI_STMT_SELECT || 
S->have_blobs) : 1, 0, NULL, NULL,
                                mode));
 
        if (!stmt->executed) {
@@ -166,7 +174,10 @@
        
        *indpp = &P->indicator;
 
-       if (ZVAL_IS_NULL(param->parameter)) {
+       if (P->thing) {
+               *bufpp = P->thing;
+               *alenp = sizeof(void*);
+       } else if (ZVAL_IS_NULL(param->parameter)) {
                /* insert a NULL value into the column */
                P->indicator = -1; /* NULL */
                *bufpp = 0;
@@ -176,9 +187,6 @@
                convert_to_string(param->parameter);
                *bufpp = Z_STRVAL_P(param->parameter);
                *alenp = Z_STRLEN_P(param->parameter);
-       } else {
-               php_error_docref(NULL TSRMLS_CC, E_WARNING, "P->thing should 
not be set??");
-               return OCI_ERROR;
        }
 
        *piecep = OCI_ONE_PIECE;
@@ -195,6 +203,16 @@
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "param is NULL in 
oci_bind_output_cb; this should not happen");
                return OCI_ERROR;
        }
+
+       if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB) {
+               P->actual_len = sizeof(OCILobLocator*);
+               *bufpp = P->thing;
+               *alenpp = &P->actual_len;
+               *piecep = OCI_ONE_PIECE;
+               *rcodepp = &P->retcode;
+               *indpp = &P->indicator;
+               return OCI_CONTINUE;
+       } 
        
        if (Z_TYPE_P(param->parameter) == IS_OBJECT || 
Z_TYPE_P(param->parameter) == IS_RESOURCE) {
                return OCI_CONTINUE;
@@ -246,21 +264,10 @@
                                                return 0;
 
                                        case PDO_PARAM_LOB:
-                                               /* fake lobs for now */
-                                               if (Z_TYPE_P(param->parameter) 
== IS_RESOURCE) {
-                                                       php_stream *stm;
-                                                       
php_stream_from_zval_no_verify(stm, &param->parameter);
-                                                       if (stm) {
-                                                               
SEPARATE_ZVAL_IF_NOT_REF(&param->parameter);
-                                                               
Z_TYPE_P(param->parameter) = IS_STRING;
-                                                               
Z_STRLEN_P(param->parameter) = php_stream_copy_to_mem(stm,
-                                                                               
&Z_STRVAL_P(param->parameter), PHP_STREAM_COPY_ALL, 0);
-                                                       } else {
-                                                               
pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a stream resource" 
TSRMLS_CC);
-                                                               return 0;
-                                                       }
-                                               }
-                                               /* fall through */
+                                               /* P->thing is now an 
OCILobLocator * */
+                                               P->oci_type = SQLT_BLOB;
+                                               value_sz = 
sizeof(OCILobLocator*);
+                                               break;
 
                                        case PDO_PARAM_STR:
                                        default:
@@ -296,6 +303,12 @@
                        case PDO_PARAM_EVT_EXEC_PRE:
                                P->indicator = 0;
                                P->used_for_output = 0;
+                               if (PDO_PARAM_TYPE(param->param_type) == 
PDO_PARAM_LOB) {
+                                       ub4 empty = 0;
+                                       STMT_CALL(OCIDescriptorAlloc, 
(S->H->env, &P->thing, OCI_DTYPE_LOB, 0, NULL));
+                                       STMT_CALL(OCIAttrSet, (P->thing, 
OCI_DTYPE_LOB, &empty, 0, OCI_ATTR_LOBEMPTY, S->err));
+                                       S->have_blobs = 1;
+                               }
                                return 1;
 
                        case PDO_PARAM_EVT_EXEC_POST:
@@ -322,6 +335,70 @@
                                                Z_STRVAL_P(param->parameter) = 
erealloc(Z_STRVAL_P(param->parameter), P->actual_len+1);
                                                
Z_STRVAL_P(param->parameter)[P->actual_len] = '\0';
                                        }
+                               } else if (PDO_PARAM_TYPE(param->param_type) == 
PDO_PARAM_LOB && P->thing) {
+                                       php_stream *stm;
+
+                                       if (Z_TYPE_P(param->parameter) == 
IS_NULL) {
+                                               /* if the param is NULL, then 
we assume that they
+                                                * wanted to bind a lob locator 
into it from the query
+                                                * */
+
+                                               stm = 
oci_create_lob_stream(stmt, (OCILobLocator*)P->thing TSRMLS_CC);
+                                               if (stm) {
+                                                       OCILobOpen(S->H->svc, 
S->err, (OCILobLocator*)P->thing, OCI_LOB_READWRITE);
+                                                       php_stream_to_zval(stm, 
param->parameter);
+                                                       P->thing = NULL;
+                                               }
+                                       } else {
+                                               /* we're a LOB being used for 
insert; transfer the data now */
+                                               size_t n;
+                                               ub4 amt, offset = 1;
+                                               char *consume;
+
+                                               
php_stream_from_zval_no_verify(stm, &param->parameter);
+                                               if (stm) {
+                                                       OCILobOpen(S->H->svc, 
S->err, (OCILobLocator*)P->thing, OCI_LOB_READWRITE);
+                                                       do {
+                                                               char buf[8192];
+                                                               n = 
php_stream_read(stm, buf, sizeof(buf));
+                                                               if ((int)n <= 
0) {
+                                                                       break;
+                                                               }
+                                                               consume = buf;
+                                                               do {
+                                                                       amt = n;
+                                                                       
OCILobWrite(S->H->svc, S->err, (OCILobLocator*)P->thing,
+                                                                               
        &amt, offset, consume, n,
+                                                                               
        OCI_ONE_PIECE,
+                                                                               
        NULL, NULL, 0, SQLCS_IMPLICIT);
+                                                                       offset 
+= amt;
+                                                                       n -= 
amt;
+                                                                       consume 
+= amt;
+                                                               } while (n);
+                                                       } while (1);
+                                                       OCILobClose(S->H->svc, 
S->err, (OCILobLocator*)P->thing);
+                                                       
OCILobFlushBuffer(S->H->svc, S->err, (OCILobLocator*)P->thing, 0);
+                                               } else if 
(Z_TYPE_P(param->parameter) == IS_STRING) {
+                                                       /* stick the string 
into the LOB */
+                                                       consume = 
Z_STRVAL_P(param->parameter);
+                                                       n = 
Z_STRLEN_P(param->parameter);
+                                                       if (n) {
+                                                               
OCILobOpen(S->H->svc, S->err, (OCILobLocator*)P->thing, OCI_LOB_READWRITE);
+                                                               while (n) {
+                                                                       amt = n;
+                                                                       
OCILobWrite(S->H->svc, S->err, (OCILobLocator*)P->thing,
+                                                                               
        &amt, offset, consume, n,
+                                                                               
        OCI_ONE_PIECE,
+                                                                               
        NULL, NULL, 0, SQLCS_IMPLICIT);
+                                                                       consume 
+= amt;
+                                                                       n -= 
amt;
+                                                               }
+                                                               
OCILobClose(S->H->svc, S->err, (OCILobLocator*)P->thing);
+                                                       }
+                                               }
+                                               OCIDescriptorFree(P->thing, 
OCI_DTYPE_LOB);
+                                               P->thing = NULL;
+                                       }
                                }
 
                                return 1;
@@ -371,6 +448,28 @@
        return 0;
 } /* }}} */
 
+static sb4 oci_define_callback(dvoid *octxp, OCIDefine *define, ub4 iter, 
dvoid **bufpp,
+               ub4 **alenpp, ub1 *piecep, dvoid **indpp, ub2 **rcodepp)
+{
+       pdo_oci_column *col = (pdo_oci_column*)octxp;
+
+       switch (col->dtype) {
+               case SQLT_BLOB:
+               case SQLT_CLOB:
+                       *piecep = OCI_ONE_PIECE;
+                       *bufpp = col->data;
+                       *alenpp = &col->datalen;
+                       break;
+
+               default:
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING,
+                               "unhandled datatype in oci_define_callback; 
this should not happen");
+                       return OCI_ERROR;
+       }
+
+       return OCI_CONTINUE;
+}
+
 static int oci_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC) /* {{{ */
 {
        pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
@@ -409,11 +508,12 @@
        col->namelen = namelen;
        col->name = estrndup(colname, namelen);
 
+       S->cols[colno].dtype = dtype;
+       
        /* how much room do we need to store the field */
        switch (dtype) {
                case SQLT_LBI:
                case SQLT_LNG:
-                       dyn = FALSE;
                        if (dtype == SQLT_LBI) {
                                dtype = SQLT_BIN;
                        } else {
@@ -423,10 +523,17 @@
                        S->cols[colno].data = emalloc(S->cols[colno].datalen + 
1);
                        col->param_type = PDO_PARAM_STR;
                        break;
+
+               case SQLT_BLOB:
+               case SQLT_CLOB:
+                       col->param_type = PDO_PARAM_LOB;
+                       STMT_CALL(OCIDescriptorAlloc, (S->H->env, 
(dvoid**)&S->cols[colno].data, OCI_DTYPE_LOB, 0, NULL));
+                       S->cols[colno].datalen = sizeof(OCILobLocator*);
+                       dyn = TRUE;
+                       break;
                                                                                
                                                                                
                                                                                
                
                case SQLT_BIN:
                default:
-                       dyn = FALSE;
                        if (dtype == SQLT_DAT || dtype == SQLT_NUM
 #ifdef SQLT_TIMESTAMP
                                        || dtype == SQLT_TIMESTAMP
@@ -450,15 +557,125 @@
                        col->param_type = PDO_PARAM_STR;
        }
 
-       if (!dyn) {
-               STMT_CALL(OCIDefineByPos, (S->stmt, &S->cols[colno].def, 
S->err, colno+1,
-                                       S->cols[colno].data, 
S->cols[colno].datalen, dtype, &S->cols[colno].indicator,
-                                       &S->cols[colno].fetched_len, 
&S->cols[colno].retcode, OCI_DEFAULT));
+       STMT_CALL(OCIDefineByPos, (S->stmt, &S->cols[colno].def, S->err, 
colno+1,
+                               S->cols[colno].data, S->cols[colno].datalen, 
dtype, &S->cols[colno].indicator,
+                               &S->cols[colno].fetched_len, 
&S->cols[colno].retcode, dyn ? OCI_DYNAMIC_FETCH : OCI_DEFAULT));
+
+       if (dyn) {
+               STMT_CALL(OCIDefineDynamic, (S->cols[colno].def, S->err, 
&S->cols[colno],
+                               oci_define_callback));
        }
        
        return 1;
 } /* }}} */
 
+struct oci_lob_self {
+       pdo_stmt_t *stmt;
+       pdo_oci_stmt *S;
+       OCILobLocator *lob;
+       ub4 offset;
+};
+
+static size_t oci_blob_write(php_stream *stream, const char *buf, size_t count 
TSRMLS_DC)
+{
+       struct oci_lob_self *self = (struct oci_lob_self*)stream->abstract;
+       ub4 amt;
+       sword r;
+
+       amt = count;
+       r = OCILobWrite(self->S->H->svc, self->S->err, self->lob,
+               &amt, self->offset, (char*)buf, count,
+               OCI_ONE_PIECE,
+               NULL, NULL, 0, SQLCS_IMPLICIT);
+
+       if (r != OCI_SUCCESS) {
+               return (size_t)-1;
+       }
+       
+       self->offset += amt;
+       return amt;
+}
+
+static size_t oci_blob_read(php_stream *stream, char *buf, size_t count 
TSRMLS_DC)
+{
+       struct oci_lob_self *self = (struct oci_lob_self*)stream->abstract;
+       ub4 amt;
+       sword r;
+
+       amt = count;
+       r = OCILobRead(self->S->H->svc, self->S->err, self->lob,
+               &amt, self->offset, buf, count,
+               NULL, NULL, 0, SQLCS_IMPLICIT);
+
+       if (r != OCI_SUCCESS) {
+               return (size_t)-1;
+       }
+
+       self->offset += amt;
+       return amt;
+}
+
+static int oci_blob_close(php_stream *stream, int close_handle TSRMLS_DC)
+{
+       struct oci_lob_self *self = (struct oci_lob_self*)stream->abstract;
+       pdo_stmt_t *stmt = self->stmt;
+
+       if (close_handle) {
+               OCILobClose(self->S->H->svc, self->S->err, self->lob);
+               OCIDescriptorFree(self->lob, OCI_DTYPE_LOB);
+               efree(self);
+       }
+
+       php_pdo_stmt_delref(stmt TSRMLS_CC);
+       return 0;
+}
+
+static int oci_blob_flush(php_stream *stream TSRMLS_DC)
+{
+       struct oci_lob_self *self = (struct oci_lob_self*)stream->abstract;
+       OCILobFlushBuffer(self->S->H->svc, self->S->err, self->lob, 0);
+       return 0;
+}
+
+static int oci_blob_seek(php_stream *stream, off_t offset, int whence, off_t 
*newoffset TSRMLS_DC)
+{
+       struct oci_lob_self *self = (struct oci_lob_self*)stream->abstract;
+       /* TODO: implement */
+       return -1;      
+}
+
+static php_stream_ops oci_blob_stream_ops = {
+       oci_blob_write,
+       oci_blob_read,
+       oci_blob_close,
+       oci_blob_flush,
+       "pdo_oci blob stream",
+       NULL, /*oci_blob_seek,*/
+       NULL,
+       NULL,
+       NULL
+};
+
+static php_stream *oci_create_lob_stream(pdo_stmt_t *stmt, OCILobLocator *lob 
TSRMLS_DC)
+{
+       php_stream *stm;
+       struct oci_lob_self *self = ecalloc(1, sizeof(*self));
+       self->lob = lob;
+       self->offset = 1; /* 1-based */
+       self->stmt = stmt;
+       self->S = (pdo_oci_stmt*)stmt->driver_data;
+
+       stm = php_stream_alloc(&oci_blob_stream_ops, self, 0, "r+b");
+
+       if (stm) {
+               php_pdo_stmt_addref(stmt TSRMLS_CC);
+               return stm;
+       }
+
+       efree(self);
+       return NULL;
+}
+
 static int oci_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsigned 
long *len, int *caller_frees TSRMLS_DC) /* {{{ */
 {
        pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
@@ -472,6 +689,16 @@
                return 1;
        } else if (C->indicator == 0) {
                /* it was stored perfectly */
+
+               if (C->dtype == SQLT_BLOB || C->dtype == SQLT_CLOB) {
+                       if (C->data) {
+                               *ptr = (char*)oci_create_lob_stream(stmt, 
(OCILobLocator*)C->data TSRMLS_CC);
+                               OCILobOpen(S->H->svc, S->err, 
(OCILobLocator*)C->data, OCI_LOB_READONLY);
+                       }
+                       *len = 0;
+                       return *ptr ? 1 : 0;
+               }
+               
                *ptr = C->data;
                *len = C->fetched_len;
                return 1;
http://cvs.php.net/diff.php/php-src/ext/pdo_oci/php_pdo_oci_int.h?r1=1.4&r2=1.4.2.1&ty=u
Index: php-src/ext/pdo_oci/php_pdo_oci_int.h
diff -u php-src/ext/pdo_oci/php_pdo_oci_int.h:1.4 
php-src/ext/pdo_oci/php_pdo_oci_int.h:1.4.2.1
--- php-src/ext/pdo_oci/php_pdo_oci_int.h:1.4   Mon Jul 11 22:43:39 2005
+++ php-src/ext/pdo_oci/php_pdo_oci_int.h       Sun Oct 30 21:11:27 2005
@@ -16,7 +16,7 @@
   +----------------------------------------------------------------------+
 */
 
-/* $Id: php_pdo_oci_int.h,v 1.4 2005/07/12 02:43:39 wez Exp $ */
+/* $Id: php_pdo_oci_int.h,v 1.4.2.1 2005/10/31 02:11:27 wez Exp $ */
 
 #include <oci.h>
 
@@ -51,7 +51,9 @@
        sb2                     indicator;
 
        char *data;
-       unsigned long datalen;
+       ub4 datalen;
+
+       ub2 dtype;
 
 } pdo_oci_column;
 
@@ -64,6 +66,7 @@
        ub4             exec_type;
        pdo_oci_column *cols;
        pdo_oci_error_info einfo;
+       unsigned int have_blobs:1;
 } pdo_oci_stmt;
 
 typedef struct {

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to