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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
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 26 15:01:32 2024 UTC