]> granicus.if.org Git - php/commitdiff
fix #36934 (OCILob->read() doesn't move internal pointer when reading 0's)
authorAntony Dovgal <tony2001@php.net>
Wed, 5 Apr 2006 14:07:16 +0000 (14:07 +0000)
committerAntony Dovgal <tony2001@php.net>
Wed, 5 Apr 2006 14:07:16 +0000 (14:07 +0000)
no support for Unicode CLOBs in Oracle < 10, sorry.

ext/oci8/config.m4
ext/oci8/oci8_lob.c
ext/oci8/php_oci8_int.h

index 52d3a871de6bd8563d3afcbd7dc50d4f72ae17da..00af24fd58d7fa48a31c6dcac25979f95578953a 100644 (file)
@@ -232,6 +232,13 @@ if test "$PHP_OCI8" != "no" && test "$PHP_OCI8_INSTANT_CLIENT" = "no"; then
       ], [], [
         -L$OCI8_DIR/$OCI8_LIB_DIR $OCI8_SHARED_LIBADD
       ])
+
+      PHP_CHECK_LIBRARY(clntsh, OCILobRead2,
+      [
+        AC_DEFINE(HAVE_OCI_LOB_READ2,1,[ ])
+      ], [], [
+        -L$OCI8_DIR/$OCI8_LIB_DIR $OCI8_SHARED_LIBADD
+      ])
  
       ;;
       
@@ -242,6 +249,7 @@ if test "$PHP_OCI8" != "no" && test "$PHP_OCI8_INSTANT_CLIENT" = "no"; then
       AC_DEFINE(HAVE_OCI_ENV_NLS_CREATE,1,[ ])
       AC_DEFINE(HAVE_OCI_ENV_CREATE,1,[ ])
       AC_DEFINE(HAVE_OCI_STMT_PREPARE2,1,[ ])
+      AC_DEFINE(HAVE_OCI_LOB_READ2,1,[ ])
       AC_DEFINE(HAVE_OCI8_TEMP_LOB,1,[ ])
       AC_DEFINE(PHP_OCI8_HAVE_COLLECTIONS,1,[ ])
       ;;
@@ -354,6 +362,7 @@ dnl Header directory for manual installation
   AC_DEFINE(HAVE_OCI_ENV_NLS_CREATE,1,[ ])
   AC_DEFINE(HAVE_OCI_ENV_CREATE,1,[ ])
   AC_DEFINE(HAVE_OCI_STMT_PREPARE2,1,[ ])
+  AC_DEFINE(HAVE_OCI_LOB_READ2,1,[ ])
   AC_DEFINE(HAVE_OCI8_TEMP_LOB,1,[ ])
   AC_DEFINE(PHP_OCI8_HAVE_COLLECTIONS,1,[ ])
 
index 352d9d161e4891426087a5e6bca2c2e1e9315862..752c477aa78ab3e2cfb33ff017bdc715da174b31 100644 (file)
@@ -150,8 +150,11 @@ int php_oci_lob_read (php_oci_descriptor *descriptor, long read_length, long ini
 {
        php_oci_connection *connection = descriptor->connection;
        ub4 length = 0;
-       int bytes_read, bytes_total = 0, offset = 0, data_len_chars = 0;
+       int bytes_read, bytes_total = 0, offset = 0;
        int requested_len = read_length; /* this is by default */
+#if defined(HAVE_OCI_LOB_READ2)
+       int chars_read = 0, is_clob = 0;
+#endif
 
        *data_len = 0;
        *data = NULL;
@@ -190,6 +193,23 @@ int php_oci_lob_read (php_oci_descriptor *descriptor, long read_length, long ini
                        return 1;
                }
        }
+#ifdef HAVE_OCI_LOB_READ2
+       else {
+               ub2 charset_id = 0;
+
+               connection->errcode = PHP_OCI_CALL(OCILobCharSetId, (connection->env, connection->err, descriptor->descriptor, &charset_id));
+
+               if (connection->errcode != OCI_SUCCESS) {
+                       php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+                       PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+                       return 1;
+               }
+
+               if (charset_id > 0) { /* charset_id is always > 0 for [N]CLOBs */
+                       is_clob = 1;
+               }
+       }
+#endif
 
        *data = (char *)emalloc(requested_len + 1);
        bytes_read = requested_len;
@@ -198,7 +218,46 @@ int php_oci_lob_read (php_oci_descriptor *descriptor, long read_length, long ini
        /* TODO
         * We need to make sure this function works with Unicode LOBs
         * */
-       
+
+#if defined(HAVE_OCI_LOB_READ2)
+
+       do {
+               chars_read = 0;
+               connection->errcode = PHP_OCI_CALL(OCILobRead2, 
+                       (
+                               connection->svc, 
+                               connection->err, 
+                               descriptor->descriptor, 
+                               (oraub8 *)&bytes_read,                                                          /* IN/OUT bytes toread/read */
+                               (oraub8 *)&chars_read,
+                               (oraub8) offset + 1,                                                            /* offset (starts with 1) */ 
+                               (dvoid *) ((char *) *data + *data_len), 
+                               (oraub8) requested_len,                                                                 /* size of buffer */ 
+                               0, 
+                               NULL,
+                               (OCICallbackLobRead2) 0,                                        /* callback... */ 
+                               (ub2) connection->charset,      /* The character set ID of the buffer data. */ 
+                               (ub1) SQLCS_IMPLICIT                                    /* The character set form of the buffer data. */
+                       )
+               );
+
+               bytes_total += bytes_read;
+               if (is_clob) {
+                       offset += chars_read;
+               } else {
+                       offset += bytes_read;
+               }
+               
+               *data_len += bytes_read;
+               
+               if (connection->errcode != OCI_NEED_DATA) {
+                       break;
+               }
+               *data = erealloc(*data, *data_len + PHP_OCI_LOB_BUFFER_SIZE + 1);       
+       } while (connection->errcode == OCI_NEED_DATA);
+
+#else
+
        do {
                connection->errcode = PHP_OCI_CALL(OCILobRead, 
                        (
@@ -217,11 +276,7 @@ int php_oci_lob_read (php_oci_descriptor *descriptor, long read_length, long ini
                );
 
                bytes_total += bytes_read;
-               /* 
-                * Oracle doesn't tell use how many CHARS were read, 
-                * so we have to count them to get the correct offset for CLOBS */
-               data_len_chars = OCIMultiByteStrnDisplayLength(connection->env, *data, bytes_total); 
-               offset = initial_offset + data_len_chars;
+               offset += bytes_read;
                
                *data_len += bytes_read;
                
@@ -231,6 +286,8 @@ int php_oci_lob_read (php_oci_descriptor *descriptor, long read_length, long ini
                *data = erealloc(*data, *data_len + PHP_OCI_LOB_BUFFER_SIZE + 1);       
        } while (connection->errcode == OCI_NEED_DATA);
 
+#endif
+       
        if (connection->errcode != OCI_SUCCESS) {
                php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
@@ -239,7 +296,7 @@ int php_oci_lob_read (php_oci_descriptor *descriptor, long read_length, long ini
                return 1;
        }
        
-       descriptor->lob_current_position += data_len_chars
+       descriptor->lob_current_position = offset
 
        if (descriptor->type == OCI_DTYPE_FILE) {
                connection->errcode = PHP_OCI_CALL(OCILobFileClose, (connection->svc, connection->err, descriptor->descriptor));
index 0553bc70b997e08e74a583069729422a8ab0351a..94da6eed2acd2f26f068cfac89785b222a1da857 100644 (file)
@@ -78,7 +78,7 @@ extern zend_class_entry *oci_coll_class_entry_ptr;
 #define PHP_OCI_MAX_NAME_LEN  64
 #define PHP_OCI_MAX_DATA_SIZE INT_MAX
 #define PHP_OCI_PIECE_SIZE    (64*1024)-1
-#define PHP_OCI_LOB_BUFFER_SIZE 1048576l 
+#define PHP_OCI_LOB_BUFFER_SIZE 32768 
 
 #define PHP_OCI_ASSOC               1<<0
 #define PHP_OCI_NUM                 1<<1