Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the DBD-Oracle CPAN distribution.

Report information
The Basics
Id: 55028
Status: resolved
Priority: 0/
Queue: DBD-Oracle

People
Owner: Nobody in particular
Requestors: bohica [...] ntlworld.com
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 1.24a
Fixed in: 1.47_00



Subject: DBD INVALID_HANDLE: OCILobGetLength
The following script fails with: DBD::Oracle::db ora_lob_length failed: (DBD INVALID_HANDLE: OCILobGetLength) at empty_lob.pl line 26. Since as far as I am aware, there is no way in DBD::Oracle to detect a NULL lob via the API I wonder how can you deal with NULL lobs? use strict; use warnings; use DBI; use DBD::Oracle qw(:ora_types); use Data::Dumper; my $h = DBI->connect; $h->do(<<'EOT'); create procedure p_mje(plob OUT NOCOPY clob) AS BEGIN plob := NULL; END; EOT my $s = $h->prepare(<<'EOT', {ora_auto_lob => 0, ora_check_sql => 0}); begin p_mje(?); end; EOT my $lob; $s->bind_param_inout(1, \$lob, 20, {ora_type => ORA_CLOB}); $s->execute; print Dumper([$lob]); my $len = $h->ora_lob_length($lob); END { $h->do(q{drop procedure p_mje}); } Martin -- Martin J. Evans Wetherby, UK
One quick thing on this Martin Show quoted text
> $h->do(<<'EOT'); > create procedure p_mje(plob OUT NOCOPY clob) AS > BEGIN > plob := NULL; > END; > EOT
does the above procedure produce an lob locator that is 'Null' or a 'Null' lob??
On Wed Apr 14 15:58:37 2010, PYTHIAN wrote: Show quoted text
> One quick thing on this Martin >
> > $h->do(<<'EOT'); > > create procedure p_mje(plob OUT NOCOPY clob) AS > > BEGIN > > plob := NULL; > > END; > > EOT
> > does the above procedure produce an lob locator that is 'Null' or > a 'Null' lob?? > >
I can't remember right now but I thing the former (and this is why it was a problem) - will check tomorrow. Martin -- Martin J. Evans Wetherby, UK
On Wed Apr 14 16:02:00 2010, MJEVANS wrote: Show quoted text
> On Wed Apr 14 15:58:37 2010, PYTHIAN wrote:
> > One quick thing on this Martin > >
> > > $h->do(<<'EOT'); > > > create procedure p_mje(plob OUT NOCOPY clob) AS > > > BEGIN > > > plob := NULL; > > > END; > > > EOT
> > > > does the above procedure produce an lob locator that is 'Null' or > > a 'Null' lob?? > > > >
> > I can't remember right now but I thing the former (and this is why it > was a problem) - will check tomorrow. > > Martin
I think: DBD::Oracle::db ora_lob_length failed: (DBD INVALID_HANDLE: OCILobGetLength) at empty_lob.pl line 26. is the key. I think OCILogGetLength is passed a NULL handle. Martin -- Martin J. Evans Wetherby, UK
Well working this one up and I have an answer seems the lob locator that is being returned from the function/sql is not inialized by the process that created it so it is retruned as 'invalid' What I am going to do is add the OCI command 'OCILobLocatorIsInit' so the user can test the lob before it is used Look for the patch in Trunk later today
Well I marked it as 'rejected' as it is not a bug in DBD oracle But just for you I added in OCILobLocatorIsInit as the function ora_lob_is_init so you the user can test for this condition before an error is thrown have fun with it and you can find it here http://svn.perl.org/modules/dbd-oracle/trunk
On Fri Apr 23 12:16:31 2010, PYTHIAN wrote: Show quoted text
> Well I marked it as 'rejected' as it is not a bug in DBD oracle > > But just for you I added in OCILobLocatorIsInit as the function > ora_lob_is_init > > so you the user can test for this condition before an error is thrown > > have fun with it and you can find it here > > http://svn.perl.org/modules/dbd-oracle/trunk
Thanks, I will look at it but I still don't understand. If I return a NULL lob from a procedure and Oracle says, it is null so I'm not going to give you a real lob locator, I'm just going to given you NULL then why doesn't DBD::Oracle check for NULL before attempting to use it resulting in the invalid handle. I don't see why the onus should be on Perl code outside of DBI/DBD::Oracle to check for this as I can create a Perl example that does not even know about lob locators. Martin -- Martin J. Evans Wetherby, UK
Its a funny Oracle thing Lob locater can be in one of two states initialized or not. a Lob 'field' can be null or contain a lob locater. That Lob loacter must be initialized even if it points to nothing I think in the case of your code it is returning an uninitialized locater. The empty_clob and empyt_blob SQL function will insert an empty initialized locater in a field hence the reason one will normally never get and uninitialized locater. Hope this helps On Fri Apr 23 12:41:23 2010, MJEVANS wrote: Show quoted text
> On Fri Apr 23 12:16:31 2010, PYTHIAN wrote:
> > Well I marked it as 'rejected' as it is not a bug in DBD oracle > > > > But just for you I added in OCILobLocatorIsInit as the function > > ora_lob_is_init > > > > so you the user can test for this condition before an error is thrown > > > > have fun with it and you can find it here > > > > http://svn.perl.org/modules/dbd-oracle/trunk
> > Thanks, I will look at it but I still don't understand. If I return a > NULL lob from a procedure and Oracle says, it is null so I'm not going > to give you a real lob locator, I'm just going to given you NULL then > why doesn't DBD::Oracle check for NULL before attempting to use it > resulting in the invalid handle. > > I don't see why the onus should be on Perl code outside of > DBI/DBD::Oracle to check for this as I can create a Perl example that > does not even know about lob locators. > > Martin
On Fri Apr 23 12:58:28 2010, PYTHIAN wrote: Show quoted text
> Its a funny Oracle thing > > Lob locater can be in one of two states initialized or not. > > a Lob 'field' can be null or contain a lob locater. That Lob loacter > must be initialized even if it points to nothing > > I think in the case of your code it is returning an uninitialized > locater. > > The empty_clob and empyt_blob SQL function will insert an empty > initialized locater in a field hence the reason one will normally never > get and uninitialized locater. > > Hope this helps
It does, thanks John. I'll try empty_clob. Martin -- Martin J. Evans Wetherby, UK Show quoted text
> > On Fri Apr 23 12:41:23 2010, MJEVANS wrote:
> > On Fri Apr 23 12:16:31 2010, PYTHIAN wrote:
> > > Well I marked it as 'rejected' as it is not a bug in DBD oracle > > > > > > But just for you I added in OCILobLocatorIsInit as the function > > > ora_lob_is_init > > > > > > so you the user can test for this condition before an error is thrown > > > > > > have fun with it and you can find it here > > > > > > http://svn.perl.org/modules/dbd-oracle/trunk
> > > > Thanks, I will look at it but I still don't understand. If I return a > > NULL lob from a procedure and Oracle says, it is null so I'm not going > > to give you a real lob locator, I'm just going to given you NULL then > > why doesn't DBD::Oracle check for NULL before attempting to use it > > resulting in the invalid handle. > > > > I don't see why the onus should be on Perl code outside of > > DBI/DBD::Oracle to check for this as I can create a Perl example that > > does not even know about lob locators. > > > > Martin
>
On Mon Apr 26 04:00:16 2010, MJEVANS wrote: Show quoted text
> On Fri Apr 23 12:58:28 2010, PYTHIAN wrote:
> > Its a funny Oracle thing > > > > Lob locater can be in one of two states initialized or not. > > > > a Lob 'field' can be null or contain a lob locater. That Lob
loacter Show quoted text
> > must be initialized even if it points to nothing > > > > I think in the case of your code it is returning an uninitialized > > locater. > > > > The empty_clob and empyt_blob SQL function will insert an empty > > initialized locater in a field hence the reason one will normally
never Show quoted text
> > get and uninitialized locater. > > > > Hope this helps
> > It does, thanks John. > > I'll try empty_clob. > > Martin
Sorry John, I've been really snowed under lately. The original example I provided does work if you use empty_clob. For anyone reading this here it is: use strict; use warnings; use DBI; use DBD::Oracle qw(:ora_types); use Data::Dumper; my $h = DBI->connect; $h->do(<<'EOT'); create procedure p_mje(plob OUT NOCOPY clob) AS BEGIN plob := empty_clob(); END; EOT my $s = $h->prepare(<<'EOT', {ora_auto_lob => 0, ora_check_sql => 0}); begin p_mje(?); end; EOT my $lob; $s->bind_param_inout(1, \$lob, 20, {ora_type => ORA_CLOB}); $s->execute; print Dumper([$lob]); my $len = $h->ora_lob_length($lob); END { $h->do(q{drop procedure p_mje}); } Thanks for looking in to this. Martin -- Martin J. Evans Wetherby, UK
Tested by user
On Fri May 28 13:16:29 2010, PYTHIAN wrote: Show quoted text
> Tested by user
Sorry to come back to this so late but in actual fact things don't quite work as you'd expect. If you use empty_clob to set up an out param in a procedure and then try and retrieve it via DBD::Oracle you get a segmentation violation: use strict; use warnings; use DBI; use DBD::Oracle qw(:ora_types); use Data::Dumper; my $h = DBI->connect; $h->do(<<'EOT'); create procedure p_mje(plob OUT NOCOPY clob) AS BEGIN plob := empty_clob(); END; EOT my $s = $h->prepare(<<'EOT', {ora_auto_lob => 0, ora_check_sql => 0}); begin p_mje(?); end; EOT my $lob; $s->bind_param_inout(1, \$lob, 20, {ora_type => ORA_CLOB}); $s->execute; print Dumper([$lob]); my $len = $h->ora_lob_length($lob); print "$len\n"; # the following segfaults # seems you need to test $len is not 0 first my $lob = $h->ora_lob_read($lob, 1, $len); END { $h->do(q{drop procedure p_mje}); } Personally I do think it is a bug that you get a segfault but at the very minimum it should be mentioned in the docs that if you attempt to read a lob with a zero length you'll cause your program to segfault. Martin -- Martin J. Evans Wetherby, UK
Here is a stack trace: Program received signal SIGSEGV, Segmentation fault. XS_DBD__Oracle__db_ora_lob_read (my_perl=0x8188008, cv=0x82f2198) at Oracle.xs:421 421 bufp_len = SvLEN(dest_sv); /* XXX bytes not chars? (lab: yes) */ #0 XS_DBD__Oracle__db_ora_lob_read (my_perl=0x8188008, cv=0x82f2198) at Oracle.xs:421 #1 0x00744469 in XS_DBI_dispatch (my_perl=0x8188008, cv=0x81fd888) at DBI.xs:3424 #2 0x080b12c0 in Perl_pp_entersub () #3 0x080af688 in Perl_runops_standard () #4 0x080adbb2 in perl_run () #5 0x08063ffd in main () Martin -- Martin J. Evans Wetherby, UK
On Mon Jul 12 06:07:56 2010, MJEVANS wrote: Show quoted text
> Here is a stack trace: > > Program received signal SIGSEGV, Segmentation fault. > XS_DBD__Oracle__db_ora_lob_read (my_perl=0x8188008, cv=0x82f2198) at > Oracle.xs:421 > 421 bufp_len = SvLEN(dest_sv); /* XXX bytes not chars? (lab: yes) */ > > > #0 XS_DBD__Oracle__db_ora_lob_read (my_perl=0x8188008, cv=0x82f2198) at > Oracle.xs:421 > #1 0x00744469 in XS_DBI_dispatch (my_perl=0x8188008, cv=0x81fd888) at > DBI.xs:3424 > #2 0x080b12c0 in Perl_pp_entersub () > #3 0x080af688 in Perl_runops_standard () > #4 0x080adbb2 in perl_run () > #5 0x08063ffd in main () > > Martin
Problem seems to be in the following code which does not trap a length of 0: void ora_lob_read(dbh, locator, offset, length) SV *dbh OCILobLocator *locator UV offset UV length PREINIT: D_imp_dbh(dbh); ub4 amtp; STRLEN bufp_len; SV *dest_sv; dvoid *bufp; sword status; ub1 csform; CODE: csform = SQLCS_IMPLICIT; /* new SV with length 0 * 4 */ dest_sv = sv_2mortal(newSV(length*4)); /*LAB: crude hack that works... tim did it else where XXX */ SvPOK_on(dest_sv); /* following line segfaults: */ bufp_len = SvLEN(dest_sv); /* XXX bytes not chars? (lab: yes) */ bufp = SvPVX(dest_sv); Martin -- Martin J. Evans Wetherby, UK
I tried reproducing with the following but it does not segfault for me: #!/usr/bin/perl use Inline C => <<'END_C'; void test(UV length) { STRLEN bufp_len; SV *dest_sv; void *bufp; printf("length is %u\n", length); dest_sv = sv_2mortal(newSV(length*4)); printf("dest_sv = %p\n", dest_sv); SvPOK_on(dest_sv); bufp_len = SvLEN(dest_sv); bufp = SvPVX(dest_sv); } END_C test(0); Including it just in case it helps. Martin -- Martin J. Evans Wetherby, UK
On Mon Jul 12 08:59:37 2010, MJEVANS wrote: Show quoted text
> I tried reproducing with the following but it does not segfault for me: > > #!/usr/bin/perl > > use Inline C => <<'END_C'; > > void test(UV length) { > > STRLEN bufp_len; > SV *dest_sv; > void *bufp; > > printf("length is %u\n", length); > dest_sv = sv_2mortal(newSV(length*4)); > printf("dest_sv = %p\n", dest_sv); > SvPOK_on(dest_sv); > bufp_len = SvLEN(dest_sv); > bufp = SvPVX(dest_sv); > } > > END_C > > test(0); > > Including it just in case it helps. > > Martin
Still segfaulting on trunk so I'll try and look into this more. Martin -- Martin J. Evans Wetherby, UK
This is still the case with 1.28. Martin -- Martin J. Evans Wetherby, UK
On Thu Mar 24 06:40:15 2011, MJEVANS wrote: Show quoted text
> This is still the case with 1.28. > > Martin
revision 15334 fixes this by returning undef. Will be in next release after 1.46. Martin -- Martin J. Evans Wetherby, UK