[ 
https://issues.apache.org/jira/browse/DERBY-3732?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Mike Matrigali updated DERBY-3732:
----------------------------------


The 2 cases I try to think about with stream/blobs/clobs are always the 
following:
1) The data is coming off the disk, through store as a stream, and back to user 
somehow
 - ie. select
2) The data is coming from user to be put into store as a stream - ie. insert.

Mostly the datatype code should not really care which of these 2 cases is in 
effect, but
I think Resetable is a case that matters.

The case you are testing is #1, with getLength() being called by the query 
itself on a stream
created by the store.  That stream is always going to be a OverflowInputStream 
when it comes
out of store - does not matter what type.  But type code should not use that.  
I think using
instanceof Resetable is the right thing.

In case 2 embedded I think the stream may come directly from user - but I am 
not sure what
jdbc layer may do to it before it gets made into a SQLBinary.  A different case 
might be what
comes to the embedded engine after a stream gets sent in from a network client 
across drda
and then into the embedded engine.  In both of these cases I don't know if you 
can actually
get getLength() called, but I also don't think you can count on resetting the 
stream so seems 
cleaner to leave the code as is for this case rather than have the code pretend 
it could handle it.  I don't really know a lot about case 2, so may be off 
track.  The fact that the stream has
the length encoding in it means that some derby code has already got involved 
and modified
the stream the user provided.

I don't know if there are any other situations with streams available in the 
datatype  -
 maybe triggers? 

you probably should ignore the skip comment, better to get it right than worry 
about optimizing it.  Your fix should be way faster in case where length exists 
at front, and be way less memory intensive in the other case so a good 
incremental improvement.

> SQL Length function materializes lob into memory
> ------------------------------------------------
>
>                 Key: DERBY-3732
>                 URL: https://issues.apache.org/jira/browse/DERBY-3732
>             Project: Derby
>          Issue Type: Improvement
>          Components: SQL
>    Affects Versions: 10.3.3.0, 10.4.1.3, 10.5.0.0
>            Reporter: Kathey Marsden
>            Priority: Minor
>         Attachments: derby-3732_proto_diff.txt, LengthLargeLob.zip, 
> LengthThruBlob.java
>
>
> Currently the SQL length function materializes the entire lob into memory. In 
> SQLBinary.getLength() we have 
> public final int      getLength() throws StandardException
>       {
>               if (stream != null) {
>                       if (streamValueLength != -1)
>                               return streamValueLength;
>               }
>               return (getBytes() == null) ? 0 : getBytes().length;
>       }
> Which actually is doubly bad because we call getBytes twice and materialize 
> it twice.
> It would be good to read the length from the stream if available and 
> otherwise stream the value to get the length, rather than materializing it 
> into memory.
> To reproduce, run the attached repro.
> java -Xmx16M  LengthLargeLob
> It gives an out of memory exception
> Caused by: java.lang.OutOfMemoryError: Java heap space
>         at 
> org.apache.derby.iapi.types.SQLBinary.readFromStream(SQLBinary.java:415)
>         at 
> org.apache.derby.iapi.types.SQLBinary.readExternal(SQLBinary.java:318)
>         at org.apache.derby.iapi.types.SQLBinary.getValue(SQLBinary.java:220)
>         at org.apache.derby.iapi.types.SQLBinary.getBytes(SQLBinary.java:210)
>         at org.apache.derby.iapi.types.SQLBinary.getLength(SQLBinary.java:250)
>         at 
> org.apache.derby.impl.sql.execute.BaseActivation.getDB2Length(BaseActivation.java:1684)
>         at 
> org.apache.derby.exe.acf81e0010x011axa317x5db8x0000003d9dc81.e1(Unknown 
> Source)
>         at 
> org.apache.derby.impl.services.reflect.DirectCall.invoke(ReflectGeneratedClass.java:141)
>         at 
> org.apache.derby.impl.sql.execute.ProjectRestrictResultSet.doProjection(ProjectRestrictResultSet.java:497)
>         at 
> org.apache.derby.impl.sql.execute.ProjectRestrictResultSet.getNextRowCore(ProjectRestrictResultSet.java:291)
>         at 
> org.apache.derby.impl.sql.execute.BasicNoPutResultSetImpl.getNextRow(BasicNoPutResultSetImpl.java:460)
>         at 
> org.apache.derby.impl.jdbc.EmbedResultSet.movePosition(EmbedResultSet.java:423)
>         ... 2 more
> [
>  

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to