php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #70700 LOB read loop ends early for multibyte strings
Submitted: 2015-10-12 19:29 UTC Modified: 2017-01-25 00:05 UTC
Votes:1
Avg. Score:4.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: ashnazg@php.net Assigned: sixd (profile)
Status: Assigned Package: OCI8 related
PHP Version: 5.5.30 OS: RHEL6, Win7
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2015-10-12 19:29 UTC] ashnazg@php.net
Description:
------------
When using the "while !$lob->eof() { $lob->read($chunk); fwrite($chunk) }" loop to read the contents of a long CLOB that contains only single-byte characters, everything works fine (can get a 10,000,000 char clob no problem).

However, if the CLOB contains mutibyte characters, it seems as though the size of the first LOB->read() call is as far as the loop will go.  Thus, reading the LOB in chunks does not succeed, though no errors are given.

A workaround is to use LOB->size() to determine the full size of the CLOB, and then do one LOB->read() on a larger size chunk (thus getting the entire CLOB in one single, huge read).  I have to guess this is hard on memory usage when large CLOBs are in play, and is thus not a desirable workaround.

Test script:
---------------
(will provide a PHPT in a PR)


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-10-12 19:31 UTC] ashnazg@php.net
Note, it seems at least a little plausible in my mind that #60994 might be related to this bug, as in the bug condition here might be the root cause of the bug behavior on #60994.  See http://stackoverflow.com/questions/33026617/pdo-oci-truncates-large-multibyte-clobs for my rationale on that thought.
 [2015-10-12 20:26 UTC] ashnazg@php.net
PHPT test for this bug is in PR #1569 (https://github.com/php/php-src/pull/1569)
 [2015-10-13 02:05 UTC] sixd@php.net
-Status: Open +Status: Feedback -Assigned To: +Assigned To: sixd
 [2015-10-13 02:05 UTC] sixd@php.net
Thanks for the testcase.
Can you give details of your environment - versions, NLS settings etc?

The PDO_OCI and OCI8 code bases are different so the SO issue may have a different cause or solutions.
 [2015-10-13 15:05 UTC] ashnazg@php.net
My environments:

RHEL6:
- PHP 5.5.24
- oci8 => 1.4.10
- Oracle Run-time Client Library Version => 11.2.0.3.0
- Oracle Instant Client Version => 12.1
- Temporary Lob support => enabled


Win7:
- PHP 5.5.11 
- oci8 => 1.4.10
- Oracle Run-time Client Library Version => 11.2.0.2.0
- Oracle Instant Client Version => 11.2
- Temporary Lob support => enabled

Database:
NLS_LANGUAGE	AMERICAN
NLS_CHARACTERSET	AL32UTF8
NLS_NCHAR_CHARACTERSET	AL16UTF16
NLS_LENGTH_SEMANTICS	CHAR

I don't run these multibyte CLOB tests against my older database that uses WE8MSWIN1252/AL16UTF16, as I've read that PDO OCI doesn't have NCLOB support implemented (that only affects my OCI8 testing because it's a DBAL/ORM system, and thus I'm trying to keep the 'available features' matched between OCI8 and PDO OCI).
 [2015-10-14 05:38 UTC] sixd@php.net
What's the client NLS_LANG?

Neither OCI8 or PDO_OCI support NCHAR / NCLOB.
 [2015-10-14 21:42 UTC] ashnazg@php.net
I can't seem to google a way to determine client NLS_LANG...

The only examples I see are from in sqlplus:
SQL> !
$ echo $NLS_LANG

but that returns nothing.  Perhaps that means my client is not setting it?

(also, that's good to know that OCI8 doesn't cover N-stuff either... was only aware of PDO OCI not handling it)
 [2015-10-25 04:22 UTC] php-bugs at lists dot php dot net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.
 [2015-10-29 15:36 UTC] ashnazg@php.net
The bugtracker will not allow me to change the status to ReOpened.

I am indeed still having this problem.  In my last comment, I asked for a way to determine the answer to your question about "client NLS_LANG".

Is running the PHPT test I provided not an option to see if you can duplicate the issue?
 [2015-11-02 18:15 UTC] sixd@php.net
-Status: No Feedback +Status: Feedback
 [2015-11-02 18:15 UTC] sixd@php.net
If you are using multibyte characters you will almost certainly want NLS_LANG set. It is just an environment variable, so you can 'echo' it, and/or check phpinfo(), or run php -i,  

Review http://www.oracle.com/technetwork/topics/php/underground-php-oracle-manual-098250.html
 [2015-11-15 04:22 UTC] php-bugs at lists dot php dot net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.
 [2017-01-25 00:05 UTC] sixd@php.net
-Status: No Feedback +Status: Open -Type: Bug +Type: Documentation Problem
 [2017-01-25 00:05 UTC] sixd@php.net
This is a doc bug.

The following comments from a github account-less developer are regarding the testcase in https://github.com/php/php-src/pull/1569

"Thank you for reporting this issue and providing a PR. The reason why lob->read() stops at the first loop is because it returns all of data within one loop. lob->read(length) reads length of bytes from BLOB and length of characters from CLOB. So in #1560 test, when lob->read(8192) is called to read multibyte string from a CLOB column, and it actually reads 8192 characters so that the total data (4100 characters) is read in one chunk. However, only 8192 bytes are written into the file that's why only 8192 bytes gets printed later:

fwrite($fh, $data, 8192);

So to make this test behave as expected, we need to replace all the appearances of above line to:

fwrite($fh, $data, strlen($data)); // write all of data in $data to the file

For more info about OCI Lob read, please refer to
(1) OCILobRead2 doc (http://docs.oracle.com/database/122/LNOCI/lob-functions.htm#LNOCI17214)
(2) OCI8 driver code for lob reading (http://lxr.php.net/xref/PHP-MASTER/ext/oci8/oci8_lob.c#326).

Hence, it's not a code bug but the behavior of Lob read is not documented properly. We will update the doc."
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Thu Jul 18 08:01:25 2019 UTC