php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #56601 Bug when reading UTF8 CLOBs
Submitted: 2005-10-19 07:08 UTC Modified: 2005-10-26 14:52 UTC
From: jfbustarret at tf1 dot fr Assigned:
Status: Closed Package: oci8 (PECL)
PHP Version: 5.0.3 OS: Linux
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: jfbustarret at tf1 dot fr
New email:
PHP Version: OS:

 

 [2005-10-19 07:08 UTC] jfbustarret at tf1 dot fr
Description:
------------
Using PHP 5.0.5.

Our database (Oracle 9i version 9.2) is in UTF8.

When reading some CLOBs, we have the following error :

OCI8 DEBUG: OCIStmtExecute at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:321)
OCI8 DEBUG: OCIAttrGet at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:350)
OCI8 DEBUG: OCIParamGet at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:372)
OCI8 DEBUG: OCIAttrGet at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:381)
OCI8 DEBUG: OCIAttrGet at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:391)
OCI8 DEBUG: OCIAttrGet at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:404)
OCI8 DEBUG: OCIAttrGet at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:414)
OCI8 DEBUG: OCIAttrGet at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:424)
OCI8 DEBUG: OCIDescriptorFree at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:432)
OCI8 DEBUG: OCIDescriptorAlloc at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_lob.c:73)
OCI8 DEBUG: OCIDefineByPos at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:550)
OCI8 DEBUG: OCIAttrGet at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:963)
OCI8 DEBUG: OCIStmtFetch at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:147)
OCI8 DEBUG: OCILobGetLength at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_lob.c:124)
OCI8 DEBUG: OCILobRead at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_lob.c:214)
<br />
<b>Warning</b>:  OCI-Lob::load() [<a href='function.load'>function.load</a>]: OCI_NEED_DATA in <b>/data/www/commons/commons/class/system/Datab
ase.class.php</b> on line <b>433</b><br />
OCI8 DEBUG: OCIStmtFetch at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:147)
<br />
<b>Warning</b>:  ocifetch() [<a href='function.ocifetch'>function.ocifetch</a>]: Unknown OCI error code: 1010 in <b>/data/www/commons/commons/
class/system/Database.class.php</b> on line <b>412</b><br />
OCI8 DEBUG: OCIAttrGet at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:963)
OCI8 DEBUG: OCIAttrGet at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:984)
OCI8 DEBUG: OCIHandleFree at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:588)
OCI8 DEBUG: OCIHandleFree at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:594)
OCI8 DEBUG: OCIDescriptorFree at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_lob.c:472)
OCI8 DEBUG: OCIHandleAlloc at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:58)
OCI8 DEBUG: OCIHandleAlloc at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:61)
OCI8 DEBUG: OCIStmtPrepare at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:67)
OCI8 DEBUG: OCIAttrSet at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:119)
OCI8 DEBUG: OCIAttrSet at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:128)
OCI8 DEBUG: OCIBindByName at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:789)
OCI8 DEBUG: OCIBindDynamic at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:798)
OCI8 DEBUG: OCIAttrSet at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:119)
OCI8 DEBUG: OCIAttrSet at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:128)
OCI8 DEBUG: OCIAttrGet at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:297)
OCI8 DEBUG: OCIStmtExecute at (/soft/sources/php/php-5.0.5/ext/oci8/oci8_statement.c:321)
OCI8 DEBUG: OCIErrorGet at (/soft/sources/php/php-5.0.5/ext/oci8/oci8.c:809)
<br />
<b>Warning</b>:  ociexecute() [<a href='function.ociexecute'>function.ociexecute</a>]: ORA-03127: no new operations allowed until the active operation ends in <b>/data/www/commons/commons/class/system/Database.class.php</b> on line <b>389</b><br />

The php_oci_lob_read code looks wrong.

The OCILobRead documentation says that amtp/bytes_read (out) and block_read are in bytes while amtp/bytes_read (in) is in characters (offsets are also in characters). In UTF8, num of characters < bytes.

If php_oci_lob_read needs to read PHP_OCI_LOB_BUFFER_SIZE characters, OCILobRead will read min(bytes_read (in characters), block_length (in bytes)) = block_length = PHP_OCI_LOB_BUFFER_SIZE bytes.

It will then wrongly assume it has read everything.

The 1.0 oci8 lib worked fine before (it does read until OCI_NEED_DATA is finished).

(BTW : shouldn't line 218 in oci_log.c (block_length = PHP_OCI_LOB_BUFFER_SIZE) be bytes_read = PHP_OCI_LOB_BUFFER_SIZE ?)


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-10-19 07:16 UTC] tony2001 at phpclub dot net
Please provide a short reproduce case.
 [2005-10-19 09:55 UTC] jfbustarret at tf1 dot fr
Sample code :

<?php

require_once("environnement.dev.conf.php");

//oci_internal_debug(true);

//$content = str_repeat('?', 1048576l);
for($i=0; $i<1; $i++) {
        $content .= str_repeat('?', 1048576);
}
$content .= '?';
echo "strlen(content)=".strlen($content)."<br />";
$content = utf8_encode($content);

$connection = OCILogon(DB_USER, DB_PASSWORD, DB_SERVER);

$query = "delete from jeff where a='a'";
$parsedQuery = OCIParse($connection, $query);
OCIExecute($parsedQuery, OCI_DEFAULT);
OCIFreeStatement($parsedQuery);

$query = "insert into jeff (a,c) values ('a', empty_clob()) returning c into :C";
$parsedQuery = OCIParse($connection, $query);
$lob = OCINewDescriptor($connection, OCI_D_LOB);
OCIBindByName($parsedQuery, ":C", &$lob, -1, OCI_B_CLOB);
OCIExecute($parsedQuery, OCI_DEFAULT);
$lob->save($content);

OCICommit($connection);
OCIFreeDesc($lob);
OCIFreeStatement($parsedQuery);

$query = "select c, DBMS_LOB.GETLENGTH(c) as len from jeff where a='a'";
$parsedQuery = OCIParse($connection, $query);
OCIExecute($parsedQuery, OCI_DEFAULT);
$row = oci_fetch_assoc($parsedQuery);
$content = $row['C']->load();
$content = utf8_decode($content);
echo "loblen=".$row['LEN']." vs lob->size()=".$row['C']->size()." vs strlen(content)=".strlen($content)."<br />";
OCIFreeStatement($parsedQuery);
OCIFreeDesc($row['C']);

?>

This code displays :

strlen(content)=1048577

Warning: OCI-Lob::load() [function.load]: OCI_NEED_DATA in /data/www/www/htdocs/testing/jfb/clob.php on line 37
loblen=1048577 vs lob->size()=1048577 vs strlen(content)=0

Warning: Unknown: ORA-03127: no new operations allowed until the active operation ends in Unknown on line 0

Some DB info :

SQL> select * from nls_database_parameters where parameter='NLS_CHARACTERSET';

PARAMETER
------------------------------
VALUE
--------------------------------------------------------------------------------
NLS_CHARACTERSET
UTF8

SQL> desc jeff;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 A                                         NOT NULL VARCHAR2(10)
 C                                                  CLOB
 [2005-10-19 10:08 UTC] jfbustarret at tf1 dot fr
With length under (or equal to) 524287, it works.
Above, same error.
With very large lengths, it displays :
strlen(content)=2097153
loblen=2097153 vs lob->size()=2097153 vs strlen(content)=1048576
 [2005-10-19 17:04 UTC] tony2001 at phpclub dot net
I can't see any errors with your code.
And NLS_CHARACTERSET is AL32UTF8, btw.
Also it would be very useful if you write what you expected to get as the result (so I wouldn't have to guess myself) and what you really get.

Please try this patch:
http://tony2001.phpclub.net/dev/tmp/pecl_bug5719.diff
 [2005-10-20 02:51 UTC] jfbustarret at tf1 dot fr
I get :

strlen(content)=1048577

Warning: OCI-Lob::load() [function.load]: OCI_NEED_DATA in
/data/www/www/htdocs/testing/jfb/clob.php on line 37
loblen=1048577 vs lob->size()=1048577 vs strlen(content)=0

Warning: Unknown: ORA-03127: no new operations allowed until the active
operation ends in Unknown on line 0

instead of :

strlen(content)=1048577

loblen=1048577 vs lob->size()=1048577 vs strlen(content)=1048577
 [2005-10-20 03:18 UTC] jfbustarret at tf1 dot fr
With the patch, oci->load() works, but oci->read() does not.

works :
$content = $row['C']->load();

does not work :
$content = $row['C']->read(round($row['C']->size()/2));

IMHO, I think you should remove the data_len < requested_len and only rely on OCI_NEED_DATA because with varying-width charset you're unable to know how many bytes you have to read.
 [2005-10-20 07:24 UTC] tony2001 at phpclub dot net
>does not work:
>$content = $row['C']->read(round($row['C']->size()/2));

And "doesn't work" means ... ?
Remember that I still can't see any errors/warnings here.
Could you give me an account @ this host? It would be much more convenient to debug the problem.
 [2005-10-21 09:12 UTC] jfbustarret at tf1 dot fr
"does not work" means "same error message" (OCI_NEED_DATA followed by ORA-03127)

I can't give you any access to my servers. Sorry.
 [2005-10-26 02:53 UTC] tony2001 at phpclub dot net
Please try this patch:
http://tony2001.phpclub.net/dev/tmp/oci8_lob.diff
 [2005-10-26 14:52 UTC] tony2001 at phpclub dot net
This bug has been fixed in CVS.

In case this was a documentation problem, the fix will show up at the
end of next Sunday (CET) on pecl.php.net.

In case this was a pecl.php.net website problem, the change will show
up on the website in short time.
 
Thank you for the report, and for helping us make PECL better.


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Dec 12 14:01:28 2024 UTC